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;
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) {
}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;
+ }
}
}
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;
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;
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;
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);
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,
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;
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);
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;
if (ts->skip_changes)
return;
+ if (skip_identical(h, tssf))
+ return;
ts->stream->ts_id = h->id;
clear_programs(ts);
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;
return;
if (ts->skip_changes)
return;
+ if (skip_identical(h, tssf))
+ return;
+
onid = get16(&p, p_end);
if (onid < 0)
return;
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;