正确的 AVFrame RGB 值
Posted
技术标签:
【中文标题】正确的 AVFrame RGB 值【英文标题】:Correct RGB values for AVFrame 【发布时间】:2022-01-11 18:48:23 【问题描述】:我必须从 cairo 表面像素数据中填充 ffmpeg AVFrame->数据。我有这个代码:
/* Image info and pixel data */
width = cairo_image_surface_get_width( surface );
height = cairo_image_surface_get_height( surface );
stride = cairo_image_surface_get_stride( surface );
pix = cairo_image_surface_get_data( surface );
for( row = 0; row < height; row++ )
data = pix + row * stride;
for( col = 0; col < width; col++ )
img->video_frame->data[0][row * img->video_frame->linesize[0] + col] = data[0];
img->video_frame->data[1][row * img->video_frame->linesize[1] + col] = data[1];
//img->video_frame->data[2][row * img->video_frame->linesize[2] + col] = data[2];
data += 4;
img->video_frame->pts++;
但是导出的视频中的颜色是错误的。原来的心是红色的。有人可以指出我正确的方向吗?遗憾的是,encode.c 示例毫无用处,并且在 Internet 上存在很多关于 Y、Cr 和 Cb 的混淆,我真的不明白。请随时询问更多详情。非常感谢。
【问题讨论】:
能否请您发布一个完整的代码示例 - 我们可以编译和执行的东西?您可能需要有创意 - 考虑将 8x8 输入图像发布为 C 数组(由代码初始化)。你能描述一下pix
的数据排列吗(是width
、height
和stride
的行主要RGBA)吗? YCbCr像素格式在哪一部分使用?
非常感谢您的回复。我很感激。该代码是 GTK3 GUI 的一部分,它将一系列图片转换为电影。这是我自 2009 年以来一直在开发的项目。遗憾的是,我无法提供代码 sn-p,但该软件是开源的。 cairo 表面为 RGB24。 AV 上下文创建为 AV_PIX_FMT_YUV420P,因为如果我使用 AV_PIX_FMT_RGB24,我会在编码期间收到错误消息:“输入宽度大于步幅”。希望这会有所帮助,请随时询问更多信息。
我目前对 YCbCr 的理解是它是由 Luminance/Red-diff/Blue-diff 组成的,其中 Luminance 是亮度,Red-diff 和 Blue-diff 是色度值,带有关于 Red/green 的信息和蓝/绿分别。它通过将黑白图像与两个色度通道相结合来工作
【参考方案1】:
您需要使用libswscale
将源图像数据从RGB24
转换为YUV420P
。
类似:
int width = cairo_image_surface_get_width( surface );
int height = cairo_image_surface_get_height( surface );
int stride = cairo_image_surface_get_stride( surface );
uint8_t *pix = cairo_image_surface_get_data( surface );
uint8_t *data[1] = pix ;
int linesize[1] = stride ;
struct SwsContext *sws_ctx = sws_getContext(width, height, AV_PIX_FMT_RGB24 ,
width, height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, NULL, NULL, NULL);
sws_scale(sws_ctx, data, linesize, 0, height,
img->video_frame->data, img->video_frame->linesize);
sws_freeContext(sws_ctx);
在此处查看示例:scaling_video
【讨论】:
感谢您的回复。我还使用了 sws_scale,在编码过程中没有错误,但视频甚至无法播放,VLC 在终端窗口中显示了一堆这些无用的消息:[h264 @ 0x7f1508c82700] 位于 POC 不可用 [h264 @ 0x7f1508c9f400] mmco: unref short失败 [h264 @ 0x7f1508cd8f80] 位于 POC 不可用 该示例没有帮助,因为它从 YUV420P 转换,但感谢我很感激。如果您想了解更多信息,我可以将更改提交到 SVN 服务器,您可以看看,它是一个不错的 GUI 和一个不错的软件,可惜被低估了。 @GiuTor 您能否将示例 cairo 图像转储到某个文件并发布格式、宽度和高度? 这段代码对于转储图像是否正确: /* 图像信息和像素数据 */ width = cairo_image_surface_get_width(surface);高度 = cairo_image_surface_get_height( 表面 ); stride = cairo_image_surface_get_stride(surface); pix = cairo_image_surface_get_data(表面);文件 *fp = fopen("cairo_image.raw","w"); fwrite (pix, 4*width, sizeof(pix), fp); fclose(fp);以上是关于正确的 AVFrame RGB 值的主要内容,如果未能解决你的问题,请参考以下文章
如何将像素格式为 AV_PIX_FMT_CUDA 的 FFmpeg AVFrame 转换为像素格式为 AV_PIX_FMT_RGB 的新 AVFrame