22#include <freerdp/config.h>
25#include <winpr/stream.h>
26#include <freerdp/log.h>
27#include <freerdp/utils/profiler.h>
29#include "rdpgfx_common.h"
31#include "rdpgfx_codec.h"
43 UINT error = ERROR_INVALID_DATA;
44 meta->regionRects =
nullptr;
45 meta->quantQualityVals =
nullptr;
47 if (!Stream_CheckAndLogRequiredLengthWLog(gfx->base.log, s, 4))
50 Stream_Read_UINT32(s, meta->numRegionRects);
52 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(gfx->base.log, s, meta->numRegionRects, 8ull))
57 if (!meta->regionRects)
59 WLog_Print(gfx->base.log, WLOG_ERROR,
"malloc failed!");
60 error = CHANNEL_RC_NO_MEMORY;
64 meta->quantQualityVals =
67 if (!meta->quantQualityVals)
69 WLog_Print(gfx->base.log, WLOG_ERROR,
"malloc failed!");
70 error = CHANNEL_RC_NO_MEMORY;
74 WLog_Print(gfx->base.log, WLOG_TRACE,
"H264_METABLOCK: numRegionRects: %" PRIu32
"",
75 meta->numRegionRects);
77 for (UINT32 index = 0; index < meta->numRegionRects; index++)
79 regionRect = &(meta->regionRects[index]);
81 if ((error = rdpgfx_read_rect16(gfx->base.log, s, regionRect)))
83 WLog_Print(gfx->base.log, WLOG_ERROR,
84 "rdpgfx_read_rect16 failed with error %" PRIu32
"!", error);
88 WLog_Print(gfx->base.log, WLOG_TRACE,
89 "regionRects[%" PRIu32
"]: left: %" PRIu16
" top: %" PRIu16
" right: %" PRIu16
90 " bottom: %" PRIu16
"",
91 index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom);
94 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(gfx->base.log, s, meta->numRegionRects, 2ull))
96 error = ERROR_INVALID_DATA;
100 for (UINT32 index = 0; index < meta->numRegionRects; index++)
102 quantQualityVal = &(meta->quantQualityVals[index]);
103 Stream_Read_UINT8(s, quantQualityVal->qpVal);
104 Stream_Read_UINT8(s, quantQualityVal->qualityVal);
105 quantQualityVal->qp = quantQualityVal->qpVal & 0x3F;
106 quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1;
107 quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1;
108 WLog_Print(gfx->base.log, WLOG_TRACE,
109 "quantQualityVals[%" PRIu32
"]: qp: %" PRIu8
" r: %" PRIu8
" p: %" PRIu8
110 " qualityVal: %" PRIu8
"",
111 index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p,
112 quantQualityVal->qualityVal);
115 return CHANNEL_RC_OK;
117 free_h264_metablock(meta);
125 WLog_Print(gfx->base.log, WLOG_DEBUG,
"Got GFX %s",
126 rdpgfx_get_codec_id_string(WINPR_ASSERTING_INT_CAST(UINT16, cmd->codecId)));
128 RdpgfxClientContext* context = gfx->context;
130 return CHANNEL_RC_OK;
132 const UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->SurfaceCommand, context, cmd);
135 WLog_Print(gfx->base.log, WLOG_ERROR,
136 "context->SurfaceCommand failed with error %" PRIu32
"", error);
148 wStream* s = Stream_New(cmd->data, cmd->length);
152 WLog_Print(gfx->base.log, WLOG_ERROR,
"Stream_New failed!");
153 return CHANNEL_RC_NO_MEMORY;
156 UINT error = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta));
157 if (error != CHANNEL_RC_OK)
159 Stream_Free(s, FALSE);
160 WLog_Print(gfx->base.log, WLOG_ERROR,
161 "rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
165 h264.data = Stream_Pointer(s);
166 h264.length = (UINT32)Stream_GetRemainingLength(s);
167 Stream_Free(s, FALSE);
168 cmd->extra = (
void*)&h264;
170 error = logSurfaceCommand(gfx, cmd);
172 free_h264_metablock(&h264.meta);
173 cmd->extra =
nullptr;
184 UINT error = CHANNEL_RC_OK;
190 wStream* s = Stream_New(cmd->data, cmd->length);
194 WLog_Print(gfx->base.log, WLOG_ERROR,
"Stream_New failed!");
195 return CHANNEL_RC_NO_MEMORY;
198 if (!Stream_CheckAndLogRequiredLengthWLog(gfx->base.log, s, 4))
200 error = ERROR_INVALID_DATA;
204 Stream_Read_UINT32(s, tmp);
205 h264.cbAvc420EncodedBitstream1 = tmp & 0x3FFFFFFFUL;
206 h264.LC = (tmp >> 30UL) & 0x03UL;
210 error = ERROR_INVALID_DATA;
214 pos1 = Stream_GetPosition(s);
216 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
218 WLog_Print(gfx->base.log, WLOG_ERROR,
219 "rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
223 pos2 = Stream_GetPosition(s);
224 h264.bitstream[0].data = Stream_Pointer(s);
228 const size_t bitstreamLen = 1ULL * h264.cbAvc420EncodedBitstream1 - pos2 + pos1;
230 if ((bitstreamLen > UINT32_MAX) ||
231 !Stream_CheckAndLogRequiredLengthWLog(gfx->base.log, s, bitstreamLen))
233 error = ERROR_INVALID_DATA;
237 h264.bitstream[0].length = (UINT32)bitstreamLen;
238 Stream_Seek(s, bitstreamLen);
240 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
242 WLog_Print(gfx->base.log, WLOG_ERROR,
243 "rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
247 h264.bitstream[1].data = Stream_Pointer(s);
249 const size_t len = Stream_GetRemainingLength(s);
250 if (len > UINT32_MAX)
252 h264.bitstream[1].length = (UINT32)len;
256 const size_t len = Stream_GetRemainingLength(s);
257 if (len > UINT32_MAX)
259 h264.bitstream[0].length = (UINT32)len;
262 cmd->extra = (
void*)&h264;
264 error = logSurfaceCommand(gfx, cmd);
267 Stream_Free(s, FALSE);
268 free_h264_metablock(&h264.bitstream[0].meta);
269 free_h264_metablock(&h264.bitstream[1].meta);
270 cmd->extra =
nullptr;
281 UINT error = CHANNEL_RC_OK;
282 PROFILER_ENTER(context->SurfaceProfiler)
284 switch (cmd->codecId)
286 case RDPGFX_CODECID_AVC420:
287 if ((error = rdpgfx_decode_AVC420(gfx, cmd)))
288 WLog_Print(gfx->base.log, WLOG_ERROR,
289 "rdpgfx_decode_AVC420 failed with error %" PRIu32
"", error);
293 case RDPGFX_CODECID_AVC444:
294 case RDPGFX_CODECID_AVC444v2:
295 if ((error = rdpgfx_decode_AVC444(gfx, cmd)))
296 WLog_Print(gfx->base.log, WLOG_ERROR,
297 "rdpgfx_decode_AVC444 failed with error %" PRIu32
"", error);
302 error = logSurfaceCommand(gfx, cmd);
306 PROFILER_EXIT(context->SurfaceProfiler)