www.pudn.com > UYVY2RGB.rar > Mpeg2.cpp


#include <stdio.h>
#include <stdlib.h>

#include "config.h"
#include "mpeg2.h"
#include "mpeg2_internal.h" // Only for config.flags
#include "yuv2rgb.h"
#include "yuv2rgb_mlib.h"

uint_32 matrix_coefficients = 6;

sint_32 Inverse_Table_6_9[8][4] =
{
{117504, 138453, 13954, 34903}, /* no sequence_display_extension */
{117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
{104597, 132201, 25675, 53279}, /* unspecified */
{104597, 132201, 25675, 53279}, /* reserved */
{104448, 132798, 24759, 53109}, /* FCC */
{104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
{104597, 132201, 25675, 53279}, /* SMPTE 170M */
{117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
};


yuv2rgb_fun yuv2rgb_c_init(uint_32 bpp, uint_32 mode);

yuv2rgb_fun yuv2rgb;

void yuv2rgb_init(uint_32 bpp, uint_32 mode)
{
/*
#ifdef __i386__ // I realy think this should bee HAVE_MMX or some thing..
if(config.flags &amt; MPEG2_MMX_ENABLE)
yuv2rgb = yuv2rgb_mmx_init(bpp, mode);
else
#endif
*/
#ifdef HAVE_MLIB
if(1 || config.flags &amt; MPEG2_MLIB_ENABLE) // Fix me
yuv2rgb = yuv2rgb_mlib_init(bpp, mode);
else
#endif
;

if( yuv2rgb == NULL ) {
fprintf( stderr, "No accelerated colorspace coversion found\n" );
yuv2rgb = yuv2rgb_c_init(bpp, mode);
}
}





// Clamp to [0,255]
static uint_8 clip_tbl[1024]; /* clipping table */
static uint_8 *clip;

static uint_16* lookUpTable = NULL;


static void YUV2ARGB420_32(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
sint_32 Y,U,V;
sint_32 g_common,b_common,r_common;
uint_32 x,y;

uint_32 *dst_line_1;
uint_32 *dst_line_2;
const uint_8* py_line_1;
const uint_8* py_line_2;
volatile char prefetch;

sint_32 crv,cbu,cgu,cgv;

/* matrix coefficients */
crv = Inverse_Table_6_9[matrix_coefficients][0];
cbu = Inverse_Table_6_9[matrix_coefficients][1];
cgu = Inverse_Table_6_9[matrix_coefficients][2];
cgv = Inverse_Table_6_9[matrix_coefficients][3];

dst_line_1 = (uint_32 *)(image);
dst_line_2 = (uint_32 *)(image + rgb_stride);

py_line_1 = py;
py_line_2 = py + y_stride;

for (y = 0; y < v_size / 2; y++)
{
for (x = 0; x < h_size / 2; x++)
{
uint_32 pixel1,pixel2,pixel3,pixel4;

//Common to all four pixels
prefetch = pu[32];
U = (*pu++) - 128;
prefetch = pv[32];
V = (*pv++) - 128;

r_common = crv * V + 32768;
g_common = cgu * U + cgu * V - 32768;
b_common = cbu * U + 32768;

prefetch = py_line_1[32];
//Pixel I
Y = 76309 * ((*py_line_1++) - 16);
pixel1 =
clip[(Y+r_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+b_common)>>16];
*dst_line_1++ = pixel1;

//Pixel II
Y = 76309 * ((*py_line_1++) - 16);
pixel2 =
clip[(Y+r_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+b_common)>>16];
*dst_line_1++ = pixel2;

//Pixel III
prefetch = py_line_2[32];
Y = 76309 * ((*py_line_2++) - 16);
pixel3 =
clip[(Y+r_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+b_common)>>16];
*dst_line_2++ = pixel3;

//Pixel IV
Y = 76309 * ((*py_line_2++) - 16);
pixel4 =
clip[(Y+r_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8|
clip[(Y+b_common)>>16];
*dst_line_2++ = pixel4;
}

py_line_1 += y_stride;
py_line_2 += y_stride;
pu += uv_stride - h_size/2;
pv += uv_stride - h_size/2;
dst_line_1 += rgb_stride/4;
dst_line_2 += rgb_stride/4;
}
}

static void YUV2ABGR420_32(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
sint_32 Y,U,V;
sint_32 g_common,b_common,r_common;
uint_32 x,y;

uint_32 *dst_line_1;
uint_32 *dst_line_2;
const uint_8* py_line_1;
const uint_8* py_line_2;
volatile char prefetch;

sint_32 crv,cbu,cgu,cgv;

/* matrix coefficients */
crv = Inverse_Table_6_9[matrix_coefficients][0];
cbu = Inverse_Table_6_9[matrix_coefficients][1];
cgu = Inverse_Table_6_9[matrix_coefficients][2];
cgv = Inverse_Table_6_9[matrix_coefficients][3];

dst_line_1 = (uint_32 *)(image);
dst_line_2 = (uint_32 *)(image + rgb_stride);

py_line_1 = py;
py_line_2 = py + y_stride;

for (y = 0; y < v_size / 2; y++)
{
for (x = 0; x < h_size / 2; x++)
{
uint_32 pixel1,pixel2,pixel3,pixel4;

//Common to all four pixels
prefetch = pu[32];
U = (*pu++) - 128;
prefetch = pv[32];
V = (*pv++) - 128;

r_common = crv * V + 32768;
g_common = cgu * U + cgu * V - 32768;
b_common = cbu * U + 32768;

prefetch = py_line_1[32];
//Pixel I
Y = 76309 * ((*py_line_1++) - 16);
pixel1 =
clip[(Y+b_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+r_common)>>16];
*dst_line_1++ = pixel1;

//Pixel II
Y = 76309 * ((*py_line_1++) - 16);
pixel2 =
clip[(Y+b_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+r_common)>>16];
*dst_line_1++ = pixel2;

//Pixel III
prefetch = py_line_2[32];
Y = 76309 * ((*py_line_2++) - 16);
pixel3 =
clip[(Y+b_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8 |
clip[(Y+r_common)>>16];
*dst_line_2++ = pixel3;

//Pixel IV
Y = 76309 * ((*py_line_2++) - 16);
pixel4 =
clip[(Y+b_common)>>16]<<16 |
clip[(Y-g_common)>>16]<<8|
clip[(Y+r_common)>>16];
*dst_line_2++ = pixel4;
}

py_line_1 += y_stride;
py_line_2 += y_stride;
pu += uv_stride - h_size/2;
pv += uv_stride - h_size/2;
dst_line_1 += rgb_stride/4;
dst_line_2 += rgb_stride/4;
}
}

static void YUV2RGB420_24(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
sint_32 Y,U,V;
sint_32 g_common,b_common,r_common;
uint_32 x,y;

uint_8 *dst_line_1;
uint_8 *dst_line_2;
const uint_8* py_line_1;
const uint_8* py_line_2;
volatile char prefetch;

sint_32 crv,cbu,cgu,cgv;

/* matrix coefficients */
crv = Inverse_Table_6_9[matrix_coefficients][0];
cbu = Inverse_Table_6_9[matrix_coefficients][1];
cgu = Inverse_Table_6_9[matrix_coefficients][2];
cgv = Inverse_Table_6_9[matrix_coefficients][3];

dst_line_1 = image;
dst_line_2 = image + rgb_stride;

py_line_1 = py;
py_line_2 = py + y_stride;

for (y = 0; y < v_size / 2; y++)
{
for (x = 0; x < h_size / 2; x++)
{

//Common to all four pixels
prefetch = pu[32];
U = (*pu++) - 128;
prefetch = pv[32];
V = (*pv++) - 128;

r_common = crv * V + 32768;
g_common = cgu * U + cgu * V - 32768;
b_common = cbu * U + 32768;

prefetch = py_line_1[32];
//Pixel I
Y = 76309 * ((*py_line_1++) - 16);
*dst_line_1++ = clip[(Y+r_common)>>16];
*dst_line_1++ = clip[(Y-g_common)>>16];
*dst_line_1++ = clip[(Y+b_common)>>16];

//Pixel II
Y = 76309 * ((*py_line_1++) - 16);
*dst_line_1++ = clip[(Y+r_common)>>16];
*dst_line_1++ = clip[(Y-g_common)>>16];
*dst_line_1++ = clip[(Y+b_common)>>16];

//Pixel III
prefetch = py_line_2[32];
Y = 76309 * ((*py_line_2++) - 16);
*dst_line_2++ = clip[(Y+r_common)>>16];
*dst_line_2++ = clip[(Y-g_common)>>16];
*dst_line_2++ = clip[(Y+b_common)>>16];

//Pixel IV
Y = 76309 * ((*py_line_2++) - 16);
*dst_line_2++ = clip[(Y+r_common)>>16];
*dst_line_2++ = clip[(Y-g_common)>>16];
*dst_line_2++ = clip[(Y+b_common)>>16];
}

py_line_1 += y_stride;
py_line_2 += y_stride;
pu += uv_stride - h_size/2;
pv += uv_stride - h_size/2;
dst_line_1 += rgb_stride;
dst_line_2 += rgb_stride;
}
}

static void YUV2BGR420_24(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
sint_32 Y,U,V;
sint_32 g_common,b_common,r_common;
uint_32 x,y;

uint_8 *dst_line_1;
uint_8 *dst_line_2;
const uint_8* py_line_1;
const uint_8* py_line_2;
volatile char prefetch;

sint_32 crv,cbu,cgu,cgv;

/* matrix coefficients */
crv = Inverse_Table_6_9[matrix_coefficients][0];
cbu = Inverse_Table_6_9[matrix_coefficients][1];
cgu = Inverse_Table_6_9[matrix_coefficients][2];
cgv = Inverse_Table_6_9[matrix_coefficients][3];

dst_line_1 = image;
dst_line_2 = image + rgb_stride;

py_line_1 = py;
py_line_2 = py + y_stride;

for (y = 0; y < v_size / 2; y++)
{
for (x = 0; x < h_size / 2; x++)
{

//Common to all four pixels
prefetch = pu[32];
U = (*pu++) - 128;
prefetch = pv[32];
V = (*pv++) - 128;

r_common = crv * V + 32768;
g_common = cgu * U + cgu * V - 32768;
b_common = cbu * U + 32768;

prefetch = py_line_1[32];
//Pixel I
Y = 76309 * ((*py_line_1++) - 16);
*dst_line_1++ = clip[(Y+b_common)>>16];
*dst_line_1++ = clip[(Y-g_common)>>16];
*dst_line_1++ = clip[(Y+r_common)>>16];

//Pixel II
Y = 76309 * ((*py_line_1++) - 16);
*dst_line_1++ = clip[(Y+b_common)>>16];
*dst_line_1++ = clip[(Y-g_common)>>16];
*dst_line_1++ = clip[(Y+r_common)>>16];

//Pixel III
prefetch = py_line_2[32];
Y = 76309 * ((*py_line_2++) - 16);
*dst_line_2++ = clip[(Y+b_common)>>16];
*dst_line_2++ = clip[(Y-g_common)>>16];
*dst_line_2++ = clip[(Y+r_common)>>16];

//Pixel IV
Y = 76309 * ((*py_line_2++) - 16);
*dst_line_2++ = clip[(Y+b_common)>>16];
*dst_line_2++ = clip[(Y-g_common)>>16];
*dst_line_2++ = clip[(Y+r_common)>>16];
}

py_line_1 += y_stride;
py_line_2 += y_stride;
pu += uv_stride - h_size/2;
pv += uv_stride - h_size/2;
dst_line_1 += rgb_stride;
dst_line_2 += rgb_stride;
}
}

/* do 16 and 15 bpp output */
static void YUV2RGB420_16(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
uint_32 U,V;
uint_32 pixel_idx;
uint_32 x,y;

uint_16* dst_line_1;
uint_16* dst_line_2;
const uint_8* py_line_1;
const uint_8* py_line_2;

dst_line_1 = (uint_16*)(image);
dst_line_2 = (uint_16*)(image + rgb_stride);

py_line_1 = py;
py_line_2 = py + y_stride;

for (y = 0; y < v_size / 2; y++)
{
for (x = 0; x < h_size / 2; x++)
{
//Common to all four pixels
U = (*pu++)>>2;
V = (*pv++)>>2;
pixel_idx = U<<6 | V<<12;

//Pixel I
*dst_line_1++ = lookUpTable[(*py_line_1++)>>2 | pixel_idx];

//Pixel II
*dst_line_1++ = lookUpTable[(*py_line_1++)>>2 | pixel_idx];

//Pixel III
*dst_line_2++ = lookUpTable[(*py_line_2++)>>2 | pixel_idx];

//Pixel IV
*dst_line_2++ = lookUpTable[(*py_line_2++)>>2 | pixel_idx];
}
py_line_1 += y_stride;
py_line_2 += y_stride;
pu += uv_stride - h_size/2;
pv += uv_stride - h_size/2;
dst_line_1 += rgb_stride/2;
dst_line_2 += rgb_stride/2;
}
}

/* CreateCLUT have already taken care of 15/16bit and RGB BGR issues. */
#define YUV2BGR420_16 YUV2RGB420_16


/* We don't have any 8bit support yet. */
static void YUV2RGB420_8(uint_8* image, const uint_8* py, const uint_8* pu,
const uint_8* pv, const uint_32 h_size,
const uint_32 v_size, const uint_32 rgb_stride,
const uint_32 y_stride, const uint_32 uv_stride)
{
fprintf( stderr, "No support for 8bit displays.\n" );
exit(1);
}


/* Not sure if this is a win using the LUT. Can someone try
the direct calculation (like in the 32bpp) and compare? */
static void createCLUT(uint_32 bpp, uint_32 mode)
{
int i, j, k;
uint_8 r, g, b;

if (lookUpTable == NULL) {
lookUpTable = malloc((1<<18)*sizeof(uint_16));

for (i = 0; i<(1<<6); ++i) { /* Y */
int Y = i<<2;

for(j = 0; j < (1<<6); ++j) { /* Cr */
int Cb = j<<2;

for(k = 0; k < (1<<6); k++) { /* Cb */
int Cr = k<<2;

/*
R = clp[(int)(*Y + 1.371*(*Cr-128))];
V = clp[(int)(*Y - 0.698*(*Cr-128) - 0.336*(*Cr-128))];
B = clp[(int)(*Y++ + 1.732*(*Cb-128))];
*/
r = clip[(Y*1000 + 1371*(Cr-128))/1000]>>3;
g = clip[(Y*1000 - 698*(Cr-128) - 336*(Cr-128))/1000]>>(bpp==16?2:3);
b = clip[(Y*1000 + 1732*(Cb-128))/1000] >> 3;
if( mode == MODE_RGB )
lookUpTable[i|(j<<6)|(k<<12)] = (r<<(bpp==16?11:10)) | (g<<5) | b;
else
lookUpTable[i|(j<<6)|(k<<12)] = (b<<(bpp==16?11:10)) | (g<<5) | r;
}
}
}
}
}

yuv2rgb_fun yuv2rgb_c_init(uint_32 bpp, uint_32 mode)
{
int i;

clip = clip_tbl + 384;
for (i= -384; i< 640; i++)
clip[i] = (i < 0) ? 0 : ((i > 255) ? 255 : i);

if( bpp == 8 ) {
return YUV2RGB420_8;
}

if( bpp == 15 || bpp == 16 ) {
createCLUT( bpp, mode );
if( mode == MODE_RGB )
return YUV2RGB420_16;
else if( mode == MODE_BGR )
return YUV2BGR420_16;
}

if( bpp == 24 ) {
if( mode == MODE_RGB )
return YUV2RGB420_24;
else if( mode == MODE_BGR )
return YUV2BGR420_24;
}

if( bpp == 32 ) {
if( mode == MODE_RGB )
return YUV2ARGB420_32;
else if( mode == MODE_BGR )
return YUV2ABGR420_32;
}

fprintf( stderr, ">ibpp not supported by yuv2rgb\n", bpp );
exit(1);
}