簡體   English   中英

如何將音頻數據放入 AVFrame 進行編碼

[英]How to put audio data in AVFrame for encode

我嘗試將原始 PCM 聲音編碼為 G711A 和 G711U,然后對其進行解碼,使用此編解碼器一切正常,因為我可以為 AVCodecContext frame_size 選擇任何值進行編碼,但在 Opus 編解碼器的情況下,AVCodecContext frame_size 等於 120,所以如果我理解正確,如果我的輸入數據數組大小大於 120,那么我需要進行某種緩沖並將我的輸入數據分成幾個部分,然后依次將其放入 AVFrame->data 並將 AVFrame 傳遞給編碼。

結果我得到了一個非常糟糕的聲音,我不僅在使用 Opus 編解碼器時得到這個結果,而且在 G711 中如果我將它的 AVCodecContext frame_size 設置為某個小於我輸入數據大小的值。

所以我的問題是:如果輸入數據的大小大於 AVCodecContext frame_size,那么編碼輸入數據的正確方法是什么? 我是否需要將我的輸入數據拆分為 <= AVCodecContext frame_size 如果是這樣我應該怎么做?

此時我的代碼如下所示:

void encode(uint8_t *data, unsigned int length)
{
    int rawOffset = 0;
    int rawDelta = 0;
    int rawSamplesCount = frameEncode->nb_samples <= length ? frameEncode->nb_samples : length;

    while (rawSamplesCount > 0)
    {
        memcpy(frameEncode->data[0], &data[rawOffset], sizeof(uint8_t) * rawSamplesCount);

        encodeFrame();

        rawOffset += rawSamplesCount;
        rawDelta = length - rawOffset;
        rawSamplesCount = rawDelta > frameEncode->nb_samples ? frameEncode->nb_samples : rawDelta;
    }

    av_frame_unref(frameEncode);
}

void encodeFrame()
{
    /* send the frame for encoding */
    int ret = avcodec_send_frame(contextEncoder, frameEncode);
    if (ret < 0)
    {
        LOGE(TAG, "[encodeFrame] avcodec_send_frame error: %s", av_err2str(ret));
        return;
    }

    /* read all the available output packets (in general there may be any number of them) */
    while (ret >= 0)
    {
        ret = avcodec_receive_packet(contextEncoder, packetEncode);
        if (ret < 0 && ret != AVERROR(EAGAIN)) LOGE(TAG, "[encodeFrame] error in avcodec_receive_packet: %s", av_err2str(ret));
        if (ret < 0) break;
        std::pair<uint8_t*, unsigned int> p = std::pair<uint8_t*, unsigned int>();
        p.first = (uint8_t *)(malloc(sizeof(uint8_t) * packetEncode->size));
        memcpy(p.first, packetEncode->data, (size_t)packetEncode->size);
        p.second = (unsigned int)(packetEncode->size);

        listEncode.push_back(p); // place encoded data into list to finally create one array of encoded data from it
    }
    av_packet_unref(packetEncode);
}

您可以看到我將輸入數據分成幾個部分,然后將其放入 frame->data 中,然后將幀傳遞給編碼,但我不確定這是正確的方法。

UPD:我注意到,當我使用 G711 時,如果我將 AVCodecContext frame_size 設置為 160,並且我的輸入數據大小為 160 或 320,一切正常,但如果輸入數據大小為 640,那么我會聽到糟糕的嗡嗡聲。

你說了這么多, “所以如果我理解正確,如果我的輸入數據數組大小大於 120,那么我需要做某種緩沖並將我的輸入數據分成幾個部分,然后依次將其放入 AVFrame->data 並傳遞AVFrame 進行編碼。”

這就是你需要的。 BUffer樣本並每次發送固定數量進行編碼。

暫無
暫無

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

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