channels/rdpgfx: parse H264 bitmap stream and meta block

This commit is contained in:
Marc-André Moreau 2014-07-08 17:37:29 -04:00
parent f7e5365719
commit 6f1acb01dd
4 changed files with 69 additions and 23 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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 */