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(); } }
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; }