www.pudn.com > MPEG2systemsrc.rar > TSConsumer.C
/* Copyright (C) 1995, Tektronix Inc. All Rights Reserved.
*
* Usage Restrictions
*
* License is granted to copy, to use, and to make and to use derivative
* works for research and evaluation purposes only.
*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license
* fee or royalty on an "as is" basis. Tektronix Inc. disclaims any and
* all warranties, whether express, implied, or statuary, including any
* implied warranties or merchantability or of fitness for a particular
* purpose. In no event shall the copyright-holder be liable for any
* incidental, punitive, or consequential damages of any kind whatsoever
* arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and
* user's customers, employees, agents, transferees, successors, and
* assigns.
*
* The Tektronix Inc. does not represent or warrant that the programs
* furnished hereunder are free of infringement of any third-party
* patents.
*/
/* TSConsumer class implementation */
#include "Utilities.H"
#include "TSConsumer.H"
#include "PESConsumer.H"
#include "Section.H"
#include "SectionConsumers.H"
extern "C"
{
#include
}
TSConsumer::TSConsumer (Decoder* d, TS* t) : Consumer(d)
{
ts = t;
}
void TSConsumer::read_sync ()
{
char bits = 0;
char bit;
char sync = (char) 0x47;
int found = FALSE;
int k = 0;
while (!found)
{
if (bits == sync)
found = TRUE;
else
{
bit = iport->read_bit();
bits = bits << 1;
if (bit == '1') bits++;
}
if (k++ > 1000)
{
sys_error("can't find sync - exiting");
}
}
if (k > 9)
{
sys_message("trouble finding sync on TP");
}
}
void TSConsumer::read_ts_packet ()
{
// read sync_byte
read_sync();
// read transport_error_indicator
char transport_error_indicator = iport->read_bit();
// read payload_unit_start_indicator
char payload_unit_start_indicator = iport->read_bit();
// read transport_priority
char priority = iport->read_bit();
// read pid
int pid = iport->read_uimsbf(13, "reading pid");
if (pid == 8191)
{
for (int i = 0; i < 185; i++)
(void) iport->read_byte();
return;
}
ts = decoder->get_ts(pid);
if (ts == NULL)
{
decoder->get_manager()->Trigger(UnexpectedPid, new Wrapper(pid));
for (int i = 0; i < 185; i++)
(void) iport->read_byte();
return;
}
// now adjust ts structure with fields read so far
if (transport_error_indicator == ONE)
ts->transport_error_code = 'E';
else
ts->transport_error_code = '0';
if (payload_unit_start_indicator == ONE)
ts->payload_unit_start_code = 'A';
else
ts->payload_unit_start_code = '0';
if (priority == ONE)
ts->priority_code = 'H';
else
ts->priority_code = 'L';
// read transport_scrambling_control; currently uses only "00" or "11"
char scramble1 = iport->read_bit();
char scramble2 = iport->read_bit();
if ((scramble1 == ZERO) && (scramble2 == ZERO))
ts->scrambling_code = '0';
else
ts->scrambling_code = 'S';
// read adaptation field control
char afc1 = iport->read_bit();
char afc2 = iport->read_bit();
// read continuity_counter
int oldcc = ts->continuity_counter;
ts->continuity_counter = iport->read_uimsbf(4, "reading continuity_counter");
if (oldcc != NOCC)
{
int expectedcc = (oldcc >= 15) ? 0 : oldcc+1;
if (expectedcc != ts->continuity_counter)
{
decoder->get_manager()->Trigger(Discontinuity, ts);
}
}
// read adaptation_field
if (afc1 == '1')
read_adaptation();
else
{
delete ts->adaptation;
ts->adaptation = NULL;
}
// call TSParsed callback
decoder->get_manager()->Trigger(TSParsed, ts);
// read the payload or flush out rest of packet
if (afc2 == '1')
read_payload();
else
{
int header_length = ts->get_header_length();
int nbytes = 188 - header_length;
for (int i = 0; i < nbytes; i++)
(void) iport->read_byte();
}
}
void TSConsumer::read_adaptation ()
{
// get clean adaptation structure
if (ts->adaptation) delete ts->adaptation;
ts->adaptation = new AdaptationField();
// read adaptation_field_length
ts->adaptation->adaptation_field_length =
iport->read_uimsbf(8, "reading adaptation_field_length");
if (ts->adaptation->adaptation_field_length == 0) return;
// read discontinuity_indicator
char discontinuity = iport->read_bit();
if (discontinuity == ONE)
{
ts->adaptation->discontinuity_code = 'D';
decoder->get_manager()->Trigger(Discontinuity, ts);
}
else
ts->adaptation->discontinuity_code = 'O';
// read random_access_indicator
char random = iport->read_bit();
if (random == ONE)
{
ts->adaptation->random_access_code = 'R';
decoder->get_manager()->Trigger(RandomAccess, ts);
}
else
ts->adaptation->random_access_code = 'O';
// read elementary_stream_priority_indicator
char priority = iport->read_bit();
if (priority == ONE)
ts->adaptation->elem_stream_priority_code = 'H';
else
ts->adaptation->elem_stream_priority_code = 'L';
// read optional field flags
char PCR_flag = iport->read_bit();
char OPCR_flag = iport->read_bit();
char splicing_point_flag = iport->read_bit();
char transport_private_data_flag = iport->read_bit();
char adaptation_field_extension_flag = iport->read_bit();
// read PCR
if (PCR_flag == ONE)
{
ts->adaptation->PCR = iport->read_timestamp27_ts_format();
decoder->get_manager()->Trigger(PCREvent, ts);
}
// read OPCR
if (OPCR_flag == ONE)
{
ts->adaptation->OPCR = iport->read_timestamp27_ts_format();
}
// read splice_countdown
if (splicing_point_flag == ONE)
{
ts->adaptation->splice_countdown =
iport->read_tcimsbf(8, "reading spice_countdown");
}
else
ts->adaptation->splice_countdown = NOSPLICE;
// read private_data
if (transport_private_data_flag == ONE)
{
ts->adaptation->transport_private_data_length =
iport->read_uimsbf(8, "reading transport_private_data_length");
for (int i = 0; i < ts->adaptation->transport_private_data_length; i++)
(void) iport->read_byte();
}
// read extension
if (adaptation_field_extension_flag == ONE)
{
ts->adaptation->adaptation_extension_length =
iport->read_uimsbf(8, "reading adaptation_extension_length");
for (int j = 0; j < ts->adaptation->adaptation_extension_length; j++)
(void) iport->read_byte();
}
// read stuffing bytes
int current_length = ts->adaptation->get_length();
int fields_length = ts->adaptation->get_fields_length();
ts->adaptation->number_stuffing_bytes =
ts->adaptation->adaptation_field_length - (fields_length + 1);
if (ts->adaptation->number_stuffing_bytes > 0)
{
for (int k = 0; k < ts->adaptation->number_stuffing_bytes; k++)
(void) iport->read_byte();
}
}
void TSConsumer::read_payload ()
{
int header_length = ts->get_header_length();
int nbytes = 188 - header_length;
Consumer* cons = decoder->get_cons(ts->pid);
if (cons == NULL)
{
sys_error("can't find consumer in TSConsumer::read_payload");
}
else
{
if (ts->payload_unit_start_code == 'A') cons->set_cstate(CSTART);
cons->connect(iport);
cons->read_partial(nbytes);
}
}