summaryrefslogtreecommitdiff
path: root/libavformat/mpegts.c
diff options
context:
space:
mode:
authorNico Sabbi <nicola.sabbi@poste.it>2007-09-25 20:58:37 +0000
committerNico Sabbi <nicola.sabbi@poste.it>2007-09-25 20:58:37 +0000
commit172d1171d2ae2bda29c3060f7390293cb3a0b2d1 (patch)
treef72d1cd58098209a588992d30e42e9dd61f00679 /libavformat/mpegts.c
parent1d257254f165184f6bd5bc18702a93e4f9b54a57 (diff)
added structures and code to keep track of pids<->programs mapping: it's needed
to decide which pids to discard in order to feed to the caller only AVProgram(s) that have the AV_DISCARD_ALL flag not set Originally committed as revision 10581 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r--libavformat/mpegts.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index d5a74ff6c5..825eadc779 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -76,6 +76,13 @@ struct MpegTSFilter {
} u;
};
+#define MAX_PIDS_PER_PROGRAM 64
+typedef struct {
+ unsigned int id; //program id/service id
+ unsigned int nb_pids;
+ unsigned int pids[MAX_PIDS_PER_PROGRAM];
+} Program_t;
+
struct MpegTSContext {
/* user data */
AVFormatContext *stream;
@@ -99,6 +106,9 @@ struct MpegTSContext {
/******************************************/
/* private mpegts data */
/* scan context */
+ /** structure to keep track of Program->pids mapping */
+ unsigned int nb_prg;
+ Program_t *prg;
/** filters for various streams specified by PMT + for the PAT and PMT */
@@ -136,6 +146,85 @@ struct PESContext {
extern AVInputFormat mpegts_demuxer;
+static void clear_program(MpegTSContext *ts, unsigned int programid)
+{
+ int i;
+
+ for(i=0; i<ts->nb_prg; i++)
+ if(ts->prg[i].id == programid)
+ ts->prg[i].nb_pids = 0;
+}
+
+static void clear_programs(MpegTSContext *ts)
+{
+ av_freep(&ts->prg);
+ ts->nb_prg=0;
+}
+
+static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
+{
+ Program_t *p;
+ void *tmp = av_realloc(ts->prg, (ts->nb_prg+1)*sizeof(Program_t));
+ if(!tmp)
+ return;
+ ts->prg = tmp;
+ p = &ts->prg[ts->nb_prg];
+ p->id = programid;
+ p->nb_pids = 0;
+ ts->nb_prg++;
+}
+
+static void add_pid_to_pmt(MpegTSContext *ts, unsigned int programid, unsigned int pid)
+{
+ int i;
+ Program_t *p = NULL;
+ for(i=0; i<ts->nb_prg; i++) {
+ if(ts->prg[i].id == programid) {
+ p = &ts->prg[i];
+ break;
+ }
+ }
+ if(!p)
+ return;
+
+ if(p->nb_pids >= MAX_PIDS_PER_PROGRAM)
+ return;
+ p->pids[p->nb_pids++] = pid;
+}
+
+/**
+ * \brief discard_pid() decides if the pid is to be discarded according
+ * to caller's programs selection
+ * \param ts : - TS context
+ * \param pid : - pid
+ * \return 1 if the pid is only comprised in programs that have .discard=AVDISCARD_ALL
+ * 0 otherwise
+ */
+static int discard_pid(MpegTSContext *ts, unsigned int pid)
+{
+ int i, j, k;
+ int used = 0, discarded = 0;
+ Program_t *p;
+ for(i=0; i<ts->nb_prg; i++) {
+ p = &ts->prg[i];
+ for(j=0; j<p->nb_pids; j++) {
+ if(p->pids[j] != pid)
+ continue;
+ //is program with id p->id set to be discarded?
+ for(k=0; k<ts->stream->nb_programs; k++) {
+ if(ts->stream->programs[k]->id == p->id) {
+ if(ts->stream->programs[k]->discard == AVDISCARD_ALL)
+ discarded++;
+ else
+ used++;
+ }
+ }
+ }
+ }
+
+ return (!used && discarded);
+}
+
/**
* Assembles PES packets out of TS packets, and then calls the "section_cb"
* function when they are complete.
@@ -403,9 +492,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (h->tid != PMT_TID)
return;
+ clear_program(ts, h->id);
pcr_pid = get16(&p, p_end) & 0x1fff;
if (pcr_pid < 0)
return;
+ add_pid_to_pmt(ts, h->id, pcr_pid);
#ifdef DEBUG_SI
av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid);
#endif
@@ -505,6 +596,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (pes)
st = new_pes_av_stream(pes, 0);
}
+ add_pid_to_pmt(ts, h->id, pid);
break;
default:
/* we ignore the other streams */
@@ -544,6 +636,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (h->tid != PAT_TID)
return;
+ clear_programs(ts);
for(;;) {
sid = get16(&p, p_end);
if (sid < 0)
@@ -560,6 +653,9 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
av_new_program(ts->stream, sid);
ts->stop_parse--;
mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);
+ add_pat_entry(ts, sid);
+ add_pid_to_pmt(ts, sid, 0); //add pat pid to program
+ add_pid_to_pmt(ts, sid, pmt_pid);
}
}
/* not found */
@@ -887,6 +983,8 @@ static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
const uint8_t *p, *p_end;
pid = AV_RB16(packet + 1) & 0x1fff;
+ if(pid && discard_pid(ts, pid))
+ return;
is_start = packet[1] & 0x40;
tss = ts->pids[pid];
if (ts->auto_guess && tss == NULL && is_start) {