avformat/mpegts: parse sections with multiple tables
[ffmpeg.git] / libavformat / mpegts.c
index 0d1dda1..3c9f942 100644 (file)
@@ -391,7 +391,8 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
                                const uint8_t *buf, int buf_size, int is_start)
 {
     MpegTSSectionFilter *tss = &tss1->u.section_filter;
-    int len;
+    uint8_t *cur_section_buf = NULL;
+    int len, offset;
 
     if (is_start) {
         memcpy(tss->section_buf, buf, buf_size);
@@ -408,23 +409,26 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
         tss->section_index += len;
     }
 
+    offset = 0;
+    cur_section_buf = tss->section_buf;
+    while (cur_section_buf - tss->section_buf < MAX_SECTION_SIZE && cur_section_buf[0] != 0xff) {
     /* compute section length if possible */
-    if (tss->section_h_size == -1 && tss->section_index >= 3) {
-        len = (AV_RB16(tss->section_buf + 1) & 0xfff) + 3;
+    if (tss->section_h_size == -1 && tss->section_index - offset >= 3) {
+        len = (AV_RB16(cur_section_buf + 1) & 0xfff) + 3;
         if (len > MAX_SECTION_SIZE)
             return;
         tss->section_h_size = len;
     }
 
     if (tss->section_h_size != -1 &&
-        tss->section_index >= tss->section_h_size) {
+        tss->section_index >= offset + tss->section_h_size) {
         int crc_valid = 1;
         tss->end_of_section_reached = 1;
 
         if (tss->check_crc) {
-            crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, tss->section_buf, tss->section_h_size);
+            crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, cur_section_buf, tss->section_h_size);
             if (tss->section_h_size >= 4)
-                tss->crc = AV_RB32(tss->section_buf + tss->section_h_size - 4);
+                tss->crc = AV_RB32(cur_section_buf + tss->section_h_size - 4);
 
             if (crc_valid) {
                 ts->crc_validity[ tss1->pid ] = 100;
@@ -434,10 +438,18 @@ static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1,
                 crc_valid = 2;
         }
         if (crc_valid) {
-            tss->section_cb(tss1, tss->section_buf, tss->section_h_size);
+            tss->section_cb(tss1, cur_section_buf, tss->section_h_size);
             if (crc_valid != 1)
                 tss->last_ver = -1;
         }
+
+        cur_section_buf += tss->section_h_size;
+        offset += tss->section_h_size;
+        tss->section_h_size = -1;
+    } else {
+        tss->end_of_section_reached = 0;
+        break;
+    }
     }
 }