lpcmstrm_in.cpp
来自「Motion JPEG编解码器源代码」· C++ 代码 · 共 324 行
CPP
324 行
/* * lpcmstrm_in.c: LPCM Audio strem class members handling scanning and * buffering raw input stream. * * Takes a *RAW* LPCM stream as input. * This is *signed* linear 16, 20, or 24-bit sample PCM. * Samples are stored msb first. * How 20-bit samples are allocated to bytes? I just don't know, but * believe 4 bits are appended after the lsb (samples are msb-byte aligned). * * Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com> * Copyright (C) 2000,2001 Brent Byeler for original header-structure * parsing code. * * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include <math.h>#include <stdlib.h>#include <string.h>#include "audiostrm.hpp"#include "interact.hpp"#include "multiplexor.hpp"const unsigned int LPCMStream::default_buffer_size = 58*1024;const unsigned int LPCMStream::ticks_per_frame_90kHz = 150;LPCMStream::LPCMStream(IBitStream &ibs, LpcmParams *parms, Multiplexor &into) : AudioStream( ibs, into ), parms(parms){ num_frames = 0;}bool LPCMStream::Probe(IBitStream &bs ){ char *last_dot = strrchr( bs.StreamName(), '.' ); return last_dot != NULL && strcmp( last_dot+1, "lpcm") == 0;}/************************************************************************* * * Reads initial stream parameters and displays feedback banner to users * *************************************************************************/void LPCMStream::Init ( const int _stream_num){ stream_num = _stream_num; header_skip = 0; MuxStream::Init( PRIVATE_STR_1, 1, // Buffer scale default_buffer_size, false, muxinto.buffers_in_audio, muxinto.always_buffers_in_audio ); // This seems to be necessary not only for some software players but // for some standalone players too. Yuck... shades of the VCD audio // sectors. min_pes_header_len = 10; mjpeg_info ("Scanning for header info: LPCM Audio stream %02x (%s)", stream_num, bs.StreamName() ); AU_start = bs.bitcount(); // This is a dummy debug version that simply assumes 48kHz // two channel 16 bit sample LPCM samples_per_second = parms->SamplesPerSec(); channels = parms->Channels(); bits_per_sample = parms->BitsPerSample(); bytes_per_frame = samples_per_second * channels * bits_per_sample / 8 * ticks_per_frame_90kHz / 90000; frame_index = 0; dynamic_range_code = 0x80; /* Presentation/decoding time-stamping */ access_unit.start = AU_start; access_unit.length = bytes_per_frame; access_unit.PTS = static_cast<clockticks>(decoding_order) * (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); OutputHdrInfo();}unsigned int LPCMStream::NominalBitRate(){ return samples_per_second * channels * bits_per_sample;}void LPCMStream::FillAUbuffer(unsigned int frames_to_buffer ){ last_buffered_AU += frames_to_buffer; mjpeg_debug( "Scanning %d MPEG LPCM audio frames to frame %d", frames_to_buffer, last_buffered_AU ); while ( !bs.eos() && decoding_order < last_buffered_AU && !muxinto.AfterMaxPTS(access_unit.PTS) ) { int skip=access_unit.length; bs.SeekFwdBits( skip ); prev_offset = AU_start; AU_start = bs.bitcount(); if( AU_start - prev_offset != access_unit.length*8 ) { mjpeg_warn("Discarding incomplete final frame LPCM stream %d", stream_num); aunits.DropLast(); --decoding_order; break; } // Here we would check for header data but LPCM has no headers... if( bs.eos() ) break; access_unit.start = AU_start; access_unit.length = bytes_per_frame; access_unit.PTS = static_cast<clockticks>(decoding_order) * (CLOCKS_per_90Kth_sec * ticks_per_frame_90kHz); access_unit.DTS = access_unit.PTS; access_unit.dorder = decoding_order; decoding_order++; aunits.Append( access_unit ); num_frames++; num_syncword++; if (num_syncword >= old_frames+10 ) { mjpeg_debug ("Got %d frame headers.", num_syncword); old_frames=num_syncword; } mjpeg_debug( "Got frame %d\n", decoding_order ); } last_buffered_AU = decoding_order; eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);}void LPCMStream::Close(){ stream_length = AU_start / 8; mjpeg_info ("AUDIO_STATISTICS: %02x", stream_id); mjpeg_info ("Audio stream length %lld bytes.", stream_length); mjpeg_info ("Frames : %8u ", num_frames);}/************************************************************************* OutputAudioInfo gibt gesammelte Informationen zu den Audio Access Units aus. Prints information on audio access units*************************************************************************/void LPCMStream::OutputHdrInfo (){ mjpeg_info("LPCM AUDIO STREAM:"); mjpeg_info ("Bit rate : %8u bytes/sec (%u) bit/sec)", NominalBitRate()/8, NominalBitRate() ); mjpeg_info ("Channels : %d", channels); mjpeg_info ("Bits per sample: %d", bits_per_sample ); mjpeg_info ("Frequency : %d Hz", samples_per_second );}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+1)>>8; dst[3] = (starting_frame_offset+1)&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;}/* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?