我正在学习视频编码&在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)但这里没有这样的东西!我完全是这个领域的新人......
有人可以帮助我吗?
非常感谢!
答案 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之间转换(稍微有损)。
答案 1 :(得分:1)
我认为可以对原始视频进行编码。在您所指的样本中。您必须使用CODEC_ID_RAWVIDEO在avcodec_find_encoder中查找原始图像的编码器。在编解码器上下文pix_fmt中,即c-> pix_fmt,您可以使用PIX_FMT_RGB24。最后,您需要创建虚拟rgb24帧而不是YCbCr。