⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac3decoder.cc

📁 Linux下比较早的基于命令行的DVD播放器
💻 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 "AC3Decoder.h"#include "AudioProcessor.h"#include "util/Log.h"#include "util/Config.h"extern "C" { #include <liba52/mm_accel.h>}#include "config.h"#include <cstring>#include <cmath>#include <cassert>// This is needed for GCC 2.95, otherwise it is declared // in <unistd.h>extern "C" {void swab(const void* from, void* to, ssize_t n);}//------------------------------------------------------------------------------namespace {#if defined(MM_ACCEL_SSE)    int mmAccel = MM_ACCEL_X86_SSE;#elif defined(MM_ACCEL_MMXEXT)    int mmAccel = MM_ACCEL_X86_MMXEXT;#elif defined(MM_ACCEL_MMX)    int mmAccel = MM_ACCEL_X86_MMX;#elif defined(MM_ACCEL_3DNOWEXT)    int mmAccel = MM_ACCEL_X86_3DNOWEXT;#elif defined(MM_ACCEL_3DNOW)    int mmAccel = MM_ACCEL_X86_3DNOW;#else    int mmAccel = 0; #endif}//------------------------------------------------------------------------------using output::AC3Decoder;//------------------------------------------------------------------------------//------------------------------------------------------------------------------inline int16_t AC3Decoder::blah(int32_t i) {    if (i > 0x43c07fff) {//          Log::debug("output::AC3Decoder::blah: Positive overshoot!\n");        return 32767;    }    else if (i < 0x43bf8000) {//          Log::debug("output::AC3Decoder::blah: Negative overshoot!\n");        return -32768;    }    else {        return i - 0x43c00000;    }}/*----------------------------------------------------------------------------*/inline void AC3Decoder::float_to_int(float * _f, int16_t * s16, int num_channels) {    int i;    int32_t * f = (int32_t *) _f;       /* XXX assumes IEEE float format */        for (i = 0; i < 256; i++) {        s16[num_channels*i] = blah (f[i]);    }}//------------------------------------------------------------------------------inline bool AC3Decoder::isEmpty() const{    return frameOffset==0;}//------------------------------------------------------------------------------//------------------------------------------------------------------------------AC3Decoder::AC3Decoder(AudioProcessor* audioProcessor) :    AudioDecoder(*audioProcessor),    samples(a52_init(mmAccel)),    frameOffset(0),    frameLength( (size_t)-1 ),    outputFlags(A52_STEREO),    outputLevel(Config::get().defaultVolume),    audioEnabled(true){    memset(&a52State, 0, sizeof(a52State));}//------------------------------------------------------------------------------void AC3Decoder::reset(){    frameOffset = 0;    frameLength = (size_t)-1;}//------------------------------------------------------------------------------void AC3Decoder::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.setOutputLength(outputLength);            audioProcessor.outputPacket();        }    }}//------------------------------------------------------------------------------bool AC3Decoder::decode(const unsigned char*& data,                         const unsigned char* end){    static const char syncWord[2] = { 0x0b, 0x77 };    static const unsigned syncInfoLength = 7;        while(data<end) {        while(data<end && frameOffset < sizeof(syncWord)) {            if ( *data == syncWord[frameOffset] ) {                frameBuffer[frameOffset] = *data;                ++frameOffset;            } else {                frameOffset = 0;            }            ++data;        }        if (data>=end) return false;        if( frameOffset >= sizeof(syncWord) && frameOffset < syncInfoLength ) {            copy(data, end, syncInfoLength);        }        if (frameOffset==syncInfoLength) {            int flags = outputFlags, sampleRate, bitRate;                        frameLength = a52_syncinfo(frameBuffer,                                       &flags, &sampleRate, &bitRate);            if (frameLength==0) {                Log::debug("output::AC3Decoder::decode: invalid frame");                frameOffset = 0;            }//              Log::debug("output::AC3Decoder::decode: frame length: %u, flags: %0x, sampleRate: %d, bitRate: %d\n",//                         frameLength, flags, sampleRate, bitRate);            assert(frameLength==0 || (frameLength>=128 && frameLength<=maxFrameSize));            assert( (frameLength%2)==0 );            setFormat(flags, sampleRate);        }        if (data>=end) return false;                if ( frameOffset>=syncInfoLength && frameOffset<frameLength) {            copy(data, end, frameLength);        }                if (frameOffset==frameLength) {            bool frameValid =                 (audioProcessor.getOutputFormat().encoding == AC3) ?                prepareFrameForHardwareDecoding() : decodeFrame();            frameOffset = 0;            frameLength = (size_t)-1;                        if (frameValid) return true;        }    }    return false;}//------------------------------------------------------------------------------bool AC3Decoder::toggleAudio(){    audioEnabled = !audioEnabled;    if (!audioEnabled) {        memset(audioProcessor.getOutputBuffer(), 0, outputLength);    }    return audioEnabled;}//------------------------------------------------------------------------------void AC3Decoder::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);}//------------------------------------------------------------------------------void AC3Decoder::setFormat(int flags, int sampleRate){    AudioFormat& format = audioProcessor.getOutputFormat();    format.encoding =         (Config::get().audioMode == AM_DIGITAL_AC3) ? AC3 : LPCM_LE;    format.sampleRate = (unsigned)sampleRate;        if (format.encoding==LPCM_LE) {        format.numberOfChannels = 2;    } else {        switch(flags&A52_CHANNEL_MASK) {          case A52_MONO:            format.numberOfChannels = 1;            break;          case A52_STEREO:            format.numberOfChannels = 2;            break;          case A52_3F:          case A52_2F1R:            format.numberOfChannels = 3;            break;          case A52_3F1R:          case A52_2F2R:            format.numberOfChannels = 4;            break;          case A52_3F2R:          default:            format.numberOfChannels = 5;            break;        }        if (flags&A52_LFE) {            ++format.numberOfChannels;        }    }}//------------------------------------------------------------------------------bool AC3Decoder::decodeFrame(){    if (!audioEnabled) return true;    int flags = outputFlags | A52_ADJUST_LEVEL;    float level = pow(2.0, ((int)outputLevel-40)/10.0);    if (a52_frame(&a52State, frameBuffer, &flags, &level, 384)) {        Log::error("output::AC3Decoder::decodeFrame: A52 frame error\n");        return false;    }    /*      a52_dynrng(&a52State, 0, 0); */    int16_t* decodedOutput = reinterpret_cast<int16_t*>(audioProcessor.getOutputBuffer());        for (size_t i = 0; i < 6; i++) {        if (a52_block(&a52State, samples)) {            Log::error("output::AC3Decoder::decodeFrame: A52 block error: %u\n", i);            return false;        }                float_to_int (samples + 0*256, decodedOutput + (i*256*2),   2);        float_to_int (samples + 1*256, decodedOutput + (i*256*2)+1, 2);    }    return true;}//------------------------------------------------------------------------------bool AC3Decoder::prepareFrameForHardwareDecoding(){    unsigned char* output = audioProcessor.getOutputBuffer();    output[0] = 0x72;    output[1] = 0xf8;        output[2] = 0x1f;    output[3] = 0x4e;    output[4] = 0x01;    output[5] = 0x00;    output[6] = (frameLength<<3) & 0xff;    output[7] = (frameLength>>5) & 0xff;    swab(frameBuffer, output+8, frameLength);    memset(output + 8 + frameLength, 0, outputLength - 8 - frameLength);        return true;}//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -