FFmpeg AVFrame变量的YUV Frame旋转

来源:互联网 发布:ubuntu修改文件夹权限 编辑:程序博客网 时间:2024/06/06 03:11

最近在用FFmpeg和DShow框架交互,在Frame的层面处理一些数据。

需要从DShow FIlter获取数据,然后用buffer初始化AVFrame,再交给FFmpeg的Filter处理。

我在Dshow Filter上做了输入输出格式的兼容处理,支持输入输出IYUV、YV12、NV12、RGB24、RGB32等五种格式。(其中RGB24格式的输入还是有点问题,做sws_scale转换的时候,会报内存读写错误,但偶尔却可以正常通过)

这个时候会发现,ffmpeg下用buffer初始化AVFrame数据的时候,如果是RGB色系的,会发生一些问题。

1.RGB24:上下颠倒、色差

2.RGB32:上下颠倒

对于DShow中的RGB24,FFmpeg实际应该用BGR24初始化AVFrame。否则输出的buffer数据使用RGB24色彩空间读取,会发生明显的色彩偏差。

对于所有RGB色彩,FFmpeg直接取出,都会发现图像是“上下颠倒”


我在做DShow交互的时候发现,如果输入输出都是RGB色彩空间,排除色差的问题(使用BGR24就解决了),“上下颠倒”的问题就不会产生。

因此,如何对于输入输出仅有一方是RGB色系的颠倒现象进行纠正,同时不过多的影响时间复杂度,是最主要需要解决的问题。

这篇博文,主要是借这个问题,描述一下如何在ffmpeg里面进行图像颠倒操作。


在面临需要进行图像旋转、反转操作的时候,通常还需要兼顾效率问题(时间复杂度、空间复杂度)。

如果不需要考虑上述问题,那么进行一次O(n)的逐字节拷贝,完全可以解决任意的旋转、反转问题。

不过,既然FFmpeg会存在RGB的倒转问题,那么就一定有可以高速便捷处理的办法。


首先,分析一下问题。存在使RGB发生倒转现象的操作,应该是av_image_fill_arrays填充Frame的操作。但同时也注意到,如果使用了sws_scale发生从RGB——YUV——RGB的时候,翻转就正常了。

因此,我尝试借助ffmpeg现成的函数进行一些高效的处理:

1.进行两次av_image_fill_arrays

2.进行两次sws_scale,获得正常的YUV

然而上述的操作全部都失败了


后来,经过不懈的查找,发现仅需要修改AVFrame的linesize属性,就可以让AVFrame在ffmpeg中的处理被视为图像反转。

    //关键是这一步,上下翻转图像    pFrame_->data[0] += pFrame_->linesize[0] * (codec_->height - 1);    pFrame_->linesize[0] = -pFrame_->linesize[0];    pFrame_->data[1]+= pFrame_->linesize[1] * (codec_->height / 2 - 1);    pFrame_->linesize[1] = -pFrame_->linesize[1];    pFrame_->data[2] += pFrame_->linesize[2]* (codec_->height / 2 - 1);    pFrame_->linesize[2] = -pFrame_->linesize[2];   //图像翻转完之后回到正常的读写步骤         length = av_image_copy_to_buffer((unsigned char*)vopBuf, 640*480*4,                                                (const uint8_t* const *)pFrame_->data, (const int*) pFrame_->linesize,                                                codec_->pix_fmt, codec_->width, codec_->height, 1);