Message ID | 20180517224926.4106-2-ffmpeg@tmm1.net |
---|---|
State | New |
Headers | show |
On Thu, May 17, 2018 at 3:49 PM, Aman Gupta <ffmpeg@tmm1.net> wrote: > From: Aman Gupta <aman@tmm1.net> > > This can be used to detect changes to the streams in an AVProgram > Forgot to add: I have seen two related patches in the wild that attempt to solve this same problem in different ways. The first is in MythTV's ffmpeg fork, where they added a void (*streams_changed)(void*); to AVFormatContext and call it from their mpegts demuxer when the PMT changes. The second was proposed by XBMC in https://ffmpeg.org/pipermail/ffmpeg-devel/2012-December/135036.html, where they created a new AVMEDIA_TYPE_DATA stream with id=0 and attempted to send packets to it whenever the PMT changed. The approach in this patch is similar to what's used by AVFormatContext.event_flags and AVFMT_EVENT_FLAG_METADATA_UPDATED. I re-used AVProgram.flags for this purpose (which appears not to be used for anything else). To be more explicit, it might be better to add AVProgram.event_flags. Note that either way, the user would need to clear AV_PROGRAM_CHANGED after detecting it (which should be documented). Another possibility would be to remove AV_PROGRAM_CHANGED altogether, which means the user would need to keep a copy of program->version and compare it to detect changes. Aman > > Signed-off-by: Aman Gupta <aman@tmm1.net> > --- > libavformat/mpegts.c | 20 ++++++++++++++++---- > 1 file changed, 16 insertions(+), 4 deletions(-) > > diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c > index fc9bb3940e..e83238d733 100644 > --- a/libavformat/mpegts.c > +++ b/libavformat/mpegts.c > @@ -330,12 +330,24 @@ static void set_pmt_found(MpegTSContext *ts, > unsigned int programid) > p->pmt_found = 1; > } > > -static void set_pcr_pid(AVFormatContext *s, unsigned int programid, > unsigned int pid) > +static void update_av_program_info(AVFormatContext *s, unsigned int > programid, > + unsigned int pid, int version) > { > int i; > for (i = 0; i < s->nb_programs; i++) { > - if (s->programs[i]->id == programid) { > - s->programs[i]->pcr_pid = pid; > + AVProgram *program = s->programs[i]; > + if (program->id == programid) { > + int old_pcr_pid = program->pcr_pid, > + old_version = program->pmt_version; > + program->pcr_pid = pid; > + program->pmt_version = version; > + > + if (old_version != -1 && old_version != version) { > + program->flags |= AV_PROGRAM_CHANGED; > + av_log(s, AV_LOG_DEBUG, > + "detected PMT change on program %d (version=%d/%d, > pcr_pid=0x%x/0x%x)\n", > + programid, old_version, version, old_pcr_pid, pid); > + } > break; > } > } > @@ -2036,7 +2048,7 @@ static void pmt_cb(MpegTSFilter *filter, const > uint8_t *section, int section_len > return; > pcr_pid &= 0x1fff; > add_pid_to_pmt(ts, h->id, pcr_pid); > - set_pcr_pid(ts->stream, h->id, pcr_pid); > + update_av_program_info(ts->stream, h->id, pcr_pid, h->version); > > av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid); > > -- > 2.14.2 > >
On Thu, 17 May 2018 18:13:34 -0700 Aman Gupta <aman@tmm1.net> wrote: > On Thu, May 17, 2018 at 3:49 PM, Aman Gupta <ffmpeg@tmm1.net> wrote: > > > From: Aman Gupta <aman@tmm1.net> > > > > This can be used to detect changes to the streams in an AVProgram > > > > Forgot to add: I have seen two related patches in the wild that attempt to > solve this same problem in different ways. > > The first is in MythTV's ffmpeg fork, where they added a void > (*streams_changed)(void*); to AVFormatContext and call it from their mpegts > demuxer when the PMT changes. > > The second was proposed by XBMC in > https://ffmpeg.org/pipermail/ffmpeg-devel/2012-December/135036.html, where > they created a new AVMEDIA_TYPE_DATA stream with id=0 and attempted to send > packets to it whenever the PMT changed. > > The approach in this patch is similar to what's used by > AVFormatContext.event_flags and AVFMT_EVENT_FLAG_METADATA_UPDATED. > > I re-used AVProgram.flags for this purpose (which appears not to be used > for anything else). To be more explicit, it might be better to add > AVProgram.event_flags. Note that either way, the user would need to clear > AV_PROGRAM_CHANGED after detecting it (which should be documented). > > Another possibility would be to remove AV_PROGRAM_CHANGED altogether, which > means the user would need to keep a copy of program->version and compare it > to detect changes. Probably needs new doxygen that says that the API user can clear that change flag when convenient.
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index fc9bb3940e..e83238d733 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -330,12 +330,24 @@ static void set_pmt_found(MpegTSContext *ts, unsigned int programid) p->pmt_found = 1; } -static void set_pcr_pid(AVFormatContext *s, unsigned int programid, unsigned int pid) +static void update_av_program_info(AVFormatContext *s, unsigned int programid, + unsigned int pid, int version) { int i; for (i = 0; i < s->nb_programs; i++) { - if (s->programs[i]->id == programid) { - s->programs[i]->pcr_pid = pid; + AVProgram *program = s->programs[i]; + if (program->id == programid) { + int old_pcr_pid = program->pcr_pid, + old_version = program->pmt_version; + program->pcr_pid = pid; + program->pmt_version = version; + + if (old_version != -1 && old_version != version) { + program->flags |= AV_PROGRAM_CHANGED; + av_log(s, AV_LOG_DEBUG, + "detected PMT change on program %d (version=%d/%d, pcr_pid=0x%x/0x%x)\n", + programid, old_version, version, old_pcr_pid, pid); + } break; } } @@ -2036,7 +2048,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; pcr_pid &= 0x1fff; add_pid_to_pmt(ts, h->id, pcr_pid); - set_pcr_pid(ts->stream, h->id, pcr_pid); + update_av_program_info(ts->stream, h->id, pcr_pid, h->version); av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid);