BOOL YV12RGB24(BYTE *yuv, BYTE *rgb)
{
if (!yuv || !rgb)
return FALSE;
BYTE* yData = yuv;
BYTE* vData = yuv + frameWidth*frameHeight*5/4;
BYTE* uData = yuv + frameWidth*frameHeight;
if (!uData || !vData)
return FALSE;
for (int iRow = 0; iRow < frameHeight; iRow++)
{
for (int jCol = 0; jCol < frameWidth; jCol++)
{
int Y = yData[iRow*frameWidth + jCol];
int U = uData[(iRow / 2)*(frameWidth / 2) + (jCol / 2)];
int V = vData[(iRow / 2)*(frameWidth / 2) + (jCol / 2)];
int R = Y + (U - 128) + (((U - 128) * 103) >> 8);
int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);
int B = Y + (V - 128) + (((V - 128) * 198) >> 8);
// r分量值
R = R<0 ? 0 : R;
rgb[3 * (iRow*frameWidth + jCol) + 2] = R > 255 ? 255 : R;
// g分量值
G = G<0 ? 0 : G;
rgb[3 * (iRow*frameWidth + jCol) + 1] = G>255 ? 255 : G;
// b分量值
B = B<0 ? 0 : B;
rgb[3 * (iRow*frameWidth + jCol) + 0] = B>255 ? 255 : B;
}
}
return TRUE;
}
//算法优化加速
BOOL YV12RGB24(BYTE *yuv, BYTE *rgb)
{
if (!yuv || !rgb)
return FALSE;
BYTE* yData = yuv;
BYTE* vData = yuv + frameWidth*frameHeight + frameWidth/2 * frameHeight/2;
BYTE* uData = yuv + frameWidth*frameHeight;
if (!uData || !vData)
return FALSE;
BYTE *pRGB = rgb;
for (int iRow = 0; iRow < frameHeight; iRow++)
{
int iIndex = (iRow >> 1)*(frameWidth >> 1);
for (int jCol = 0; jCol < frameWidth; jCol++)
{
int Y = yData[iRow*frameWidth + jCol];
int U = uData[iIndex + (jCol >> 1)];
int V = vData[iIndex + (jCol >> 1)];
int R = Y + (U - 128) + (((U - 128) * 103) >> 8);
int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);
int B = Y + (V - 128) + (((V - 128) * 198) >> 8);
// b分量值
if (B >= 0 && B <= 255)
*pRGB++ = B;
else *pRGB++ = B < 0 ? 0 : 255;
// g分量值
if (G >= 0 && G <= 255)
*pRGB++ = G;
else *pRGB++ = G < 0 ? 0 : 255;
// r分量值
if (R >= 0 && R <= 255)
*pRGB++ = R;
else *pRGB++ = R < 0 ? 0 : 255;
}
}
return TRUE;
}
//查找表加速
static int __s_r_1370705v[256] = {0};
static int __s_b_1732446u[256] = {0};
static int __s_g_337633u[256] = {0};
static int __s_g_698001v[256] = {0};
/* 初始化YUV转RGB转换对照表 */
static bool initYUV2RGBTabel()
{
for (int i = 0; i < 256; i++) {
__s_r_1370705v[i] = (1.370705 * (i-128));
__s_b_1732446u[i] = (1.732446 * (i-128));
__s_g_337633u[i] = (0.337633 * (i-128));
__s_g_698001v[i] = (0.698001 * (i-128));
}
return true;
}
void YUV420ToRGBA(uint8_t* pYUV, int width, int height, uint8_t* pRGBA) {
const int frameSize = width * height;
const int chromaSize = frameSize >> 2;
const int halfWidth = width >> 1;
uint8_t* yData = pYUV;
uint8_t* uData = pYUV + frameSize;
uint8_t* vData = pYUV + frameSize + chromaSize;
for (int iRow = 0; iRow < height; iRow++) {
int iIndex = (iRow >> 1)*halfWidth;
for (int jCol = 0; jCol < width; jCol++) {
int uvIndex = iIndex + (jCol >> 1);
int Y = *yData++;
int U = uData[uvIndex];
int V = vData[uvIndex];/*
int R = Y + (U - 128) + (((U - 128) * 103) >> 8);
int G = Y - (((V - 128) * 88) >> 8) - (((U - 128) * 183) >> 8);
int B = Y + (V - 128) + (((V - 128) * 198) >> 8);*/
int R = Y + __s_r_1370705v[V];
int G = Y - __s_g_337633u[U] - __s_g_698001v[V];
int B = Y + __s_b_1732446u[U];
*pRGBA++ = (B < 0 ? 0 : (B > 255 ? 255 : B));
*pRGBA++ = (G < 0 ? 0 : (G > 255 ? 255 : G));
*pRGBA++ = (R < 0 ? 0 : (R > 255 ? 255 : R));
*pRGBA++ = 0xFF;
}
}
}
void I420ToNV21(uint8_t *pSrcData, uint8_t *pDstData, int nWidth, int nHeight)
{
int nFrameSize = nWidth*nHeight;
uint8_t *pSrcData_U = pSrcData + nFrameSize;
uint8_t *pSrcData_V = pSrcData + nFrameSize + (nFrameSize >> 2);
uint8_t *pDstData_UV = pDstData + nFrameSize;
memcpy(pDstData, pSrcData, nFrameSize);//y分量
for(int i = 0, j = 0; i < (nFrameSize >> 2); i++, j += 2)
{
pDstData_UV[j] = pSrcData_U[i];//u分量
pDstData_UV[j+1] = pSrcData_V[i];//v分量
}
}
#include "libyuv.h"
int yuvlen = nWidth * nHeight * 3 / 2;
uchar *yuv21 = (uchar *) malloc(yuvlen);
if (yuv21) {
libyuv::ARGBToNV21(rgba, nWidth * 4, yuv21, nWidth, yuv21 + nWidth * nHeight, nWidth, nWidth, nHeight);
free(yuv21);
}
//注:libyuv比ffmpeg快三倍以上