diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index 961dce410..74d0a0dcc 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -24,6 +24,8 @@ #include #include +#include "rdpgfx_common.h" + #include "rdpgfx_codec.h" int rdpgfx_decode_uncompressed(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) @@ -46,8 +48,66 @@ int rdpgfx_decode_planar(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) return 1; } +int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s) +{ + UINT32 index; + RDPGFX_RECT16* regionRect; + RDPGFX_H264_METABLOCK metablock; + RDPGFX_H264_QUANT_QUALITY* quantQualityVal; + + Stream_Read_UINT32(s, metablock.numRegionRects); /* numRegionRects (4 bytes) */ + + metablock.regionRects = (RDPGFX_RECT16*) malloc(metablock.numRegionRects * sizeof(RDPGFX_RECT16)); + + if (!metablock.regionRects) + return -1; + + metablock.quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(metablock.numRegionRects * sizeof(RDPGFX_H264_QUANT_QUALITY)); + + if (!metablock.quantQualityVals) + return -1; + + printf("H264_METABLOCK: numRegionRects: %d\n", (int) metablock.numRegionRects); + + for (index = 0; index < metablock.numRegionRects; index++) + { + regionRect = &(metablock.regionRects[index]); + rdpgfx_read_rect16(s, regionRect); + + printf("regionRects[%d]: left: %d top: %d right: %d bottom: %d\n", + index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom); + } + + for (index = 0; index < metablock.numRegionRects; index++) + { + quantQualityVal = &(metablock.quantQualityVals[index]); + Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */ + Stream_Read_UINT8(s, quantQualityVal->qualityVal); /* qualityVal (1 byte) */ + + quantQualityVal->qp = quantQualityVal->qpVal & 0x3F; + quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1; + quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1; + + printf("quantQualityVals[%d]: qp: %d r: %d p: %d qualityVal: %d\n", + index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal); + } + + free(metablock.regionRects); + free(metablock.quantQualityVals); + + return 1; +} + int rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { + wStream* s; + + s = Stream_New(cmd->data, cmd->length); + + rdpgfx_read_h264_metablock(gfx, s); + + Stream_Free(s, FALSE); + return 1; } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index f50010f93..b91ed88cf 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -426,6 +426,9 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.length = pdu.bitmapDataLength; cmd.data = pdu.bitmapData; + if (cmd.codecId == RDPGFX_CODECID_H264) + rdpgfx_decode(gfx, &cmd); + if (context && context->SurfaceCommand) { context->SurfaceCommand(context, &cmd); diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index e4070194b..f0bdbc4ce 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -332,5 +332,26 @@ struct _RDPGFX_MAP_SURFACE_TO_WINDOW_PDU }; typedef struct _RDPGFX_MAP_SURFACE_TO_WINDOW_PDU RDPGFX_MAP_SURFACE_TO_WINDOW_PDU; +/* H264 */ + +struct _RDPGFX_H264_QUANT_QUALITY +{ + BYTE qpVal; + BYTE qualityVal; + + BYTE qp; + BYTE r; + BYTE p; +}; +typedef struct _RDPGFX_H264_QUANT_QUALITY RDPGFX_H264_QUANT_QUALITY; + +struct _RDPGFX_H264_METABLOCK +{ + UINT32 numRegionRects; + RDPGFX_RECT16* regionRects; + RDPGFX_H264_QUANT_QUALITY* quantQualityVals; +}; +typedef struct _RDPGFX_H264_METABLOCK RDPGFX_H264_METABLOCK; + #endif /* FREERDP_CHANNEL_RDPGFX_H */ diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index f690b3f23..ba5992670 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -171,7 +171,7 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, if (!h264 || !h264->pDecoder) return -1; -#if 0 +#if 1 printf("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 @@ -214,7 +214,7 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; -#if 0 +#if 1 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, @@ -314,8 +314,12 @@ H264_CONTEXT* h264_context_new(BOOL Compressor) } ZeroMemory(&sDecParam, sizeof(sDecParam)); - sDecParam.iOutputColorFormat = videoFormatARGB; + sDecParam.iOutputColorFormat = videoFormatI420; + sDecParam.uiEcActiveFlag = 1; + sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; + status = (*h264->pDecoder)->Initialize(h264->pDecoder, &sDecParam); + if (status != 0) { printf("Failed to initialize OpenH264 decoder (status=%ld)\n", status); @@ -323,6 +327,7 @@ H264_CONTEXT* h264_context_new(BOOL Compressor) } status = (*h264->pDecoder)->SetOption(h264->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat); + if (status != 0) { printf("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status);