[FFmpeg-devel,v3,2/3] avformat/mpegts: keep track of AVProgram.pmt_version and set AV_PROGRAM_CHANGED on version updates

Submitted by Aman Gupta on May 17, 2018, 10:49 p.m.

Details

Message ID 20180517224926.4106-2-ffmpeg@tmm1.net
State New
Headers show

Commit Message

Aman Gupta May 17, 2018, 10:49 p.m.
From: Aman Gupta <aman@tmm1.net>

This can be used to detect changes to the streams in an AVProgram

Signed-off-by: Aman Gupta <aman@tmm1.net>
---
 libavformat/mpegts.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

Comments

Aman Gupta May 18, 2018, 1:13 a.m.
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
>
>
wm4 May 18, 2018, 9:48 a.m.
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.

Patch hide | download patch | download mbox

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);