diff options
author | Alex Converse <alex.converse@gmail.com> | 2011-10-10 12:50:00 -0700 |
---|---|---|
committer | Alex Converse <alex.converse@gmail.com> | 2011-10-28 14:54:14 -0700 |
commit | c5302670244bd587d6ff3b6e8ef73451d1c01211 (patch) | |
tree | 225e7cbde53539b85b7b8b4975bf455dcd91e701 /libavformat/mpegts.c | |
parent | 4682a1dc3aa2554ad7077f5db32d0f2d598d018e (diff) | |
download | ffmpeg-c5302670244bd587d6ff3b6e8ef73451d1c01211.tar.gz |
mpegts: MP4 OD support
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r-- | libavformat/mpegts.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index abc3596d91..4c9462cead 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -74,6 +74,7 @@ typedef struct MpegTSSectionFilter { struct MpegTSFilter { int pid; + int es_id; int last_cc; /* last cc code (-1 if first packet) */ enum MpegTSFilterType type; union { @@ -317,6 +318,7 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int ts->pids[pid] = filter; filter->type = MPEGTS_SECTION; filter->pid = pid; + filter->es_id = -1; filter->last_cc = -1; sec = &filter->u.section_filter; sec->section_cb = section_cb; @@ -345,6 +347,7 @@ static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid, ts->pids[pid] = filter; filter->type = MPEGTS_PES; filter->pid = pid; + filter->es_id = -1; filter->last_cc = -1; pes = &filter->u.pes_filter; pes->pes_cb = pes_cb; @@ -934,6 +937,20 @@ static int parse_MP4IODescrTag(MP4DescrParseContext *d, int64_t off, int len) return parse_mp4_descr_arr(d, off, len); } +static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len) +{ + int id_flags; + if (len < 2) + return 0; + id_flags = avio_rb16(&d->pb); + if (!(id_flags & 0x0020)) { //URL_Flag + update_offsets(&d->pb, &off, &len); + return parse_mp4_descr_arr(d, off, len); //ES_Descriptor[] + } else { + return 0; + } +} + static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) { int es_id = 0; @@ -987,6 +1004,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, case MP4IODescrTag: parse_MP4IODescrTag(d, off, len1); break; + case MP4ODescrTag: + parse_MP4ODescrTag(d, off, len1); + break; case MP4ESDescrTag: parse_MP4ESDescrTag(d, off, len1); break; @@ -1014,6 +1034,70 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, return 0; } +static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size, + Mp4Descr *descr, int *descr_count, int max_descr_count) +{ + MP4DescrParseContext d; + if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0) + return -1; + + parse_mp4_descr_arr(&d, avio_tell(&d.pb), size); + + *descr_count = d.descr_count; + return 0; +} + +static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, const uint8_t *p_end) +{ + AVIOContext pb; + Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }}; + int mp4_descr_count = 0; + int i, pid; + + mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT); + + for (pid = 0; pid < NB_PID_MAX; pid++) { + if (!ts->pids[pid]) + continue; + for (i = 0; i < mp4_descr_count; i++) { + PESContext *pes; + AVStream *st; + if (ts->pids[pid]->es_id != mp4_descr[i].es_id) + continue; + if (!(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES)) { + av_log(s, AV_LOG_ERROR, "pid %x is not PES\n", pid); + continue; + } + pes = ts->pids[pid]->u.pes_filter.opaque; + st = pes->st; + if (!st) { + continue; + } + + ffio_init_context(&pb, mp4_descr[i].dec_config_descr, + mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL); + ff_mp4_read_dec_config_descr(s, st, &pb); + if (st->codec->codec_id == CODEC_ID_AAC && + st->codec->extradata_size > 0) + st->need_parsing = 0; + if (st->codec->codec_id == CODEC_ID_H264 && + st->codec->extradata_size > 0) + st->need_parsing = 0; + + if (st->codec->codec_id <= CODEC_ID_NONE) { + } else if (st->codec->codec_id < CODEC_ID_FIRST_AUDIO) { + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + } else if (st->codec->codec_id < CODEC_ID_FIRST_SUBTITLE) { + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + } else if (st->codec->codec_id < CODEC_ID_FIRST_UNKNOWN) { + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + } + } + } + for (i = 0; i < mp4_descr_count; i++) + av_free(mp4_descr[i].dec_config_descr); +} + static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) { MpegTSContext *ts = filter->u.section_filter.opaque; @@ -1030,6 +1114,7 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le if (h->tid != M4OD_TID) return; + SL_packet(ts->stream, ts, p, p_end); } int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, @@ -1061,6 +1146,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type switch(desc_tag) { case 0x1E: /* SL descriptor */ desc_es_id = get16(pp, desc_end); + if (ts && ts->pids[pid]) + ts->pids[pid]->es_id = desc_es_id; for (i = 0; i < mp4_descr_count; i++) if (mp4_descr[i].dec_config_descr_len && mp4_descr[i].es_id == desc_es_id) { @@ -1258,6 +1345,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len } else { st = avformat_new_stream(pes->stream, NULL); st->id = pid; + st->codec->codec_type = AVMEDIA_TYPE_DATA; } } |