www.pudn.com > MPEG2systemsrc.rar > PESProducer.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.
*/
/* PES class implementation */
#include "PESProducer.H"
#include "OPortToRam.H"
#include "Encoder.H"
#include "IPortFromFile.H"
extern "C"
{
#include
}
PESProducer::PESProducer (Encoder* e, PES* p) : Producer(e)
{
pes = p;
timestamp_lock = FALSE;
esport = NULL; // defer initialization of esport until first usage
}
int PESProducer::fill_buffer ()
{
if (buf) delete buf;
length_stored = pes->PES_packet_length + 6;
buf = (char*) malloc (length_stored);
OutputPort* save_port = oport;
oport = new OPortToRam(buf, length_stored, NULL);
send_pes_packet();
delete oport;
oport = save_port;
buf_index = 0;
return length_stored;
}
void PESProducer::send_pes_packet ()
{
oport->write_pattern("000000000000000000000001");
oport->write_uimsbf(pes->stream_id, 8);
oport->write_uimsbf(pes->PES_packet_length, 16);
if ((pes->stream_id != id_private_stream_2) &&
(pes->stream_id != id_padding_stream))
{
oport->write_pattern("10");
// write PES_scrambling_control; currently uses only "00" or "11"
if (pes->scrambling_code == 'S') oport->write_pattern("11");
else oport->write_pattern("00");
// write PES_priority
if (pes->priority_code == 'H') oport->write_bit('1');
else oport->write_bit('0');
// write data_alignment_indicator
if (pes->alignment_indicator_code == 'A') oport->write_bit('1');
else oport->write_bit('0');
// write copyright
if (pes->copyright_code == 'C') oport->write_bit('1');
else oport->write_bit('0');
// write copy_or_original
if (pes->original_code == 'O') oport->write_bit('1');
else oport->write_bit('0');
// write PTS_DTS_flags
if (pes->PTS) oport->write_bit('1'); else oport->write_bit('0');
if (pes->DTS) oport->write_bit('1'); else oport->write_bit('0');
// write ESCR_flag
if (pes->ESCR) oport->write_bit('1'); else oport->write_bit('0');
// write ES_rate_flag
if (pes->ES_rate) oport->write_bit('1'); else oport->write_bit('0');
// write DSM_trick_mode_flag
if (pes->trick_mode) oport->write_bit('1'); else oport->write_bit('0');
// write additional_copy_info_flag
if (pes->additional_copy_info) oport->write_bit('1'); else oport->write_bit('0');
// write PES_CRC_flag
if (pes->previous_CRC) oport->write_bit('1'); else oport->write_bit('0');
// write PES_extension_flag
if (pes->extension) oport->write_bit('1'); else oport->write_bit('0');
// write PES_header_data_length
oport->write_uimsbf(pes->get_header_length() - 9, 8);
// output all optional fields
// output PTS, DTS
if (pes->PTS)
{
if (timestamp_lock == FALSE)
{
TimeStamp90 PTS = encoder->sys_time + encoder->sys_const;
pes->PTS = &PTS;
// FIX -- distinguish between PTS and DTS semantics
if (pes->DTS) pes->DTS = pes->PTS;
}
if (pes->PTS && !pes->DTS)
{
oport->write_pattern("0010");
oport->write_timestamp90(pes->PTS);
}
if (pes->PTS && pes->DTS)
{
oport->write_pattern("0011");
oport->write_timestamp90(pes->PTS);
oport->write_pattern("0001");
oport->write_timestamp90(pes->DTS);
}
}
// output ESCR
if (pes->ESCR)
{
oport->write_reserved_bits(2);
oport->write_timestamp27_pes_format(pes->ESCR);
}
// output ES_rate
if (pes->ES_rate)
{
oport->write_markerbit();
oport->write_uimsbf(pes->ES_rate, 22);
oport->write_markerbit();
}
// output DSM_trick_mode field
if (pes->trick_mode)
send_trick_mode();
// output additional_copy_info
if (pes->additional_copy_info)
{
oport->write_markerbit();
char mask = (char) 1;
for (int i = 0; i < 7; i++)
{
if (pes->additional_copy_info & mask)
oport->write_bit('1'); else oport->write_bit('0');
mask = mask << 1;
}
}
// output previous_PES_packet_CRC
if (pes->previous_CRC)
oport->write_uimsbf(pes->previous_CRC, 16);
// output PES extension fields
if (pes->extension)
send_extension();
// output stuffing bytes
for (int i = 0; i < pes->number_stuffing_bytes; i++)
oport->write_byte(0xff);
// output payload
send_payload();
}
}
void PESProducer::send_trick_mode ()
{
if (pes->trick_mode == NULL) return;
switch (pes->trick_mode->trick_mode_control_code)
{
case 'F':
oport->write_pattern("000");
send_field_id();
if (pes->trick_mode->intra_slice_refresh_code == 'I')
oport->write_bit('1');
else
oport->write_bit('0');
send_frequency_truncation();
break;
case 'S':
oport->write_pattern("001");
oport->write_uimsbf(pes->trick_mode->field_rep_control, 5);
break;
case 'Z':
oport->write_pattern("010");
send_field_id();
oport->write_reserved_bits(3);
break;
case 'R':
oport->write_pattern("011");
send_field_id();
if (pes->trick_mode->intra_slice_refresh_code == 'I')
oport->write_bit('1');
else
oport->write_bit('0');
send_frequency_truncation();
break;
}
}
void PESProducer::send_field_id ()
{
if (pes->trick_mode == NULL) return;
switch (pes->trick_mode->field_id_code)
{
case '1':
oport->write_pattern("00");
break;
case '2':
oport->write_pattern("01");
break;
case 'B':
oport->write_pattern("10");
break;
}
}
void PESProducer::send_frequency_truncation ()
{
if (pes->trick_mode == NULL) return;
switch (pes->trick_mode->frequency_truncation_code)
{
case 'D':
oport->write_pattern("00");
break;
case '3':
oport->write_pattern("01");
break;
case '6':
oport->write_pattern("10");
break;
case 'A':
oport->write_pattern("11");
break;
}
}
void PESProducer::send_extension ()
{
if (pes->extension == NULL) return;
// output flags
if (pes->extension->PES_private_data) oport->write_bit('1');
else oport->write_bit('0');
if (pes->extension->pack_header) oport->write_bit('1');
else oport->write_bit('0');
if (pes->extension->pp_seq_counter_code == '1') oport->write_bit('1');
else oport->write_bit('0');
if (pes->extension->P_STD_buffer_code == '1') oport->write_bit('1');
else oport->write_bit('0');
oport->write_reserved_bits(3);
if (pes->extension->PES_extension_field_length) oport->write_bit('1');
else oport->write_bit('0');
// output PES_private_data
if (pes->extension->PES_private_data)
{
for (int i = 0; i < 16; i++)
{
oport->write_byte(pes->extension->PES_private_data[i]);
}
}
// output pack_header
if (pes->extension->pack_header)
{
oport->write_uimsbf(pes->extension->pack_field_length, 8);
for (int j = 0; j < pes->extension->pack_field_length; j++)
{
oport->write_byte(pes->extension->pack_header[j]);
}
}
// output pp_seq_counter
if (pes->extension->pp_seq_counter_code == ONE)
{
oport->write_markerbit();
oport->write_uimsbf(pes->extension->pp_seq_counter, 7);
oport->write_markerbit();
oport->write_uimsbf(pes->extension->original_stuff_length, 7);
}
// output P_STD_buffer
if (pes->extension->P_STD_buffer_code == ONE)
{
oport->write_pattern("01");
oport->write_bit(pes->extension->P_STD_buffer_scale);
oport->write_uimsbf(pes->extension->P_STD_buffer_size, 13);
}
// output PES_extension_field
if (pes->extension->PES_extension_field_length)
{
oport->write_markerbit();
oport->write_uimsbf(pes->extension->PES_extension_field_length, 7);
for (int k = 0; k < pes->extension->PES_extension_field_length; k++)
{
oport->write_byte(0xff);
}
}
}
void PESProducer::send_payload ()
{
// calculate payload length
int payload_length = pes->get_length() - pes->get_header_length();
if (payload_length <= 0) return;
// prepare esport
if (!esport)
{
esport = new IPortFromFile(pes->file_name, CYCLE);
}
// read/write loop
char byte;
for (int i = 0; i < payload_length; i++)
{
byte = esport->read_byte();
oport->write_byte(byte);
}
}