RGB帧编码 - FFmpeg / libav

时间:2014-01-31 16:06:07

标签: video encoding ffmpeg video-encoding libavcodec

我正在学习视频编码&在FFmpeg解码。我在page上尝试了代码示例(仅限视频编码和解码部分)。这里创建的虚拟图像是YCbCr格式。如何通过创建RGB帧来实现类似的编码?我被困在:

首先,如何创建这个RGB虚拟帧?

其次,如何编码呢?使用哪种编解码器?他们中的大多数只使用YUV420p ......

编辑:我有一个YCbCr编码器和解码器,如page所示。问题是,我的数据库中有RGB帧序列,我需要对其进行编码。但编码器适用于YCbCr。所以,我想知道以某种方式将RGB帧转换为YCbCr(或YUV420P),然后对它们进行编码。 在解码结束时,我得到解码的YCbCr帧,然后将它们转换回RGB。怎么继续呢?

我确实尝试过swscontext,但转换的帧会丢失颜色信息并且还会缩放错误。我想过用两个for循环和colorspace conversion formulae手动完成它 但我无法使用FFmpeg / libav库访问帧的单个像素!就像在OpenCV中一样,我们可以通过以下方式轻松访问它:Mat img(x,y)但这里没有这样的东西!我完全是这个领域的新人......

有人可以帮助我吗?

非常感谢!

2 个答案:

答案 0 :(得分:4)

转换的最佳方式是使用swscale。你可以手动完成,但你的版本会慢一些。没有用于访问ffmpeg中像素数据的API。您必须直接访问缓冲区YUV420P是平面格式,因此第一个缓冲区是Y平面,每个像素1个字节。 U / V平面为4个像素的1个字节。这是因为在假设亮度(Y)通道包含最多信息的情况下,U和V平面被缩放到Y平面的1/4大小。

00250     picture->data[0] = picture_buf;
00251     picture->data[1] = picture->data[0] + size;
00252     picture->data[2] = picture->data[1] + size / 4;

其次,让我们看看颜色空间转换。

void YUVfromRGB(double& Y, double& U, double& V, const double R, const double G, const double B)
{
  Y =  0.257 * R + 0.504 * G + 0.098 * B +  16;
  U = -0.148 * R - 0.291 * G + 0.439 * B + 128;
  V =  0.439 * R - 0.368 * G - 0.071 * B + 128;
}

插入一些虚拟值:

R = 255, G = 255, B = 255
Y =  235

R = 0, G = 0, B = 0
Y = 16

如您所见,范围0 - > 255被压缩到16 - > 235.因此,我们已经证明RGB颜色空间中存在一些在(数字)YUV颜色空间中不存在的颜色。那么我们为什么要使用YUV呢?这就是彩色空间电视一直使用到1950年,当时彩色通道(U / V)被添加到现有的黑白通道(Y)。

在这里阅读更多内容: http://en.wikipedia.org/wiki/YCbCr

缩放错误是您没有正确使用swscale。很可能你不了解线路步幅: http://msdn.microsoft.com/en-us/library/windows/desktop/aa473780(v=vs.85).aspx

我不知道任何在RGB色彩空间中运行的视频编解码器。您可以使用libswscale在RGB和YUV之间转换(稍微有损)。

此视频将说明: https://xiph.org/video/vid2.shtml

答案 1 :(得分:1)

我认为可以对原始视频进行编码。在您所指的样本中。您必须使用CODEC_ID_RAWVIDEO在avcodec_find_encoder中查找原始图像的编码器。在编解码器上下文pix_fmt中,即c-> pix_fmt,您可以使用PIX_FMT_RGB24。最后,您需要创建虚拟rgb24帧而不是YCbCr。