primitives: added RGB to AVC444YUV converter
This commit is contained in:
parent
c0f4b6bcad
commit
13a60ae138
@ -190,6 +190,11 @@ typedef pstatus_t (*__YUV444SplitToYUV420_t)(
|
|||||||
BYTE* pMainDst[3], const UINT32 dstMainStep[3],
|
BYTE* pMainDst[3], const UINT32 dstMainStep[3],
|
||||||
BYTE* pAuxDst[3], const UINT32 srcAuxStep[3],
|
BYTE* pAuxDst[3], const UINT32 srcAuxStep[3],
|
||||||
const prim_size_t* roi);
|
const prim_size_t* roi);
|
||||||
|
typedef pstatus_t (*__RGBToAVC444YUV_t)(
|
||||||
|
const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||||
|
BYTE* pMainDst[3], const UINT32 dstMainStep[3],
|
||||||
|
BYTE* pAuxDst[3], const UINT32 dstAuxStep[3],
|
||||||
|
const prim_size_t* roi);
|
||||||
typedef pstatus_t (*__andC_32u_t)(
|
typedef pstatus_t (*__andC_32u_t)(
|
||||||
const UINT32* pSrc,
|
const UINT32* pSrc,
|
||||||
UINT32 val,
|
UINT32 val,
|
||||||
@ -240,6 +245,7 @@ typedef struct
|
|||||||
__YUV420CombineToYUV444_t YUV420CombineToYUV444;
|
__YUV420CombineToYUV444_t YUV420CombineToYUV444;
|
||||||
__YUV444SplitToYUV420_t YUV444SplitToYUV420;
|
__YUV444SplitToYUV420_t YUV444SplitToYUV420;
|
||||||
__YUV444ToRGB_8u_P3AC4R_t YUV444ToRGB_8u_P3AC4R;
|
__YUV444ToRGB_8u_P3AC4R_t YUV444ToRGB_8u_P3AC4R;
|
||||||
|
__RGBToAVC444YUV_t RGBToAVC444YUV;
|
||||||
} primitives_t;
|
} primitives_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -703,7 +703,252 @@ static pstatus_t general_RGBToYUV420_8u_P3AC4R(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INLINE pstatus_t general_RGBToAVC444YUV_BGRX(
|
||||||
|
const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||||
|
BYTE* pDst1[3], const UINT32 dst1Step[3],
|
||||||
|
BYTE* pDst2[3], const UINT32 dst2Step[3],
|
||||||
|
const prim_size_t* roi)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Note:
|
||||||
|
* Read information in function general_RGBToAVC444YUV_ANY below !
|
||||||
|
*/
|
||||||
|
|
||||||
|
UINT32 x, y, n, numRows, numCols;
|
||||||
|
BOOL evenRow = TRUE;
|
||||||
|
BYTE *b1, *b2, *b3, *b4, *b5, *b6, *b7;
|
||||||
|
const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep;
|
||||||
|
|
||||||
|
numRows = (roi->height + 1) & ~1;
|
||||||
|
numCols = (roi->width + 1) & ~1;
|
||||||
|
|
||||||
|
for (y = 0; y < numRows; y++, evenRow = !evenRow)
|
||||||
|
{
|
||||||
|
const BYTE* src = y < roi->height ? pSrc + y * srcStep : pMaxSrc;
|
||||||
|
UINT32 i = y >> 1;
|
||||||
|
|
||||||
|
b1 = pDst1[0] + y * dst1Step[0];
|
||||||
|
|
||||||
|
if (evenRow)
|
||||||
|
{
|
||||||
|
b2 = pDst1[1] + i * dst1Step[1];
|
||||||
|
b3 = pDst1[2] + i * dst1Step[2];
|
||||||
|
b6 = pDst2[1] + i * dst2Step[1];
|
||||||
|
b7 = pDst2[2] + i * dst2Step[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = (i & ~7) + i;
|
||||||
|
b4 = pDst2[0] + dst2Step[0] * n;
|
||||||
|
b5 = b4 + 8 * dst2Step[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 0; x < numCols; x += 2)
|
||||||
|
{
|
||||||
|
BYTE R, G, B, Y1, Y2, U1, U2, V1, V2;
|
||||||
|
|
||||||
|
B = src[0];
|
||||||
|
G = src[1];
|
||||||
|
R = src[2];
|
||||||
|
|
||||||
|
Y1 = Y2 = RGB2Y(R, G, B);
|
||||||
|
U1 = U2 = RGB2U(R, G, B);
|
||||||
|
V1 = V2 = RGB2V(R, G, B);
|
||||||
|
|
||||||
|
if (x + 1 < roi->width)
|
||||||
|
{
|
||||||
|
B = src[4];
|
||||||
|
G = src[5];
|
||||||
|
R = src[6];
|
||||||
|
Y2 = RGB2Y(R, G, B);
|
||||||
|
U2 = RGB2U(R, G, B);
|
||||||
|
V2 = RGB2V(R, G, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
*b1++ = Y1;
|
||||||
|
*b1++ = Y2;
|
||||||
|
|
||||||
|
if (evenRow)
|
||||||
|
{
|
||||||
|
*b2++ = U1;
|
||||||
|
*b3++ = V1;
|
||||||
|
*b6++ = U2;
|
||||||
|
*b7++ = V2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*b4++ = U1;
|
||||||
|
*b4++ = U2;
|
||||||
|
*b5++ = V1;
|
||||||
|
*b5++ = V2;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PRIMITIVES_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE pstatus_t general_RGBToAVC444YUV_ANY(
|
||||||
|
const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||||
|
BYTE* pDst1[3], const UINT32 dst1Step[3],
|
||||||
|
BYTE* pDst2[3], const UINT32 dst2Step[3],
|
||||||
|
const prim_size_t* roi)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Note: According to [MS-RDPEGFX 2.2.4.4 RFX_AVC420_BITMAP_STREAM] the
|
||||||
|
* width and height of the MPEG-4 AVC/H.264 codec bitstream MUST be aligned
|
||||||
|
* to a multiple of 16.
|
||||||
|
* Hence the passed destination YUV420/CHROMA420 buffers must have been
|
||||||
|
* allocated accordingly !!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [MS-RDPEGFX 3.3.8.3.2 YUV420p Stream Combination] defines the following "Bx areas":
|
||||||
|
*
|
||||||
|
* YUV420 frame (main view):
|
||||||
|
* B1: From Y444 all pixels
|
||||||
|
* B2: From U444 all pixels in even rows with even columns
|
||||||
|
* B3: From V444 all pixels in even rows with even columns
|
||||||
|
*
|
||||||
|
* Chroma420 frame (auxillary view):
|
||||||
|
* B45: From U444 and V444 all pixels from all odd rows
|
||||||
|
* (The odd U444 and V444 rows must be interleaved in 8-line blocks in B45 !!!)
|
||||||
|
* B6: From U444 all pixels in even rows with odd columns
|
||||||
|
* B7: From V444 all pixels in even rows with odd columns
|
||||||
|
*
|
||||||
|
* Microsoft's horrible unclear description in MS-RDPEGFX translated to pseudo code looks like this:
|
||||||
|
*
|
||||||
|
* for (y = 0; y < fullHeight; y++)
|
||||||
|
* {
|
||||||
|
* for (x = 0; x < fullWidth; x++)
|
||||||
|
* {
|
||||||
|
* B1[x,y] = Y444[x,y];
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* for (y = 0; y < halfHeight; y++)
|
||||||
|
* {
|
||||||
|
* for (x = 0; x < halfWidth; x++)
|
||||||
|
* {
|
||||||
|
* B2[x,y] = U444[2 * x, 2 * y];
|
||||||
|
* B3[x,y] = V444[2 * x, 2 * y];
|
||||||
|
* B6[x,y] = U444[2 * x + 1, 2 * y];
|
||||||
|
* B7[x,y] = V444[2 * x + 1, 2 * y];
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* for (y = 0; y < halfHeight; y++)
|
||||||
|
* {
|
||||||
|
* yU = (y / 8) * 16; // identify first row of correct 8-line U block in B45
|
||||||
|
* yU += (y % 8); // add offset rows in destination block
|
||||||
|
* yV = yU + 8; // the corresponding v line is always 8 rows ahead
|
||||||
|
*
|
||||||
|
* for (x = 0; x < fullWidth; x++)
|
||||||
|
* {
|
||||||
|
* B45[x,yU] = U444[x, 2 * y + 1];
|
||||||
|
* B45[x,yV] = V444[x, 2 * y + 1];
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
const UINT32 bpp = GetBytesPerPixel(srcFormat);
|
||||||
|
UINT32 x, y, n, numRows, numCols;
|
||||||
|
BOOL evenRow = TRUE;
|
||||||
|
BYTE *b1, *b2, *b3, *b4, *b5, *b6, *b7;
|
||||||
|
const BYTE* pMaxSrc = pSrc + (roi->height - 1) * srcStep;
|
||||||
|
|
||||||
|
numRows = (roi->height + 1) & ~1;
|
||||||
|
numCols = (roi->width + 1) & ~1;
|
||||||
|
|
||||||
|
for (y = 0; y < numRows; y++, evenRow = !evenRow)
|
||||||
|
{
|
||||||
|
const BYTE* src = y < roi->height ? pSrc + y * srcStep : pMaxSrc;
|
||||||
|
UINT32 i = y >> 1;
|
||||||
|
|
||||||
|
b1 = pDst1[0] + y * dst1Step[0];
|
||||||
|
|
||||||
|
if (evenRow)
|
||||||
|
{
|
||||||
|
b2 = pDst1[1] + i * dst1Step[1];
|
||||||
|
b3 = pDst1[2] + i * dst1Step[2];
|
||||||
|
b6 = pDst2[1] + i * dst2Step[1];
|
||||||
|
b7 = pDst2[2] + i * dst2Step[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = (i & ~7) + i;
|
||||||
|
b4 = pDst2[0] + dst2Step[0] * n;
|
||||||
|
b5 = b4 + 8 * dst2Step[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 0; x < numCols; x += 2)
|
||||||
|
{
|
||||||
|
BYTE R, G, B, Y1, Y2, U1, U2, V1, V2;
|
||||||
|
UINT32 color;
|
||||||
|
|
||||||
|
color = ReadColor(src, srcFormat);
|
||||||
|
SplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
|
||||||
|
|
||||||
|
Y1 = Y2 = RGB2Y(R, G, B);
|
||||||
|
U1 = U2 = RGB2U(R, G, B);
|
||||||
|
V1 = V2 = RGB2V(R, G, B);
|
||||||
|
|
||||||
|
if (x + 1 < roi->width)
|
||||||
|
{
|
||||||
|
color = ReadColor(src + bpp, srcFormat);
|
||||||
|
SplitColor(color, srcFormat, &R, &G, &B, NULL, NULL);
|
||||||
|
|
||||||
|
Y2 = RGB2Y(R, G, B);
|
||||||
|
U2 = RGB2U(R, G, B);
|
||||||
|
V2 = RGB2V(R, G, B);
|
||||||
|
}
|
||||||
|
|
||||||
|
*b1++ = Y1;
|
||||||
|
*b1++ = Y2;
|
||||||
|
|
||||||
|
if (evenRow)
|
||||||
|
{
|
||||||
|
*b2++ = U1;
|
||||||
|
*b3++ = V1;
|
||||||
|
*b6++ = U2;
|
||||||
|
*b7++ = V2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*b4++ = U1;
|
||||||
|
*b4++ = U2;
|
||||||
|
*b5++ = V1;
|
||||||
|
*b5++ = V2;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += 2 * bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PRIMITIVES_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE pstatus_t general_RGBToAVC444YUV(
|
||||||
|
const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||||
|
BYTE* pDst1[3], const UINT32 dst1Step[3],
|
||||||
|
BYTE* pDst2[3], const UINT32 dst2Step[3],
|
||||||
|
const prim_size_t* roi)
|
||||||
|
{
|
||||||
|
switch (srcFormat)
|
||||||
|
{
|
||||||
|
case PIXEL_FORMAT_BGRA32:
|
||||||
|
case PIXEL_FORMAT_BGRX32:
|
||||||
|
return general_RGBToAVC444YUV_BGRX(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return general_RGBToAVC444YUV_ANY(pSrc, srcFormat, srcStep, pDst1, dst1Step, pDst2, dst2Step, roi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !PRIMITIVES_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
void primitives_init_YUV(primitives_t* prims)
|
void primitives_init_YUV(primitives_t* prims)
|
||||||
{
|
{
|
||||||
@ -713,5 +958,6 @@ void primitives_init_YUV(primitives_t* prims)
|
|||||||
prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
|
prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
|
||||||
prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
|
prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
|
||||||
prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
|
prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
|
||||||
|
prims->RGBToAVC444YUV = general_RGBToAVC444YUV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user