FFmpeg学习4:音频格式转换

前段时间,在学习试用FFmpeg播放音频的时候总是有杂音,网上的很多教程是基于之前版本的FFmpeg的,而新的FFmepg3中audio增加了平面(planar)格式,而SDL播放音频是不支持平面格式的,所以通过FFmpeg解码出来的数据不能直接发送到SDL进行播放,需要进行一个格式转换。通过网上一些资料,也能够正确的播放音频了,但是对具体的音频转换过程不是很了解,这里就对FFmpeg的对音频的存储格式及格式转换做个总结。本文主要有以下几个方面的内容:
* AVSampleFormat 音频sample的存储格式
* channel layout 各个通道存储顺序
* 使用FFmpeg对音频数据进行格式转换
* 音频解码API avcodec_decode_audio4在新版中已废弃,替换为使用更为简单的avcodec_send_packetavcodec_receive_frame。本文简单的介绍了该API的使用。

AVSampleFormat

在FFmpeg中使用枚举AVSampleFormat表示音频的采样格式,其声明如下:

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
};

和图像的像素存储格式类似,可以使用8位无符号整数、16位有符号整数、32位有符号整数以及单精度浮点数,双精度浮点数表示一个采样。但是,没有使用
24位的有符号整数,这是因为这些不同的格式使用的是原生的C类型,而C中是没有24位的长度的类型的。

Sample value 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.

对于浮点格式,其值在[-1.0,1.0]之间,任何在该区间之外的值都超过了最大音量的范围。
和YUV的图像格式格式,音频的采样格式分为平面(planar)和打包(packed)两种类型,在枚举值中上半部分是packed类型,后面(有P后缀的)是planar类型。
对于planar格式的,每一个通道的值都有一个单独的plane,所有的plane必须有相同的大小;对于packed类型,所有的数据在同一个数据平面中,不同通道的数据
交叉保存。
另外,在AVFrame中表示音频采样格式的字段format是一个int型,在使用AVSampleFormat时候需要进行一个类型转换,将int转换为AVSampleFormat枚举值。

在头文件samplefmt.h提供了和音频采样格式相关的一些函数,现列举一些如下:
* const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
根据枚举值获取其相应的格式名称(字符串)
* enum AVSampleFormat av_get_sample_fmt(const char *name)
根据格式名字(字符串)获取相应的枚举值
* enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
传入planar类型的采样格式,返回其可转换的packed类型的采样格式。例如传入 AV_SAMPLE_FMT_S32P,其返回值为 AV_SAMPLE_FMT_S32
* enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt)
和上面函数类似,不同的是传入的是packed类型的格式。
* int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt
判断一个采样格式是不是planar类型的
* int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
每个采样值所占用的字节数
* int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,enum AVSampleFormat sample_fmt, int align)
根据输入的参数,计算其所占用空间的大小(字节数)。linesize可设为null,align是buff空间的对齐格式(0=default,1 = no alignment)

channel_layout

从上面可知,sample有两种类型的存储方式:平面(planar&

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值