samplefmt.c阅读笔记
2014-03-09 23:27
323 查看
知识点一:
* 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.
这解释了音频smaple_fmt中什么是planar,什么是packed。
知识点二:
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
};
此枚举的AV_SAMPLE_FMT_NB定义得很巧妙。从-1开始,那么最后一个枚举的值就是这个枚举内可枚举的情况的总数。
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_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_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 },
};
结构体SampleFmtInfo的定义及全局变量sample_fmt_info的定义也很巧妙,如果没有这样的定义,那么对不同sample format的属性的获取就得通过
大量的if else了。
av_get_sample_fmt_name
av_get_sample_fmt
等函数的实现证明了这点。
知识点三:
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
enum AVSampleFormat sample_fmt, int align)
{
int line_size;
int sample_size = av_get_bytes_per_sample(sample_fmt);
int planar = av_sample_fmt_is_planar(sample_fmt);
/* validate parameter ranges */
if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
return AVERROR(EINVAL);
/* auto-select alignment if not specified */
if (!align) {
align = 1;
nb_samples = FFALIGN(nb_samples, 32);
}
/* check for integer overflow */
if (nb_channels > INT_MAX / align ||
(int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)
return AVERROR(EINVAL);
line_size = planar ? FFALIGN(nb_samples * sample_size, align) :
FFALIGN(nb_samples * sample_size * nb_channels, align);
if (linesize)
*linesize = line_size;
return planar ? line_size * nb_channels : line_size;
}
1、大小=采样数×每个采样的大小×通道数。如果是planar,则先对齐再×通道数。
2、从此函数的参数有nb_samples及nb_channels及解码后的AVFrame中的采样个数与通道参数可基本推测出采样个数指的都是单通道。
当然:
AVFrame的
/**
* number of audio samples (per channel) described by this frame
*/
int nb_samples;
这个描述更明确了。
3、此函数除了获得函数,还得到linesize。linesize为每个plan数据字节大小
知识点四:
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)
{
int ch, planar, buf_size, line_size;
planar = av_sample_fmt_is_planar(sample_fmt);
buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples,
sample_fmt, align);
if (buf_size < 0)
return buf_size;
audio_data[0] = (uint8_t *)buf;
for (ch = 1; planar && ch < nb_channels; ch++)
audio_data[ch] = audio_data[ch-1] + line_size;
if (linesize)
*linesize = line_size;
#if FF_API_SAMPLES_UTILS_RETURN_ZERO
return 0;
#else
return buf_size;
#endif
}
1、将buf中的音频数据转成由audio_data指向。
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples,
int nb_channels, enum AVSampleFormat sample_fmt)
{
int planar = av_sample_fmt_is_planar(sample_fmt);
int planes = planar ? nb_channels : 1;
int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
int data_size = nb_samples * block_align;
int fill_char = (sample_fmt == AV_SAMPLE_FMT_U8 ||
sample_fmt == AV_SAMPLE_FMT_U8P) ? 0x80 : 0x00;
int i;
offset *= block_align;
for (i = 0; i < planes; i++)
memset(audio_data[i] + offset, fill_char, data_size);
return 0;
}
1、如果为AV_SAMPLE_FMT_U8或AV_SAMPLE_FMT_U8P,则设置成0x80,其它格式则将数据设置为0x00
总结:
AVFrame中的data数组存放着指向音频数据的指针;
如果音频的samplefmt为planar格式,则,每个channel对应一个plannar(平面),每个plannar对应data
,如第一个音频通道数据由data[0]的指针指向,第二个音频通道的数据由data[1]的指针指向。linesize为一个平面的音频数据字节大小。
如果音频的samplefmt为packed格式,则,只有一个平面,对应的数据在data[0]对应的指针中指向。linesize即为音频数据的字节大小。多个通道的音频采样交错排布。如采样1左声道,采样1右声道,采样2左声道,采样2右声道......
AVFrame中的nb_samples字段为每个音频通道所拥有的采样数。
* 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.
这解释了音频smaple_fmt中什么是planar,什么是packed。
知识点二:
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
};
此枚举的AV_SAMPLE_FMT_NB定义得很巧妙。从-1开始,那么最后一个枚举的值就是这个枚举内可枚举的情况的总数。
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_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_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 },
};
结构体SampleFmtInfo的定义及全局变量sample_fmt_info的定义也很巧妙,如果没有这样的定义,那么对不同sample format的属性的获取就得通过
大量的if else了。
av_get_sample_fmt_name
av_get_sample_fmt
等函数的实现证明了这点。
知识点三:
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples,
enum AVSampleFormat sample_fmt, int align)
{
int line_size;
int sample_size = av_get_bytes_per_sample(sample_fmt);
int planar = av_sample_fmt_is_planar(sample_fmt);
/* validate parameter ranges */
if (!sample_size || nb_samples <= 0 || nb_channels <= 0)
return AVERROR(EINVAL);
/* auto-select alignment if not specified */
if (!align) {
align = 1;
nb_samples = FFALIGN(nb_samples, 32);
}
/* check for integer overflow */
if (nb_channels > INT_MAX / align ||
(int64_t)nb_channels * nb_samples > (INT_MAX - (align * nb_channels)) / sample_size)
return AVERROR(EINVAL);
line_size = planar ? FFALIGN(nb_samples * sample_size, align) :
FFALIGN(nb_samples * sample_size * nb_channels, align);
if (linesize)
*linesize = line_size;
return planar ? line_size * nb_channels : line_size;
}
1、大小=采样数×每个采样的大小×通道数。如果是planar,则先对齐再×通道数。
2、从此函数的参数有nb_samples及nb_channels及解码后的AVFrame中的采样个数与通道参数可基本推测出采样个数指的都是单通道。
当然:
AVFrame的
/**
* number of audio samples (per channel) described by this frame
*/
int nb_samples;
这个描述更明确了。
3、此函数除了获得函数,还得到linesize。linesize为每个plan数据字节大小
知识点四:
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)
{
int ch, planar, buf_size, line_size;
planar = av_sample_fmt_is_planar(sample_fmt);
buf_size = av_samples_get_buffer_size(&line_size, nb_channels, nb_samples,
sample_fmt, align);
if (buf_size < 0)
return buf_size;
audio_data[0] = (uint8_t *)buf;
for (ch = 1; planar && ch < nb_channels; ch++)
audio_data[ch] = audio_data[ch-1] + line_size;
if (linesize)
*linesize = line_size;
#if FF_API_SAMPLES_UTILS_RETURN_ZERO
return 0;
#else
return buf_size;
#endif
}
1、将buf中的音频数据转成由audio_data指向。
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples,
int nb_channels, enum AVSampleFormat sample_fmt)
{
int planar = av_sample_fmt_is_planar(sample_fmt);
int planes = planar ? nb_channels : 1;
int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
int data_size = nb_samples * block_align;
int fill_char = (sample_fmt == AV_SAMPLE_FMT_U8 ||
sample_fmt == AV_SAMPLE_FMT_U8P) ? 0x80 : 0x00;
int i;
offset *= block_align;
for (i = 0; i < planes; i++)
memset(audio_data[i] + offset, fill_char, data_size);
return 0;
}
1、如果为AV_SAMPLE_FMT_U8或AV_SAMPLE_FMT_U8P,则设置成0x80,其它格式则将数据设置为0x00
总结:
AVFrame中的data数组存放着指向音频数据的指针;
如果音频的samplefmt为planar格式,则,每个channel对应一个plannar(平面),每个plannar对应data
,如第一个音频通道数据由data[0]的指针指向,第二个音频通道的数据由data[1]的指针指向。linesize为一个平面的音频数据字节大小。
如果音频的samplefmt为packed格式,则,只有一个平面,对应的数据在data[0]对应的指针中指向。linesize即为音频数据的字节大小。多个通道的音频采样交错排布。如采样1左声道,采样1右声道,采样2左声道,采样2右声道......
AVFrame中的nb_samples字段为每个音频通道所拥有的采样数。
相关文章推荐
- PHP中的$this用法
- 基于LoadRunner构建接口测试框架
- ITF Demo代码(用VBScript构建的接口测试框架)
- springmvc和struts2的差别
- Medoo Error的使用:查看错误SQL信息
- Oracle视图
- javaweb之Cookie显示商品的浏览记录和Cookie的常见应用有哪些
- Unity3D不能创建工程
- EasyUI入门
- 技术人生“白天求生存,晚上谋发展”
- 扫描算法 编程珠玑
- 基于LoadRunner构建接口测试框架
- hdu 3394 图的双联通分量
- 《C++对象模型》读后感——前言
- Erlang 的新数据结构 map 浅析
- 适配iOS 6.1 和7.0
- 数据库设计(1)
- 对链表进行归并排序
- Thinking in BigData(14)大数据之DM经典模型(5)
- dll文件32位64位检测工具以及Windows文件夹SysWow64的坑