summaryrefslogtreecommitdiff
path: root/libavformat/mpegts.c
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2020-12-27 23:05:16 +0100
committerMarton Balint <cus@passwd.hu>2021-01-09 22:38:12 +0100
commitf143a6c1515cb0c4db4dbead46d0e7c53fafc5db (patch)
tree860d0749e2c8b058ebe4b9697ac3369147831024 /libavformat/mpegts.c
parent10c8e532943cc1339cf42d3f84eed4eafd8b0ca8 (diff)
avformat/mpegts: only clear programs which no longer exist or have a new PMT
Otherwise there can be a small period when the programs only contain the PMT pid. Also make sure skip_clear only affects AVProgram clear, and that pmt_pid is always kept as the first entry of the PID list of the programs. Also reject PMTs for programs on the wrong PID. Signed-off-by: Marton Balint <cus@passwd.hu>
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r--libavformat/mpegts.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 1b990f7a66..ee69e2ca29 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -20,6 +20,7 @@
*/
#include "libavutil/buffer.h"
+#include "libavutil/common.h"
#include "libavutil/crc.h"
#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
@@ -301,7 +302,9 @@ static void clear_programs(MpegTSContext *ts)
static struct Program * add_program(MpegTSContext *ts, unsigned int programid)
{
- struct Program *p;
+ struct Program *p = get_program(ts, programid);
+ if (p)
+ return p;
if (av_reallocp_array(&ts->prg, ts->nb_prg + 1, sizeof(*ts->prg)) < 0) {
ts->nb_prg = 0;
return NULL;
@@ -2303,10 +2306,12 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (ts->skip_unknown_pmt && !prg)
return;
- if (!ts->skip_clear) {
+ if (prg && prg->nb_pids && prg->pids[0] != ts->current_pid)
+ return;
+ if (!ts->skip_clear)
clear_avprogram(ts, h->id);
- clear_program(prg);
- }
+ clear_program(prg);
+ add_pid_to_program(prg, ts->current_pid);
pcr_pid = get16(&p, p_end);
if (pcr_pid < 0)
@@ -2485,6 +2490,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
int sid, pmt_pid;
+ int nb_prg = 0;
AVProgram *program;
av_log(ts->stream, AV_LOG_TRACE, "PAT:\n");
@@ -2503,7 +2509,6 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
return;
ts->stream->ts_id = h->id;
- clear_programs(ts);
for (;;) {
sid = get16(&p, p_end);
if (sid < 0)
@@ -2537,9 +2542,19 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (!ts->pids[pmt_pid])
mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
prg = add_program(ts, sid);
- add_pid_to_program(prg, pmt_pid);
+ if (prg) {
+ unsigned prg_idx = prg - ts->prg;
+ if (prg->nb_pids && prg->pids[0] != pmt_pid)
+ clear_program(prg);
+ add_pid_to_program(prg, pmt_pid);
+ if (prg_idx > nb_prg)
+ FFSWAP(struct Program, ts->prg[nb_prg], ts->prg[prg_idx]);
+ if (prg_idx >= nb_prg)
+ nb_prg++;
+ }
}
}
+ ts->nb_prg = nb_prg;
if (sid < 0) {
int i,j;