]> 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 2caa6c64740349d4e92c2f882ee73ef308a4922b..613584e4b6b06f4602238f89b1ef337de165f253 100644 (file)
@@ -76,6 +76,8 @@ 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;
@@ -419,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) {
@@ -426,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;
+        }
     }
 }
 
@@ -580,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;
@@ -1469,9 +1488,8 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
         return;
     if (h.tid != M4OD_TID)
         return;
-    if (h.version == tssf->last_ver)
+    if (skip_identical(&h, tssf))
         return;
-    tssf->last_ver = h.version;
 
     mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count,
                 MAX_MP4_DESCR_COUNT);
@@ -1591,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,
@@ -1814,9 +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 (h->version == tssf->last_ver)
+    if (skip_identical(h, tssf))
         return;
-    tssf->last_ver = h->version;
 
     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);
@@ -1984,9 +2003,8 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     if (ts->skip_changes)
         return;
 
-    if (h->version == tssf->last_ver)
+    if (skip_identical(h, tssf))
         return;
-    tssf->last_ver = h->version;
     ts->stream->ts_id = h->id;
 
     clear_programs(ts);
@@ -2059,9 +2077,8 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
         return;
     if (ts->skip_changes)
         return;
-    if (h->version == tssf->last_ver)
+    if (skip_identical(h, tssf))
         return;
-    tssf->last_ver = h->version;
 
     onid = get16(&p, p_end);
     if (onid < 0)