diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index 74d0a0dcc..4881db399 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -48,39 +48,47 @@ int rdpgfx_decode_planar(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) return 1; } -int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s) +int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METABLOCK* meta) { 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) + if (Stream_GetRemainingLength(s) < 4) return -1; - metablock.quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(metablock.numRegionRects * sizeof(RDPGFX_H264_QUANT_QUALITY)); + Stream_Read_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */ - if (!metablock.quantQualityVals) + if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 8)) return -1; - printf("H264_METABLOCK: numRegionRects: %d\n", (int) metablock.numRegionRects); + meta->regionRects = (RDPGFX_RECT16*) malloc(meta->numRegionRects * sizeof(RDPGFX_RECT16)); - for (index = 0; index < metablock.numRegionRects; index++) + if (!meta->regionRects) + return -1; + + meta->quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) malloc(meta->numRegionRects * sizeof(RDPGFX_H264_QUANT_QUALITY)); + + if (!meta->quantQualityVals) + return -1; + + printf("H264_METABLOCK: numRegionRects: %d\n", (int) meta->numRegionRects); + + for (index = 0; index < meta->numRegionRects; index++) { - regionRect = &(metablock.regionRects[index]); + regionRect = &(meta->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++) + if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 2)) + return -1; + + for (index = 0; index < meta->numRegionRects; index++) { - quantQualityVal = &(metablock.quantQualityVals[index]); + quantQualityVal = &(meta->quantQualityVals[index]); Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */ Stream_Read_UINT8(s, quantQualityVal->qualityVal); /* qualityVal (1 byte) */ @@ -92,22 +100,41 @@ int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s) 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) { + int status; wStream* s; + RDPGFX_H264_BITMAP_STREAM h264; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; s = Stream_New(cmd->data, cmd->length); - rdpgfx_read_h264_metablock(gfx, s); + if (!s) + return -1; + + status = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta)); + + if (status < 0) + return -1; + + h264.data = Stream_Pointer(s); + h264.length = (UINT32) Stream_GetRemainingLength(s); Stream_Free(s, FALSE); + cmd->extra = (void*) &h264; + + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, cmd); + } + + free(h264.meta.regionRects); + free(h264.meta.quantQualityVals); + return 1; } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index b91ed88cf..f778e163b 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -427,11 +427,15 @@ int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream cmd.data = pdu.bitmapData; if (cmd.codecId == RDPGFX_CODECID_H264) - rdpgfx_decode(gfx, &cmd); - - if (context && context->SurfaceCommand) { - context->SurfaceCommand(context, &cmd); + rdpgfx_decode(gfx, &cmd); + } + else + { + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, &cmd); + } } return 1; diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 69dacdaee..7778d18a1 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -339,6 +339,12 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_ BYTE* DstData = NULL; xfGfxSurface* surface; RECTANGLE_16 invalidRect; + RDPGFX_H264_BITMAP_STREAM* h264; + + h264 = (RDPGFX_H264_BITMAP_STREAM*) cmd->extra; + + if (!h264) + return -1; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); @@ -348,7 +354,7 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_ DstData = surface->data; #if 1 - status = h264_decompress(xfc->h264, cmd->data, cmd->length, &DstData, + status = h264_decompress(xfc->h264, h264->data, h264->length, &DstData, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); #else status = -1; diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index f0bdbc4ce..24943ff5f 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -179,6 +179,7 @@ struct _RDPGFX_SURFACE_COMMAND UINT32 height; UINT32 length; BYTE* data; + void* extra; }; typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND; @@ -353,5 +354,13 @@ struct _RDPGFX_H264_METABLOCK }; typedef struct _RDPGFX_H264_METABLOCK RDPGFX_H264_METABLOCK; +struct _RDPGFX_H264_BITMAP_STREAM +{ + RDPGFX_H264_METABLOCK meta; + UINT32 length; + BYTE* data; +}; +typedef struct _RDPGFX_H264_BITMAP_STREAM RDPGFX_H264_BITMAP_STREAM; + #endif /* FREERDP_CHANNEL_RDPGFX_H */