在使用FFMPEG处理音频的时候,经常会有AV_SAMPLE_FMT_S16和AV_SAMPLE_FMT_S16P之间的转换,特别是在使用SDL的时候需要转换,今天就要好好研究下。
下面是ffmpeg2.7.1中AVSampleFormat的定义。
/** * Audio sample formats * * - 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. * * - 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. * * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg * (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 };
首先看下planar的含义:
那到底平面格式和非平面格式有什么区别呢?
假设现在有2个通道channel1, channel2.
那么AV_SAMPLE_FMT_S16在内存的格式就为: c1, c2, c1, c2, c1, c2, ....
而AV_SAMPLE_FMT_S16P在内存的格式为: c1, c1, c1,... c2, c2, c2,...
现在就先理解到这里,够用的了。
// 参考:
//1. http://www.xuebuyuan.com/1624234.html
//2. http://stackoverflow.com/questions/18888986/what-is-the-difference-between-av-sample-fmt-s16p-and-av-sample-fmt-s16
AV_SAMPLE_FMT_S16P
is planar signed 16 bit audio, i.e. 2 bytes for each sample which is same for AV_SAMPLE_FMT_S16
.
The only difference is in AV_SAMPLE_FMT_S16
samples of each channel are interleaved i.e. if you have two channel audio then the samples buffer will look like
c1 c1 c2 c2 c1 c1 c2 c2...
where c1
is a sample for channel1 and c2
is sample for channel2.
while for one frame of planar audio you will have something like
c1 c1 c1 c1 .... c2 c2 c2 c2 ..
now how is it stored in AVFrame:
for planar audio:
data[i] will contain the data of channel i (assuming channel 0 is first channel).
however if you have more channels then 8 then data for rest of the channels can be found in extended_data attribute of AVFrame.
for non-planar audio
data[0] will contain the data for all channels in an interleaved manner.