mirror of https://git.ffmpeg.org/ffmpeg.git
avformat/mpegts: parse sections with multiple tables
Fixes PMT parsing in some mpegts streams which contain multiple tables within the PMT pid. Previously, the parser assumed only one table was present in each packet, and discarded the rest of the section data after attempting to parse the first table. A similar issue was documented in the BeyondTV software[1], which helped me diagnose the same bug in the ffmpeg mpegts demuxer. I also tried DVBInspector, libdvbpsi's dvbinfo, and tstools' tsinfo to help debug. The former two properly read PMTs with multiple tables, whereas the last has the same bug as ffmpeg. I've created a minimal sample[2] which contains the combined PMT. Here's what ffmpeg probe shows before and after this patch: Before: Input #0, mpegts, from 'combined-pmt-tids.ts': Duration: 00:00:01.08, start: 4932.966167, bitrate: 741 kb/s Program 1 No Program Stream #0:0[0xf9d]: Audio: ac3, 48000 Hz, mono, fltp, 96 kb/s Stream #0:1[0xf9b]: Audio: mp3, 0 channels, fltp Stream #0:2[0xf9c]: Unknown: none After: Input #0, mpegts, from 'combined-pmt-tids.ts': Duration: 00:00:01.11, start: 4932.966167, bitrate: 718 kb/s Program 1 Stream #0:0[0xf9b]: Video: mpeg2video ([2][0][0][0] / 0x0002), none(tv, top first), 29.97 fps, 29.97 tbr, 90k tbn, 90k tbc Stream #0:1[0xf9c](eng): Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, 5.1(side), fltp, 384 kb/s Stream #0:2[0xf9d](spa): Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, mono, fltp, 96 kb/s With the patch, the PMT is parsed correctly so the streams are created in the correct order, are associated with "Program 1", and their codecs are set correctly. [1] http://forums.snapstream.com/vb/showpost.php?p=343816&postcount=201 [2] https://s3.amazonaws.com/tmm1/combined-pmt-tids.ts Signed-off-by: Aman Gupta <aman@tmm1.net> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
18074b309f
commit
9152c1e495
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue