我的问题解释得非常快:我必须使用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
能力因此听起来很正常。
答案 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 以忽略对齐。
希望这会帮助别人:)