一 测试环境
机型:Intel(R) Xeon(R) Gold 5218
ffmpeg版本4.3-dev
解码视频分辨率 720x1280 , 解码后 AVFrame linesize 768
解码视频分辨率 480x640, 解码后AVFrame linesize 512
二 linesize计算过程
avcodec_default_get_buffer2
-->update_frame_pool()
-->video_get_buffer()
video_get_buffer()-->
for (i = 0; i < 4 && pool->pools[i]; i++) {
pic->linesize[i] = pool->linesize[i];
由上面代码可见,AVFrame的linesize源自于 pool的linesize
三 pool 的 linesize计算过程
update_frame_pool()
case AVMEDIA_TYPE_VIDEO: {
int linesize[4];
int w = frame->width;
int h = frame->height;
int unaligned;
ptrdiff_t linesize1[4];
size_t size[4];
avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
do {
// NOTE: do not align linesizes individually, this breaks e.g. assumptions
// that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2
ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
if (ret < 0)
goto fail;
// increase alignment of w for next try (rhs gives the lowest bit set in w)
w += w & ~(w - 1);
unaligned = 0;
for (i = 0; i < 4; i++)
unaligned |= linesize[i] % pool->stride_align[i];
} while (unaligned);
for (i = 0; i < 4; i++)
linesize1[i] = linesize[i];
ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1);
if (ret < 0)
goto fail;
for (i = 0; i < 4; i++) {
pool->linesize[i] = linesize[i]; //这里赋值给pool的linesize
linesize列表 通过 av_image_fill_linesizes获取,基本就是等于 width。
循环中
w += w & ~(w - 1); //每次将最低有效二进制位+1,这样做的目的,比如当前是16的整数倍,调整为32的整数倍。然后64的整数倍。
直到最终对 stride_align[i]取余为0.
avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align);
函数获取 stride_align
for (i = 0; i < 4; i++)
linesize_align[i] = STRIDE_ALIGN;
#if HAVE_SIMD_ALIGN_64
define STRIDE_ALIGN 64 /* AVX-512 */
#elif HAVE_SIMD_ALIGN_32
define STRIDE_ALIGN 32
#elif HAVE_SIMD_ALIGN_16
define STRIDE_ALIGN 16
#else
define STRIDE_ALIGN 8
#endif
当机器支持avx512, STRIDE_ALIGN 64.
总结:ffmpeg的AVFrame linesize对齐方式和机器支持的simd有关,avx512就是64字节,avx256就是32字节