25#include <freerdp/config.h>
31#include <winpr/assert.h>
32#include <winpr/cast.h>
34#include <winpr/print.h>
35#include <winpr/sysinfo.h>
36#include <winpr/bitstream.h>
37#include <winpr/intrin.h>
39#include "rfx_bitstream.h"
52#define GetMinBits(_val, _nbits) \
68static inline uint32_t UpdateParam(uint32_t* param, int32_t deltaP)
73 const uint32_t udeltaP = WINPR_ASSERTING_INT_CAST(uint32_t, -deltaP);
80 *param += WINPR_ASSERTING_INT_CAST(uint32_t, deltaP);
84 return (*param) >> LSGR;
87static BOOL g_LZCNT = FALSE;
89static INIT_ONCE rfx_rlgr_init_once = INIT_ONCE_STATIC_INIT;
91static BOOL CALLBACK rfx_rlgr_init(
PINIT_ONCE once, PVOID param, PVOID* context)
95 WINPR_UNUSED(context);
97 g_LZCNT = IsProcessorFeaturePresentEx(PF_EX_LZCNT);
101static INLINE UINT32 lzcnt_s(UINT32 x)
113 WINPR_ASSERT(n >= 16);
120 WINPR_ASSERT(n >= 8);
127 WINPR_ASSERT(n >= 4);
134 WINPR_ASSERT(n >= 2);
141 WINPR_ASSERT(n >= 2);
145 WINPR_ASSERT(n >= x);
152int rfx_rlgr_decode(RLGR_MODE mode,
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
153 INT16* WINPR_RESTRICT pDstData, UINT32 rDstSize)
170 INT16* pOutput = NULL;
173 const SSIZE_T DstSize = rDstSize;
175 InitOnceExecuteOnce(&rfx_rlgr_init_once, rfx_rlgr_init, NULL, NULL);
183 if ((mode != RLGR1) && (mode != RLGR3))
186 if (!pSrcData || !SrcSize)
189 if (!pDstData || !DstSize)
196 BitStream_Attach(bs, pSrcData, SrcSize);
199 while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize))
209 cnt = lzcnt_s(bs->accumulator);
211 size_t nbits = BitStream_GetRemainingLength(bs);
214 cnt = WINPR_ASSERTING_INT_CAST(uint32_t, nbits);
216 vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
218 while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
220 BitStream_Shift32(bs);
222 cnt = lzcnt_s(bs->accumulator);
224 nbits = BitStream_GetRemainingLength(bs);
229 WINPR_ASSERT(cnt + vk <= UINT32_MAX);
230 vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
233 BitStream_Shift(bs, (vk % 32));
235 if (BitStream_GetRemainingLength(bs) < 1)
238 BitStream_Shift(bs, 1);
242 const UINT32 add = (1 << k);
257 if (BitStream_GetRemainingLength(bs) < k)
260 bs->mask = ((1 << k) - 1);
261 run += ((bs->accumulator >> (32 - k)) & bs->mask);
262 BitStream_Shift(bs, k);
266 if (BitStream_GetRemainingLength(bs) < 1)
269 sign = (bs->accumulator & 0x80000000) ? 1 : 0;
270 BitStream_Shift(bs, 1);
274 cnt = lzcnt_s(~(bs->accumulator));
276 nbits = BitStream_GetRemainingLength(bs);
281 vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
283 while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
285 BitStream_Shift32(bs);
287 cnt = lzcnt_s(~(bs->accumulator));
289 nbits = BitStream_GetRemainingLength(bs);
294 WINPR_ASSERT(cnt + vk <= UINT32_MAX);
295 vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
298 BitStream_Shift(bs, (vk % 32));
300 if (BitStream_GetRemainingLength(bs) < 1)
303 BitStream_Shift(bs, 1);
307 if (BitStream_GetRemainingLength(bs) < kr)
310 bs->mask = ((1 << kr) - 1);
312 code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
315 BitStream_Shift(bs, kr);
356 mag = WINPR_ASSERTING_INT_CAST(int16_t, (code + 1)) * -1;
358 mag = WINPR_ASSERTING_INT_CAST(int16_t, code + 1);
362 offset = WINPR_ASSERTING_INT_CAST(
size_t, (pOutput)-pDstData);
365 if ((offset + size) > rDstSize)
366 size = WINPR_ASSERTING_INT_CAST(
size_t, DstSize) - offset;
370 ZeroMemory(pOutput, size *
sizeof(INT16));
374 if ((pOutput - pDstData) < DstSize)
386 cnt = lzcnt_s(~(bs->accumulator));
388 size_t nbits = BitStream_GetRemainingLength(bs);
393 vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
395 while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
397 BitStream_Shift32(bs);
399 cnt = lzcnt_s(~(bs->accumulator));
401 nbits = BitStream_GetRemainingLength(bs);
406 WINPR_ASSERT(cnt + vk <= UINT32_MAX);
407 vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
410 BitStream_Shift(bs, (vk % 32));
412 if (BitStream_GetRemainingLength(bs) < 1)
415 BitStream_Shift(bs, 1);
419 if (BitStream_GetRemainingLength(bs) < kr)
422 bs->mask = ((1 << kr) - 1);
424 code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
427 BitStream_Shift(bs, kr);
442 kr = (krp >> LSGR) & UINT32_MAX;
488 mag = WINPR_ASSERTING_INT_CAST(INT16, (code + 1) >> 1) * -1;
490 mag = WINPR_ASSERTING_INT_CAST(INT16, code >> 1);
493 if ((pOutput - pDstData) < DstSize)
499 else if (mode == RLGR3)
505 mag = WINPR_ASSERTING_INT_CAST(int16_t, code);
506 nIdx = 32 - lzcnt_s(WINPR_ASSERTING_INT_CAST(uint32_t, mag));
509 if (BitStream_GetRemainingLength(bs) < nIdx)
512 bs->mask = ((1 << nIdx) - 1);
514 val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask);
517 BitStream_Shift(bs, nIdx);
532 else if (!val1 && !val2)
545 mag = WINPR_ASSERTING_INT_CAST(int16_t, (val1 + 1) >> 1) * -1;
547 mag = WINPR_ASSERTING_INT_CAST(int16_t, val1 >> 1);
549 if ((pOutput - pDstData) < DstSize)
556 mag = WINPR_ASSERTING_INT_CAST(int16_t, (val2 + 1) >> 1) * -1;
558 mag = WINPR_ASSERTING_INT_CAST(int16_t, val2 >> 1);
560 if ((pOutput - pDstData) < DstSize)
562 *pOutput = WINPR_ASSERTING_INT_CAST(int16_t, mag);
569 offset = WINPR_ASSERTING_INT_CAST(
size_t, (pOutput - pDstData));
571 if (offset < rDstSize)
573 size = WINPR_ASSERTING_INT_CAST(
size_t, DstSize) - offset;
574 ZeroMemory(pOutput, size * 2);
578 offset = WINPR_ASSERTING_INT_CAST(
size_t, (pOutput - pDstData));
580 if ((DstSize < 0) || (offset != (
size_t)DstSize))
587#define GetNextInput(_n) \
602#define OutputBits(numBits, bitPattern) rfx_bitstream_put_bits(bs, bitPattern, numBits)
605static inline void OutputBit(
RFX_BITSTREAM* bs, uint32_t count, UINT8 bit)
607 UINT16 _b = ((bit) ? 0xFFFF : 0);
608 const uint32_t rem = count % 16;
609 for (uint32_t x = 0; x < count - rem; x += 16)
610 rfx_bitstream_put_bits(bs, _b, 16);
613 rfx_bitstream_put_bits(bs, _b, rem);
618static inline UINT32 Get2MagSign(INT32 input)
621 return WINPR_ASSERTING_INT_CAST(UINT32, 2 * input);
622 return WINPR_ASSERTING_INT_CAST(UINT32, -2 * input - 1);
626#define CodeGR(krp, val) rfx_rlgr_code_gr(bs, krp, val)
628static void rfx_rlgr_code_gr(
RFX_BITSTREAM* bs, uint32_t* krp, UINT32 val)
630 uint32_t kr = *krp >> LSGR;
634 const uint32_t vk = val >> kr;
635 OutputBit(bs, vk, 1);
641 OutputBits(kr, val & ((1 << kr) - 1));
647 (void)UpdateParam(krp, -2);
651 (void)UpdateParam(krp, WINPR_CXX_COMPAT_CAST(int32_t, vk));
655int rfx_rlgr_encode(RLGR_MODE mode,
const INT16* WINPR_RESTRICT data, UINT32 data_size,
656 BYTE* WINPR_RESTRICT buffer, UINT32 buffer_size)
666 rfx_bitstream_attach(bs, buffer, buffer_size);
674 while (data_size > 0)
680 uint32_t numZeros = 0;
689 while (input == 0 && data_size > 0)
697 while (numZeros >= runmax)
701 k = UpdateParam(&kp, UP_GR);
709 OutputBits(k, numZeros);
716 (UINT32)(input < 0 ? -input : input);
717 sign = (input < 0 ? 1 : 0);
719 OutputBit(bs, 1, sign);
720 CodeGR(&krp, mag ? mag - 1 : 0);
722 k = UpdateParam(&kp, -DN_GR);
736 twoMs = Get2MagSign(input);
744 k = UpdateParam(&kp, -DQ_GR);
748 k = UpdateParam(&kp, UQ_GR);
764 twoMs1 = Get2MagSign(input);
766 twoMs2 = Get2MagSign(input);
767 sum2Ms = twoMs1 + twoMs2;
769 CodeGR(&krp, sum2Ms);
772 GetMinBits(sum2Ms, nIdx);
773 OutputBits(nIdx, twoMs1);
777 if (twoMs1 && twoMs2)
779 k = UpdateParam(&kp, -2 * DQ_GR);
781 else if (!twoMs1 && !twoMs2)
783 k = UpdateParam(&kp, 2 * UQ_GR);
789 rfx_bitstream_flush(bs);
790 uint32_t processed_size = rfx_bitstream_get_processed_bytes(bs);
791 winpr_aligned_free(bs);
793 return WINPR_ASSERTING_INT_CAST(
int, processed_size);