当样本数量不同时,为什么avcodec_fill_audio_frame返回-22?

时间:2017-07-21 15:15:38

标签: c++ ffmpeg encode pcm libavcodec

我的问题解释得非常快:我必须使用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个样本组成(并且它失败)。样本计数和数据大小是这些会话之间唯一不同的参数。

编辑:如果我在frame_size中设置了AVCodecContext字段,则在avcodec_open2之后返回0,但选择的mu-law编码器具有AV_CODEC_CAP_VARIABLE_FRAME_SIZE能力因此听起来很正常。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

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

  • 使用对齐参数调用avcodec_fill_audio_frame 1 以忽略对齐。

希望这会帮助别人:)