Example #1
0
void ElementaryStream::Muxed (unsigned int bytes_muxed)
{
	clockticks   decode_time;
  
	if (bytes_muxed == 0 || MuxCompleted() )
		return;


	/* Work through what's left of the current AU and the following AU's
	   updating the info until we reach a point where an AU had to be
	   split between packets.
	   NOTE: It *is* possible for this loop to iterate. 

	   The DTS/PTS field for the packet in this case would have been
	   given the that for the first AU to start in the packet.
	   Whether Joe-Blow's hardware VCD player handles this properly is
	   another matter of course!
	*/

	decode_time = RequiredDTS();
	while (au_unsent < bytes_muxed)
	{	  
        AUMuxed(true);          // Update stream specific tracking 
                                // of AUs muxed...
		bufmodel.Queued(au_unsent, decode_time);
		bytes_muxed -= au_unsent;
        new_au_next_sec = NextAU();
        if( !new_au_next_sec )
			return;
		decode_time = RequiredDTS();
	};

	// We've now reached a point where the current AU overran or
	// fitted exactly.  We need to distinguish the latter case
	// so we can record whether the next packet starts with an
	// existing AU or not - info we need to decide what PTS/DTS
	// info to write at the start of the next packet.
	
	if (au_unsent > bytes_muxed)
	{
        AUMuxed(false);
		bufmodel.Queued( bytes_muxed, decode_time);
		au_unsent -= bytes_muxed;
		new_au_next_sec = false;
	} 
	else //  if (au_unsent == bytes_muxed)
	{
        AUMuxed(false);
		bufmodel.Queued(bytes_muxed, decode_time);
		new_au_next_sec = NextAU();
	}	   

}
void AudioStream::OutputSector ( )

{
	clockticks   PTS;
	unsigned int max_packet_data; 	 
	unsigned int actual_payload;
	unsigned int old_au_then_new_payload;

	PTS = RequiredDTS();
	old_au_then_new_payload = 
		muxinto.PacketPayload( *this, buffers_in_header, false, false );
    bool last_packet = Lookahead() == 0;
    // Ensure we have access units data buffered to allow a sector to be
    // written.
	max_packet_data = 0;
	if( (muxinto.running_out && NextRequiredPTS() > muxinto.runout_PTS)
        || last_packet)
	{
		/* We're now in the last AU of a segment.  So we don't want to
		   go beyond it's end when writing sectors. Hence we limit
		   packet payload size to (remaining) AU length.
		*/
		max_packet_data = au_unsent+StreamHeaderSize();
	}
  
	/* CASE: packet starts with new access unit			*/
	
	if (new_au_next_sec)
    {
		actual_payload = 
			muxinto.WritePacket ( max_packet_data,
								  *this,
								  buffers_in_header, PTS, 0,
								  TIMESTAMPBITS_PTS);

    }


	/* CASE: packet starts with old access unit, no new one	*/
	/*       starts in this very same packet			*/
	else if (!(new_au_next_sec) && 
			 (au_unsent >= old_au_then_new_payload))
    {
		actual_payload = 
			muxinto.WritePacket ( max_packet_data,
								  *this,
								  buffers_in_header, 0, 0,
								  TIMESTAMPBITS_NO );
    }


	/* CASE: packet starts with old access unit, a new one	*/
	/*       starts in this very same packet			*/
	else /* !(new_au_next_sec) &&  (au_unsent < old_au_then_new_payload)) */
    {
		/* is there another access unit anyway ? */
		if( !last_packet )
		{
			PTS = NextRequiredDTS();
			actual_payload = 
				muxinto.WritePacket ( max_packet_data,
									  *this,
									  buffers_in_header, PTS, 0,
									  TIMESTAMPBITS_PTS );

		} 
		else
		{
			actual_payload = muxinto.WritePacket ( max_packet_data,
                                                   *this,
                                                   buffers_in_header, 0, 0,
                                                   TIMESTAMPBITS_NO );
		};
		
    }

    ++nsec;

	buffers_in_header = always_buffers_in_header;
	
}
Example #3
0
bool VideoStream::MuxPossible( clockticks currentSCR )
{
	return ( ElementaryStream::MuxPossible(currentSCR) && 
             RequiredDTS() < currentSCR + max_STD_buffer_delay );
}
Example #4
0
void VideoStream::OutputSector ( )

{
	unsigned int max_packet_payload; 	 
	unsigned int actual_payload;
	unsigned int old_au_then_new_payload;
	clockticks  DTS,PTS;
    int autype;

	max_packet_payload = 0;	/* 0 = Fill sector */
  	/* 	
       I-frame aligning.  For the last AU of segment or for formats
       with ACCESS-POINT sectors where I-frame (and preceding headers)
       are sector aligned.

       We need to look ahead to see how much we may put into the current packet
       without without touching the next I-frame (which is supposed to be
       placed at the start of its own sector).

       N.b.runout_PTS is the PTS of the after which the next I frame
       marks the start of the next sequence.
	*/

	if( muxinto.sector_align_iframeAUs || muxinto.running_out )
	{
		max_packet_payload = ExcludeNextIFramePayload();
	}

	/* Figure out the threshold payload size below which we can fit more
	   than one AU into a packet N.b. because fitting more than one in
	   imposses an overhead of additional header fields so there is a
	   dead spot where we *have* to stuff the packet rather than start
	   fitting in an extra AU.  Slightly over-conservative in the case
	   of the last packet...  */

	old_au_then_new_payload = muxinto.PacketPayload( *this,
					buffers_in_header, 
					true, true);

	/* CASE: Packet starts with new access unit			*/
	if (new_au_next_sec  )
	{
        autype = AUType();

        // Some types of output format (e.g. DVD) require special
        // control sectors before the sector starting a new GOP
        // N.b. this implies muxinto.sector_align_iframeAUs
        //
        if( gop_control_packet && autype == IFRAME )
        {
            OutputGOPControlSector();
        }

        //
        // If we demand every AU should have its own timestamp
        // We can't start two in the same sector...
        //
        if(  dtspts_for_all_au  && max_packet_payload == 0 )
            max_packet_payload = au_unsent;

        PTS = RequiredPTS();
        DTS = RequiredDTS();
		actual_payload =
			muxinto.WritePacket ( max_packet_payload,
        						*this,
        						NewAUBuffers(autype), 
                                PTS, DTS,
        						NewAUTimestamps(autype) );
        muxinto.IndexLastPacket(*this, autype );

	}

	/* CASE: Packet begins with old access unit, no new one	*/
	/*	     can begin in the very same packet					*/

	else if ( au_unsent >= old_au_then_new_payload ||
              (max_packet_payload != 0 && au_unsent >= max_packet_payload) )
	{
		actual_payload = 
			muxinto.WritePacket( au_unsent,
    							*this,
    							false, 0, 0,
    							TIMESTAMPBITS_NO );
        // No new frame starts so no indexing...
	}

	/* CASE: Packet begins with old access unit, a new one	*/
	/*	     could begin in the very same packet			*/
	else /* if ( !new_au_next_sec  && 
			(au_unsent < old_au_then_new_payload)) */
	{
		/* Is there a new access unit ? */
		if( Lookahead() != 0 )
		{
            autype = NextAUType();

			if(  dtspts_for_all_au  && max_packet_payload == 0 )
				max_packet_payload = au_unsent + Lookahead()->length;

			PTS = NextRequiredPTS();
			DTS = NextRequiredDTS();

			actual_payload = 
				muxinto.WritePacket ( max_packet_payload,
            						*this,
            						NewAUBuffers(autype), 
                                    PTS, DTS,
            						NewAUTimestamps(autype) );
            muxinto.IndexLastPacket(*this, autype );
		} 
		else
		{
			actual_payload = muxinto.WritePacket ( au_unsent, 
							*this, false, 0, 0,
							TIMESTAMPBITS_NO);
		}
	}
	++nsec;
	buffers_in_header = always_buffers_in_header;
}
unsigned int 
LPCMStream::ReadPacketPayload(uint8_t *dst, unsigned int to_read)
{
    unsigned int header_size = LPCMStream::StreamHeaderSize();
    bitcount_t read_start = bs.GetBytePos();
    unsigned int bytes_read = bs.GetBytes( dst+header_size, 
                                           to_read-header_size );
    bs.Flush( read_start );
    
	clockticks   decode_time;
    bool starting_frame_found = false;
    uint8_t starting_frame_index = 0;

    int starting_frame_offset = 
        (new_au_next_sec || au_unsent > bytes_read )
        ? 0 
        : au_unsent;

    unsigned int frames = 0;
    unsigned int bytes_muxed = bytes_read;
  
	if (bytes_muxed == 0 || MuxCompleted() )
    {
		goto completion;
    }


	/* Work through what's left of the current frames and the
	   following frames's updating the info until we reach a point where
	   an frame had to be split between packets. 

	   The DTS/PTS field for the packet in this case would have been
	   given the that for the first AU to start in the packet.

	*/

	decode_time = RequiredDTS();
	while (au_unsent < bytes_muxed)
	{	  
        assert( bytes_muxed > 1 );
		bufmodel.Queued(au_unsent, decode_time);
		bytes_muxed -= au_unsent;
        if( new_au_next_sec )
        {
            ++frames;
            if( ! starting_frame_found )
            {
                starting_frame_index = static_cast<uint8_t>(au->dorder % 20);
                starting_frame_found = true;
            }
        }
		if( !NextAU() )
        {
            goto completion;
        }
		new_au_next_sec = true;
		decode_time = RequiredDTS();
	};

	// We've now reached a point where the current AU overran or
	// fitted exactly.  We need to distinguish the latter case so we
	// can record whether the next packet starts with the tail end of
	// // an already started frame or a new one. We need this info to
	// decide what PTS/DTS info to write at the start of the next
	// packet.
	
	if (au_unsent > bytes_muxed)
	{
        if( new_au_next_sec )
            ++frames;
		bufmodel.Queued( bytes_muxed, decode_time);
		au_unsent -= bytes_muxed;
		new_au_next_sec = false;
	} 
	else //  if (au_unsent == bytes_muxed)
	{
		bufmodel.Queued(bytes_muxed, decode_time);
        if( new_au_next_sec )
            ++frames;
        new_au_next_sec = NextAU();
	}	   
completion:
    // Generate the LPCM header...
    // Note the index counts from the low byte of the offset so
    // the smallest value is 1!
    dst[0] = LPCM_SUB_STR_0 + stream_num;
    dst[1] = frames;
    dst[2] = (starting_frame_offset+4)>>8;
    dst[3] = (starting_frame_offset+4)&0xff;
    unsigned int bps_code;
    switch( bits_per_sample )
    {
    case 16 : bps_code = 0; break;
    case 20 : bps_code = 1; break;
    case 24 : bps_code = 2; break;
    default : bps_code = 3; break;
    }
    dst[4] = starting_frame_index;
    unsigned int bsf_code = (samples_per_second == 48000) ? 0 : 1;
    unsigned int channels_code = channels - 1;
    dst[5] = (bps_code << 6) | (bsf_code << 4) | channels_code;
    dst[6] = dynamic_range_code;
	return bytes_read+header_size;
}