#include <winpr/print.h>
#include <winpr/bitstream.h>
- #include <freerdp/codec/color.h>
+ #include <freerdp/primitives.h>
-
#include <freerdp/codec/h264.h>
- #include <sys/time.h>
-
- #ifdef WITH_H264_SSSE3
- extern int freerdp_check_ssse3();
- extern int freerdp_image_yuv420p_to_xrgb_ssse3(BYTE *pDstData,BYTE **pSrcData,int nWidth,int nHeight,int *iStride,int scanline);
- #endif
-
- #define USE_GRAY_SCALE 0
- #define USE_UPCONVERT 0
-
- static BYTE clip(int x)
- {
- if (x < 0) return 0;
- if (x > 255) return 255;
- return (BYTE)x;
- }
-
- static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V)
- {
- BYTE R, G, B;
-
- #if USE_GRAY_SCALE
- /*
- * Displays the Y plane as a gray-scale image.
- */
- R = Y;
- G = Y;
- B = Y;
- #else
- int C, D, E;
-
- #if 0
- /*
- * Documented colorspace conversion from YUV to RGB.
- * See http://msdn.microsoft.com/en-us/library/ms893078.aspx
- */
-
- C = Y - 16;
- D = U - 128;
- E = V - 128;
-
- R = clip(( 298 * C + 409 * E + 128) >> 8);
- G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8);
- B = clip(( 298 * C + 516 * D + 128) >> 8);
- #endif
-
- #if 0
- /*
- * These coefficients produce better results.
- * See http://www.microchip.com/forums/m599060.aspx
- */
-
- C = Y;
- D = U - 128;
- E = V - 128;
-
- R = clip(( 256 * C + 359 * E + 128) >> 8);
- G = clip(( 256 * C - 88 * D - 183 * E + 128) >> 8);
- B = clip(( 256 * C + 454 * D + 128) >> 8);
- #endif
-
- #if 1
- /*
- * These coefficients produce excellent results.
- */
-
- C = Y;
- D = U - 128;
- E = V - 128;
-
- R = clip(( 256 * C + 403 * E + 128) >> 8);
- G = clip(( 256 * C - 48 * D - 120 * E + 128) >> 8);
- B = clip(( 256 * C + 475 * D + 128) >> 8);
- #endif
-
- #endif
-
- return RGB32(R, G, B);
- }
-
- #if USE_UPCONVERT
- static BYTE* h264_convert_420_to_444(BYTE* chroma420, int chroma420Width, int chroma420Height, int chroma420Stride)
- {
- BYTE *chroma444, *src, *dst;
- int chroma444Width;
- int chroma444Height;
- int i, j;
-
- chroma444Width = chroma420Width * 2;
- chroma444Height = chroma420Height * 2;
-
- chroma444 = (BYTE*) malloc(chroma444Width * chroma444Height);
-
- if (!chroma444)
- return NULL;
-
- /* Upconvert in the horizontal direction. */
-
- for (j = 0; j < chroma420Height; j++)
- {
- src = chroma420 + j * chroma420Stride;
- dst = chroma444 + j * chroma444Width;
- dst[0] = src[0];
- for (i = 1; i < chroma420Width; i++)
- {
- dst[2*i-1] = (3 * src[i-1] + src[i] + 2) >> 2;
- dst[2*i] = (src[i-1] + 3 * src[i] + 2) >> 2;
- }
- dst[chroma444Width-1] = src[chroma420Width-1];
- }
-
- /* Upconvert in the vertical direction (in-place, bottom-up). */
-
- for (i = 0; i < chroma444Width; i++)
- {
- src = chroma444 + i + (chroma420Height-2) * chroma444Width;
- dst = chroma444 + i + (2*(chroma420Height-2)+1) * chroma444Width;
- dst[2*chroma444Width] = src[chroma444Width];
- for (j = chroma420Height - 2; j >= 0; j--)
- {
- dst[chroma444Width] = (src[0] + 3 * src[chroma444Width] + 2) >> 2;
- dst[0] = (3 * src[0] + src[chroma444Width] + 2) >> 2;
- dst -= 2 * chroma444Width;
- src -= chroma444Width;
- }
- }
-
- return chroma444;
- }
- #endif
-
- 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);
- }
-
+#ifdef WITH_LIBAVCODEC
int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height)
{
UINT32 size;
return 1;
}
+#endif
- 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;
-
- #if USE_UPCONVERT
- /* Convert 4:2:0 YUV to 4:4:4 YUV. */
- pSrcData[1] = h264_convert_420_to_444(pSrcData[1], nWidth / 2, nHeight / 2, nSrcStep[1]);
- pSrcData[2] = h264_convert_420_to_444(pSrcData[2], nWidth / 2, nHeight / 2, nSrcStep[1]);
-
- nSrcStep[1] = nWidth;
-
- shift = 0;
- #endif
-
- 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);
- }
-
- #if USE_UPCONVERT
- free(pSrcData[1]);
- free(pSrcData[2]);
- #endif
+ /**
+ * Dummy subsystem
+ */
- return 1;
+ static int dummy_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
+ BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
+ {
+ return -1;
}
- BYTE* h264_strip_nal_unit_au_delimiter(BYTE* pSrcData, UINT32* pSrcSize)
+ static void dummy_uninit(H264_CONTEXT* h264)
{
- BYTE* data = pSrcData;
- UINT32 size = *pSrcSize;
- BYTE forbidden_zero_bit = 0;
- BYTE nal_ref_idc = 0;
- BYTE nal_unit_type = 0;
-
- /* ITU-T H.264 B.1.1 Byte stream NAL unit syntax */
-
- while (size > 0)
- {
- if (*data)
- break;
-
- data++;
- size--;
- }
-
- if (*data != 1)
- return pSrcData;
-
- data++;
- size--;
-
- forbidden_zero_bit = (data[0] >> 7);
- nal_ref_idc = (data[0] >> 5);
- nal_unit_type = (data[0] & 0x1F);
- if (forbidden_zero_bit)
- return pSrcData; /* invalid */
-
- if (nal_unit_type == 9)
- {
- /* NAL Unit AU Delimiter */
-
- printf("NAL Unit AU Delimiter: idc: %d\n", nal_ref_idc);
-
- data += 2;
- size -= 2;
-
- *pSrcSize = size;
- return data;
- }
-
- return pSrcData;
}
+ static BOOL dummy_init(H264_CONTEXT* h264)
+ {
+ return TRUE;
+ }
+ static H264_CONTEXT_SUBSYSTEM g_Subsystem_dummy =
+ {
+ "dummy",
+ dummy_init,
+ dummy_uninit,
+ dummy_decompress
+ };
- /*************************************************
- *
- * OpenH264 Implementation
- *
- ************************************************/
+ /**
+ * OpenH264 subsystem
+ */
#ifdef WITH_OPENH264
printf("%d - %s\n", level, message);
}
-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)
+static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
{
+ 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;
+
+ struct timeval T1,T2;
+
- if (!h264->pDecoder)
+ if (!sys->pDecoder)
return -1;
/*
ZeroMemory(&sBufferInfo, sizeof(sBufferInfo));
- state = (*h264->pDecoder)->DecodeFrame2(
- h264->pDecoder,
+ gettimeofday(&T1,NULL);
+ state = (*sys->pDecoder)->DecodeFrame2(
+ sys->pDecoder,
pSrcData,
SrcSize,
- pYUVData,
+ h264->pYUVData,
&sBufferInfo);
/**
*/
if (sBufferInfo.iBufferStatus != 1)
- state = (*h264->pDecoder)->DecodeFrame2(h264->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo);
+ state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, pYUVData, &sBufferInfo);
+
+ gettimeofday(&T2,NULL);
+ printf("OpenH264: decoding took: %u sec %u usec\n",(unsigned int)(T2.tv_sec-T1.tv_sec),(unsigned int)(T2.tv_usec-T1.tv_usec));
pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer;
if (pSystemBuffer->iFormat != videoFormatI420)
return -1;
- if (h264_prepare_rgb_buffer(h264, pSystemBuffer->iWidth, pSystemBuffer->iHeight) < 0)
- return -1;
--
- if (g_H264DumpFrames)
- {
- h264_dump_yuv_data(h264->pYUVData, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride);
- }
- roi.width = h264->width;
- roi.height = h264->height;
--
- g_H264FrameId++;
- /* 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);
+ h264->iStride[0] = pSystemBuffer->iStride[0];
+ h264->iStride[1] = pSystemBuffer->iStride[1];
+ h264->width = pSystemBuffer->iWidth;
+ h264->height = pSystemBuffer->iHeight;
-
return 1;
}
static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
{
- AVPacket packet;
- int gotFrame = 0;
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;
+
+ struct timeval T1,T2;
+
av_init_packet(&packet);
packet.data = pSrcData;
packet.size = SrcSize;
- status = avcodec_decode_video2(h264->codecContext, h264->videoFrame, &gotFrame, &packet);
+ gettimeofday(&T1,NULL);
+ status = avcodec_decode_video2(sys->codecContext, sys->videoFrame, &gotFrame, &packet);
+ gettimeofday(&T2,NULL);
+
+ printf("libavcodec: decoding took: %u sec %u usec\n",(unsigned int)(T2.tv_sec-T1.tv_sec),(unsigned int)(T2.tv_usec-T1.tv_usec));
if (status < 0)
{
return FALSE;
}
- #endif
-
+ static H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec =
+ {
+ "libavcodec",
+ libavcodec_init,
+ libavcodec_uninit,
+ libavcodec_decompress
+ };
+ #endif
int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
- BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
+ BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nDstHeight, RDPGFX_RECT16* regionRects, int numRegionRects)
{
- UINT32 UncompressedSize;
BYTE* pDstData;
- UINT32 UncompressedSize;
+ BYTE* pDstPoint;
+
+ BYTE** pYUVData;
+ BYTE* pYUVPoint[3];
+
+ RDPGFX_RECT16* rect;
+ int* iStride;
+ int ret, i, cx, cy;
++ int UncompressedSize;
+
+ struct timeval T1,T2;
if (!h264)
return -1;
#if 0
- pSrcData = h264_strip_nal_unit_au_delimiter(pSrcData, &SrcSize);
- #endif
-
- #if 0
- printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, numRegionRects=%d\n",
- pSrcData, SrcSize, *ppDstData, nDstStep, numRegionRects);
+ printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n",
+ pSrcData, SrcSize, *ppDstData, nDstStep, nXDst, nYDst, nWidth, nHeight);
#endif
- /* Allocate a destination buffer (if needed). */
+ if (!(pDstData = *ppDstData))
+ return -1;
- UncompressedSize = nWidth * nHeight * 4;
- if (g_H264DumpFrames)
- {
- h264_dump_h264_data(pSrcData, SrcSize);
- }
-
-
- #ifdef WITH_OPENH264
- ret = openh264_decompress(h264, pSrcData, SrcSize);
- if (ret != 1)
- return ret;
-
- pYUVData = h264->pYUVData;
- iStride = h264->iStride;
- #endif
-
- #ifdef WITH_LIBAVCODEC
- return libavcodec_decompress(
- h264, pSrcData, SrcSize,
- pDstData, DstFormat, nDstStep,
- nXDst, nYDst, nWidth, nHeight);
- #endif
- if (UncompressedSize == 0)
++<<<<<<< HEAD
++ if (h264->subsystem->Decompress(h264, pSrcData, SrcSize,
++ pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight))
+ return -1;
- pDstData = *ppDstData;
- /* Convert I420 (same as IYUV) to XRGB. */
- if (!pDstData)
- {
- pDstData = (BYTE*) malloc(UncompressedSize);
+ UncompressedSize = h264->width * h264->height * 4;
+ if (UncompressedSize > (nDstStep * nDstHeight))
+ return -1;
- if (!pDstData)
- return -1;
- *ppDstData = pDstData;
+ gettimeofday(&T1,NULL);
+ for (i = 0; i < numRegionRects; i++){
+ rect = &(regionRects[i]);
+ cx = rect->right - rect->left;
+ cy = rect->bottom - rect->top;
+
+ pDstPoint = pDstData + rect->top * nDstStep + rect->left * 4;
+ pYUVPoint[0] = pYUVData[0] + rect->top * iStride[0] + rect->left;
+
+ ret = rect->top/2 * iStride[1] + rect->left/2;
+ pYUVPoint[1] = pYUVData[1] + ret;
+ pYUVPoint[2] = pYUVData[2] + ret;
+
+#if 0
+ printf("regionRect: x: %d, y: %d, cx: %d, cy: %d\n",
+ rect->left, rect->top, cx, cy);
+#endif
+
+#ifdef WITH_H264_SSSE3
+ freerdp_image_yuv420p_to_xrgb_ssse3(pDstPoint, pYUVPoint, cx, cy, iStride, nDstStep);
+#else
- freerdp_image_copy_yuv420p_to_xrgb(pDstPoint, nDstStep, 0, 0,
- cx, cy, pYUVPoint, iStride, 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)
++ */
+#endif
}
+ gettimeofday(&T2,NULL);
+ printf("converting took %u sec %u usec\n",(unsigned int)(T2.tv_sec-T1.tv_sec),(unsigned int)(T2.tv_usec-T1.tv_usec));
- return h264->subsystem->Decompress(h264, pSrcData, SrcSize,
- pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight);
+ return 1;
}
int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
{
h264->Compressor = Compressor;
- #ifdef WITH_OPENH264
- if (!openh264_init(h264))
- {
- free(h264);
+ h264->subsystem = &g_Subsystem_dummy;
+
++#ifdef WITH_LIBAVCODEC
+ if (h264_prepare_rgb_buffer(h264, 256, 256) < 0)
return NULL;
- }
+#endif
- #ifdef WITH_LIBAVCODEC
- if (!libavcodec_init(h264))
+ if (!h264_context_init(h264))
{
free(h264);
return NULL;
{
if (h264)
{
- #ifdef WITH_OPENH264
- openh264_free(h264);
- #endif
-
+#ifdef WITH_LIBAVCODEC
- libavcodec_free(h264);
_aligned_free(h264->data);
+#endif
+ h264->subsystem->Uninit(h264);
+
free(h264);
}
}