obs之libfaac编码

obs源码之libaac编码。

#include "Main.h"

#include "../libfaac/include/faac.h"


//AAC is pretty good, I changed my  mind
class AACEncoder : public AudioEncoder
{
    UINT curBitRate;

    bool bFirstPacket;

    faacEncHandle faac;
    DWORD numReadSamples;
    DWORD outputSize;

    List<float> inputBuffer;

    List<BYTE>  aacBuffer;
    List<BYTE>  header;

    List<DWORD> bufferedTimestamps;
    DWORD curEncodeTimestamp;
    bool bFirstFrame;

public:
    AACEncoder(UINT bitRate)
    {
        curBitRate = bitRate;

        faac = faacEncOpen(44100, 2, &numReadSamples, &outputSize);

        //Log(TEXT("numReadSamples: %d"), numReadSamples);
        aacBuffer.SetSize(outputSize+2);
        aacBuffer[0] = 0xaf;
        aacBuffer[1] = 0x1;

        faacEncConfigurationPtr config = faacEncGetCurrentConfiguration(faac);
        config->bitRate = (bitRate*1000)/2;
        config->quantqual = 100;
        config->inputFormat = FAAC_INPUT_FLOAT;
        config->mpegVersion = MPEG4;
        config->aacObjectType = LOW;
        config->useLfe = 0;
        config->outputFormat = 0;

        int ret = faacEncSetConfiguration(faac, config);
        if(!ret)
            CrashError(TEXT("aac configuration failed"));

        BYTE *tempHeader;
        DWORD len;

        header.SetSize(2);
        header[0] = 0xaf;
        header[1] = 0x00;

        faacEncGetDecoderSpecificInfo(faac, &tempHeader, &len);
        header.AppendArray(tempHeader, len);
        free(tempHeader);

        bFirstPacket = true;
        bFirstFrame  = true;

        Log(TEXT("------------------------------------------"));
        Log(TEXT("%s"), GetInfoString().Array());
    }

    ~AACEncoder()
    {
        faacEncClose(faac);
    }

    bool Encode(float *input, UINT numInputFrames, DataPacket &packet, DWORD ×tamp)
    {
        if(bFirstFrame)
        {
            curEncodeTimestamp = timestamp;
            bFirstFrame = false;
        }

        //------------------------------------------------

        DWORD curTimestamp = timestamp;

        UINT lastSampleSize = inputBuffer.Num();
        UINT numInputSamples = numInputFrames*2;
        inputBuffer.AppendArray(input, numInputSamples);

        int ret = 0;

        if(inputBuffer.Num() >= numReadSamples)
        {
            //now we have to upscale the floats.  fortunately we almost always have SSE
            UINT floatsLeft  = numReadSamples;
            float *inputTemp = inputBuffer.Array();
            if(App->SSE2Available() && (UPARAM(inputTemp) & 0xF) == 0)
            {
                UINT alignedFloats = floatsLeft & 0xFFFFFFFC;

                for(UINT i=0; i<alignedFloats; i += 4)
                {
                    float *pos = inputTemp+i;
                    _mm_store_ps(pos, _mm_mul_ps(_mm_load_ps(pos), _mm_set_ps1(32767.0f)));
                }

                floatsLeft &= 0x3;
                inputTemp  += alignedFloats;
            }

            if(floatsLeft)
            {
                for(UINT i=0; i<floatsLeft; i++)
                    inputTemp[i] *= 32767.0f;
            }

            ret = faacEncEncode(faac, (int32_t*)inputBuffer.Array(), numReadSamples, aacBuffer.Array()+2, outputSize);
            if(ret > 0)
            {
                if(bFirstPacket)
                {
                    bFirstPacket = false;
                    ret = 0;
                }
                else
                {
                    packet.lpPacket = aacBuffer.Array();
                    packet.size     = ret+2;

                    timestamp = bufferedTimestamps[0];
                    bufferedTimestamps.Remove(0);
                }
            }
            else if(ret < 0)
                AppWarning(TEXT("aac encode error"));

            inputBuffer.RemoveRange(0, numReadSamples);

            bufferedTimestamps << curEncodeTimestamp;
            curEncodeTimestamp = curTimestamp + (((numReadSamples-lastSampleSize)/2)*10/441);
        }

        return ret > 0;
    }

    UINT GetFrameSize() const
    {
        return 1024;
    }

    void GetHeaders(DataPacket &packet)
    {
        packet.lpPacket = header.Array();
        packet.size = header.Num();
    }

    int GetBitRate() const {return curBitRate;}
    CTSTR GetCodec() const {return TEXT("AAC");}

    String GetInfoString() const
    {
        String strInfo;
        strInfo << TEXT("Audio Encoding: AAC")  <<
                   TEXT("\r\n    bitrate: ") << IntString(curBitRate);

        return strInfo;
    }
};


AudioEncoder* CreateAACEncoder(UINT bitRate)
{
    return new AACEncoder(bitRate);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值