Mik*_*ike 4 rgb yuv video-encoding webm libvpx
我有一个应用程序,生成一堆jpgs,我需要变成一个webm视频.我正在尝试将jggs中的rgb数据转换为vpxenc示例.我可以在输出视频中看到原始jpgs的基本形状,但是所有内容都是浅绿色(即使是应该是黑色的像素大约是绿色的一半),并且每隔一条扫描线都有一些垃圾.
我正在尝试提供VPX_IMG_FMT_YV12数据,我假设其结构如下:
对于每个帧8位Y数据每个2x2 V块的8位平均值每个2x2 U块的8位平均值
这是一个源图像和即将发布的视频的屏幕截图:
我完全有可能错误地进行RGB-> YV12转换,但即使我只编码8位Y数据并将U和V块设置为0,视频看起来也差不多.我基本上通过这个等式运行我的RGB数据:
// (R, G, and B are 0-255)
float y = 0.299f*R + 0.587f*G + 0.114f*B;
float v = (R-y)*0.713f;
float u = (B-v)*0.565f;
Run Code Online (Sandbox Code Playgroud)
..然后,以产生2×2为U和V,我写入vpxenc滤波值,我只是做(A + B + C + d)/ 4,其中a,b,C,d为的U或V值每个2x2像素块.
所以我想知道:
是否有更简单的方法(在代码中)获取RGB数据并将其提供给vpx_codec_encode以获得一个不错的webm视频?
我的RGB-> YV12转换错了吗?
任何帮助将不胜感激.
freefallr:当然.这是代码.请注意,它将RGB-> YUV转换为适当位置,并将YV12输出放入pFullYPlane/pDownsampledUPlane/pDownsampledVPlane.当我修改他们的vpxenc样本以使用这些数据时,此代码生成了漂亮的WebM视频.
void RGB_To_YV12( unsigned char *pRGBData, int nFrameWidth, int nFrameHeight, void *pFullYPlane, void *pDownsampledUPlane, void *pDownsampledVPlane )
{
int nRGBBytes = nFrameWidth * nFrameHeight * 3;
// Convert RGB -> YV12. We do this in-place to avoid allocating any more memory.
unsigned char *pYPlaneOut = (unsigned char*)pFullYPlane;
int nYPlaneOut = 0;
for ( int i=0; i < nRGBBytes; i += 3 )
{
unsigned char B = pRGBData[i+0];
unsigned char G = pRGBData[i+1];
unsigned char R = pRGBData[i+2];
float y = (float)( R*66 + G*129 + B*25 + 128 ) / 256 + 16;
float u = (float)( R*-38 + G*-74 + B*112 + 128 ) / 256 + 128;
float v = (float)( R*112 + G*-94 + B*-18 + 128 ) / 256 + 128;
// NOTE: We're converting pRGBData to YUV in-place here as well as writing out YUV to pFullYPlane/pDownsampledUPlane/pDownsampledVPlane.
pRGBData[i+0] = (unsigned char)y;
pRGBData[i+1] = (unsigned char)u;
pRGBData[i+2] = (unsigned char)v;
// Write out the Y plane directly here rather than in another loop.
pYPlaneOut[nYPlaneOut++] = pRGBData[i+0];
}
// Downsample to U and V.
int halfHeight = nFrameHeight >> 1;
int halfWidth = nFrameWidth >> 1;
unsigned char *pVPlaneOut = (unsigned char*)pDownsampledVPlane;
unsigned char *pUPlaneOut = (unsigned char*)pDownsampledUPlane;
for ( int yPixel=0; yPixel < halfHeight; yPixel++ )
{
int iBaseSrc = ( (yPixel*2) * nFrameWidth * 3 );
for ( int xPixel=0; xPixel < halfWidth; xPixel++ )
{
pVPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 2];
pUPlaneOut[yPixel * halfWidth + xPixel] = pRGBData[iBaseSrc + 1];
iBaseSrc += 6;
}
}
}
Run Code Online (Sandbox Code Playgroud)