簡體   English   中英

FFMPEG C++ 容積過濾器

[英]FFMPEG C++ Volume Filter

在 C++ 代碼中使用 FFMPEG 音頻過濾器似乎有點麻煩。 如果我只有“abuffer”和“abuffersink”過濾器,並從過濾器圖中抓取音頻幀,那聽起來很完美。 一旦我在圖中添加了另一個過濾器(在這種情況下,它是一個“音量”過濾器),就會引入很多噪聲。 我不知道是什么原因造成的。

並非所有過濾器都是這種情況——例如,“aecho”工作得很好。 有什么想法嗎? 以下是相關代碼:

過濾器創建

char args[512];
int ret = 0;

_filterGraph = avfilter_graph_alloc();

// abuffer must be the first filter used -- it feeds data into the filter graph
/******************
ABUFFER FILTER
*******************/
_abufferFilter = avfilter_get_by_name("abuffer");

/*buffer audio source : decoded frames will be
inserted here. */
if (!_inAudioCodecContext->channel_layout)
{
    _inAudioCodecContext->channel_layout = av_get_default_channel_layout(_inAudioStream->codec->channels);
}

snprintf(args, sizeof(args),
    "sample_rate=%d:sample_fmt=%s:channel_layout=0x%" PRIx64,
    _inAudioCodecContext->sample_rate,
    av_get_sample_fmt_name(_inAudioCodecContext->sample_fmt),
    _inAudioCodecContext->channel_layout);

ret = avfilter_graph_create_filter(&_abufferFilterCtx, _abufferFilter, "abuffer", args, NULL, _filterGraph);
char *errorCode = new char[256];
av_strerror(ret, errorCode, 256);

/******************
VOLUME FILTER
*******************/
snprintf(args, sizeof(args),
    "%f",
    2.0f);
_volumeFilter = avfilter_get_by_name("volume");
ret = avfilter_graph_create_filter(&_volumeFilterCtx, _volumeFilter, "volume", args, NULL, _filterGraph);
char *errorCode = new char[256];
av_strerror(ret, errorCode, 256);

/******************
ABUFFERSINK FILTER
*******************/
// abuffersink must be the last filter used -- it gets data out of the filter graph
_abuffersinkFilter = avfilter_get_by_name("abuffersink");
ret = avfilter_graph_create_filter(&_abufferSinkFilterCtx, _abuffersinkFilter, "abuffersink", NULL, NULL, _filterGraph);

// Link the source buffer to the volume filter
// If I link this to the sink buffer and comment out the next line
// Audio sounds perfect
ret = avfilter_link(_abufferFilterCtx, 0, _volumeFilterCtx, 0);
// Link the volume filter to the sink buffer
ret = avfilter_link(_volumeFilterCtx, 0, _abufferSinkFilterCtx, 0);
ret = avfilter_graph_config(_filterGraph, NULL);

return ret;

從緩沖區讀取幀

// Read a frame from the audio stream/file
ret = av_read_frame(_inFormatContext, &_packet);
int frameFinished = 0;
// Decode the resulting packet into a single frame for processing
int length = avcodec_decode_audio4(_inAudioCodecContext, _audioFrame, &frameFinished, &_packet);

if (frameFinished)
{
    // Insert the frame into the source filter
    ret = av_buffersrc_write_frame(_abufferFilterCtx, _audioFrame);
    while (true)
    {
        // Pull a frame from the filter graph
        ret = av_buffersink_get_frame(_abufferSinkFilterCtx, _audioFrame);

        // EOF or EAGAIN is expected when filtering frames, set the error to "0"
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
        {
            ret = 0;
            break;
        }
        if (ret < 0)
        {
            break;
        }
    }

    // This keeps going, doing some resampling and conversion based on codec output selection, but that isn't relevant to the issue

我想通了。 它默認為“浮點”精度,所以如果格式是固定的,我必須添加以下內容:

snprintf(args, sizeof(args),
    "volume=%f:precision=fixed",
    1.0f);
_volumeFilter = avfilter_get_by_name("volume");
ret = avfilter_graph_create_filter(&_volumeFilterCtx, _volumeFilter, "volume", args, NULL, _filterGraph);

暫無
暫無

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

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