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"
33#define TAG CHANNELS_TAG("rdpgfx.client")
45 UINT error = ERROR_INVALID_DATA;
46 meta->regionRects = NULL;
47 meta->quantQualityVals = NULL;
49 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
52 Stream_Read_UINT32(s, meta->numRegionRects);
54 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, meta->numRegionRects, 8ull))
59 if (!meta->regionRects)
61 WLog_ERR(TAG,
"malloc failed!");
62 error = CHANNEL_RC_NO_MEMORY;
66 meta->quantQualityVals =
69 if (!meta->quantQualityVals)
71 WLog_ERR(TAG,
"malloc failed!");
72 error = CHANNEL_RC_NO_MEMORY;
76 WLog_DBG(TAG,
"H264_METABLOCK: numRegionRects: %" PRIu32
"", meta->numRegionRects);
78 for (UINT32 index = 0; index < meta->numRegionRects; index++)
80 regionRect = &(meta->regionRects[index]);
82 if ((error = rdpgfx_read_rect16(s, regionRect)))
84 WLog_ERR(TAG,
"rdpgfx_read_rect16 failed with error %" PRIu32
"!", error);
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_CheckAndLogRequiredLengthOfSize(TAG, 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;
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);
130 RdpgfxClientContext* context = gfx->context;
131 wStream* s = Stream_New(cmd->data, cmd->length);
135 WLog_ERR(TAG,
"Stream_New failed!");
136 return CHANNEL_RC_NO_MEMORY;
139 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta))))
141 Stream_Free(s, FALSE);
142 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
146 h264.data = Stream_Pointer(s);
147 h264.length = (UINT32)Stream_GetRemainingLength(s);
148 Stream_Free(s, FALSE);
149 cmd->extra = (
void*)&h264;
153 IFCALLRET(context->SurfaceCommand, error, context, cmd);
156 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
159 free_h264_metablock(&h264.meta);
177 RdpgfxClientContext* context = gfx->context;
178 wStream* s = Stream_New(cmd->data, cmd->length);
182 WLog_ERR(TAG,
"Stream_New failed!");
183 return CHANNEL_RC_NO_MEMORY;
186 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
188 error = ERROR_INVALID_DATA;
192 Stream_Read_UINT32(s, tmp);
193 h264.cbAvc420EncodedBitstream1 = tmp & 0x3FFFFFFFUL;
194 h264.LC = (tmp >> 30UL) & 0x03UL;
198 error = ERROR_INVALID_DATA;
202 pos1 = Stream_GetPosition(s);
204 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
206 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
210 pos2 = Stream_GetPosition(s);
211 h264.bitstream[0].data = Stream_Pointer(s);
215 const size_t bitstreamLen = 1ULL * h264.cbAvc420EncodedBitstream1 - pos2 + pos1;
217 if ((bitstreamLen > UINT32_MAX) || !Stream_CheckAndLogRequiredLength(TAG, s, bitstreamLen))
219 error = ERROR_INVALID_DATA;
223 h264.bitstream[0].length = (UINT32)bitstreamLen;
224 Stream_Seek(s, bitstreamLen);
226 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
228 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
232 h264.bitstream[1].data = Stream_Pointer(s);
234 const size_t len = Stream_GetRemainingLength(s);
235 if (len > UINT32_MAX)
237 h264.bitstream[1].length = (UINT32)len;
241 const size_t len = Stream_GetRemainingLength(s);
242 if (len > UINT32_MAX)
244 h264.bitstream[0].length = (UINT32)len;
247 cmd->extra = (
void*)&h264;
251 IFCALLRET(context->SurfaceCommand, error, context, cmd);
254 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
258 Stream_Free(s, FALSE);
259 free_h264_metablock(&h264.bitstream[0].meta);
260 free_h264_metablock(&h264.bitstream[1].meta);
272 UINT error = CHANNEL_RC_OK;
273 RdpgfxClientContext* context = gfx->context;
274 PROFILER_ENTER(context->SurfaceProfiler)
276 switch (cmd->codecId)
278 case RDPGFX_CODECID_AVC420:
279 if ((error = rdpgfx_decode_AVC420(gfx, cmd)))
280 WLog_ERR(TAG,
"rdpgfx_decode_AVC420 failed with error %" PRIu32
"", error);
284 case RDPGFX_CODECID_AVC444:
285 case RDPGFX_CODECID_AVC444v2:
286 if ((error = rdpgfx_decode_AVC444(gfx, cmd)))
287 WLog_ERR(TAG,
"rdpgfx_decode_AVC444 failed with error %" PRIu32
"", error);
294 IFCALLRET(context->SurfaceCommand, error, context, cmd);
297 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
303 PROFILER_EXIT(context->SurfaceProfiler)