www.pudn.com > MPEG2systemsrc.rar > SectionConsumers.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.
*/
/* SectionConsumer class implementation */
#include "Utilities.H"
#include "IPortFromRam.H"
#include "SectionConsumers.H"
#include "Decoder.H"
#include "Events.H"
#include "PES.H"
#include "PESConsumer.H"
extern "C"
{
#include
}
SectionConsumer::SectionConsumer (Decoder* d, Section* s) : Consumer(d)
{
sec = s;
buf_index = -1;
length_expected = -1;
}
static int char2int (char c)
{
int result = 0;
for (int i = 7; i >= 0; i--)
{
if ((c & (1 << i)) == 0) result = result * 2;
else result = result * 2 + 1;
}
return result;
}
/* This function is called to read TP payloads. */
int SectionConsumer::read_partial (int n)
{
int i = 0;
while (i < n)
{
switch (cstate)
{
case CSTART:
buf = (char*) malloc (1024); // FIX -- private sections can be 4096
buf_index = 0;
cstate = SCHEAD1;
break;
case SCHEAD1:
if (buf_index < 4)
{
buf[buf_index] = iport->read_byte();
buf_index++; i++;
}
if (buf_index == 4)
{
// FIX -- this case assumes ptr == 0
if (buf[0] != 0)
{
sys_error("non zero pointer offset in SectionConsumer");
}
length_expected = (char2int(buf[2]) & 0xF) << 8;
length_expected += char2int(buf[3]) + 4;
cstate = SCHEAD2;
}
break;
case SCHEAD2:
if (buf_index < length_expected)
{
buf[buf_index] = iport->read_byte();
buf_index++; i++;
}
if (buf_index == length_expected)
{
InputPort* save_port = iport;
iport = new IPortFromRam(buf, length_expected);
read_section();
delete iport;
iport = save_port;
delete buf; buf_index = 0; // done with buf
cstate = SCFLUSH;
}
break;
case SCFLUSH:
char c = iport->read_byte();
assert(c == (char) 0xff);
i++;
break;
default:
sys_error("unknown SectionConsumer state");
}
}
return n;
}
void SectionConsumer::read_header_a ()
{
// read pointer field
// FIX -- this assumes that there is always a pointer field
sec->pointer = iport->read_uimsbf(8, "reading pointer field");
// skip to start of section
for (int k = 0; k < sec->pointer; k++)
(void) iport->read_byte();
// start CRC
iport->start_crc();
// read table_id (should be 0)
sec->table_id = iport->read_uimsbf(8, "reading table_id");
// read section_syntax_code
char syntax = iport->read_bit();
if (syntax == ONE)
sec->section_syntax_code = 'S';
else
sec->section_syntax_code = 'L';
// read '0' and reserved bits
iport->read_bit();
iport->read_reserved_bits(2);
// read section_length
sec->section_length = iport->read_uimsbf(12, "reading section_length");
}
void SectionConsumer::read_header_b ()
{
// read reserved bits
iport->read_reserved_bits(2);
// read version_number
sec->version_number = iport->read_uimsbf(5, "reading version_number");
// read current_next_indicator
char cur_next = iport->read_bit();
if (cur_next == ONE)
sec->current_next_code = 'C';
else
sec->current_next_code = 'N';
// read section_number
sec->section_number = iport->read_uimsbf(8, "reading section_number");
// read last_section_number
sec->last_section_number = iport->read_uimsbf(8, "reading last_section_number");
}
void SectionConsumer::read_CRC ()
{
// read CRC
iport->stop_crc();
if (!iport->check_crc())
decoder->get_manager()->Trigger(BadCRC, sec);
}
PATConsumer::PATConsumer (Decoder* d, PATSection* s)
: SectionConsumer(d, s)
{
patsec = s;
}
void PATConsumer::read_section ()
{
// read header_a
read_header_a();
// read transport_stream_id
patsec->transport_stream_id = iport->read_uimsbf(16,
"reading trans_strm_id");
// read header_b
read_header_b();
// create new directory; get old one
Directory* newdir = new Directory();
Directory* olddir = decoder->get_dir();
int network_pid = decoder->get_networkpid();
// read loop
for (int i = 0; i < patsec->section_length - 9; i += 4)
{
int prog_number = iport->read_uimsbf(16, "reading program number");
iport->read_reserved_bits(3);
if (prog_number == 0)
{
network_pid = iport->read_uimsbf(13, "reading network_pid");
}
else
{
int pid = iport->read_uimsbf(13, "reading pid");
// update Directory
Program* program = olddir->get_program(prog_number);
if (program)
{
// not a new program
newdir->add_program(program);
}
else
{
// a new program
newdir->add_program(new Program(prog_number, pid));
}
}
}
// setup decoder using new directory
decoder->install_netpid(network_pid);
decoder->install_dir(newdir);
// read CRC
read_CRC();
// call PATParsed callback
decoder->get_manager()->Trigger(PATParsed, patsec);
}
MapConsumer::MapConsumer (Decoder* d, MapSection* s)
: SectionConsumer(d, s)
{
mapsec = s;
}
void MapConsumer::read_section ()
{
// read header_a
read_header_a();
// read program_number
mapsec->program_number = iport->read_uimsbf(16, "reading program_number");
// read header_b
read_header_b();
// read reserved bits
iport->read_reserved_bits(3);
// read pcr_pid
mapsec->pcr_pid = iport->read_uimsbf(13, "reading pcr_pid");
// read reserved bits
iport->read_reserved_bits(4);
// create new program with same program number
Program* newprog = new Program(mapsec->program_number,
decoder->get_ts()->pid);
// read program_info_length and info into newprog
mapsec->program_info_length =
iport->read_uimsbf(12, "reading program_info_length");
// FIX - implement descriptors for program info
for (int i = 0; i < mapsec->program_info_length; i++)
{
(void) iport->read_byte();
}
// read loop
int bytes_in_loop =
mapsec->section_length - mapsec->program_info_length - 13;
for (int j = 0; j < bytes_in_loop; )
{
// read fields
int stream_type = iport->read_uimsbf(8, "reading stream_type");
iport->read_reserved_bits(3);
int elem_pid = iport->read_uimsbf(13, "reading elem_pid");
EStream* estream = new EStream((StreamType) stream_type, elem_pid, NULL);
newprog->add_estream(estream);
// read estream info
iport->read_reserved_bits(4);
int info_length = iport->read_uimsbf(12, "reading es_info_length");
// FIX - implement descriptors for estream info
for (int k = 0; k < info_length; k++)
(void) iport->read_byte();
j += 5 + info_length;
}
// get dir and install new program
decoder->install_prog(newprog);
// read CRC
read_CRC();
// call MapParsed callback
decoder->get_manager()->Trigger(MapParsed, mapsec);
}
CAConsumer::CAConsumer (Decoder* d, CASection* s)
: SectionConsumer(d, s)
{
casec = s;
}
void CAConsumer::read_section ()
{
// read header_a
read_header_a();
// read 16/18 reservered bits, read_header_b() will read 2 more bits.
iport->read_reserved_bits(16);
// read header_b
read_header_b();
// read loop
int bytes_in_loop = casec->section_length - 9;
for (int j = 0; j < bytes_in_loop; )
{
// read descriptor
int descriptor_tag = iport->read_uimsbf(8, "reading des_tag");
if (descriptor_tag != 9)
sys_message("bad descriptor in CASection");
int descriptor_length = iport->read_uimsbf(8, "reading des_length");
int CA_system_id = iport->read_uimsbf(16, "reading CA_system_id");
iport->read_reserved_bits(3);
int ca_pid = iport->read_uimsbf(13, "reading des_tag");
// FIX -- eventually add a CAConsumer to consume ca_pid; ignore for now
for (int k = 0; k < descriptor_length - 4; k++)
(void) iport->read_byte();
j += descriptor_length + 2;
}
// read CRC
read_CRC();
// call CAParsed callback
decoder->get_manager()->Trigger(CAParsed, casec);
}
PriConsumer::PriConsumer (Decoder* d, PriSection* s)
: SectionConsumer(d, s)
{
prisec = s;
}
void PriConsumer::read_section ()
{
// read header_a
read_header_a();
// check syntax indicator
if (prisec->section_syntax_code == 'S')
{
for (int i = 0; i < prisec->section_length; i++)
(void) iport->read_byte();
}
else
{
// read table_id_extension
prisec->table_id_extension =
iport->read_uimsbf(16, "reading table_id_ext");
// read header_b
read_header_b();
// read loop
int bytes_in_loop = prisec->section_length - 9;
for (int j = 0; j < bytes_in_loop; j++)
{
(void) iport->read_byte();
}
// read CRC
read_CRC();
}
}