FFmpeg API 之 AVSampleFormat

  • 音频采样格式所描述的数据总是使用本地字节序。因此,采样数据可以用本地C语言类型来表示。虽然 有符号的32位 采样格式是一种非常常见的原始音频数据格式,但由于C语言中没有对应的类型,因此在FFmpeg中也就没有这种采样格式。

  • 浮点数类型的音频采样格式基于如下设定:全部音量的取值范围为 [-1.0~1.0] ,它表示了完整的音量范围。任何超出这个范围的值都在音量可取范围之外。

  • 音频采样数据的布局

    对于 planar 采样格式来说,每个通道都有自己独立的数据缓冲区,通常称为一个平面(planar),和表示该缓冲区大小的 linesize 变量,其单位是 byte,对于所有平面来说,其大小必须是一样的。

    对于 packed 采样格式来说,仅有一个缓冲区以及表示其大小的linesize变量。每次采样,都按照通道顺序依次将其采样值保存到缓冲区中。

 

AVSampleFormat 表示采样格式。如上面所述,无24位整数的采样格式。

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

以下是对采样格式的一些常见函数:

//获取采样格式的字符串名称
const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt);

//根据字符串名称获取采样格式
enum AVSampleFormat av_get_sample_fmt(const char *name);

//获取参数指定的采样格式可替换的采样格式,即planar <-> packed互换
//参数planar指定我们要获取的采样类型
//如果参数就是我们想要的,那么原样返回
enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar);
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt);
enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt);

//返回采样格式的描述,即“名称  位深”
//如果sample_fmt是一个负数,则返回表头一样的东西:”name depth“
char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt);

//返回采样格式一次采样的字节数 
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt);

//查看采样格式是planar还是packed
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt);

//返回保存音频数据所需的字节数
//linesize用于保存返回的值
//成功返回0,失败返回负的错误值
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,enum AVSampleFormat sample_fmt, int align);

 

我们知道,AVFrame既可以保存视频数据又可以保存音频数据。

而为了保存原始的音频数据和视频数据,FFmpeg也提供了其他的数据结构。

如表示一张图片的AVPicture:

typedef struct AVPicture {
    attribute_deprecated
    uint8_t *data[AV_NUM_DATA_POINTERS];    ///< pointers to the image data planes
    attribute_deprecated
    int linesize[AV_NUM_DATA_POINTERS];     ///< number of bytes per line
} AVPicture;

又如,av_image 一系列函数所操作的对象,就是 uint8_t *data[4] 和 int linesize[4]。

而在这里保存音频的结构也是类似的,即多块缓冲区,和一个表示这些缓冲区大小的Int值。

以上的不同之处在于,视频只要4块缓冲区就绝对够用了,而音频则不一定。还有一点就是视频不同缓存区,或者说不同数据平面的大小可能是不相等的,而音频各个数据平面的大小必定是一样的,因此有一个表达平面数据大小的int值就可以了。

这就是AVFrame,用于保存视频的缓冲区,用于保存音频的缓冲区之间的相同和不同点。

 

有了以上的知识,我们就可以轻易理解下面的函数了。

//将buf中的采样数据,填充到音频缓冲区audio_data和linesize中
//buf中的数据长度至少是 av_samples_get_buffer_size大小
int av_samples_fill_arrays(uint8_t **audio_data, int *linesize,
                           const uint8_t *buf,
                           int nb_channels, int nb_samples,
                           enum AVSampleFormat sample_fmt, 
                           int  align);

//分配存储音频采样数据的缓冲区
//保存缓存区指针的数组是用户分配的
//audio_data和linesize为输出数据
int av_samples_alloc(uint8_t **audio_data, int *linesize,
                     int nb_channels,
                     int nb_samples, 
                     enum AVSampleFormat sample_fmt, int align);

//分配存储采样数据的缓冲区
//不同的是这个函数会将保存数据的指针数组也分配
int av_samples_alloc_array_and_samples(uint8_t ***audio_data, 
                                       int *linesize, 
                                       int nb_channels,
                                       int nb_samples, 
                                       enum AVSampleFormat 
                                       sample_fmt,
                                       int align);

//拷贝采样数据
int av_samples_copy(uint8_t **dst, uint8_t * const *src,
                    int dst_offset,
                    int src_offset, int nb_samples, 
                    int nb_channels,
                    enum AVSampleFormat sample_fmt);

//以静音数据填充缓冲区
int av_samples_set_silence(uint8_t **audio_data, int offset,
                           int nb_samples,
                           int nb_channels,
                           enum AVSampleFormat sample_fmt);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值