summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_ts.c212
1 files changed, 88 insertions, 124 deletions
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index ef1a7a6ea..bd67c269e 100644
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -378,7 +378,7 @@ typedef struct {
uint32_t program_number[MAX_PMTS];
uint32_t pmt_pid[MAX_PMTS];
uint8_t *pmt[MAX_PMTS];
- uint8_t *pmt_write_ptr[MAX_PMTS];
+ int pmt_write_pos[MAX_PMTS];
uint32_t last_pmt_crc;
/*
* Stuff to do with the transport header. As well as the video
@@ -971,7 +971,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
if (this->pmt[program_count] != NULL) {
free(this->pmt[program_count]);
this->pmt[program_count] = NULL;
- this->pmt_write_ptr[program_count] = NULL;
+ this->pmt_write_pos[program_count] = 0;
}
}
#ifdef TS_PAT_LOG
@@ -1413,8 +1413,7 @@ static int apid_check(demux_ts_t*this, unsigned int pid) {
/*
* NAME demux_ts_parse_pmt
*
- * Parse a PMT. The PMT is expected to be exactly one section long,
- * and that section is expected to be contained in a single TS packet.
+ * Parse a PMT. The PMT is expected to be exactly one section long.
*
* In other words, the PMT is assumed to describe a reasonable number of
* video, audio and other streams (with descriptors).
@@ -1424,6 +1423,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
unsigned char *originalPkt,
unsigned char *pkt,
unsigned int pusi,
+ int plen,
uint32_t program_count) {
#ifdef TS_PMT_LOG
@@ -1431,7 +1431,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
uint32_t version_number;
#endif
uint32_t section_syntax_indicator;
- uint32_t section_length = 0; /* to calm down gcc */
+ uint32_t section_length;
uint32_t program_number;
uint32_t current_next_indicator;
uint32_t section_number;
@@ -1443,154 +1443,119 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
unsigned int pid;
unsigned char *stream;
unsigned int i;
- int count;
- uint8_t *ptr = NULL;
- unsigned char len;
- unsigned int offset=0;
int mi;
- /*
- * A new section should start with the payload unit start
- * indicator set. We allocate some mem (max. allowed for a PM section)
- * to copy the complete section into one chunk.
- */
+ /* reassemble the section */
if (pusi) {
- pkt+=pkt[4]; /* pointer to start of section */
- offset=1;
-
- free(this->pmt[program_count]);
- this->pmt[program_count] = (uint8_t *) calloc(4096, sizeof(unsigned char));
- this->pmt_write_ptr[program_count] = this->pmt[program_count];
-
-#ifdef TS_PMT_LOG
- table_id = pkt[5] ;
-#endif
- section_syntax_indicator = (pkt[6] >> 7) & 0x01;
- section_length = (((uint32_t) pkt[6] << 8) | pkt[7]) & 0x03ff;
- program_number = ((uint32_t) pkt[8] << 8) | pkt[9];
-#ifdef TS_PMT_LOG
- version_number = (pkt[10] >> 1) & 0x1f;
-#endif
- current_next_indicator = pkt[10] & 0x01;
- section_number = pkt[11];
- last_section_number = pkt[12];
-
-#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT table_id: %2x\n", table_id);
- printf (" section_syntax: %d\n", section_syntax_indicator);
- printf (" section_length: %d (%#.3x)\n",
- section_length, section_length);
- printf (" program_number: %#.4x\n", program_number);
- printf (" version_number: %d\n", version_number);
- printf (" c/n indicator: %d\n", current_next_indicator);
- printf (" section_number: %d\n", section_number);
- printf (" last_section_number: %d\n", last_section_number);
-#endif
-
- if ((section_syntax_indicator != 1) || !current_next_indicator) {
-#ifdef TS_PMT_LOG
- printf ("ts_demux: section_syntax_indicator != 1 "
- "|| !current_next_indicator\n");
-#endif
- return;
- }
-
- if (program_number != this->program_number[program_count]) {
- /* several programs can share the same PMT pid */
-#ifdef TS_PMT_LOG
-printf("Program Number is %i, looking for %i\n",program_number,this->program_number[program_count]);
- printf ("ts_demux: waiting for next PMT on this PID...\n");
-#endif
+ /* allocate space for largest possible section */
+ if (!this->pmt[program_count])
+ this->pmt[program_count] = malloc (4098);
+ if (!this->pmt[program_count])
return;
- }
-
- if ((section_number != 0) || (last_section_number != 0)) {
+ this->pmt_write_pos[program_count] = 0;
+ /* offset the section by n + 1 bytes. this is sometimes used to let it end
+ at an exact TS packet boundary */
+ plen -= (unsigned int)pkt[0] + 1;
+ pkt += (unsigned int)pkt[0] + 1;
+ if (plen < 1) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: FIXME (unsupported) PMT consists of multiple (%d) sections\n", last_section_number);
+ "demux_ts: demux error! PMT with invalid pointer\n");
return;
}
-
+ } else {
+ if (!this->pmt_write_pos[program_count])
+ return;
}
+ if (plen > 4098 - this->pmt_write_pos[program_count])
+ plen = 4098 - this->pmt_write_pos[program_count];
+ memcpy (this->pmt[program_count] + this->pmt_write_pos[program_count], pkt, plen);
+ this->pmt_write_pos[program_count] += plen;
- if (!this->pmt[program_count]) {
- /* not the first TS packet of a PMT, or the calloc didn't work */
-#ifdef TS_PMT_LOG
- printf ("ts_demux: not the first TS packet of a PMT...\n");
-#endif
+ /* lets see if we got the section length already */
+ pkt = this->pmt[program_count];
+ if (this->pmt_write_pos[program_count] < 3)
+ return;
+ section_length = ((((uint32_t)pkt[1] << 8) | pkt[2]) & 0xfff) + 3;
+ /* this should be at least the head plus crc */
+ if (section_length < 8 + 4) {
+ this->pmt_write_pos[program_count] = 0;
return;
}
- if (!pusi){
- section_length = (this->pmt[program_count][1] << 8
- | this->pmt[program_count][2]) & 0x03ff;
- }
-
- count=ts_payloadsize(originalPkt);
-
- ptr = originalPkt+offset+(PKT_SIZE-count);
- len = count-offset;
- memcpy (this->pmt_write_ptr[program_count], ptr, len);
- this->pmt_write_ptr[program_count] +=len;
+ /* lets see if we got the section complete */
+ if (this->pmt_write_pos[program_count] < section_length)
+ return;
+ /* OK now parse it */
+ this->pmt_write_pos[program_count] = 0;
#ifdef TS_PMT_LOG
- printf ("ts_demux: wr_ptr: %p, will be %p when finished\n",
- this->pmt_write_ptr[program_count],
- this->pmt[program_count] + section_length);
+ table_id = (unsigned int)pkt[0];
#endif
- if (this->pmt_write_ptr[program_count] < this->pmt[program_count]
- + section_length) {
- /* didn't get all TS packets for this section yet */
+ section_syntax_indicator = (pkt[1] >> 7) & 0x01;
+ program_number = ((uint32_t)pkt[3] << 8) | pkt[4];
#ifdef TS_PMT_LOG
- printf ("ts_demux: didn't get all PMT TS packets yet...\n");
+ version_number = ((uint32_t)pkt[5] >> 1) & 0x1f;
#endif
- return;
- }
+ current_next_indicator = pkt[5] & 0x01;
+ section_number = pkt[6];
+ last_section_number = pkt[7];
- if (!section_length) {
- free (this->pmt[program_count]);
- this->pmt[program_count] = NULL;
#ifdef TS_PMT_LOG
- printf ("ts_demux: eek, zero-length section?\n");
+ printf ("demux_ts: PMT table_id: %.2x\n", table_id);
+ printf (" section_syntax: %d\n", section_syntax_indicator);
+ printf (" section_length: %d (%#.3x)\n", section_length, section_length);
+ printf (" program_number: %#.4x\n", program_number);
+ printf (" version_number: %d\n", version_number);
+ printf (" c/n indicator: %d\n", current_next_indicator);
+ printf (" section_number: %d\n", section_number);
+ printf (" last_section_number: %d\n", last_section_number);
#endif
- return;
- }
-#ifdef TS_PMT_LOG
- printf ("ts_demux: have all TS packets for the PMT section\n");
-#endif
+ if ((section_syntax_indicator != 1) || !current_next_indicator)
+ return;
- crc32 = (uint32_t) this->pmt[program_count][section_length+3-4] << 24;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-3] << 16;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-2] << 8;
- crc32 |= (uint32_t) this->pmt[program_count][section_length+3-1] ;
+ if ((section_number != 0) || (last_section_number != 0)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_ts: FIXME (unsupported) PMT consists of multiple (%d) sections\n", last_section_number);
+ return;
+ }
/* Check CRC. */
- calc_crc32 = htonl(av_crc(this->class->av_crc, 0xffffffff,
- this->pmt[program_count], section_length+3-4));
+ crc32 = (uint32_t) pkt[section_length - 4] << 24;
+ crc32 |= (uint32_t) pkt[section_length - 3] << 16;
+ crc32 |= (uint32_t) pkt[section_length - 2] << 8;
+ crc32 |= (uint32_t) pkt[section_length - 1];
+ calc_crc32 = htonl (av_crc (this->class->av_crc, 0xffffffff, pkt, section_length - 4));
if (crc32 != calc_crc32) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_ts: demux error! PMT with invalid CRC32: packet_crc32: %#.8x calc_crc32: %#.8x\n",
- crc32,calc_crc32);
+ "demux_ts: demux error! PMT with invalid CRC32: packet_crc32: %#.8x calc_crc32: %#.8x\n",
+ crc32, calc_crc32);
return;
}
- else {
#ifdef TS_PMT_LOG
- printf ("demux_ts: PMT CRC32 ok.\n");
+ printf ("demux_ts: PMT CRC32 ok.\n");
#endif
- if ( crc32==this->last_pmt_crc ) {
+
+ if (program_number != this->program_number[program_count]) {
+ /* several programs can share the same PMT pid */
#ifdef TS_PMT_LOG
- printf("demux_ts: PMT with CRC32=%d already parsed. Skipping.\n", crc32);
+printf("Program Number is %i, looking for %i\n",program_number,this->program_number[program_count]);
+ printf ("ts_demux: waiting for next PMT on this PID...\n");
#endif
- return;
- }
- else {
+ return;
+ }
+
+ if (crc32 == this->last_pmt_crc) {
#ifdef TS_PMT_LOG
- printf("demux_ts: new PMT, parsing...\n");
+ printf("demux_ts: PMT with CRC32=%d already parsed. Skipping.\n", crc32);
#endif
- this->last_pmt_crc = crc32;
- }
+ return;
}
+ this->last_pmt_crc = crc32;
+
+ /* dont "parse" the CRC */
+ section_length -= 4;
/*
* Forget the current video, audio and subtitle PIDs; if the PMT has not
@@ -1608,8 +1573,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
* ES definitions start here...we are going to learn upto one video
* PID and one audio PID.
*/
- program_info_length = ((this->pmt[program_count][10] << 8)
- | this->pmt[program_count][11]) & 0x0fff;
+ program_info_length = ((pkt[10] << 8) | pkt[11]) & 0x0fff;
/* Program info descriptor is currently just ignored.
* printf ("demux_ts: program_info_desc: ");
@@ -1617,8 +1581,8 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
* printf ("%.2x ", this->pmt[program_count][12+i]);
* printf ("\n");
*/
- stream = &this->pmt[program_count][12] + program_info_length;
- coded_length = 13 + program_info_length;
+ stream = pkt + 12 + program_info_length;
+ coded_length = 12 + program_info_length;
if (coded_length > section_length) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux error! PMT with inconsistent progInfo length\n");
@@ -2264,8 +2228,8 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
this->program_number[program_count],
this->pmt_pid[program_count]);
#endif
- demux_ts_parse_pmt (this, originalPkt, originalPkt+data_offset-4,
- payload_unit_start_indicator,
+ demux_ts_parse_pmt (this, originalPkt, originalPkt + data_offset,
+ payload_unit_start_indicator, PKT_SIZE - data_offset,
program_count);
return;
}
@@ -2664,7 +2628,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->program_number[i] = INVALID_PROGRAM;
this->pmt_pid[i] = INVALID_PID;
this->pmt[i] = NULL;
- this->pmt_write_ptr[i] = NULL;
+ this->pmt_write_pos[i] = 0;
}
this->scrambled_npids = 0;