簡體   English   中英

使用OpenAL和FFMPEG流式傳輸音頻

[英]Streaming Audio with OpenAL and FFMPEG

好吧,基本上我正在研究一個簡單的視頻播放器,我可能會問另一個關於滯后視頻\\同步到音頻的問題,但是現在我遇到了音頻問題。 我設法做的是瀏覽視頻的所有音頻幀並將它們添加到矢量緩沖區,然后使用OpenAL從該緩沖區播放音頻。

這是低效率和內存占用,所以我需要能夠使用我猜稱為旋轉緩沖區的流。 我遇到了一些問題,一個是關於OpenAL流媒體的信息不多,更不用說使用FFMPEG解碼音頻並將其傳輸到OpenAL的正確方法了。 我甚至不太習慣使用矢量作為我的緩沖區,因為我真的不知道矢量在C ++中是如何工作的,但我有些人設法從我的頭腦中拉出一些東西來使其工作。

目前我有一個如下所示的Video類:

class Video
{
    public:
        Video(string MOV);
        ~Video();
        bool HasError();
        string GetError();
        void UpdateVideo();
        void RenderToQuad(float Width, float Height);
        void CleanTexture();
    private:
        string FileName;
        bool Error;
        int videoStream, audioStream, FrameFinished, ErrorLevel;
        AVPacket packet;
        AVFormatContext *pFormatCtx;
        AVCodecContext *pCodecCtx, *aCodecCtx;
        AVCodec *pCodec, *aCodec;
        AVFrame *pFrame, *pFrameRGB, *aFrame;

        GLuint VideoTexture;
        struct SwsContext* swsContext;

        ALint state;
        ALuint bufferID, sourceID;
        ALenum format;
        ALsizei freq;

        vector <uint8_t> bufferData;
};

底部的私有變量是相關的。 目前我正在將類構造函數中的音頻解碼為AVFrame,並將數據添加到bufferData,如下所示:

    av_init_packet(&packet);

    alGenBuffers(1, &bufferID);
    alGenSources(1, &sourceID);

    alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);

    int GotFrame = 0;

    freq = aCodecCtx->sample_rate;
    if (aCodecCtx->channels == 1)
        format = AL_FORMAT_MONO16;
    else
        format = AL_FORMAT_STEREO16;

    while (av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if (packet.stream_index == audioStream)
        {
            avcodec_decode_audio4(aCodecCtx, aFrame, &GotFrame, &packet);
            bufferData.insert(bufferData.end(), aFrame->data[0], aFrame->data[0] + aFrame->linesize[0]);
            av_free_packet(&packet);
        }
    }
    av_seek_frame(pFormatCtx, audioStream, 0, AVSEEK_FLAG_BACKWARD);

    alBufferData(bufferID, format, &bufferData[0], static_cast<ALsizei>(bufferData.size()), freq);

    alSourcei(sourceID, AL_BUFFER, bufferID);

在我的UpdateVideo()中,我通過視頻流將視頻解碼為OpenGL紋理,因此我可以在那里解碼我的音頻並對其進行流式處理:

void Video::UpdateVideo()
{
    alGetSourcei(sourceID, AL_SOURCE_STATE, &state);
    if (state != AL_PLAYING)
        alSourcePlay(sourceID);
    if (av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if (packet.stream_index == videoStream)
        {
            avcodec_decode_video2(pCodecCtx, pFrame, &FrameFinished, &packet);
            if (FrameFinished)
            {
                sws_scale(swsContext, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                av_free_packet(&packet);
            }
        }
        else if (packet.stream_index == audioStream)
        {
            /*
            avcodec_decode_audio4(aCodecCtx, aFrame, &FrameFinishd, &packet);
            if (FrameFinished)
            {
                //Update Audio and rotate buffers here!
            }
            */
        }
        glGenTextures(1, &VideoTexture);
        glBindTexture(GL_TEXTURE_2D, VideoTexture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, 3, pCodecCtx->width, pCodecCtx->height, 0, GL_RGB, GL_UNSIGNED_BYTE, pFrameRGB->data[0]);
    }
    else
    {
        av_seek_frame(pFormatCtx, videoStream, 0, AVSEEK_FLAG_BACKWARD);
    }
}

所以我想最重要的問題是我該怎么辦? 我一點也不清楚。 任何幫助表示贊賞,謝謝!

首先,您需要創建OpenAL流式聲源。 此外,您需要緩沖池來讀取流式數據並通過OpenAL排隊等待播放。

在open時,你需要從pull中填充一些緩沖區並將它們添加到源隊列(alSourceQueueBuffers)。 在更新過程中,您需要排隊已經播放的緩沖區

int processed = 0;
ALuint bufID = 0;
// ...
alGetSourcei(source_handle, AL_BUFFERS_PROCESSED, &processed);
while (processed--) {
    alGetError();
    alSourceUnqueueBuffers(source_handle, 1, &bufID);
    // return buffId to buffers pool;
}

然后你需要從池中獲取空緩沖區並用緩沖區id調用你的bufferData代碼。

在bufferData中,您不需要創建源 - 將其作為參數傳遞。 您也不需要設置源參數。 只需將現有緩沖區排隊到現有源。 而不是alSourcei(sourceID,AL_BUFFER,bufferID)你需要使用alSourceQueueBuffers(sourceID,1,&bufferID)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM