On Mon, May 14, 2018 at 03:54:01PM -0700, Aman Gupta wrote: > From: Aman Gupta <a...@tmm1.net> > > This new optional flag makes it easier to deal with mpegts > samples where the PMT is updated and elementary streams move > to different PIDs in the middle of playback. > > Previously, new AVStreams were created per PID, and it was up > to the user to figure out which streams had migrated to a new PID > (by iterating over the list of AVProgram and making guesses), and > switch seamlessly to the new AVStream during playback. > > Transcoding or remuxing these streams with ffmpeg on the CLI was > also quite painful, and the user would need to extract each set of > PIDs into a separate file and then stitch them back together. > > With this new option, the mpegts demuxer will automatically detect > PMT changes and feed data from the new PID to the original AVStream > that was created for the orignal PID. For mpegts samples with > stream_identifier_descriptor available, the unique ID is used to merge > PIDs together. If the stream id is not available, the demuxer attempts > to map PIDs based on their order and relation to the PCR pid. > > With this change, I am able to playback and transcode/remux these > two samples which previously caused issues: > > https://tmm1.s3.amazonaws.com/pmt-version-change.ts > https://kuroko.fushizen.eu/videos/pid_switch_sample.ts > > I also have another longer sample which contains multiple PMT > changes, some of which change the ES pids and others which do not: > > https://tmm1.s3.amazonaws.com/multiple-pmt-change.ts > > Demuxing this sample with the new option shows several new log > messages as the PMT changes are handled: > > [mpegts @ 0x7ffe18801200] detected PMT change (version=3/4, > pcr_pid=0xf98/0xf9b) > [mpegts @ 0x7ffe18801200] re-using existing video stream 0 (pid=0xf98) > for new pid=0xf9b > [mpegts @ 0x7ffe18801200] re-using existing audio stream 1 (pid=0xf99) > for new pid=0xf9c > [mpegts @ 0x7ffe18801200] re-using existing audio stream 2 (pid=0xf9a) > for new pid=0xf9d > [mpegts @ 0x7ffe18801200] detected PMT change (version=4/5, > pcr_pid=0xf9b/0xfa9) > [mpegts @ 0x7ffe18801200] re-using existing video stream 0 (pid=0xf98) > for new pid=0xfa9 > [mpegts @ 0x7ffe18801200] re-using existing audio stream 1 (pid=0xf99) > for new pid=0xfaa > [mpegts @ 0x7ffe18801200] re-using existing audio stream 2 (pid=0xf9a) > for new pid=0xfab
This sounds like an interresting feature this should also get a fate test > > Signed-off-by: Aman Gupta <a...@tmm1.net> > --- > doc/demuxers.texi | 4 ++ > libavformat/mpegts.c | 105 > +++++++++++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 105 insertions(+), 4 deletions(-) > > diff --git a/doc/demuxers.texi b/doc/demuxers.texi > index e7c2abce57..2f7d7e0f3a 100644 > --- a/doc/demuxers.texi > +++ b/doc/demuxers.texi > @@ -552,6 +552,10 @@ Show the detected raw packet size, cannot be set by the > user. > Scan and combine all PMTs. The value is an integer with value from -1 > to 1 (-1 means automatic setting, 1 means enabled, 0 means > disabled). Default value is -1. > + > +@item merge_pmt_versions > +Re-use existing streams when a PMT's version is updated and elementary > +streams move to different PIDs. Default value is 0. > @end table > > @section mpjpeg > diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c > index 27b1c30a44..c42e564a7e 100644 > --- a/libavformat/mpegts.c > +++ b/libavformat/mpegts.c > @@ -84,6 +84,8 @@ typedef struct MpegTSSectionFilter { > unsigned int end_of_section_reached : 1; > SectionCallback *section_cb; > void *opaque; > + int orig_pcr_pid; /* pmt specific */ > + int last_pcr_pid; > } MpegTSSectionFilter; > > struct MpegTSFilter { > @@ -147,6 +149,7 @@ struct MpegTSContext { > int scan_all_pmts; > > int resync_size; > + int merge_pmt_versions; > > /******************************************/ > /* private mpegts data */ > @@ -172,6 +175,8 @@ static const AVOption options[] = { > {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | > AV_OPT_FLAG_READONLY }, > {"scan_all_pmts", "scan and combine all PMTs", offsetof(MpegTSContext, > scan_all_pmts), AV_OPT_TYPE_BOOL, > {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM }, > + {"merge_pmt_versions", "re-use streams when PMT's version/pids change", > offsetof(MpegTSContext, merge_pmt_versions), AV_OPT_TYPE_BOOL, > + {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, > {"skip_changes", "skip changing / adding streams / programs", > offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_BOOL, > {.i64 = 0}, 0, 1, 0 }, > {"skip_clear", "skip clearing programs", offsetof(MpegTSContext, > skip_clear), AV_OPT_TYPE_BOOL, > @@ -1073,7 +1078,8 @@ static int mpegts_push_data(MpegTSFilter *filter, > if (ts->skip_changes) > goto skip; > > - pes->st = avformat_new_stream(ts->stream, NULL); > + if (!pes->st) > + pes->st = avformat_new_stream(ts->stream, NULL); > if (!pes->st) > return AVERROR(ENOMEM); > pes->st->id = pes->pid; > @@ -1982,6 +1988,68 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, > AVStream *st, int stream_type > *pp = desc_end; > return 0; > } > +static AVStream *find_matching_stream(MpegTSContext *ts, int pid, > + int stream_id, > + int pcr_pid, int orig_pcr_pid) > +{ > + AVFormatContext *s = ts->stream; > + int i, orig_pid = orig_pcr_pid + (pid - pcr_pid); > + AVStream *found = NULL; > + > + for (i = 0; i < s->nb_streams; i++) { > + AVStream *st = s->streams[i]; > + if (stream_id != -1) { > + if (st->stream_identifier == stream_id+1) { > + found = st; > + break; > + } > + } else if (pcr_pid != orig_pcr_pid && st->id == orig_pid) { > + found = st; > + break; > + } > + } > + > + if (found) { > + av_log(ts->stream, AV_LOG_DEBUG, "re-using existing %s stream %d > (pid=0x%x) for new pid=0x%x\n", > + av_get_media_type_string(found->codecpar->codec_type), i, > found->id, pid); > + } > + > + return found; > +} > + > +static int parse_stream_identifier_desc(uint8_t *p, uint8_t *p_end) > +{ > + const uint8_t **pp = &p; libavformat/mpegts.c:2022:26: warning: initialization from incompatible pointer type [enabled by default] > + const uint8_t *desc_list_end; > + const uint8_t *desc_end; > + int desc_list_len; > + int desc_len, desc_tag; > + > + desc_list_len = get16(&p, p_end); type mismatch: libavformat/mpegts.c:2028:5: warning: passing argument 1 of ‘get16’ from incompatible pointer type [enabled by default] [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Opposition brings concord. Out of discord comes the fairest harmony. -- Heraclitus
signature.asc
Description: PGP signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel