00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "avformat.h"
00028 #include "internal.h"
00029 #include "subtitles.h"
00030 #include "libavutil/avstring.h"
00031 #include "libavutil/bprint.h"
00032 #include "libavutil/intreadwrite.h"
00033
00034 typedef struct {
00035 FFDemuxSubtitlesQueue q;
00036 } SAMIContext;
00037
00038 static int sami_probe(AVProbeData *p)
00039 {
00040 const unsigned char *ptr = p->buf;
00041
00042 if (AV_RB24(ptr) == 0xEFBBBF)
00043 ptr += 3;
00044 return !strncmp(ptr, "<SAMI>", 6) ? AVPROBE_SCORE_MAX : 0;
00045 }
00046
00047 static int sami_read_header(AVFormatContext *s)
00048 {
00049 SAMIContext *sami = s->priv_data;
00050 AVStream *st = avformat_new_stream(s, NULL);
00051 AVBPrint buf, hdr_buf;
00052 char c = 0;
00053 int res = 0, got_first_sync_point = 0;
00054
00055 if (!st)
00056 return AVERROR(ENOMEM);
00057 avpriv_set_pts_info(st, 64, 1, 1000);
00058 st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
00059 st->codec->codec_id = AV_CODEC_ID_SAMI;
00060
00061 av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
00062 av_bprint_init(&hdr_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
00063
00064 while (!url_feof(s->pb)) {
00065 AVPacket *sub;
00066 const int64_t pos = avio_tell(s->pb) - (c != 0);
00067 int is_sync, n = ff_smil_extract_next_chunk(s->pb, &buf, &c);
00068
00069 if (n == 0)
00070 break;
00071
00072 is_sync = !av_strncasecmp(buf.str, "<SYNC", 5);
00073 if (is_sync)
00074 got_first_sync_point = 1;
00075
00076 if (!got_first_sync_point) {
00077 av_bprintf(&hdr_buf, "%s", buf.str);
00078 } else {
00079 sub = ff_subtitles_queue_insert(&sami->q, buf.str, buf.len, !is_sync);
00080 if (!sub) {
00081 res = AVERROR(ENOMEM);
00082 goto end;
00083 }
00084 if (is_sync) {
00085 const char *p = ff_smil_get_attr_ptr(buf.str, "Start");
00086 sub->pos = pos;
00087 sub->pts = p ? strtol(p, NULL, 10) : 0;
00088 sub->duration = -1;
00089 }
00090 }
00091 av_bprint_clear(&buf);
00092 }
00093
00094 st->codec->extradata_size = hdr_buf.len + 1;
00095 av_bprint_finalize(&hdr_buf, (char **)&st->codec->extradata);
00096 if (!st->codec->extradata) {
00097 st->codec->extradata_size = 0;
00098 res = AVERROR(ENOMEM);
00099 goto end;
00100 }
00101
00102 ff_subtitles_queue_finalize(&sami->q);
00103
00104 end:
00105 av_bprint_finalize(&buf, NULL);
00106 return res;
00107 }
00108
00109 static int sami_read_packet(AVFormatContext *s, AVPacket *pkt)
00110 {
00111 SAMIContext *sami = s->priv_data;
00112 return ff_subtitles_queue_read_packet(&sami->q, pkt);
00113 }
00114
00115 static int sami_read_close(AVFormatContext *s)
00116 {
00117 SAMIContext *sami = s->priv_data;
00118 ff_subtitles_queue_clean(&sami->q);
00119 return 0;
00120 }
00121
00122 AVInputFormat ff_sami_demuxer = {
00123 .name = "sami",
00124 .long_name = NULL_IF_CONFIG_SMALL("SAMI subtitle format"),
00125 .priv_data_size = sizeof(SAMIContext),
00126 .read_probe = sami_probe,
00127 .read_header = sami_read_header,
00128 .read_packet = sami_read_packet,
00129 .read_close = sami_read_close,
00130 .flags = AVFMT_GENERIC_INDEX,
00131 .extensions = "smi,sami",
00132 };