【问题标题】:How to encode 24-bit audio with libav/ffmpeg?如何使用 libav/ffmpeg 编码 24 位音频?
【发布时间】:2015-05-21 18:36:30
【问题描述】:

这是来自libavutil/samplefmt.h的代码sn-p:

/**
 * Audio Sample Formats
 *
 * @par
 * The data described by the sample format is always in native-endian order.
 * Sample values can be expressed by native C types, hence the lack of a signed
 * 24-bit sample format even though it is a common raw audio data format.
 *
 * @par
 * The floating-point formats are based on full volume being in the range
 * [-1.0, 1.0]. Any values outside this range are beyond full volume level.
 *
 * @par
 * The data layout as used in av_samples_fill_arrays() and elsewhere in Libav
 * (such as AVFrame in libavcodec) is as follows:
 *
 * @par
 * For planar sample formats, each audio channel is in a separate data plane,
 * and linesize is the buffer size, in bytes, for a single plane. All data
 * planes must be the same size. For packed sample formats, only the first data
 * plane is used, and samples for each channel are interleaved. In this case,
 * linesize is the buffer size, in bytes, for the 1 plane.
 */
enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double

    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar

    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

它特别提到缺少 24 位,即使它是一种常见的原始音频数据格式。那么如果我使用 libav/ffmpeg 导出到音频文件,我将如何使用 24 位音频?

导出音频文件如下所示:

AVCodec *codec = get_codec();
AVOutputFormat *oformat = get_output_format();
AVFormatContext *fmt_ctx = avformat_alloc_context();
assert(fmt_ctx);
int err = avio_open(&fmt_ctx->pb, get_output_filename(), AVIO_FLAG_WRITE);
assert(err >= 0);
fmt_ctx->oformat = oformat;
AVStream *stream = avformat_new_stream(fmt_ctx, codec);
assert(stream);
AVCodecContext *codec_ctx = stream->codec;
codec_ctx->bit_rate = get_export_bit_rate();

// How to set this to 24 bit instead of 32?
codec_ctx->sample_fmt = AV_SAMPLE_FMT_S32;

codec_ctx->sample_rate = get_sample_rate();
codec_ctx->channel_layout = get_channel_layout()
codec_ctx->channels = get_channel_count();
codec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;

【问题讨论】:

    标签: c ffmpeg libav


    【解决方案1】:

    使用 AV_SAMPLE_FMT_S32 并将 ctx->bits_per_raw_sample 设置为 24。音频需要在 32 位整数的 MSB 中,即。最后用 0 填充。

    【讨论】:

    • 为什么不是 LSB?那么 3 字节值将等于 4 字节值。
    • 因为那样它将是不同的格式。这样一来,你就可以把它当作 32 位来处理,从而简化了流程。
    • 另外,您如何确定编解码器是否支持 24 位音频?
    • 0x123456 == 0x00123456。这在我看来就像 LSB 是匹配的,而 MSB 是零。您是说要将 24 位转换为 32 位,您会将 0x123456 转换为 0x12345600
    • 根据我的测试结果,在将样本传递给 libav/ffmpeg 之前,您确实必须将0x123456 转换为0x12345600。这与将其视为 32 位相反 - not 移动值更简单。
    猜你喜欢
    • 2013-12-24
    • 2014-04-23
    • 2021-01-07
    • 1970-01-01
    • 2014-02-06
    • 2014-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多