📄 mpegaudiodecoder.cc
字号:
//// Copyright (c) 2003 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card.// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// 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 "MPEGAudioDecoder.h"#include "AudioProcessor.h"#include "util/Log.h"#include <cstring>#include <cassert>//------------------------------------------------------------------------------using output::MPEGAudioDecoder;//------------------------------------------------------------------------------const size_t MPEGAudioDecoder::bitrateTable[2][3][16] = { // MPEG 2.5 { // Layer III { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0 }, // Layer II { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0 }, // Layer I { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000, 0 } }, // MPEG 1, MPEG 2 { // Layer III { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0 }, // Layer II { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0 }, // Layer I { 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0 } },};//------------------------------------------------------------------------------const size_t MPEGAudioDecoder::sampleRateTable[3] = { 11025, 12000, 8000 };//------------------------------------------------------------------------------inline MPEGAudioDecoder::sampleType MPEGAudioDecoder::convertSample(mad_fixed_t sample){ return sample >> (MAD_F_FRACBITS-15);}//------------------------------------------------------------------------------//------------------------------------------------------------------------------inline bool MPEGAudioDecoder::isEmpty() const{ return frameOffset==0;}//------------------------------------------------------------------------------//------------------------------------------------------------------------------MPEGAudioDecoder::MPEGAudioDecoder(AudioProcessor* audioProcessor) : AudioDecoder(*audioProcessor), frameOffset(0), frameLength((size_t)-1){ reset();}//------------------------------------------------------------------------------void MPEGAudioDecoder::reset(){ mad_stream_init(&madStream); mad_frame_init(&madFrame); mad_synth_init(&madSynth);}//------------------------------------------------------------------------------void MPEGAudioDecoder::decodePacket(const unsigned char* data, size_t length, pts_t packetPTS){ const unsigned char* end = data + length; size_t offset = 0; while(offset<length && !audioProcessor.isInterrupted()) { const unsigned char* start = data + offset; if (isEmpty()) { audioProcessor.transferPTS(packetPTS); } bool hasFrame = decode(start, end); offset = start - data; if (hasFrame) { audioProcessor.outputPacket(); } } }//------------------------------------------------------------------------------bool MPEGAudioDecoder::decode(const unsigned char*& data, const unsigned char* end){ while(data<end) { while(data<end && frameOffset<2) { if ( (frameOffset==0 && *data==0xff) || (frameOffset==1 && ((*data)&0xe0)==0xe0)) { frameBuffer[frameOffset] = *data; ++frameOffset; } else { frameOffset = 0; } ++data; } while(data<end && frameOffset>=2 && frameOffset<=3) { frameBuffer[frameOffset] = *data; ++frameOffset; ++data; } if (data>=end) return false; if (frameOffset==4) { frameLength = getFrameLength(); if (frameLength<4) { Log::error("output::MPEGAudioDecoder::decode: invalid frame"); frameOffset = 0; } assert(frameLength<=frameBufferSize); } if ( frameOffset>=4 && frameOffset<frameLength) { copy(data, end, frameLength); } if (frameOffset==frameLength) { bool frameValid = decodeFrame(); frameOffset = 0; frameLength = (size_t)-1; if (frameValid) return true; } } return false;}//------------------------------------------------------------------------------size_t MPEGAudioDecoder::getFrameLength(){ assert(frameOffset>=4); unsigned versionID = (frameBuffer[1]>>3)&0x03; unsigned layerIndex = (frameBuffer[1]>>1)&0x03; if (layerIndex==0) return 0; unsigned bitrateIndex = (frameBuffer[2]>>4)&0x0f; unsigned bitrate = bitrateTable[(versionID>>1)&0x01][layerIndex-1][bitrateIndex]; unsigned sampleRateIndex = (frameBuffer[2]>>2)&0x03; if (sampleRateIndex>2) return 0; unsigned sampleRate = sampleRateTable[sampleRateIndex]; if (versionID==2) sampleRate *= 2; else if (versionID==3) sampleRate *= 4; size_t padding = (frameBuffer[2]>>1)&0x01; size_t length = 0; if (layerIndex==3) { // Layer I length = ((12 * bitrate / sampleRate)+padding)*4; } else { size_t slots = (layerIndex==1 && versionID<2) ? 72 : 144; // Layer III && MPEG 2.5 length = (slots*bitrate/sampleRate) + padding; } Log::verboseDebug("output::MPEGAudioDecoder::getFrameLength: header data: versionID=%u, layerIndex=%u, bitrateIndex=%u, sampleRateIndex=%u\n", versionID, layerIndex, bitrateIndex, sampleRateIndex); Log::verboseDebug("output::MPEGAudioDecoder::getFrameLength: header data: bitrate=%u, sampleRate=%u, padding=%u, length=%u\n", bitrate, sampleRate, padding, length); AudioFormat& format = audioProcessor.getOutputFormat(); format.encoding = LPCM_LE; format.numberOfChannels = 2; format.sampleRate = sampleRate; return length;}//------------------------------------------------------------------------------void MPEGAudioDecoder::copy(const unsigned char*& data, const unsigned char* end, size_t targetOffset){ unsigned tocopy = targetOffset - frameOffset; unsigned blockLength = end - data; if (tocopy>blockLength) tocopy = blockLength; memcpy(frameBuffer + frameOffset, data, tocopy); frameOffset += tocopy; data += tocopy; assert(data<=end);}//------------------------------------------------------------------------------bool MPEGAudioDecoder::decodeFrame(){ mad_stream_buffer(&madStream, frameBuffer, frameLength+MAD_BUFFER_GUARD); if (mad_header_decode(&madFrame.header, &madStream) || mad_frame_decode(&madFrame, &madStream)) { if (MAD_RECOVERABLE(madStream.error)) { Log::warning("output::MPEGAudioDecoder::decoder: recoverable frame error: %d\n", madStream.error); } else if (madStream.error!=MAD_ERROR_BUFLEN) { Log::error("output::MPEGAudioDecoder::decoder: unrecoverable frame error: %d\n", madStream.error); } else { Log::warning("output::MPEGAudioDecoder::decoder: MAD_ERROR_BUFLEN\n"); } reset(); return false; } synthesizeFrame(); return true;}//------------------------------------------------------------------------------void MPEGAudioDecoder::synthesizeFrame(){ mad_synth_frame(&madSynth, &madFrame); assert(madSynth.pcm.length<=maxOutputSamples); sampleType* output = reinterpret_cast<sampleType*>(audioProcessor.getOutputBuffer()); for(size_t i = 0; i<madSynth.pcm.length; ++i, output += 2) { sampleType leftSample = convertSample(madSynth.pcm.samples[0][i]); output[0] = leftSample; if (MAD_NCHANNELS(&madFrame.header)==2) { output[1] = convertSample(madSynth.pcm.samples[1][i]); } else { output[1] = leftSample; } } audioProcessor.setOutputLength(madSynth.pcm.length * sampleSize);}//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -