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 };
整形Sample的取值范围就是该整数类型的理论取值范围,比如AV_SAMPLE_FMT_U8的取值范围是从0到255,AV_SAMPLE_FMT_S16的取值范围是从-32768到32767.而浮点数有点不太一样,取值范围从-1.0到1.0。 数据类型越大,表示可以用于表示声音的范围越大,听起来也就越“高大上”
AVCodecContext有这几个成员request_channel(过时), request_channel_layout, request_sample_fmt. 通过在解码之前设定这几个成员,libav允许你指定解码后的Sample数据类型。
如果你真这么测试的话,你会发现解码后的Sample类型可能与你指定的不一致。这是因为,每个编码解码器都有支持的类型,比如说AAC编码只支持AV_SAMPLE_FMT_FLTP(在以前的版本上为AV_SAMPLE_FMT_S16),所以你需要在编码解码器支持的类型之上进行指定。
那么怎么才能知道某个编码解码器支持哪些音频采样格式(或者图像格式)呢,还暂时不是很清楚。不过应该有某种机制可以知道。
注意到AVSampleFormat里面还有几种格式以P(Planar,平面)结尾,那它们与不带P的有什么区别呢?当有多个Channel的时候,就有区别了。不带P的只有一个buffer,buffer里面Sample的分布是像这样A1B1A2B2A3B3......其中大写字母代表一个Channel,数字代表每个采样在该Channel里的编号。可以看出所有采样被放到一起(即一个buffer),不同的Channel被均匀的分布在其中。而带P的是像这样A1A2A3......B1B2B3......不同Channel各占一个buffer,且每个buffer长度一样。
音频解码之后,需要发送到第三方的音频输出库进行播放。可是这些播放库不一定支持libav的所有格式,前面说过AAC编码只会输出float planar类型的采样,那要怎样在不支持float planar的音频输出设备(比如Windows的WaveOut)上输出呢?有两种方法(其实是一种,两种方法原理一样),一个是采用libav的resample API(我试了半天,程序老是会crash),另外一种就是自己根据上面说到的布局来手动解决了。