AVFrame 宽度、高度和线条大小之间的混淆

Luc*_*lla 2 c++ opengl ffmpeg

我试图理解 AVFrame,特别是 linesize 属性。

这是我解码的 AVFrame 属性:

width = 640 
height= 360

linesize[0] = 640
linesize[1] = 320
linesize[2] = 320
Run Code Online (Sandbox Code Playgroud)

这是 YUV 420 平面图像 ( AV_PIX_FMT_YUVJ420P)

我正在阅读这段代码,这是处理 AVFrame 属性的部分:

int linesize = qAbs(m_format.renderFrame->linesize[i]);
AVRational widthRational = params.yuvwidths[i];
AVRational heightRational = params.yuvheights[i];
int width = linesize * widthRational.num / widthRational.den;
int height = m_format.renderFrame->height * heightRational.num / heightRational.den;
glTexImage2D ( GL_TEXTURE_2D, 0, params.yuvInternalformat[i],width ,height, 0, params.yuvGlFormat[i], params.dataType, NULL);
        
Run Code Online (Sandbox Code Playgroud)

其中,对于 YUV420P,widthRationalheightRational1/1和,1/1对于i=0,和1/21/2对于i = 1,2。并且yuvInternalformat并且yuvGlFormat总是GL_RED

代码中有几件事我无法理解:

为什么他取绝对值linesize?可以linesize为负数吗?文档中没有任何关于负值的内容。我明白他为什么在 中进行分数乘法height,但为什么在 中linesize?不应该linesize是平面图像的实际图像width,因此不需要乘法吗?

那么什么是linesize、应该如何width计算height才能使用glTexImage2D呢?

sza*_*ary 5

高度是以像素为单位的高度,没有什么特别的。

宽度是显示图像的宽度(以像素为单位)。

步长(Stride)或行大小(linesize)是内存中每行像素的宽度。线条尺寸必须等于或大于宽度。例如,1920x1080 的行大小通常为 1088,以使步幅可被 16 整除,但最右边的 8 列像素不会显示。

色度子采样是另一回事。对于某些颜色格式,例如 yuv420p,第一个平面(黑白平面)是全分辨率,但 2 个颜色平面是四分之一分辨率(半高和半宽)。在我的 1920x1080 示例中,这使得第二个和第三个平面的高度为 960,宽度为 540,步幅(最有可能)为 544 (544 = ceil(1080/16)*16)。

其他颜色格式(例如 RGB 或 yuv444p)的第二个和第三个平面的尺寸与第一个平面相同。