]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mpegts.c
avformat/mpegts: Detect changes in packet through CRC instead of just the 5bit version
[ffmpeg] / libavformat / mpegts.c
index 39da4712f5f6b378ef6d161cc7aefd8f292b2e90..613584e4b6b06f4602238f89b1ef337de165f253 100644 (file)
@@ -75,6 +75,9 @@ typedef void SetServiceCallback (void *opaque, int ret);
 typedef struct MpegTSSectionFilter {
     int section_index;
     int section_h_size;
+    int last_ver;
+    unsigned crc;
+    unsigned last_crc;
     uint8_t *section_buf;
     unsigned int check_crc : 1;
     unsigned int end_of_section_reached : 1;
@@ -418,6 +421,9 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
 
         if (tss->check_crc) {
             crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);
+            if (tss->section_h_size >= 4)
+                tss->crc = AV_RB32(tss->section_buf + tss->section_h_size - 4);
+
             if (crc_valid) {
                 ts->crc_validity[ tss1->pid ] = 100;
             }else if (ts->crc_validity[ tss1->pid ] > -10) {
@@ -425,8 +431,11 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
             }else
                 crc_valid = 2;
         }
-        if (crc_valid)
+        if (crc_valid) {
             tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
+            if (crc_valid != 1)
+                tss->last_ver = -1;
+        }
     }
 }
 
@@ -469,6 +478,8 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts,
     sec->opaque      = opaque;
     sec->section_buf = av_malloc(MAX_SECTION_SIZE);
     sec->check_crc   = check_crc;
+    sec->last_ver    = -1;
+
     if (!sec->section_buf) {
         av_free(filter);
         return NULL;
@@ -577,6 +588,17 @@ typedef struct SectionHeader {
     uint8_t last_sec_num;
 } SectionHeader;
 
+static int skip_identical(const SectionHeader *h, MpegTSSectionFilter *tssf)
+{
+    if (h->version == tssf->last_ver && tssf->last_crc == tssf->crc)
+        return 1;
+
+    tssf->last_ver = h->version;
+    tssf->last_crc = tssf->crc;
+
+    return 0;
+}
+
 static inline int get8(const uint8_t **pp, const uint8_t *p_end)
 {
     const uint8_t *p;
@@ -1451,6 +1473,7 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
                     int section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
+    MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h;
     const uint8_t *p, *p_end;
     AVIOContext pb;
@@ -1465,6 +1488,8 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
         return;
     if (h.tid != M4OD_TID)
         return;
+    if (skip_identical(&h, tssf))
+        return;
 
     mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count,
                 MAX_MP4_DESCR_COUNT);
@@ -1584,7 +1609,9 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         if (get16(pp, desc_end) < 0)
             break;
         if (mp4_descr_count > 0 &&
-            (st->codec->codec_id == AV_CODEC_ID_AAC_LATM || st->request_probe > 0) &&
+            (st->codec->codec_id == AV_CODEC_ID_AAC_LATM ||
+             (st->request_probe == 0 && st->codec->codec_id == AV_CODEC_ID_NONE) ||
+             st->request_probe > 0) &&
             mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) {
             AVIOContext pb;
             ffio_init_context(&pb, mp4_descr->dec_config_descr,
@@ -1787,6 +1814,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
 static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
+    MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h1, *h = &h1;
     PESContext *pes;
     AVStream *st;
@@ -1806,6 +1834,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     p = section;
     if (parse_section_header(h, &p, p_end) < 0)
         return;
+    if (skip_identical(h, tssf))
+        return;
 
     av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d\n",
             h->id, h->sec_num, h->last_sec_num, h->version);
@@ -1955,6 +1985,7 @@ out:
 static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
+    MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h1, *h = &h1;
     const uint8_t *p, *p_end;
     int sid, pmt_pid;
@@ -1972,6 +2003,8 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     if (ts->skip_changes)
         return;
 
+    if (skip_identical(h, tssf))
+        return;
     ts->stream->ts_id = h->id;
 
     clear_programs(ts);
@@ -2027,6 +2060,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
 static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
 {
     MpegTSContext *ts = filter->u.section_filter.opaque;
+    MpegTSSectionFilter *tssf = &filter->u.section_filter;
     SectionHeader h1, *h = &h1;
     const uint8_t *p, *p_end, *desc_list_end, *desc_end;
     int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type;
@@ -2043,6 +2077,9 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
         return;
     if (ts->skip_changes)
         return;
+    if (skip_identical(h, tssf))
+        return;
+
     onid = get16(&p, p_end);
     if (onid < 0)
         return;
@@ -2349,6 +2386,8 @@ static int handle_packets(MpegTSContext *ts, int64_t nb_packets)
                     av_buffer_unref(&pes->buffer);
                     pes->data_index = 0;
                     pes->state = MPEGTS_SKIP; /* skip until pes header */
+                } else if (ts->pids[i]->type == MPEGTS_SECTION) {
+                    ts->pids[i]->u.section_filter.last_ver = -1;
                 }
                 ts->pids[i]->last_cc = -1;
                 ts->pids[i]->last_pcr = -1;