问题
当我将一个aac的音频文件解码为原始的PCM数据后,使用ffplay播放测试是否成功时,需要提供给ffplay 采样率,通道数,PCM的格式类型 3个参数,否则无法播放!
所以使用ffprobe 查看原来的aac文件信息,这里我们可以看到采样率为 44100Hz, 通道为stereo表示双通道,后面跟着一个 fltp,这是个什么格式呢?

我们先看一下ffmpeg支持那些PCM格式,使用下面的命名查看
ffmpeg -formats | findstr PCM可以看到PCM的格式还是很多,具体我们选择哪一种呢?总不能一个个的试吧!

le --- 小端模式 be --- 大端模式
答案
答案就在ffmpeg源码中,首先我们看下关于采样格式的定义,它定义在FFmpeg/libavutil/samplefmt.h文件中。根据位深度,是否有符号,打包类型,定义了12种类型,AV_SAMPLE_FMT_NONE表示未知类型,最后的AV_SAMPLE_FMT_NB表示样本格式个数为12个。
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_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar
    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};而我们在命令行看到是fltp跟它有什么关系呢?具体对照表如下,定义在FFmpeg/libavutil/samplefmt.c文件中
typedef struct SampleFmtInfo {
    char name[8];
    int bits;
    int planar;
    enum AVSampleFormat altform; ///< planar<->packed alternative form
} SampleFmtInfo;
/** this table gives more information about formats */
static const SampleFmtInfo sample_fmt_info[AV_SAMPLE_FMT_NB] = {
    [AV_SAMPLE_FMT_U8]   = { .name =   "u8", .bits =  8, .planar = 0, .altform = AV_SAMPLE_FMT_U8P  },
    [AV_SAMPLE_FMT_S16]  = { .name =  "s16", .bits = 16, .planar = 0, .altform = AV_SAMPLE_FMT_S16P },
    [AV_SAMPLE_FMT_S32]  = { .name =  "s32", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_S32P },
    [AV_SAMPLE_FMT_S64]  = { .name =  "s64", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_S64P },
    [AV_SAMPLE_FMT_FLT]  = { .name =  "flt", .bits = 32, .planar = 0, .altform = AV_SAMPLE_FMT_FLTP },
    [AV_SAMPLE_FMT_DBL]  = { .name =  "dbl", .bits = 64, .planar = 0, .altform = AV_SAMPLE_FMT_DBLP },
    [AV_SAMPLE_FMT_U8P]  = { .name =  "u8p", .bits =  8, .planar = 1, .altform = AV_SAMPLE_FMT_U8   },
    [AV_SAMPLE_FMT_S16P] = { .name = "s16p", .bits = 16, .planar = 1, .altform = AV_SAMPLE_FMT_S16  },
    [AV_SAMPLE_FMT_S32P] = { .name = "s32p", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_S32  },
    [AV_SAMPLE_FMT_S64P] = { .name = "s64p", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_S64  },
    [AV_SAMPLE_FMT_FLTP] = { .name = "fltp", .bits = 32, .planar = 1, .altform = AV_SAMPLE_FMT_FLT  },
    [AV_SAMPLE_FMT_DBLP] = { .name = "dblp", .bits = 64, .planar = 1, .altform = AV_SAMPLE_FMT_DBL  },
};这里我们看到fltp表示的格式是AV_SAMPLE_FMT_FLTP,位深32位,数据存储方式位planar,与之相反的packed格式为AV_SAMPLE_FMT_FLT。
好了我们已经知道fltp表示的是float 32位数据,我们再结合前面的PCM的格式数据,再根据我们的电脑的大小端类型知道,我们需要传递的参数是应该就是 f32le
好了,我们使用ffplay 播放试试看
ffplay -ar 44100 -ac 2 -f f32le -i audio.pcm结果如下,完美播放:

备注
这里有一个planar,之前有一篇关于视频的采样格式的文章,这里我们需要注意的是音频样本的内存
存储方式。
planar --- 每个音频通道(channel )一个平面,例如双通道data[0] = LLL..., data[1] = RRR...
linesize表示单个plane的buffer size(以字节为单位)
packed --- 不管几个音频通道都只是用一个平面,数据交错存储,data[0] = LRLRLR...
linesize表示单个plane的buffer size(以字节为单位)
其他
查看aac解码器信息
ffmpeg -h decoder=aac



















