如何使用 libav/ffmpeg 编码 24 位音频?
How to encode 24-bit audio with libav/ffmpeg?
这是来自 libavutil/samplefmt.h
的代码片段:
/**
* 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;
使用AV_SAMPLE_FMT_S32并设置ctx->bits_per_raw_sample为24。然后音频需要在32位整数的MSB中,即。最后用0填充。
这是来自 libavutil/samplefmt.h
的代码片段:
/**
* 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;
使用AV_SAMPLE_FMT_S32并设置ctx->bits_per_raw_sample为24。然后音频需要在32位整数的MSB中,即。最后用0填充。