libfreerdp-primitives: add YUV420 to RGB conversion

This commit is contained in:
Marc-André Moreau 2014-09-06 17:10:27 -04:00
parent 73d121dd82
commit 437583aa9a
7 changed files with 197 additions and 175 deletions

View File

@ -164,6 +164,10 @@ typedef pstatus_t (*__RGB565ToARGB_16u32u_C3C4_t)(
UINT32* pDst, INT32 dstStep,
UINT32 width, UINT32 height,
BOOL alpha, BOOL invert);
typedef pstatus_t (*__YUV420ToRGB_8u_P3AC4R_t)(
const BYTE* pSrc[3], INT32 srcStep[3],
BYTE* pDst, INT32 dstStep,
const prim_size_t* roi);
typedef pstatus_t (*__andC_32u_t)(
const UINT32 *pSrc,
UINT32 val,
@ -209,6 +213,7 @@ typedef struct
__RGBToRGB_16s8u_P3AC4R_t RGBToRGB_16s8u_P3AC4R;
__YCoCgRToRGB_8u_AC4R_t YCoCgRToRGB_8u_AC4R;
__RGB565ToARGB_16u32u_C3C4_t RGB565ToARGB_16u32u_C3C4;
__YUV420ToRGB_8u_P3AC4R_t YUV420ToRGB_8u_P3AC4R;
} primitives_t;
#ifdef __cplusplus

View File

@ -25,73 +25,10 @@
#include <winpr/print.h>
#include <winpr/bitstream.h>
#include <freerdp/codec/color.h>
#include <freerdp/primitives.h>
#include <freerdp/codec/h264.h>
static INLINE BYTE clip(int x)
{
if (x < 0) return 0;
if (x > 255) return 255;
return (BYTE) x;
}
static INLINE UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V)
{
BYTE R, G, B;
int Yp, Up, Vp;
Yp = Y * 256;
Up = U - 128;
Vp = V - 128;
R = clip((Yp + (403 * Vp)) >> 8);
G = clip((Yp - (48 * Up) - (120 * Vp)) >> 8);
B = clip((Yp + (475 * Up)) >> 8);
return RGB32(R, G, B);
}
static int g_H264FrameId = 0;
static BOOL g_H264DumpFrames = FALSE;
static void h264_dump_h264_data(BYTE* data, int size)
{
FILE* fp;
char buf[4096];
sprintf_s(buf, sizeof(buf), "/tmp/wlog/bs_%d.h264", g_H264FrameId);
fp = fopen(buf, "wb");
fwrite(data, 1, size, fp);
fflush(fp);
fclose(fp);
}
void h264_dump_yuv_data(BYTE* yuv[], int width, int height, int stride[])
{
FILE* fp;
BYTE* srcp;
char buf[4096];
int j;
sprintf_s(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId);
fp = fopen(buf, "wb");
fwrite("P5\n", 1, 3, fp);
sprintf_s(buf, sizeof(buf), "%d %d\n", width, height);
fwrite(buf, 1, strlen(buf), fp);
fwrite("255\n", 1, 4, fp);
srcp = yuv[0];
for (j = 0; j < height; j++)
{
fwrite(srcp, 1, width, fp);
srcp += stride[0];
}
fflush(fp);
fclose(fp);
}
int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height)
{
UINT32 size;
@ -104,8 +41,11 @@ int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height)
if (size > h264->size)
{
h264->size = size;
h264->data = (BYTE*) realloc(h264->data, h264->size);
memset(h264->data, 0, h264->size);
if (!h264->data)
h264->data = (BYTE*) _aligned_malloc(h264->size, 16);
else
h264->data = (BYTE*) _aligned_realloc(h264->data, h264->size, 16);
}
if (!h264->data)
@ -114,44 +54,6 @@ int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height)
return 1;
}
int freerdp_image_copy_yuv420p_to_xrgb(BYTE* pDstData, int nDstStep, int nXDst, int nYDst,
int nWidth, int nHeight, BYTE* pSrcData[3], int nSrcStep[2], int nXSrc, int nYSrc)
{
int x, y;
BYTE* pDstPixel8;
BYTE *pY, *pU, *pV;
int shift = 1;
pY = pSrcData[0] + (nYSrc * nSrcStep[0]) + nXSrc;
pDstPixel8 = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
for (y = 0; y < nHeight; y++)
{
pU = pSrcData[1] + ((nYSrc + y) >> shift) * nSrcStep[1];
pV = pSrcData[2] + ((nYSrc + y) >> shift) * nSrcStep[1];
for (x = 0; x < nWidth; x++)
{
BYTE Y, U, V;
Y = *pY;
U = pU[(nXSrc + x) >> shift];
V = pV[(nXSrc + x) >> shift];
*((UINT32*) pDstPixel8) = YUV_to_RGB(Y, U, V);
pDstPixel8 += 4;
pY++;
}
pDstPixel8 += (nDstStep - (nWidth * 4));
pY += (nSrcStep[0] - nWidth);
}
return 1;
}
/**
* Dummy subsystem
*/
@ -205,10 +107,13 @@ static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* m
static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
{
int srcStep[3];
prim_size_t roi;
BYTE* pYUVData[3];
DECODING_STATE state;
SBufferInfo sBufferInfo;
SSysMEMBuffer* pSystemBuffer;
primitives_t* prims = primitives_get();
H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData;
if (!sys->pDecoder)
@ -262,20 +167,18 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
if (pSystemBuffer->iFormat != videoFormatI420)
return -1;
/* Convert I420 (same as IYUV) to XRGB. */
if (g_H264DumpFrames)
{
h264_dump_yuv_data(pYUVData, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride);
}
g_H264FrameId++;
if (h264_prepare_rgb_buffer(h264, pSystemBuffer->iWidth, pSystemBuffer->iHeight) < 0)
return -1;
freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0,
h264->width, h264->height, pYUVData, pSystemBuffer->iStride, 0, 0);
roi.width = h264->width;
roi.height = h264->height;
/* convert iStride[2] to srcStep[3] */
srcStep[0] = pSystemBuffer->iStride[0];
srcStep[1] = pSystemBuffer->iStride[1];
srcStep[2] = pSystemBuffer->iStride[1];
prims->YUV420ToRGB_8u_P3AC4R((const BYTE**) pYUVData, srcStep, h264->data, h264->scanline, &roi);
return 1;
}
@ -408,8 +311,12 @@ static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcS
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
{
int status;
int srcStep[3];
int gotFrame = 0;
AVPacket packet;
prim_size_t roi;
const BYTE* pSrc[3];
primitives_t* prims = primitives_get();
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData;
av_init_packet(&packet);
@ -425,26 +332,31 @@ static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcS
return -1;
}
#if 0
printf("libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])\n",
status, gotFrame, sys->videoFrame->width, sys->videoFrame->height,
sys->videoFrame->data[0], sys->videoFrame->linesize[0],
sys->videoFrame->data[1], sys->videoFrame->linesize[1],
sys->videoFrame->data[2], sys->videoFrame->linesize[2]);
fflush(stdout);
#endif
if (gotFrame)
{
if (g_H264DumpFrames)
{
h264_dump_yuv_data(sys->videoFrame->data, sys->videoFrame->width, sys->videoFrame->height, sys->videoFrame->linesize);
}
if (h264_prepare_rgb_buffer(h264, sys->videoFrame->width, sys->videoFrame->height) < 0)
return -1;
freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0,
h264->width, h264->height, sys->videoFrame->data, sys->videoFrame->linesize, 0, 0);
roi.width = h264->width;
roi.height = h264->height;
pSrc[0] = sys->videoFrame->data[0];
pSrc[1] = sys->videoFrame->data[1];
pSrc[2] = sys->videoFrame->data[2];
srcStep[0] = sys->videoFrame->linesize[0];
srcStep[1] = sys->videoFrame->linesize[1];
srcStep[2] = sys->videoFrame->linesize[2];
prims->YUV420ToRGB_8u_P3AC4R(pSrc, srcStep, h264->data, h264->scanline, &roi);
}
return 1;
@ -586,11 +498,6 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
*ppDstData = pDstData;
}
if (g_H264DumpFrames)
{
h264_dump_h264_data(pSrcData, SrcSize);
}
return h264->subsystem->Decompress(h264, pSrcData, SrcSize,
pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight);
}
@ -650,7 +557,7 @@ void h264_context_free(H264_CONTEXT* h264)
{
if (h264)
{
free(h264->data);
_aligned_free(h264->data);
h264->subsystem->Uninit(h264);

View File

@ -26,6 +26,7 @@ set(${MODULE_PREFIX}_SRCS
prim_set.c
prim_shift.c
prim_sign.c
prim_YUV.c
prim_YCoCg.c
primitives.c
prim_internal.h)

View File

@ -0,0 +1,97 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/types.h>
#include <freerdp/primitives.h>
#include <freerdp/codec/color.h>
#include "prim_internal.h"
#include "prim_YUV.h"
static INLINE BYTE clip(int x)
{
if (x < 0) return 0;
if (x > 255) return 255;
return (BYTE) x;
}
static INLINE UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V)
{
BYTE R, G, B;
int Yp, Up, Vp;
Yp = Y * 256;
Up = U - 128;
Vp = V - 128;
R = clip((Yp + (403 * Vp)) >> 8);
G = clip((Yp - (48 * Up) - (120 * Vp)) >> 8);
B = clip((Yp + (475 * Up)) >> 8);
return ARGB32(0xFF, R, G, B);
}
pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
BYTE* pDst, int dstStep, const prim_size_t* roi)
{
int x, y;
BYTE Y, U, V;
const BYTE* pY;
const BYTE* pU;
const BYTE* pV;
BYTE* pRGB = pDst;
pY = pSrc[0];
for (y = 0; y < roi->height; y++)
{
pU = pSrc[1] + (y / 2) * srcStep[1];
pV = pSrc[2] + (y / 2) * srcStep[2];
for (x = 0; x < roi->width; x++)
{
Y = *pY;
U = pU[x / 2];
V = pV[x / 2];
*((UINT32*) pRGB) = YUV_to_RGB(Y, U, V);
pRGB += 4;
pY++;
}
pRGB += (dstStep - (roi->width * 4));
pY += (srcStep[0] - roi->width);
}
return PRIMITIVES_SUCCESS;
}
void primitives_init_YUV(primitives_t* prims)
{
prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
}
void primitives_deinit_YUV(primitives_t* prims)
{
}

View File

@ -0,0 +1,27 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_PRIMITIVES_YUV_H
#define FREERDP_PRIMITIVES_YUV_H
pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep, BYTE* pDst, int dstStep, const prim_size_t* roi);
void primitives_init_YUV(primitives_t* prims);
void primitives_deinit_YUV(primitives_t* prims);
#endif /* FREERDP_PRIMITIVES_YUV_H */

View File

@ -35,54 +35,37 @@
: _mm_load_si128((__m128i *) (_ptr_)))
/* Function prototypes for all the init/deinit routines. */
extern void primitives_init_copy(
primitives_t *prims);
extern void primitives_deinit_copy(
primitives_t *prims);
extern void primitives_init_copy(primitives_t *prims);
extern void primitives_deinit_copy(primitives_t *prims);
extern void primitives_init_set(
primitives_t *prims);
extern void primitives_deinit_set(
primitives_t *prims);
extern void primitives_init_set(primitives_t *prims);
extern void primitives_deinit_set(primitives_t *prims);
extern void primitives_init_add(
primitives_t *prims);
extern void primitives_deinit_add(
primitives_t *prims);
extern void primitives_init_add(primitives_t *prims);
extern void primitives_deinit_add(primitives_t *prims);
extern void primitives_init_andor(
primitives_t *prims);
extern void primitives_deinit_andor(
primitives_t *prims);
extern void primitives_init_andor(primitives_t *prims);
extern void primitives_deinit_andor(primitives_t *prims);
extern void primitives_init_shift(
primitives_t *prims);
extern void primitives_deinit_shift(
primitives_t *prims);
extern void primitives_init_shift(primitives_t *prims);
extern void primitives_deinit_shift(primitives_t *prims);
extern void primitives_init_sign(
primitives_t *prims);
extern void primitives_deinit_sign(
primitives_t *prims);
extern void primitives_init_sign(primitives_t *prims);
extern void primitives_deinit_sign(primitives_t *prims);
extern void primitives_init_alphaComp(
primitives_t *prims);
extern void primitives_deinit_alphaComp(
primitives_t *prims);
extern void primitives_init_alphaComp(primitives_t *prims);
extern void primitives_deinit_alphaComp(primitives_t *prims);
extern void primitives_init_colors(
primitives_t *prims);
extern void primitives_deinit_colors(
primitives_t *prims);
extern void primitives_init_colors(primitives_t *prims);
extern void primitives_deinit_colors(primitives_t *prims);
extern void primitives_init_YCoCg(
primitives_t *prims);
extern void primitives_deinit_YCoCg(
primitives_t *prims);
extern void primitives_init_YCoCg(primitives_t *prims);
extern void primitives_deinit_YCoCg(primitives_t *prims);
extern void primitives_init_16to32bpp(
primitives_t *prims);
extern void primitives_deinit_16to32bpp(
primitives_t *prims);
extern void primitives_init_YUV(primitives_t *prims);
extern void primitives_deinit_YUV(primitives_t *prims);
extern void primitives_init_16to32bpp(primitives_t *prims);
extern void primitives_deinit_16to32bpp(primitives_t *prims);
#endif /* !__PRIM_INTERNAL_H_INCLUDED__ */

View File

@ -32,11 +32,11 @@ static primitives_t* pPrimitives = NULL;
/* ------------------------------------------------------------------------- */
void primitives_init(void)
{
if (pPrimitives == NULL)
if (!pPrimitives)
{
pPrimitives = calloc(1, sizeof(primitives_t));
if (pPrimitives == NULL)
if (!pPrimitives)
return;
}
@ -50,13 +50,14 @@ void primitives_init(void)
primitives_init_sign(pPrimitives);
primitives_init_colors(pPrimitives);
primitives_init_YCoCg(pPrimitives);
primitives_init_YUV(pPrimitives);
primitives_init_16to32bpp(pPrimitives);
}
/* ------------------------------------------------------------------------- */
primitives_t* primitives_get(void)
{
if (pPrimitives == NULL)
if (!pPrimitives)
primitives_init();
return pPrimitives;
@ -65,7 +66,7 @@ primitives_t* primitives_get(void)
/* ------------------------------------------------------------------------- */
void primitives_deinit(void)
{
if (pPrimitives == NULL)
if (!pPrimitives)
return;
/* Call each section's de-initialization routine. */
@ -78,6 +79,7 @@ void primitives_deinit(void)
primitives_deinit_sign(pPrimitives);
primitives_deinit_colors(pPrimitives);
primitives_deinit_YCoCg(pPrimitives);
primitives_deinit_YUV(pPrimitives);
primitives_deinit_16to32bpp(pPrimitives);
free((void*) pPrimitives);