为什么 avcodec_fill_audio_frame return -22 只有样本计数不同?

Why does avcodec_fill_audio_frame return -22 when only sample count is different?

我的问题解释起来非常快:我必须使用 FFmpeg(原始 PCM 到 G.711 mu-law)对音频样本进行编码。这是我的代码有罪的部分(我在这个例子中把原始参数显式):

AVFrame* frame = av_frame_alloc();
frame->nb_samples = 8000;
frame->format = AV_SAMPLE_FMT_S16;
frame->channels = 1;
frame->channel_layout = AV_CH_LAYOUT_MONO;
frame->sample_rate = 8000;
frame->quality = 1;

int res = avcodec_fill_audio_frame(frame, 1, AV_SAMPLE_FMT_S16, /*my samples data*/, 16000, 0);

// If res >= 0, continue with avcodec_encode_audio2

而且有效:) ...嗯,我的意思是...

当我的输入是 8000 音频样本时(S16 格式所以 16000 字节),有用。但是当我有 6000 音频样本时(仍然是 S16 格式所以 12000 字节),它失败了-22(无效参数)。有什么想法吗?

PRECISION: 此样本数不会动态变化。我的数据会话总是由 8000 个样本组成(并且有效),而其他会话的数据总是由 6000 个样本组成(并且失败)。样本数和数据大小是这些会话之间唯一不同的参数。

编辑: 如果我设置或不设置 AVCodecContext 中的 frame_size 字段,它 returns 在 avcodec_open2 之后变为 0但所选的 mu-law 编码器具有 AV_CODEC_CAP_VARIABLE_FRAME_SIZE 功能,因此听起来很正常。

每次调用 avcodec_encode_audio2() 的输入应该恰好是 N 个样本,其中 N 是 AVCodecContext::frame_size。在某些情况下,这取决于编解码器(例如 mp3 帧大小是恒定的),但在其他情况下,它可以是可变的。对于大多数编码器来说,它在编码中应该仍然是常量。看起来你的值就是默认值,mulaw 没有内置常量,所以你可以在调用 avcodec_open2() 之前指定一个不同的 frame_size 值,你应该没问题。

如果您的样本数量动态变化,您需要一个环形缓冲区来确保 avcodec_encode_audio2() 的输入仍然具有恒定数量的样本。

好的,我解决了我自己的问题,这是一个对齐问题。有两种解决方法:

  • 根据 libavcodec 所需的默认对齐方式对输入缓冲区进行初始化和填充。您可以将 av_samples_get_buffer_size 与对齐值一起使用,以 0 获得正确的大小。

  • 调用 avcodec_fill_audio_frame 并将对齐参数设置为 1 以忽略对齐。

希望这对其他人有帮助:)