Commit 172d1171 authored by Nico Sabbi's avatar Nico Sabbi
Browse files

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
parent 1d257254
...@@ -76,6 +76,13 @@ struct MpegTSFilter { ...@@ -76,6 +76,13 @@ struct MpegTSFilter {
} u; } 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 { struct MpegTSContext {
/* user data */ /* user data */
AVFormatContext *stream; AVFormatContext *stream;
...@@ -99,6 +106,9 @@ struct MpegTSContext { ...@@ -99,6 +106,9 @@ struct MpegTSContext {
/******************************************/ /******************************************/
/* private mpegts data */ /* private mpegts data */
/* scan context */ /* 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 */ /** filters for various streams specified by PMT + for the PAT and PMT */
...@@ -136,6 +146,85 @@ struct PESContext { ...@@ -136,6 +146,85 @@ struct PESContext {
extern AVInputFormat mpegts_demuxer; 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" * Assembles PES packets out of TS packets, and then calls the "section_cb"
* function when they are complete. * function when they are complete.
...@@ -403,9 +492,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len ...@@ -403,9 +492,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (h->tid != PMT_TID) if (h->tid != PMT_TID)
return; return;
clear_program(ts, h->id);
pcr_pid = get16(&p, p_end) & 0x1fff; pcr_pid = get16(&p, p_end) & 0x1fff;
if (pcr_pid < 0) if (pcr_pid < 0)
return; return;
add_pid_to_pmt(ts, h->id, pcr_pid);
#ifdef DEBUG_SI #ifdef DEBUG_SI
av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid); av_log(ts->stream, AV_LOG_DEBUG, "pcr_pid=0x%x\n", pcr_pid);
#endif #endif
...@@ -505,6 +596,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len ...@@ -505,6 +596,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (pes) if (pes)
st = new_pes_av_stream(pes, 0); st = new_pes_av_stream(pes, 0);
} }
add_pid_to_pmt(ts, h->id, pid);
break; break;
default: default:
/* we ignore the other streams */ /* we ignore the other streams */
...@@ -544,6 +636,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len ...@@ -544,6 +636,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if (h->tid != PAT_TID) if (h->tid != PAT_TID)
return; return;
clear_programs(ts);
for(;;) { for(;;) {
sid = get16(&p, p_end); sid = get16(&p, p_end);
if (sid < 0) if (sid < 0)
...@@ -560,6 +653,9 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len ...@@ -560,6 +653,9 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
av_new_program(ts->stream, sid); av_new_program(ts->stream, sid);
ts->stop_parse--; ts->stop_parse--;
mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); 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 */ /* not found */
...@@ -887,6 +983,8 @@ static void handle_packet(MpegTSContext *ts, const uint8_t *packet) ...@@ -887,6 +983,8 @@ static void handle_packet(MpegTSContext *ts, const uint8_t *packet)
const uint8_t *p, *p_end; const uint8_t *p, *p_end;
pid = AV_RB16(packet + 1) & 0x1fff; pid = AV_RB16(packet + 1) & 0x1fff;
if(pid && discard_pid(ts, pid))
return;
is_start = packet[1] & 0x40; is_start = packet[1] & 0x40;
tss = ts->pids[pid]; tss = ts->pids[pid];
if (ts->auto_guess && tss == NULL && is_start) { if (ts->auto_guess && tss == NULL && is_start) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment