22 #include <freerdp/config.h>
24 #include <winpr/crt.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")
44 UINT error = ERROR_INVALID_DATA;
45 meta->regionRects = NULL;
46 meta->quantQualityVals = NULL;
48 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
51 Stream_Read_UINT32(s, meta->numRegionRects);
53 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, meta->numRegionRects, 8ull))
58 if (!meta->regionRects)
60 WLog_ERR(TAG,
"malloc failed!");
61 error = CHANNEL_RC_NO_MEMORY;
65 meta->quantQualityVals =
68 if (!meta->quantQualityVals)
70 WLog_ERR(TAG,
"malloc failed!");
71 error = CHANNEL_RC_NO_MEMORY;
75 WLog_DBG(TAG,
"H264_METABLOCK: numRegionRects: %" PRIu32
"", meta->numRegionRects);
77 for (UINT32 index = 0; index < meta->numRegionRects; index++)
79 regionRect = &(meta->regionRects[index]);
81 if ((error = rdpgfx_read_rect16(s, regionRect)))
83 WLog_ERR(TAG,
"rdpgfx_read_rect16 failed with error %" PRIu32
"!", error);
88 "regionRects[%" PRIu32
"]: left: %" PRIu16
" top: %" PRIu16
" right: %" PRIu16
89 " bottom: %" PRIu16
"",
90 index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom);
93 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, meta->numRegionRects, 2ull))
95 error = ERROR_INVALID_DATA;
99 for (UINT32 index = 0; index < meta->numRegionRects; index++)
101 quantQualityVal = &(meta->quantQualityVals[index]);
102 Stream_Read_UINT8(s, quantQualityVal->qpVal);
103 Stream_Read_UINT8(s, quantQualityVal->qualityVal);
104 quantQualityVal->qp = quantQualityVal->qpVal & 0x3F;
105 quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1;
106 quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1;
108 "quantQualityVals[%" PRIu32
"]: qp: %" PRIu8
" r: %" PRIu8
" p: %" PRIu8
109 " qualityVal: %" PRIu8
"",
110 index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p,
111 quantQualityVal->qualityVal);
114 return CHANNEL_RC_OK;
116 free_h264_metablock(meta);
129 RdpgfxClientContext* context = gfx->context;
130 wStream* s = Stream_New(cmd->data, cmd->length);
134 WLog_ERR(TAG,
"Stream_New failed!");
135 return CHANNEL_RC_NO_MEMORY;
138 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta))))
140 Stream_Free(s, FALSE);
141 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
145 h264.data = Stream_Pointer(s);
146 h264.length = (UINT32)Stream_GetRemainingLength(s);
147 Stream_Free(s, FALSE);
148 cmd->extra = (
void*)&h264;
152 IFCALLRET(context->SurfaceCommand, error, context, cmd);
155 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
158 free_h264_metablock(&h264.meta);
176 RdpgfxClientContext* context = gfx->context;
177 wStream* s = Stream_New(cmd->data, cmd->length);
181 WLog_ERR(TAG,
"Stream_New failed!");
182 return CHANNEL_RC_NO_MEMORY;
185 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
187 error = ERROR_INVALID_DATA;
191 Stream_Read_UINT32(s, tmp);
192 h264.cbAvc420EncodedBitstream1 = tmp & 0x3FFFFFFFUL;
193 h264.LC = (tmp >> 30UL) & 0x03UL;
197 error = ERROR_INVALID_DATA;
201 pos1 = Stream_GetPosition(s);
203 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
205 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
209 pos2 = Stream_GetPosition(s);
210 h264.bitstream[0].data = Stream_Pointer(s);
214 const size_t bitstreamLen = 1ULL * h264.cbAvc420EncodedBitstream1 - pos2 + pos1;
216 if ((bitstreamLen > UINT32_MAX) || !Stream_CheckAndLogRequiredLength(TAG, s, bitstreamLen))
218 error = ERROR_INVALID_DATA;
222 h264.bitstream[0].length = (UINT32)bitstreamLen;
223 Stream_Seek(s, bitstreamLen);
225 if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
227 WLog_ERR(TAG,
"rdpgfx_read_h264_metablock failed with error %" PRIu32
"!", error);
231 h264.bitstream[1].data = Stream_Pointer(s);
233 const size_t len = Stream_GetRemainingLength(s);
234 if (len > UINT32_MAX)
236 h264.bitstream[1].length = (UINT32)len;
240 const size_t len = Stream_GetRemainingLength(s);
241 if (len > UINT32_MAX)
243 h264.bitstream[0].length = (UINT32)len;
246 cmd->extra = (
void*)&h264;
250 IFCALLRET(context->SurfaceCommand, error, context, cmd);
253 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
257 Stream_Free(s, FALSE);
258 free_h264_metablock(&h264.bitstream[0].meta);
259 free_h264_metablock(&h264.bitstream[1].meta);
271 UINT error = CHANNEL_RC_OK;
272 RdpgfxClientContext* context = gfx->context;
273 PROFILER_ENTER(context->SurfaceProfiler)
275 switch (cmd->codecId)
277 case RDPGFX_CODECID_AVC420:
278 if ((error = rdpgfx_decode_AVC420(gfx, cmd)))
279 WLog_ERR(TAG,
"rdpgfx_decode_AVC420 failed with error %" PRIu32
"", error);
283 case RDPGFX_CODECID_AVC444:
284 case RDPGFX_CODECID_AVC444v2:
285 if ((error = rdpgfx_decode_AVC444(gfx, cmd)))
286 WLog_ERR(TAG,
"rdpgfx_decode_AVC444 failed with error %" PRIu32
"", error);
293 IFCALLRET(context->SurfaceCommand, error, context, cmd);
296 WLog_ERR(TAG,
"context->SurfaceCommand failed with error %" PRIu32
"", error);
302 PROFILER_EXIT(context->SurfaceProfiler)