aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Högberg <john.hogberg@ericsson.com>2015-04-28 10:20:33 +0200
committerLuca Barbato <lu_zero@gentoo.org>2015-04-28 21:09:59 +0200
commit82de8d71118f4eafd6a43e9ea9169bd411793798 (patch)
tree81cf98110ab5f76683d6df27c759988e650aec1d
parent0c69164f451cc9ca6ce9d6e7568083e2776bc845 (diff)
downloadffmpeg-82de8d71118f4eafd6a43e9ea9169bd411793798.tar.gz
mpegts: Update the PSI/SI table only if the version change
If a PAT is finished while a PMT section filter is opened but not yet finished, the PMT section filter is closed and all the received data is discarded. This is usually not an issue but some multiplexers (With very quick PAT/PMT repetition settings) consistently emit a PMT section start, then a PAT, and then the rest of the PMT, causing the aforementioned behavior to result in no PMT being finished. In the most pathologic situation the stream information are lost and the probe fallback miscategorizes subtitles as mp3 audio. Avoid the issue through eliminating redundant PSI/SI table updates by checking their version field, which is required by the standard to be incremented on every change no matter how minor. CC: libav-stable@libav.org Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
-rw-r--r--libavformat/mpegts.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index ae9d1f4e93..8f61f1727d 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -73,6 +73,7 @@ typedef void SetServiceCallback (void *opaque, int ret);
typedef struct MpegTSSectionFilter {
int section_index;
int section_h_size;
+ int last_ver;
uint8_t *section_buf;
unsigned int check_crc : 1;
unsigned int end_of_section_reached : 1;
@@ -372,6 +373,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;
@@ -1255,6 +1258,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;
@@ -1269,6 +1273,9 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
return;
if (h.tid != M4OD_TID)
return;
+ if (h.version == tssf->last_ver)
+ return;
+ tssf->last_ver = h.version;
mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count,
MAX_MP4_DESCR_COUNT);
@@ -1507,6 +1514,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;
@@ -1526,6 +1534,9 @@ 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)
+ return;
+ tssf->last_ver = h->version;
av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d\n",
h->id, h->sec_num, h->last_sec_num);
@@ -1657,6 +1668,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;
@@ -1670,6 +1682,9 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
return;
if (h->tid != PAT_TID)
return;
+ if (h->version == tssf->last_ver)
+ return;
+ tssf->last_ver = h->version;
clear_programs(ts);
for (;;) {
@@ -1700,6 +1715,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;
@@ -1714,6 +1730,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
return;
if (h->tid != SDT_TID)
return;
+ if (h->version == tssf->last_ver)
+ return;
+ tssf->last_ver = h->version;
+
onid = get16(&p, p_end);
if (onid < 0)
return;