From f14b0e01959bfe249daed4fdba772fe1b93d1daa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 5 Sep 2014 19:11:03 -0400 Subject: [PATCH] libfreerdp-codec: cleanup h264 decoder --- client/X11/xf_gfx.c | 6 - include/freerdp/codec/h264.h | 42 +-- libfreerdp/codec/h264.c | 701 +++++++++++++++++++++++++++++------------ libfreerdp/codec/progressive.c | 4 +- libfreerdp/utils/svc_plugin.c | 5 - 5 files changed, 514 insertions(+), 244 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 50e4bf8..3efdfdc 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -512,9 +512,6 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, return -1; } - printf("xf_SurfaceCommand_Progressive: status: %d surfaceId: %d contextId: %d\n", status, - cmd->surfaceId, cmd->contextId); - region = &(xfc->progressive->region); region16_init(&clippingRects); @@ -614,9 +611,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) { - printf("DeleteEncodingContext: surfaceId: %d codecId: %d\n", - deleteEncodingContext->surfaceId, - deleteEncodingContext->codecContextId); return 1; } diff --git a/include/freerdp/codec/h264.h b/include/freerdp/codec/h264.h index 3c445d6..61bfa13 100644 --- a/include/freerdp/codec/h264.h +++ b/include/freerdp/codec/h264.h @@ -23,21 +23,22 @@ #include #include -#ifdef WITH_LIBAVCODEC -#ifdef WITH_OPENH264 -#undef WITH_OPENH264 -#endif -#endif +typedef struct _H264_CONTEXT H264_CONTEXT; -#ifdef WITH_OPENH264 -#include "wels/codec_def.h" -#include "wels/codec_api.h" -#endif +typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264); +typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264); -#ifdef WITH_LIBAVCODEC -#include -#include -#endif +typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + +struct _H264_CONTEXT_SUBSYSTEM +{ + const char* name; + pfnH264SubsystemInit Init; + pfnH264SubsystemUninit Uninit; + pfnH264SubsystemDecompress Decompress; +}; +typedef struct _H264_CONTEXT_SUBSYSTEM H264_CONTEXT_SUBSYSTEM; struct _H264_CONTEXT { @@ -49,18 +50,9 @@ struct _H264_CONTEXT UINT32 height; int scanline; -#ifdef WITH_OPENH264 - ISVCDecoder* pDecoder; -#endif - -#ifdef WITH_LIBAVCODEC - AVCodec* codec; - AVCodecContext* codecContext; - AVCodecParserContext* codecParser; - AVFrame* videoFrame; -#endif + void* pSystemData; + H264_CONTEXT_SUBSYSTEM* subsystem; }; -typedef struct _H264_CONTEXT H264_CONTEXT; #ifdef __cplusplus extern "C" { @@ -71,8 +63,6 @@ FREERDP_API int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize FREERDP_API int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); -FREERDP_API void h264_context_reset(H264_CONTEXT* h264); - FREERDP_API H264_CONTEXT* h264_context_new(BOOL Compressor); FREERDP_API void h264_context_free(H264_CONTEXT* h264); diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 9a5afb4..84095e7 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -28,65 +28,17 @@ #include #include -#define USE_GRAY_SCALE 0 -#define USE_UPCONVERT 0 - -#ifdef WITH_OPENH264 -static BYTE clip(int x) +static INLINE BYTE clip(int x) { if (x < 0) return 0; if (x > 255) return 255; - return (BYTE)x; + return (BYTE) x; } -static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V) +static INLINE 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. - */ + BYTE R, G, B; C = Y; D = U - 128; @@ -95,107 +47,172 @@ static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V) 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); } -#endif /* WITH_OPENH264 */ -#if USE_UPCONVERT -static BYTE* convert_420_to_444(BYTE* chroma420, int chroma420Width, int chroma420Height, int chroma420Stride) +static int g_H264FrameId = 0; +static BOOL g_H264DumpFrames = FALSE; + +static void h264_dump_h264_data(BYTE* data, int size) { - BYTE *chroma444, *src, *dst; - int chroma444Width; - int chroma444Height; - int i, j; + FILE* fp; + char buf[4096]; + + snprintf(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; + + snprintf(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId); + fp = fopen(buf, "wb"); + fwrite("P5\n", 1, 3, fp); + snprintf(buf, sizeof(buf), "%d %d\n", width, height); + fwrite(buf, 1, strlen(buf), fp); + fwrite("255\n", 1, 4, fp); + + srcp = yuv[0]; - chroma444Width = chroma420Width * 2; - chroma444Height = chroma420Height * 2; + for (j = 0; j < height; j++) + { + fwrite(srcp, 1, width, fp); + srcp += stride[0]; + } - chroma444 = (BYTE*) malloc(chroma444Width * chroma444Height); + fflush(fp); + fclose(fp); +} - if (!chroma444) - return NULL; +int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height) +{ + UINT32 size; - /* Upconvert in the horizontal direction. */ + h264->width = width; + h264->height = height; + h264->scanline = h264->width * 4; + size = h264->scanline * h264->height; - for (j = 0; j < chroma420Height; j++) + if (size > h264->size) { - 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]; + h264->size = size; + h264->data = (BYTE*) realloc(h264->data, h264->size); + memset(h264->data, 0, h264->size); } - /* Upconvert in the vertical direction (in-place, bottom-up). */ + if (!h264->data) + return -1; + + return 1; +} - for (i = 0; i < chroma444Width; i++) +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++) { - 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--) + pU = pSrcData[1] + ((nYSrc + y) >> shift) * nSrcStep[1]; + pV = pSrcData[2] + ((nYSrc + y) >> shift) * nSrcStep[1]; + + for (x = 0; x < nWidth; x++) { - dst[chroma444Width] = (src[0] + 3 * src[chroma444Width] + 2) >> 2; - dst[0] = (3 * src[0] + src[chroma444Width] + 2) >> 2; - dst -= 2 * chroma444Width; - src -= chroma444Width; + 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 chroma444; + return 1; } -#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) +/** + * Dummy subsystem + */ + +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) { -#ifdef WITH_OPENH264 - DECODING_STATE state; - SBufferInfo sBufferInfo; - SSysMEMBuffer* pSystemBuffer; - UINT32 UncompressedSize; - BYTE* pDstData; - BYTE* pYUVData[3]; - BYTE* pY; - BYTE* pU; - BYTE* pV; - int Y, U, V; - int i, j; + return -1; +} - if (!h264 || !h264->pDecoder) - return -1; +static void dummy_uninit(H264_CONTEXT* h264) +{ -#if 0 - DEBUG_MSG("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, DstFormat=%lx, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n", - pSrcData, SrcSize, *ppDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight); -#endif +} - /* Allocate a destination buffer (if needed). */ +static BOOL dummy_init(H264_CONTEXT* h264) +{ + return TRUE; +} - UncompressedSize = nWidth * nHeight * 4; +static H264_CONTEXT_SUBSYSTEM g_Subsystem_dummy = +{ + "dummy", + dummy_init, + dummy_uninit, + dummy_decompress +}; - if (UncompressedSize == 0) - return -1; +/** + * OpenH264 subsystem + */ - pDstData = *ppDstData; +#ifdef WITH_OPENH264 - if (!pDstData) - { - pDstData = (BYTE*) malloc(UncompressedSize); +#include "wels/codec_def.h" +#include "wels/codec_api.h" - if (!pDstData) - return -1; +struct _H264_CONTEXT_OPENH264 +{ + ISVCDecoder* pDecoder; +}; +typedef struct _H264_CONTEXT_OPENH264 H264_CONTEXT_OPENH264; - *ppDstData = pDstData; - } +static BOOL g_openh264_trace_enabled = FALSE; + +static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* message) +{ + 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) +{ + BYTE* pYUVData[3]; + DECODING_STATE state; + SBufferInfo sBufferInfo; + SSysMEMBuffer* pSystemBuffer; + H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; + + if (!sys->pDecoder) + return -1; /* * Decompress the image. The RDP host only seems to send I420 format. @@ -207,17 +224,27 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, ZeroMemory(&sBufferInfo, sizeof(sBufferInfo)); - state = (*h264->pDecoder)->DecodeFrame2( - h264->pDecoder, + state = (*sys->pDecoder)->DecodeFrame2( + sys->pDecoder, pSrcData, SrcSize, pYUVData, &sBufferInfo); + /** + * Calling DecodeFrame2 twice apparently works around Openh264 issue #1136: + * https://github.com/cisco/openh264/issues/1136 + * + * This is a hack, but it works and it is only necessary for the first frame. + */ + + if (sBufferInfo.iBufferStatus != 1) + state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, pYUVData, &sBufferInfo); + pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; #if 0 - DEBUG_MSG("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n", + printf("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n", state, pYUVData[0], pYUVData[1], pYUVData[2], sBufferInfo.iBufferStatus, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); @@ -237,47 +264,335 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, /* Convert I420 (same as IYUV) to XRGB. */ - pY = pYUVData[0]; - pU = pYUVData[1]; - pV = pYUVData[2]; + if (g_H264DumpFrames) + { + h264_dump_yuv_data(pYUVData, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride); + } -#if USE_UPCONVERT - /* Convert 4:2:0 YUV to 4:4:4 YUV. */ - pU = convert_420_to_444(pU, pSystemBuffer->iWidth / 2, pSystemBuffer->iHeight / 2, pSystemBuffer->iStride[1]); - pV = convert_420_to_444(pV, pSystemBuffer->iWidth / 2, pSystemBuffer->iHeight / 2, pSystemBuffer->iStride[1]); -#endif + g_H264FrameId++; - for (j = 0; j < nHeight; j++) + 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); + + return 1; +} + +static void openh264_uninit(H264_CONTEXT* h264) +{ + H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; + + if (sys) { - BYTE *pXRGB = pDstData + ((nYDst + j) * nDstStep) + (nXDst * 4); - int y = nYDst + j; + if (sys->pDecoder) + { + (*sys->pDecoder)->Uninitialize(sys->pDecoder); + WelsDestroyDecoder(sys->pDecoder); + sys->pDecoder = NULL; + } + + free(sys); + h264->pSystemData = NULL; + } +} + +static BOOL openh264_init(H264_CONTEXT* h264) +{ + long status; + SDecodingParam sDecParam; + H264_CONTEXT_OPENH264* sys; + static int traceLevel = WELS_LOG_DEBUG; + static EVideoFormatType videoFormat = videoFormatI420; + static WelsTraceCallback traceCallback = (WelsTraceCallback) openh264_trace_callback; + + sys = (H264_CONTEXT_OPENH264*) calloc(1, sizeof(H264_CONTEXT_OPENH264)); + + if (!sys) + { + goto EXCEPTION; + } + + h264->pSystemData = (void*) sys; + + WelsCreateDecoder(&sys->pDecoder); + + if (!sys->pDecoder) + { + printf("Failed to create OpenH264 decoder\n"); + goto EXCEPTION; + } + + ZeroMemory(&sDecParam, sizeof(sDecParam)); + sDecParam.iOutputColorFormat = videoFormatI420; + sDecParam.uiEcActiveFlag = 1; + sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; + + status = (*sys->pDecoder)->Initialize(sys->pDecoder, &sDecParam); + + if (status != 0) + { + printf("Failed to initialize OpenH264 decoder (status=%ld)\n", status); + goto EXCEPTION; + } + + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat); + + if (status != 0) + { + printf("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status); + } + + if (g_openh264_trace_enabled) + { + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_LEVEL, &traceLevel); + + if (status != 0) + { + printf("Failed to set trace level option on OpenH264 decoder (status=%ld)\n", status); + } + + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK, &traceCallback); + + if (status != 0) + { + printf("Failed to set trace callback option on OpenH264 decoder (status=%ld)\n", status); + } - for (i = 0; i < nWidth; i++) + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &h264); + + if (status != 0) { - int x = nXDst + i; - - Y = pY[(y * pSystemBuffer->iStride[0]) + x]; -#if USE_UPCONVERT - U = pU[(y * pSystemBuffer->iWidth) + x]; - V = pV[(y * pSystemBuffer->iWidth) + x]; -#else - U = pU[(y/2) * pSystemBuffer->iStride[1] + (x/2)]; - V = pV[(y/2) * pSystemBuffer->iStride[1] + (x/2)]; + printf("Failed to set trace callback context option on OpenH264 decoder (status=%ld)\n", status); + } + } + + return TRUE; + +EXCEPTION: + openh264_uninit(h264); + + return FALSE; +} + +static H264_CONTEXT_SUBSYSTEM g_Subsystem_OpenH264 = +{ + "OpenH264", + openh264_init, + openh264_uninit, + openh264_decompress +}; + #endif - *(UINT32*)pXRGB = YUV_to_RGB(Y, U, V); - - pXRGB += 4; +/** + * libavcodec subsystem + */ + +#ifdef WITH_LIBAVCODEC + +#include +#include + +struct _H264_CONTEXT_LIBAVCODEC +{ + AVCodec* codec; + AVCodecContext* codecContext; + AVCodecParserContext* codecParser; + AVFrame* videoFrame; +}; +typedef struct _H264_CONTEXT_LIBAVCODEC H264_CONTEXT_LIBAVCODEC; + +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) +{ + int status; + int gotFrame = 0; + AVPacket packet; + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; + + av_init_packet(&packet); + + packet.data = pSrcData; + packet.size = SrcSize; + + status = avcodec_decode_video2(sys->codecContext, sys->videoFrame, &gotFrame, &packet); + + if (status < 0) + { + printf("Failed to decode video frame (status=%d)\n", status); + return -1; + } + + 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); + + 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); } -#if USE_UPCONVERT - free(pU); - free(pV); + return 1; +} + +static void libavcodec_uninit(H264_CONTEXT* h264) +{ + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; + + if (!sys) + return; + + if (sys->videoFrame) + { + av_free(sys->videoFrame); + } + + if (sys->codecParser) + { + av_parser_close(sys->codecParser); + } + + if (sys->codecContext) + { + avcodec_close(sys->codecContext); + av_free(sys->codecContext); + } + + free(sys); + h264->pSystemData = NULL; +} + +static BOOL libavcodec_init(H264_CONTEXT* h264) +{ + H264_CONTEXT_LIBAVCODEC* sys; + + sys = (H264_CONTEXT_LIBAVCODEC*) calloc(1, sizeof(H264_CONTEXT_LIBAVCODEC)); + + if (!sys) + { + goto EXCEPTION; + } + + h264->pSystemData = (void*) sys; + + avcodec_register_all(); + + sys->codec = avcodec_find_decoder(CODEC_ID_H264); + + if (!sys->codec) + { + printf("Failed to find libav H.264 codec\n"); + goto EXCEPTION; + } + + sys->codecContext = avcodec_alloc_context3(sys->codec); + + if (!sys->codecContext) + { + printf("Failed to allocate libav codec context\n"); + goto EXCEPTION; + } + + if (sys->codec->capabilities & CODEC_CAP_TRUNCATED) + { + sys->codecContext->flags |= CODEC_FLAG_TRUNCATED; + } + + if (avcodec_open2(sys->codecContext, sys->codec, NULL) < 0) + { + printf("Failed to open libav codec\n"); + goto EXCEPTION; + } + + sys->codecParser = av_parser_init(CODEC_ID_H264); + + if (!sys->codecParser) + { + printf("Failed to initialize libav parser\n"); + goto EXCEPTION; + } + + sys->videoFrame = avcodec_alloc_frame(); + + if (!sys->videoFrame) + { + printf("Failed to allocate libav frame\n"); + goto EXCEPTION; + } + + return TRUE; + +EXCEPTION: + libavcodec_uninit(h264); + + return FALSE; +} + +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* pDstData; + UINT32 UncompressedSize; + + if (!h264) + return -1; + +#if 0 + 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 - return 1; + /* Allocate a destination buffer (if needed). */ + + UncompressedSize = nWidth * nHeight * 4; + + if (UncompressedSize == 0) + return -1; + + pDstData = *ppDstData; + + if (!pDstData) + { + pDstData = (BYTE*) malloc(UncompressedSize); + + if (!pDstData) + return -1; + + *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); } int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) @@ -285,9 +600,25 @@ int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppD return 1; } -void h264_context_reset(H264_CONTEXT* h264) +BOOL h264_context_init(H264_CONTEXT* h264) { +#ifdef WITH_LIBAVCODEC + if (g_Subsystem_libavcodec.Init(h264)) + { + h264->subsystem = &g_Subsystem_libavcodec; + return TRUE; + } +#endif + +#ifdef WITH_OPENH264 + if (g_Subsystem_OpenH264.Init(h264)) + { + h264->subsystem = &g_Subsystem_OpenH264; + return TRUE; + } +#endif + return FALSE; } H264_CONTEXT* h264_context_new(BOOL Compressor) @@ -300,69 +631,29 @@ H264_CONTEXT* h264_context_new(BOOL Compressor) { h264->Compressor = Compressor; -#ifdef WITH_OPENH264 + h264->subsystem = &g_Subsystem_dummy; + + if (h264_prepare_rgb_buffer(h264, 256, 256) < 0) + return NULL; + + if (!h264_context_init(h264)) { - static EVideoFormatType videoFormat = videoFormatI420; - - SDecodingParam sDecParam; - long status; - - WelsCreateDecoder(&h264->pDecoder); - - if (!h264->pDecoder) - { - DEBUG_MSG("Failed to create OpenH264 decoder\n"); - goto EXCEPTION; - } - - ZeroMemory(&sDecParam, sizeof(sDecParam)); - sDecParam.iOutputColorFormat = videoFormatARGB; - status = (*h264->pDecoder)->Initialize(h264->pDecoder, &sDecParam); - if (status != 0) - { - DEBUG_MSG("Failed to initialize OpenH264 decoder (status=%ld)\n", status); - goto EXCEPTION; - } - - status = (*h264->pDecoder)->SetOption(h264->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat); - if (status != 0) - { - DEBUG_MSG("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status); - } + free(h264); + return NULL; } -#endif - - h264_context_reset(h264); } return h264; - -#ifdef WITH_OPENH264 -EXCEPTION: - if (h264->pDecoder) - { - WelsDestroyDecoder(h264->pDecoder); - } -#endif - - free(h264); - - return NULL; } void h264_context_free(H264_CONTEXT* h264) { if (h264) { -#ifdef WITH_OPENH264 - if (h264->pDecoder) - { - (*h264->pDecoder)->Uninitialize(h264->pDecoder); - WelsDestroyDecoder(h264->pDecoder); - } -#endif + free(h264->data); + + h264->subsystem->Uninit(h264); free(h264); } } - diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index f63b689..69092d1 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -1710,8 +1710,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN if (!region->tiles) return -1; - printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", - region->numRects, region->numTiles, region->numQuant, region->numProgQuant); + //printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", + // region->numRects, region->numTiles, region->numQuant, region->numProgQuant); status = progressive_process_tiles(progressive, &block[boffset], region->tileDataSize, surface); diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index a527638..a96c360 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -114,11 +114,6 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_LAST) { - if (Stream_Capacity(s) != Stream_GetPosition(s)) - { - DEBUG_WARN( "svc_plugin_process_received: read error\n"); - } - plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); -- 2.7.4