FFmpeg api 在使用 422 或 420 色度子采样和 SD 分辨率时生成失真图像

问题描述

我创建了一个基于 FFmpeg api 的应用程序。应用程序读取视频帧,进行一些处理,然后将处理后的视频帧写入新文件。该应用程序在大多数情况下都运行良好。但是,当应用程序配置为使用 420 或 422 色度子采样和 SD 分辨率 (720x480) 时,我面临着奇怪的输出。当使用具有 HD 分辨率 (1920x1080) 的 420 或 422 色度子采样时,输出结果很好。对于失真的输出,我可以看到问题出在二次采样通道上。 Y 通道看起来不错,但 Cr 和 Cb 似乎失真了。

我没有在编码器中使用任何特定的编解码器选项,并且可以使用 prores 或 hevc 编解码器复制该问题。如果我输出到原始二进制视频文件,我看不到任何问题,确认问题发生在编码期间的某个时间,并且在二次采样后输入 AVFrame 的二进制数据格式正确。

图片如下:

Original input video

Correct output video (HD)

Distorted output video (SD)

解决方法

因此看来 FFmpeg 要求您遵守一些内存对齐约束。 FFmpeg 可能会根据您使用的像素格式、高度和宽度为每行添加一些填充(请参阅 AVFrame linesize)。我解决这个问题的方法是在调用 av_frame_alloc 并设置格式、高度和宽度后提取 linesize。您想计算每行的实际数据大小(基于宽度和像素大小),然后将光标推到 linesize 的倍数,以便您可以阅读下一行。另一件需要注意的事情是,这种行为主要在平面格式上被注意到,而不是在打包格式上。