www.pudn.com > MPEG2systemsrc.rar > TSProducer.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.
*/

/* TSProducer class implementation */

#include "Utilities.H"
#include "TSProducer.H"
#include "OPortToRam.H"

TSProducer::TSProducer (Encoder* e) : Producer(e)
{
}

void TSProducer::send_ts_packet (Producer* payload_prod)
{
  // write sync byte
  oport->write_pattern("01000111");

  // write transport_error_indicator
  if (ts->transport_error_code == 'E') oport->write_bit('1');
  else oport->write_bit('0');

  // write payload_unit_start_indicator
  if (payload_prod->get_nready() == 0)
    {
      ts->payload_unit_start_code = 'A';
      oport->write_bit('1');
      // a good time to load the payload producer
      payload_prod->fill_buffer();
    }
  else
    {
      ts->payload_unit_start_code = '0';
      oport->write_bit('0');
    }

  // write transport_priority
  if (ts->priority_code == 'H') oport->write_bit('1');
  else oport->write_bit('0');

  // write pid
  oport->write_uimsbf(ts->pid, 13);

  // write transport_scrambling_control 
  if (ts->scrambling_code == 'S') oport->write_pattern("11");
  else oport->write_pattern("00");

  // check lengths and adjust stuffing bytes
  int nready = payload_prod->get_nready();
  if (nready < 188 - ts->get_header_length())
    {
      if (ts->adaptation)
	{
	  ts->adaptation->number_stuffing_bytes +=
	    188 - ts->get_header_length() - nready;
	}
      else
	{
	  ts->adaptation = new AdaptationField();
	  if (nready < 183)
	    {
	      ts->adaptation->number_stuffing_bytes = 182 - nready;
	      ts->adaptation->adaptation_field_length =
		ts->adaptation->number_stuffing_bytes + 1;
	    }
	}
    }

  // write adaptation_field_control
  if (ts->adaptation) oport->write_bit('1');
  else oport->write_bit('0');
  if (ts->payload_code) oport->write_bit('1');
  else oport->write_bit('0');

  // write continuity_counter
  oport->write_uimsbf(ts->continuity_counter, 4);

  //send adaptation field
  if (ts->adaptation)
    send_adaptation(payload_prod);
      
  // send null payload
  if (ts->pid == 8191)
    {
      int nbytes = 188 - ts->get_header_length();
      for (int k = 0; k < nbytes; k++)
	oport->write_byte(0xff);
      return;
    }

  // send nonnull payload
  if (ts->payload_code && payload_prod)
    send_payload(payload_prod);
}

void TSProducer::send_adaptation (Producer* payload_prod)
{
  // write adaptation_field_length
  oport->write_uimsbf(ts->adaptation->get_length() - 1, 8);
  
  // write discontinuity_indicator
  if (ts->adaptation->discontinuity_code == 'D') oport->write_bit('1');
  else oport->write_bit('0');

  // write random_access_indicator
  if (ts->adaptation->random_access_code == 'R') oport->write_bit('1');
  else oport->write_bit('0');

  // write elementary_stream_priority_indicator
  if (ts->adaptation->elem_stream_priority_code == 'H') oport->write_bit('1');
  else oport->write_bit('0');

  // write PCR_flag
  if (ts->adaptation->PCR) oport->write_bit('1');
  else oport->write_bit('0');

  // write OPCR_flag
  if (ts->adaptation->OPCR) oport->write_bit('1');
  else oport->write_bit('0');
  
  // write splicing_point_flag
  if (ts->adaptation->splice_countdown != NOSPLICE) oport->write_bit('1');
  else oport->write_bit('0');
    
  // write transport_private_data_flag
  if (ts->adaptation->transport_private_data_length != NULL)
    oport->write_bit('1');
  else
    oport->write_bit('0');
  
  // write adaptation_field_extension_flag
  if (ts->adaptation->adaptation_extension_length != 0) oport->write_bit('1');
  else oport->write_bit('0');
  
  // write PCR
  if (ts->adaptation->PCR)
    oport->write_timestamp27_ts_format(ts->adaptation->PCR);
  
  // write OPCR
  if (ts->adaptation->OPCR)
    oport->write_timestamp27_ts_format(ts->adaptation->OPCR);

  // write splice_countdown
  if (ts->adaptation->splice_countdown != NOSPLICE)
    oport->write_tcimsbf(ts->adaptation->splice_countdown, 8);

  // write transport_private_data
  if (ts->adaptation->transport_private_data_length != 0)
    {
      oport->write_uimsbf(ts->adaptation->transport_private_data_length, 8);
      for (int i = 0; i < ts->adaptation->transport_private_data_length; i++)
	oport->write_byte((char) 0);
    }

  // write adaptation_field_extension
  if (ts->adaptation->adaptation_extension_length != 0)
    {
      oport->write_uimsbf(ts->adaptation->adaptation_extension_length, 8);
      for (int j = 0; j < ts->adaptation->adaptation_extension_length; j++)
	oport->write_byte((char) 0xff);
    }

  // write stuffing bytes
  if (ts->adaptation->number_stuffing_bytes != 0)
     {
      for (int k = 0; k < ts->adaptation->number_stuffing_bytes; k++)
	oport->write_byte(0xff);
    }
}

void TSProducer::send_payload (Producer* payload_prod)
{
  int nbytes = 188 - ts->get_header_length();
  if (payload_prod == NULL)
    {
      sys_error("unexpected NULL producer found");
    }
  payload_prod->connect(oport);
  // payload_prod has already been loaded 
  int done = payload_prod->send_partial(nbytes);
}