【问题标题】:Configure AVCodecContext structure to encode from raw PCM to u-law配置 AVCodecContext 结构以从原始 PCM 编码到 u-law
【发布时间】:2017-10-13 22:56:43
【问题描述】:

我正在尝试将原始 PCM 音频数据编码为 u-law,这听起来很奇怪(当它听起来时......)。我不太了解如何初始化我的 AVCodecContext 结构(以及我的输入 AVFrame)。

这是我的参数:

  • 输入:PCM(16 位签名)、MONO、44.1kHz(采样率)(来自我的 Android 设备 MIC)

  • 所需输出:G.711 u-law、MONO、8kHz(采样率)、64 kbits/s(比特率)(来自我的输出目标设备的文档)

我也知道我的输入 nb 个样本,这就是我拥有的所有信息。

所以我像这样初始化我的AVCodecContext:

AVCodec* pCodec = avcodec_find_encoder(AV_CODEC_ID_PCM_MULAW);
// ...
AVCodecContext* pCodecContext = avcodec_alloc_context3(pCodec);
// ...
// Do I need input or output params in following lines?
pCodecContext->channels = 1:
pCodecContext->channel_layout = AV_CH_LAYOUT_MONO;
pCodecContext->sample_rate = 8000;
pCodecContext->bit_rate = 64000
pCodecContext->sample_fmt = AV_SAMPLE_FMT_S16;

我的AVFrames 喜欢:

AVFrame* pFrame = av_frame_alloc();
pFrame->channels = 1;
pFrame->channel_layout = AV_CH_LAYOUT_MONO;
pFrame->sample_rate = 44100;
pFrame->format = AV_SAMPLE_FMT_S16;
pFrame->nb_samples = /*my audio data samples count*/;
avcodec_fill_audio_frame(pFrame, 1, AV_SAMPLE_FMT_S16, /*my audio data*/, /*my audio data size*/, 0);

然后,我使用avcodec_send_frame() 和avcodec_receive_packet() 进行编码。

所以我的问题是我不确定是否必须在不同的参数中输入或输出所需的值。可能我必须以某种方式编码,然后使用swresample lib“重新采样”。但是现在,我很确定我没有正确编码。请问有什么建议吗?谢谢!

【问题讨论】:

    标签: c++ audio ffmpeg encode avcodec


    【解决方案1】:

    G.711 要求您的输入为 8kHz 单声道(例如 sample_rate 为 8000)。因此,在将原始 pcm 音频样本传递给 libavcodec 之前,您必须使用 swresample 或任何其他可以做到这一点的库将它们转换为 8kHz。如果您自己捕获原始 pcm,通常可以从 os sound api 请求 8kHz 采样率。

    我很确定在 Android 设备上您可以请求 8kHz 音频。 G.711 是如此简单的编解码器,您不需要 libavcodec。您可以使用任何可用的g711.c,只需为每个样品调用linear2alaw 或linear2ulaw。基本上linear2alaw 或linear2ulaw 将每个16 位音频样本转换为一个字节的g711 比特流。

    您还应该确保正确初始化您的AVCodecContext:

    pCodecContext->channels = 1;
    pCodecContext->channel_layout = AV_CH_LAYOUT_MONO; 
    ...
    

    【讨论】:

    • 感谢您的回答,我了解我的问题并且可以使用这些知识。我认为 libavcodec 能够以不同的采样率“编码”!我需要 libavcodec,因为我可以拥有其他支持格式的其他输出设备。
    • 8kHz采样率的U-law编解码器(AVCodec编码器)打不开正常吗?
    • @N0un avcodec_find_encoder(AV_CODEC_ID_PCM_MULAW); 返回 NULL 吗?
    • @N0un 注意,还有pCodecContext->channels(1) 好像很奇怪,应该是pCodecContext->channels = 1;
    • 抱歉,我在编辑中修正了语法。不,它不返回 NULL,但 pCodec->samples_fmts() 只返回一种格式:AV_SAMPLE_FMT_S16。如果在AV_SAMPLE_FMT_U8 中对我的音频样本进行预重采样,这是一个问题,不是吗? pCodecContext->sample_fmt是编码的强制参数吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多