diff mbox

[FFmpeg-devel,2/4] V10 - SCTE-35 extraction from mpegts

Message ID 1474912787-2952-3-git-send-email-carlos@ccextractor.org
State Changes Requested
Headers show

Commit Message

Carlos Fernandez Sanz Sept. 26, 2016, 5:59 p.m. UTC
From: Carlos Fernandez <carlos@ccextractor.org>

Signed-off-by: Carlos Fernandez <carlos@ccextractor.org>
---
 libavformat/mpegts.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 2 deletions(-)

Comments

Michael Niedermayer Sept. 26, 2016, 10:25 p.m. UTC | #1
On Mon, Sep 26, 2016 at 10:59:45AM -0700, Carlos Fernandez Sanz wrote:
> From: Carlos Fernandez <carlos@ccextractor.org>
> 
> Signed-off-by: Carlos Fernandez <carlos@ccextractor.org>
> ---
>  libavformat/mpegts.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 62 insertions(+), 2 deletions(-)
> 

this breaks fate:
make: *** [fate-h264-skip-nokey] Error 1
make: *** [fate-h264-skip-nointra] Error 1
make: *** [fate-ts-demux] Error 1
make: *** [fate-copy-trac4914] Error 1
make: *** [fate-copy-trac4914-avi] Error 1
make: *** [fate-lavf-ts] Error 1

[...]
Marton Balint Sept. 27, 2016, 7:30 a.m. UTC | #2
On Mon, 26 Sep 2016, Carlos Fernandez Sanz wrote:

> From: Carlos Fernandez <carlos@ccextractor.org>
>
> Signed-off-by: Carlos Fernandez <carlos@ccextractor.org>
> ---
> libavformat/mpegts.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 62 insertions(+), 2 deletions(-)
>
> diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
> index b31d233..ad6f141 100644
> --- a/libavformat/mpegts.c
> +++ b/libavformat/mpegts.c
> @@ -725,6 +725,12 @@ static const StreamType HDMV_types[] = {
>     { 0 },
> };
> 
> +/* SCTE types */
> +static const StreamType SCTE_types[] = {
> +    { 0x86, AVMEDIA_TYPE_DATA,  AV_CODEC_ID_SCTE_35    },
> +    { 0 },
> +};
> +
> /* ATSC ? */
> static const StreamType MISC_types[] = {
>     { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
> @@ -872,6 +878,13 @@ static void reset_pes_packet_state(PESContext *pes)
>     av_buffer_unref(&pes->buffer);
> }
> 
> +static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt)
> +{
> +    av_init_packet(pkt);
> +    pkt->data = buffer;
> +    pkt->size = len;
> +}
> +
> static int new_pes_packet(PESContext *pes, AVPacket *pkt)
> {
>     char *sd;
> @@ -1590,6 +1603,27 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
>         av_free(mp4_descr[i].dec_config_descr);
> }
> 
> +static void scte_data_cb(MpegTSFilter *filter, const uint8_t *section,
> +                    int section_len)
> +{
> +    AVProgram *prg = NULL;
> +    MpegTSContext *ts = filter->u.section_filter.opaque;
> +
> +    int idx = ff_find_stream_index(ts->stream, filter->pid);
> +    new_data_packet(section, section_len, ts->pkt);
> +    if (idx >= 0) {
> +        ts->pkt->stream_index = idx;
> +    }
> +    prg = av_find_program_from_stream(ts->stream, NULL, idx);
> +    if (prg && prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) {
> +        MpegTSFilter *f = ts->pids[prg->pcr_pid];
> +        if(f)
> +            ts->pkt->pts = ts->pkt->dts = f->last_pcr/300;
> +    }
> +    ts->stop_parse = 1;
> +
> +}
> +
> static const uint8_t opus_coupled_stream_cnt[9] = {
>     1, 0, 1, 1, 2, 2, 2, 3, 3
> };
> @@ -1868,6 +1902,12 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
>     return 0;
> }
> 
> +static int is_pes_stream(int stream_type, uint32_t prog_reg_desc)
> +{
> +    return !(stream_type == 0x13 ||
> +             stream_type == 0x86 && prog_reg_desc == AV_RL32("CUEI"));
> +}
> +
> static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
> {
>     MpegTSContext *ts = filter->u.section_filter.opaque;
> @@ -1975,7 +2015,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
>                 pes->st->id = pes->pid;
>             }
>             st = pes->st;
> -        } else if (stream_type != 0x13) {
> +
> +        } else if (is_pes_stream(stream_type, prog_reg_desc)) {
>             if (ts->pids[pid])
>                 mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably
>             pes = add_pes_stream(ts, pid, pcr_pid);
> @@ -1994,7 +2035,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
>                 if (!st)
>                     goto out;
>                 st->id = pid;
> +                mpegts_find_stream_type(st, stream_type, SCTE_types);
>                 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
> +                mpegts_open_section_filter(ts, pid, scte_data_cb, ts, 1);

probably you only want to call these additional functions, if the data 
stream really is an SCTE section (if prog_reg_desc == AV_RL32("CUEI")).

>             }
>         }
> 
> @@ -2317,7 +2360,22 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
>                 }
>             }
>         }
> -
> +        if(0) {

This is some leftover, which can be deleted?

> +            AVProgram *prg = NULL;
> +            int idx = ff_find_stream_index(ts->stream, pid);
> +            p++;
> +            new_data_packet(p,p_end - p, ts->pkt);
> +            if (idx >= 0) {
> +                ts->pkt->stream_index = idx;
> +            }
> +            prg = av_find_program_from_stream(ts->stream, prg, idx);
> +            if (prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) {
> +                MpegTSFilter *f = ts->pids[prg->pcr_pid];
> +                if(f)
> +                    ts->pkt->pts = ts->pkt->dts = f->last_pcr/300;
> +            }
> +            ts->stop_parse = 1;
> +        }
>     } else {
>         int ret;
>         // Note: The position here points actually behind the current packet.
> @@ -2730,6 +2788,8 @@ static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
>                     ret = 0;
>                     break;
>                 }
> +            } else if (ts->pids[i] && ts->pids[i]->type == MPEGTS_SECTION) {
> +                return ret;

Why do you need this hunk? I think you can delete it, and everything will 
remain working. This loop flushes existing half-read PES packets, so you 
cannot simply return in the middle of the loop.

Regards,
Marton
Carlos Fernandez Sanz Sept. 27, 2016, 3:01 p.m. UTC | #3
On Tue, Sep 27, 2016 at 12:30 AM, Marton Balint <cus@passwd.hu> wrote:

>> +            } else if (ts->pids[i] && ts->pids[i]->type ==
>> MPEGTS_SECTION) {
>> +                return ret;
>
>
> Why do you need this hunk? I think you can delete it, and everything will
> remain working. This loop flushes existing half-read PES packets, so you
> cannot simply return in the middle of the loop.

If we remove it we don't get SCTE-35.

New patch coming up later today.
Carlos Fernandez Sanz Sept. 27, 2016, 8:39 p.m. UTC | #4
On Mon, Sep 26, 2016 at 3:25 PM, Michael Niedermayer
<michael@niedermayer.cc> wrote:
>
> this breaks fate:
> make: *** [fate-h264-skip-nokey] Error 1

Thanks - solved in V11.
diff mbox

Patch

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index b31d233..ad6f141 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -725,6 +725,12 @@  static const StreamType HDMV_types[] = {
     { 0 },
 };
 
+/* SCTE types */
+static const StreamType SCTE_types[] = {
+    { 0x86, AVMEDIA_TYPE_DATA,  AV_CODEC_ID_SCTE_35    },
+    { 0 },
+};
+
 /* ATSC ? */
 static const StreamType MISC_types[] = {
     { 0x81, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 },
@@ -872,6 +878,13 @@  static void reset_pes_packet_state(PESContext *pes)
     av_buffer_unref(&pes->buffer);
 }
 
+static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt)
+{
+    av_init_packet(pkt);
+    pkt->data = buffer;
+    pkt->size = len;
+}
+
 static int new_pes_packet(PESContext *pes, AVPacket *pkt)
 {
     char *sd;
@@ -1590,6 +1603,27 @@  static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
         av_free(mp4_descr[i].dec_config_descr);
 }
 
+static void scte_data_cb(MpegTSFilter *filter, const uint8_t *section,
+                    int section_len)
+{
+    AVProgram *prg = NULL;
+    MpegTSContext *ts = filter->u.section_filter.opaque;
+
+    int idx = ff_find_stream_index(ts->stream, filter->pid);
+    new_data_packet(section, section_len, ts->pkt);
+    if (idx >= 0) {
+        ts->pkt->stream_index = idx;
+    }
+    prg = av_find_program_from_stream(ts->stream, NULL, idx);
+    if (prg && prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) {
+        MpegTSFilter *f = ts->pids[prg->pcr_pid];
+        if(f)
+            ts->pkt->pts = ts->pkt->dts = f->last_pcr/300;
+    }
+    ts->stop_parse = 1;
+
+}
+
 static const uint8_t opus_coupled_stream_cnt[9] = {
     1, 0, 1, 1, 2, 2, 2, 3, 3
 };
@@ -1868,6 +1902,12 @@  int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
     return 0;
 }
 
+static int is_pes_stream(int stream_type, uint32_t prog_reg_desc)
+{
+    return !(stream_type == 0x13 ||
+             stream_type == 0x86 && prog_reg_desc == AV_RL32("CUEI"));
+}
+
 static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
@@ -1975,7 +2015,8 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 pes->st->id = pes->pid;
             }
             st = pes->st;
-        } else if (stream_type != 0x13) {
+
+        } else if (is_pes_stream(stream_type, prog_reg_desc)) {
             if (ts->pids[pid])
                 mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably
             pes = add_pes_stream(ts, pid, pcr_pid);
@@ -1994,7 +2035,9 @@  static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 if (!st)
                     goto out;
                 st->id = pid;
+                mpegts_find_stream_type(st, stream_type, SCTE_types);
                 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+                mpegts_open_section_filter(ts, pid, scte_data_cb, ts, 1);
             }
         }
 
@@ -2317,7 +2360,22 @@  static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
                 }
             }
         }
-
+        if(0) {
+            AVProgram *prg = NULL;
+            int idx = ff_find_stream_index(ts->stream, pid);
+            p++;
+            new_data_packet(p,p_end - p, ts->pkt);
+            if (idx >= 0) {
+                ts->pkt->stream_index = idx;
+            }
+            prg = av_find_program_from_stream(ts->stream, prg, idx);
+            if (prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) {
+                MpegTSFilter *f = ts->pids[prg->pcr_pid];
+                if(f)
+                    ts->pkt->pts = ts->pkt->dts = f->last_pcr/300;
+            }
+            ts->stop_parse = 1;
+        }
     } else {
         int ret;
         // Note: The position here points actually behind the current packet.
@@ -2730,6 +2788,8 @@  static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
                     ret = 0;
                     break;
                 }
+            } else if (ts->pids[i] && ts->pids[i]->type == MPEGTS_SECTION) {
+                return ret;
             }
     }