当前位置:网站首页>ffmpeg 像素格式基础知识
ffmpeg 像素格式基础知识
2022-08-05 03:08:00 【hjjdebug】
ffmpeg 像素格式基础知识
----------------------------------------
甲. YUV 颜色空间命名含义
----------------------------------------
Y分量是不压缩的,对UV色度分量进行一定程度的压缩。
YUV4:4:4
YUV4:4:0
YUV4:2:2
YUV4:2:0
YUV4:1:1
YUV4:1:0
具体的含义是什么?
考虑一个4*2的色块,共8个像素,2行(奇数行,偶数行)
第一个值总是被称为4,代表亮度在奇数行偶数行都被采样4次,总是被采样。
第二个值被称为4,2或1, 代表色度数据第一行被采样4次,2次或1次,此处的色度代表U或V
第三个值被称为4,2或1,0, 代表色度数据第二行被采样4次,2次或1次,或0次.
同一种采样方式,数据在内存中的存储又分三种方式:
1.packed: 按YUYVYUYV。。。交织在一起存放
2.planar: 按YYYYY。。。,UUUUU。。。,VVVV。。。分开存放
3.semi_planar: 按YYYY.... UVUVUV....分开存放
定义1:AVPixelFormat: 定义了像素格式 ID
enum AVPixelFormat {
AV_PIX_FMT_NONE = -1,
AV_PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
AV_PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
AV_PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
AV_PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
AV_PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
... //忽略
};
定义2:AVPixFmtDescriptor: 此数据结构定义了图像数据在内存中的组织排列形式
(gdb) ptype av_pix_fmt_descriptors
type = const struct AVPixFmtDescriptor {
const char *name;
uint8_t nb_components;
uint8_t log2_chroma_w;
uint8_t log2_chroma_h;
uint64_t flags;
AVComponentDescriptor comp[4];
const char *alias;
} [198]
这198种像素定义我就不copy了。可参看一下后面“乙部分描述"
下面是其成员的描述:
const char *name : 像素格式名称
uint8_t nb_components: 像素分量数, 取值范围 1 - 4。
例如 AV_PIX_FMT_GRAY8 只有 Y 一个分量,
AV_PIX_FMT_YUV420P 有 Y、U、V 三个分量,
AV_PIX_FMT_NV12 也有 Y、U、V 三个分量,
AV_PIX_FMT_ARGB 有 A、R、G、B 四个分量。
uint8_t log2_chroma_w:水平方向色度子采样因子。
右移的位数. 表示将亮度样本宽度右移多少位能得到色度样本的宽度.
例如对于 yuv420p 格式,若图像分辨率为 1280 x 720,
则亮度样本宽度(水平方向亮度样本数)为 1280,
色度样本宽度(水平方向色度样本数)为 1280/2 = 640,
则 log2_chroma_w 值为 1(右移 1 位)。
uint8_t log2_chroma_h: 垂直方向色度子采样因子。
uint64_t flags: 像素格式标志位组合,
例如如 AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_HWACCEL 。
标志 AV_PIX_FMT_FLAG_BE 表示大端格式.
AV_PIX_FMT_FLAG_HWACCEL 表示此像素格式用于硬解或硬编等硬件加速场合。
AVComponentDescriptor comp[4]
这个成员非常重要。数组的每个元素表示一个分量,注意是一个分量而不是一个 plane,一个 plane 可能含有多个分量
定义3:AVComponentDescriptor, AV分量描述符
(gdb) ptype av_pix_fmt_descriptors[0].comp
type = struct AVComponentDescriptor {
int plane;
int step;
int offset;
int shift;
int depth;
int step_minus1; // deprecated
int depth_minus1; // deprecated
int offset_plus1; // deprecated
} [4]
AVComponentDescriptor 定义了每个分量在内存中的实际组织形式,包含所有细节。
包含成员如下,
int plane : 当前分量位于哪个 plane 中。
例如 p010 格式有三个分量:Y、U、V,两个 plane:Y、UV。
Y plane 的形式为YYYY...,UV plane 的形式为UVUVUV...。
Y 分量的 plane 值是 0, U 分量和 V 分量的 plane 值是 1,U 样本和 V 样本交织存放在 plane 1中。
int step : 步长,表示水平方向连续的两个样本间距是多少个字节(或比特),
如果像素格式是比特流格式(标志 AV_PIX_FMT_FLAG_BITSTREAM 有效),此值表示比特数,否则此值表示字节数。
例如: p010 格式,Y plane 的形式为YYYY...,UV plane 的形式为UVUVUV...,位深是 10,
考虑对齐后,每一个 Y、每一个 U、每一个 V 都占 2 个字节,
因此 Y 分量的 step 是 2(两个 Y 相距两字节),
U 分量的 step 是 4(两个 U 相距 4 字节),
V 分量的 step 也是 4(两个 V 相距 4 字节)。
int offset : 偏移,表示在当前 plane 中,当前分量的第一个样本之前有多少个字节的数据,
如果像素格式是比特流格式(标志 AV_PIX_FMT_FLAG_BITSTREAM 有效),此值表示比特数,否则此值表示字节数。
例如 p010 格式,每一个 U 或 V 都占 2 个字节,第一个 V 样本前有 2 个字节被 U 样本占了,
所以 U 分量的 offset 值是 0,V 分量的 offset 值是 2。
int shift : 右移位数,表示将对应内存单元的值右移多少位可以得到实际值。
例如 p010 格式,位深是 10,而内存对齐后每一个 Y、U、V 样本占 16 bit,
那么 10 位的数据放在 16 位的内存单元中, 是占据高 10 位还是占据低 10 位,即是由 shift 值决定的。
p010 格式中,各分量的 shift 值都是 6 ,表示数据放在高 10 位。
从 Y plane 中获取第一个 Y 样本的值,示意代码如下:
uint8_t y_plane[1280*2];
uint16_t *p_y0 = (uint16_t *)y_plane;
uint16_t y0 = (*p_y0) >> 6;
int depth: 当前分量每个样本的位宽度,即位深。
上述参数中,
plane 表示分量所在的 plane 的序号,
offset 表示多个分量交织存放在同一个 plane 中时的排列顺序(如 p010 格式的 UV plane 中 U 在前 V 在后),
step、shift 和 depth 则是和内存对齐相关
后面的3个成员已经不推荐使用了,从略。
----------------------------------------
乙: ffmpeg 中使用的图像pix_fmts
----------------------------------------
$ffmpeg -pix_fmts , 可以查看所有的pix_fmts,
它关键是定义了下面这张表
static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
[AV_PIX_FMT_YUV420P] = {
.name = "yuv420p",
.nb_components = 3, //3个平面YUV
.log2_chroma_w = 1, //色宽小1倍 (>>1)
.log2_chroma_h = 1, //色高小1倍 (>>1)
.comp = {
{ 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y */ 亮深是8bit, 后3项不用了,前4项plane,step,offset,shift
{ 1, 1, 0, 0, 8, 0, 7, 1 }, /* U */ 色深1是8bit
{ 2, 1, 0, 0, 8, 0, 7, 1 }, /* V */ 色深2是8bit
},
.flags = AV_PIX_FMT_FLAG_PLANAR,
},
[AV_PIX_FMT_YUYV422] = {
.name = "yuyv422",
.nb_components = 3, //3个平面YUV
.log2_chroma_w = 1, //色宽小1倍 (>>1)
.log2_chroma_h = 0, //色高正常 (>>0)
.comp = {
{ 0, 2, 0, 0, 8, 1, 7, 1 }, /* Y */
{ 0, 4, 1, 0, 8, 3, 7, 2 }, /* U */
{ 0, 4, 3, 0, 8, 3, 7, 4 }, /* V */
},
},
.....
}
----------------------------------------
丙: ffmpeg 中使用的音频sample_fmt
----------------------------------------
$ffmpeg -sample_fmts 可以查看所定义的所有的音频采样格式。
关键是在samplefmt.c中, 定义了下面这张表
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 },
};
(gdb) ptype sample_fmt_info
type = const struct SampleFmtInfo {
char name[8];
int bits;
int planar;
enum AVSampleFormat altform;
} [12]
边栏推荐
- PostgreSQL数据库 用navicat 打开表结构的时候报错 cannot update secondarysnapshot during a parallel operation 怎么解决?
- 你要的七夕文案,已为您整理好!
- Everyone in China said data, you need to focus on core characteristic is what?
- Summary of domestic environments supported by SuperMap
- How to transfer a single node of Youxuan database to a cluster
- word column notes
- 627. Change of gender
- How to sort multiple fields and multiple values in sql statement
- 引领数字医学高地,中山医院探索打造未来医院“新范式”
- torch.roll()
猜你喜欢

基于生长的棋盘格角点检测方法
![[Filter tracking] based on matlab unscented Kalman filter inertial navigation + DVL combined navigation [including Matlab source code 2019]](/img/c9/fff226b6d33a773b59a0314a99a788.png)
[Filter tracking] based on matlab unscented Kalman filter inertial navigation + DVL combined navigation [including Matlab source code 2019]

Details such as compiling pretreatment

After the large pixel panorama is completed, what are the promotion methods?

沃谈小知识 |“远程透传”那点事儿

OpenGL 工作原理

2022高处安装、维护、拆除考试题模拟考试题库及在线模拟考试

How to Add Category-Specific Widgets in WordPress

【七夕节】浪漫七夕,代码传情。将爱意变成绚烂的立体场景,给她(他)一个惊喜!(送代码)

你要的七夕文案,已为您整理好!
随机推荐
sql server installation prompts that the username does not exist
如何在WordPress中添加特定类别的小工具
1873. 计算特殊奖金
Use @Mapper to query the partition status of oracle and report an error
Dynamic management of massive service instances
2022-08-04 第六小组 瞒春 学习笔记
2022 High-level installation, maintenance, and removal of exam questions mock exam question bank and online mock exam
QT语言文件制作
VSCode Change Default Terminal how to modify the Default Terminal VSCode
Simple description of linked list and simple implementation of code
How to transfer a single node of Youxuan database to a cluster
The second council meeting of the Dragon Lizard Community was successfully held!Director general election, 4 special consultants joined
2022高处安装、维护、拆除考试题模拟考试题库及在线模拟考试
.NET Application -- Helloworld (C#)
[In-depth study of 4G/5G/6G topic-51]: URLLC-16-"3GPP URLLC related protocols, specifications, and technical principles in-depth interpretation"-11-High reliability technology-2-Link adaptive enhancem
AI + Small Nucleic Acid Drugs | Eleven Completes $22 Million Seed Round Financing
rpc-remote procedure call demo
mysql没法Execute 大拿们求解
private封装
你要的七夕文案,已为您整理好!