Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/libfreerdp/codec/rfx_rlgr.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * RemoteFX Codec Library - RLGR
4
 *
5
 * Copyright 2011 Vic Lee
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
/**
21
 * This implementation of RLGR refers to
22
 * [MS-RDPRFX] 3.1.8.1.7.3 RLGR1/RLGR3 Pseudocode
23
 */
24
25
#include <freerdp/config.h>
26
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include <winpr/assert.h>
32
#include <winpr/cast.h>
33
#include <winpr/crt.h>
34
#include <winpr/print.h>
35
#include <winpr/sysinfo.h>
36
#include <winpr/bitstream.h>
37
#include <winpr/intrin.h>
38
39
#include "rfx_bitstream.h"
40
41
#include "rfx_rlgr.h"
42
43
/* Constants used in RLGR1/RLGR3 algorithm */
44
0
#define KPMAX (80) /* max value for kp or krp */
45
0
#define LSGR (3)   /* shift count to convert kp to k */
46
0
#define UP_GR (4)  /* increase in kp after a zero run in RL mode */
47
0
#define DN_GR (6)  /* decrease in kp after a nonzero symbol in RL mode */
48
0
#define UQ_GR (3)  /* increase in kp after nonzero symbol in GR mode */
49
0
#define DQ_GR (3)  /* decrease in kp after zero symbol in GR mode */
50
51
/* Returns the least number of bits required to represent a given value */
52
#define GetMinBits(_val, _nbits) \
53
0
  do                           \
54
0
  {                            \
55
0
    UINT32 _v = (_val);      \
56
0
    (_nbits) = 0;            \
57
0
    while (_v)               \
58
0
    {                        \
59
0
      _v >>= 1;            \
60
0
      (_nbits)++;          \
61
0
    }                        \
62
0
  } while (0)
63
64
/*
65
 * Update the passed parameter and clamp it to the range [0, KPMAX]
66
 * Return the value of parameter right-shifted by LSGR
67
 */
68
static inline uint32_t UpdateParam(uint32_t* param, int32_t deltaP)
69
0
{
70
0
  WINPR_ASSERT(param);
71
0
  if (deltaP < 0)
72
0
  {
73
0
    const uint32_t udeltaP = WINPR_ASSERTING_INT_CAST(uint32_t, -deltaP);
74
0
    if (udeltaP > *param)
75
0
      *param = 0;
76
0
    else
77
0
      *param -= udeltaP;
78
0
  }
79
0
  else
80
0
    *param += WINPR_ASSERTING_INT_CAST(uint32_t, deltaP);
81
82
0
  if ((*param) > KPMAX)
83
0
    (*param) = KPMAX;
84
0
  return (*param) >> LSGR;
85
0
}
86
87
static BOOL g_LZCNT = FALSE;
88
89
static INIT_ONCE rfx_rlgr_init_once = INIT_ONCE_STATIC_INIT;
90
91
static BOOL CALLBACK rfx_rlgr_init(PINIT_ONCE once, PVOID param, PVOID* context)
92
0
{
93
0
  WINPR_UNUSED(once);
94
0
  WINPR_UNUSED(param);
95
0
  WINPR_UNUSED(context);
96
97
0
  g_LZCNT = IsProcessorFeaturePresentEx(PF_EX_LZCNT);
98
0
  return TRUE;
99
0
}
100
101
static INLINE UINT32 lzcnt_s(UINT32 x)
102
0
{
103
0
  if (!x)
104
0
    return 32;
105
106
0
  if (!g_LZCNT)
107
0
  {
108
0
    UINT32 y = 0;
109
0
    UINT32 n = 32;
110
0
    y = x >> 16;
111
0
    if (y != 0)
112
0
    {
113
0
      WINPR_ASSERT(n >= 16);
114
0
      n = n - 16;
115
0
      x = y;
116
0
    }
117
0
    y = x >> 8;
118
0
    if (y != 0)
119
0
    {
120
0
      WINPR_ASSERT(n >= 8);
121
0
      n = n - 8;
122
0
      x = y;
123
0
    }
124
0
    y = x >> 4;
125
0
    if (y != 0)
126
0
    {
127
0
      WINPR_ASSERT(n >= 4);
128
0
      n = n - 4;
129
0
      x = y;
130
0
    }
131
0
    y = x >> 2;
132
0
    if (y != 0)
133
0
    {
134
0
      WINPR_ASSERT(n >= 2);
135
0
      n = n - 2;
136
0
      x = y;
137
0
    }
138
0
    y = x >> 1;
139
0
    if (y != 0)
140
0
    {
141
0
      WINPR_ASSERT(n >= 2);
142
0
      return n - 2;
143
0
    }
144
145
0
    WINPR_ASSERT(n >= x);
146
0
    return n - x;
147
0
  }
148
149
0
  return __lzcnt(x);
150
0
}
151
152
int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
153
                    INT16* WINPR_RESTRICT pDstData, UINT32 rDstSize)
154
0
{
155
0
  uint32_t vk = 0;
156
0
  size_t run = 0;
157
0
  size_t cnt = 0;
158
0
  size_t size = 0;
159
0
  size_t offset = 0;
160
0
  INT16 mag = 0;
161
0
  UINT32 k = 0;
162
0
  UINT32 kp = 0;
163
0
  UINT32 kr = 0;
164
0
  UINT32 krp = 0;
165
0
  UINT16 code = 0;
166
0
  UINT32 sign = 0;
167
0
  UINT32 nIdx = 0;
168
0
  UINT32 val1 = 0;
169
0
  UINT32 val2 = 0;
170
0
  INT16* pOutput = NULL;
171
0
  wBitStream* bs = NULL;
172
0
  wBitStream s_bs = { 0 };
173
0
  const SSIZE_T DstSize = rDstSize;
174
175
0
  InitOnceExecuteOnce(&rfx_rlgr_init_once, rfx_rlgr_init, NULL, NULL);
176
177
0
  k = 1;
178
0
  kp = k << LSGR;
179
180
0
  kr = 1;
181
0
  krp = kr << LSGR;
182
183
0
  if ((mode != RLGR1) && (mode != RLGR3))
184
0
    mode = RLGR1;
185
186
0
  if (!pSrcData || !SrcSize)
187
0
    return -1;
188
189
0
  if (!pDstData || !DstSize)
190
0
    return -1;
191
192
0
  pOutput = pDstData;
193
194
0
  bs = &s_bs;
195
196
0
  BitStream_Attach(bs, pSrcData, SrcSize);
197
0
  BitStream_Fetch(bs);
198
199
0
  while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize))
200
0
  {
201
0
    if (k)
202
0
    {
203
      /* Run-Length (RL) Mode */
204
205
0
      run = 0;
206
207
      /* count number of leading 0s */
208
209
0
      cnt = lzcnt_s(bs->accumulator);
210
211
0
      size_t nbits = BitStream_GetRemainingLength(bs);
212
213
0
      if (cnt > nbits)
214
0
        cnt = WINPR_ASSERTING_INT_CAST(uint32_t, nbits);
215
216
0
      vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
217
218
0
      while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
219
0
      {
220
0
        BitStream_Shift32(bs);
221
222
0
        cnt = lzcnt_s(bs->accumulator);
223
224
0
        nbits = BitStream_GetRemainingLength(bs);
225
226
0
        if (cnt > nbits)
227
0
          cnt = nbits;
228
229
0
        WINPR_ASSERT(cnt + vk <= UINT32_MAX);
230
0
        vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
231
0
      }
232
233
0
      BitStream_Shift(bs, (vk % 32));
234
235
0
      if (BitStream_GetRemainingLength(bs) < 1)
236
0
        break;
237
238
0
      BitStream_Shift(bs, 1);
239
240
0
      while (vk--)
241
0
      {
242
0
        const UINT32 add = (1 << k); /* add (1 << k) to run length */
243
0
        run += add;
244
245
        /* update k, kp params */
246
247
0
        kp += UP_GR;
248
249
0
        if (kp > KPMAX)
250
0
          kp = KPMAX;
251
252
0
        k = kp >> LSGR;
253
0
      }
254
255
      /* next k bits contain run length remainder */
256
257
0
      if (BitStream_GetRemainingLength(bs) < k)
258
0
        break;
259
260
0
      bs->mask = ((1 << k) - 1);
261
0
      run += ((bs->accumulator >> (32 - k)) & bs->mask);
262
0
      BitStream_Shift(bs, k);
263
264
      /* read sign bit */
265
266
0
      if (BitStream_GetRemainingLength(bs) < 1)
267
0
        break;
268
269
0
      sign = (bs->accumulator & 0x80000000) ? 1 : 0;
270
0
      BitStream_Shift(bs, 1);
271
272
      /* count number of leading 1s */
273
274
0
      cnt = lzcnt_s(~(bs->accumulator));
275
276
0
      nbits = BitStream_GetRemainingLength(bs);
277
278
0
      if (cnt > nbits)
279
0
        cnt = nbits;
280
281
0
      vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
282
283
0
      while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
284
0
      {
285
0
        BitStream_Shift32(bs);
286
287
0
        cnt = lzcnt_s(~(bs->accumulator));
288
289
0
        nbits = BitStream_GetRemainingLength(bs);
290
291
0
        if (cnt > nbits)
292
0
          cnt = nbits;
293
294
0
        WINPR_ASSERT(cnt + vk <= UINT32_MAX);
295
0
        vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
296
0
      }
297
298
0
      BitStream_Shift(bs, (vk % 32));
299
300
0
      if (BitStream_GetRemainingLength(bs) < 1)
301
0
        break;
302
303
0
      BitStream_Shift(bs, 1);
304
305
      /* next kr bits contain code remainder */
306
307
0
      if (BitStream_GetRemainingLength(bs) < kr)
308
0
        break;
309
310
0
      bs->mask = ((1 << kr) - 1);
311
0
      if (kr > 0)
312
0
        code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
313
0
      else
314
0
        code = 0;
315
0
      BitStream_Shift(bs, kr);
316
317
      /* add (vk << kr) to code */
318
319
0
      code |= (vk << kr);
320
321
0
      if (!vk)
322
0
      {
323
        /* update kr, krp params */
324
325
0
        if (krp > 2)
326
0
          krp -= 2;
327
0
        else
328
0
          krp = 0;
329
330
0
        kr = krp >> LSGR;
331
0
      }
332
0
      else if (vk != 1)
333
0
      {
334
        /* update kr, krp params */
335
336
0
        krp += vk;
337
338
0
        if (krp > KPMAX)
339
0
          krp = KPMAX;
340
341
0
        kr = krp >> LSGR;
342
0
      }
343
344
      /* update k, kp params */
345
346
0
      if (kp > DN_GR)
347
0
        kp -= DN_GR;
348
0
      else
349
0
        kp = 0;
350
351
0
      k = kp >> LSGR;
352
353
      /* compute magnitude from code */
354
355
0
      if (sign)
356
0
        mag = WINPR_ASSERTING_INT_CAST(int16_t, (code + 1)) * -1;
357
0
      else
358
0
        mag = WINPR_ASSERTING_INT_CAST(int16_t, code + 1);
359
360
      /* write to output stream */
361
362
0
      offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput)-pDstData);
363
0
      size = run;
364
365
0
      if ((offset + size) > rDstSize)
366
0
        size = WINPR_ASSERTING_INT_CAST(size_t, DstSize) - offset;
367
368
0
      if (size)
369
0
      {
370
0
        ZeroMemory(pOutput, size * sizeof(INT16));
371
0
        pOutput += size;
372
0
      }
373
374
0
      if ((pOutput - pDstData) < DstSize)
375
0
      {
376
0
        *pOutput = mag;
377
0
        pOutput++;
378
0
      }
379
0
    }
380
0
    else
381
0
    {
382
      /* Golomb-Rice (GR) Mode */
383
384
      /* count number of leading 1s */
385
386
0
      cnt = lzcnt_s(~(bs->accumulator));
387
388
0
      size_t nbits = BitStream_GetRemainingLength(bs);
389
390
0
      if (cnt > nbits)
391
0
        cnt = nbits;
392
393
0
      vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
394
395
0
      while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
396
0
      {
397
0
        BitStream_Shift32(bs);
398
399
0
        cnt = lzcnt_s(~(bs->accumulator));
400
401
0
        nbits = BitStream_GetRemainingLength(bs);
402
403
0
        if (cnt > nbits)
404
0
          cnt = nbits;
405
406
0
        WINPR_ASSERT(cnt + vk <= UINT32_MAX);
407
0
        vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
408
0
      }
409
410
0
      BitStream_Shift(bs, (vk % 32));
411
412
0
      if (BitStream_GetRemainingLength(bs) < 1)
413
0
        break;
414
415
0
      BitStream_Shift(bs, 1);
416
417
      /* next kr bits contain code remainder */
418
419
0
      if (BitStream_GetRemainingLength(bs) < kr)
420
0
        break;
421
422
0
      bs->mask = ((1 << kr) - 1);
423
0
      if (kr > 0)
424
0
        code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
425
0
      else
426
0
        code = 0;
427
0
      BitStream_Shift(bs, kr);
428
429
      /* add (vk << kr) to code */
430
431
0
      code |= (vk << kr);
432
433
0
      if (!vk)
434
0
      {
435
        /* update kr, krp params */
436
437
0
        if (krp > 2)
438
0
          krp -= 2;
439
0
        else
440
0
          krp = 0;
441
442
0
        kr = (krp >> LSGR) & UINT32_MAX;
443
0
      }
444
0
      else if (vk != 1)
445
0
      {
446
        /* update kr, krp params */
447
448
0
        krp += vk;
449
450
0
        if (krp > KPMAX)
451
0
          krp = KPMAX;
452
453
0
        kr = krp >> LSGR;
454
0
      }
455
456
0
      if (mode == RLGR1) /* RLGR1 */
457
0
      {
458
0
        if (!code)
459
0
        {
460
          /* update k, kp params */
461
462
0
          kp += UQ_GR;
463
464
0
          if (kp > KPMAX)
465
0
            kp = KPMAX;
466
467
0
          k = kp >> LSGR;
468
469
0
          mag = 0;
470
0
        }
471
0
        else
472
0
        {
473
          /* update k, kp params */
474
475
0
          if (kp > DQ_GR)
476
0
            kp -= DQ_GR;
477
0
          else
478
0
            kp = 0;
479
480
0
          k = kp >> LSGR;
481
482
          /*
483
           * code = 2 * mag - sign
484
           * sign + code = 2 * mag
485
           */
486
487
0
          if (code & 1)
488
0
            mag = WINPR_ASSERTING_INT_CAST(INT16, (code + 1) >> 1) * -1;
489
0
          else
490
0
            mag = WINPR_ASSERTING_INT_CAST(INT16, code >> 1);
491
0
        }
492
493
0
        if ((pOutput - pDstData) < DstSize)
494
0
        {
495
0
          *pOutput = mag;
496
0
          pOutput++;
497
0
        }
498
0
      }
499
0
      else if (mode == RLGR3) /* RLGR3 */
500
0
      {
501
0
        nIdx = 0;
502
503
0
        if (code)
504
0
        {
505
0
          mag = WINPR_ASSERTING_INT_CAST(int16_t, code);
506
0
          nIdx = 32 - lzcnt_s(WINPR_ASSERTING_INT_CAST(uint32_t, mag));
507
0
        }
508
509
0
        if (BitStream_GetRemainingLength(bs) < nIdx)
510
0
          break;
511
512
0
        bs->mask = ((1 << nIdx) - 1);
513
0
        if (nIdx > 0)
514
0
          val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask);
515
0
        else
516
0
          val1 = 0;
517
0
        BitStream_Shift(bs, nIdx);
518
519
0
        val2 = code - val1;
520
521
0
        if (val1 && val2)
522
0
        {
523
          /* update k, kp params */
524
525
0
          if (kp > 2 * DQ_GR)
526
0
            kp -= (2 * DQ_GR);
527
0
          else
528
0
            kp = 0;
529
530
0
          k = kp >> LSGR;
531
0
        }
532
0
        else if (!val1 && !val2)
533
0
        {
534
          /* update k, kp params */
535
536
0
          kp += (2 * UQ_GR);
537
538
0
          if (kp > KPMAX)
539
0
            kp = KPMAX;
540
541
0
          k = kp >> LSGR;
542
0
        }
543
544
0
        if (val1 & 1)
545
0
          mag = WINPR_ASSERTING_INT_CAST(int16_t, (val1 + 1) >> 1) * -1;
546
0
        else
547
0
          mag = WINPR_ASSERTING_INT_CAST(int16_t, val1 >> 1);
548
549
0
        if ((pOutput - pDstData) < DstSize)
550
0
        {
551
0
          *pOutput = mag;
552
0
          pOutput++;
553
0
        }
554
555
0
        if (val2 & 1)
556
0
          mag = WINPR_ASSERTING_INT_CAST(int16_t, (val2 + 1) >> 1) * -1;
557
0
        else
558
0
          mag = WINPR_ASSERTING_INT_CAST(int16_t, val2 >> 1);
559
560
0
        if ((pOutput - pDstData) < DstSize)
561
0
        {
562
0
          *pOutput = WINPR_ASSERTING_INT_CAST(int16_t, mag);
563
0
          pOutput++;
564
0
        }
565
0
      }
566
0
    }
567
0
  }
568
569
0
  offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput - pDstData));
570
571
0
  if (offset < rDstSize)
572
0
  {
573
0
    size = WINPR_ASSERTING_INT_CAST(size_t, DstSize) - offset;
574
0
    ZeroMemory(pOutput, size * 2);
575
0
    pOutput += size;
576
0
  }
577
578
0
  offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput - pDstData));
579
580
0
  if ((DstSize < 0) || (offset != (size_t)DstSize))
581
0
    return -1;
582
583
0
  return 1;
584
0
}
585
586
/* Returns the next coefficient (a signed int) to encode, from the input stream */
587
#define GetNextInput(_n)    \
588
0
  do                      \
589
0
  {                       \
590
0
    if (data_size > 0)  \
591
0
    {                   \
592
0
      (_n) = *data++; \
593
0
      data_size--;    \
594
0
    }                   \
595
0
    else                \
596
0
    {                   \
597
0
      (_n) = 0;       \
598
0
    }                   \
599
0
  } while (0)
600
601
/* Emit bitPattern to the output bitstream */
602
0
#define OutputBits(numBits, bitPattern) rfx_bitstream_put_bits(bs, bitPattern, numBits)
603
604
/* Emit a bit (0 or 1), count number of times, to the output bitstream */
605
static inline void OutputBit(RFX_BITSTREAM* bs, uint32_t count, UINT8 bit)
606
0
{
607
0
  UINT16 _b = ((bit) ? 0xFFFF : 0);
608
0
  const uint32_t rem = count % 16;
609
0
  for (uint32_t x = 0; x < count - rem; x += 16)
610
0
    rfx_bitstream_put_bits(bs, _b, 16);
611
612
0
  if (rem > 0)
613
0
    rfx_bitstream_put_bits(bs, _b, rem);
614
0
}
615
616
/* Converts the input value to (2 * abs(input) - sign(input)), where sign(input) = (input < 0 ? 1 :
617
 * 0) and returns it */
618
static inline UINT32 Get2MagSign(INT32 input)
619
0
{
620
0
  if (input >= 0)
621
0
    return WINPR_ASSERTING_INT_CAST(UINT32, 2 * input);
622
0
  return WINPR_ASSERTING_INT_CAST(UINT32, -2 * input - 1);
623
0
}
624
625
/* Outputs the Golomb/Rice encoding of a non-negative integer */
626
0
#define CodeGR(krp, val) rfx_rlgr_code_gr(bs, krp, val)
627
628
static void rfx_rlgr_code_gr(RFX_BITSTREAM* bs, uint32_t* krp, UINT32 val)
629
0
{
630
0
  uint32_t kr = *krp >> LSGR;
631
632
  /* unary part of GR code */
633
634
0
  const uint32_t vk = val >> kr;
635
0
  OutputBit(bs, vk, 1);
636
0
  OutputBit(bs, 1, 0);
637
638
  /* remainder part of GR code, if needed */
639
0
  if (kr)
640
0
  {
641
0
    OutputBits(kr, val & ((1 << kr) - 1));
642
0
  }
643
644
  /* update krp, only if it is not equal to 1 */
645
0
  if (vk == 0)
646
0
  {
647
0
    (void)UpdateParam(krp, -2);
648
0
  }
649
0
  else if (vk > 1)
650
0
  {
651
0
    (void)UpdateParam(krp, WINPR_CXX_COMPAT_CAST(int32_t, vk));
652
0
  }
653
0
}
654
655
int rfx_rlgr_encode(RLGR_MODE mode, const INT16* WINPR_RESTRICT data, UINT32 data_size,
656
                    BYTE* WINPR_RESTRICT buffer, UINT32 buffer_size)
657
0
{
658
0
  uint32_t k = 0;
659
0
  uint32_t kp = 0;
660
0
  uint32_t krp = 0;
661
0
  RFX_BITSTREAM* bs = NULL;
662
663
0
  if (!(bs = (RFX_BITSTREAM*)winpr_aligned_calloc(1, sizeof(RFX_BITSTREAM), 32)))
664
0
    return 0;
665
666
0
  rfx_bitstream_attach(bs, buffer, buffer_size);
667
668
  /* initialize the parameters */
669
0
  k = 1;
670
0
  kp = 1 << LSGR;
671
0
  krp = 1 << LSGR;
672
673
  /* process all the input coefficients */
674
0
  while (data_size > 0)
675
0
  {
676
0
    int input = 0;
677
678
0
    if (k)
679
0
    {
680
0
      uint32_t numZeros = 0;
681
0
      uint32_t runmax = 0;
682
0
      BYTE sign = 0;
683
684
      /* RUN-LENGTH MODE */
685
686
      /* collect the run of zeros in the input stream */
687
0
      numZeros = 0;
688
0
      GetNextInput(input);
689
0
      while (input == 0 && data_size > 0)
690
0
      {
691
0
        numZeros++;
692
0
        GetNextInput(input);
693
0
      }
694
695
      // emit output zeros
696
0
      runmax = 1 << k;
697
0
      while (numZeros >= runmax)
698
0
      {
699
0
        OutputBit(bs, 1, 0); /* output a zero bit */
700
0
        numZeros -= runmax;
701
0
        k = UpdateParam(&kp, UP_GR); /* update kp, k */
702
0
        runmax = 1 << k;
703
0
      }
704
705
      /* output a 1 to terminate runs */
706
0
      OutputBit(bs, 1, 1);
707
708
      /* output the remaining run length using k bits */
709
0
      OutputBits(k, numZeros);
710
711
      /* note: when we reach here and the last byte being encoded is 0, we still
712
         need to output the last two bits, otherwise mstsc will crash */
713
714
      /* encode the nonzero value using GR coding */
715
0
      const UINT32 mag =
716
0
          (UINT32)(input < 0 ? -input : input); /* absolute value of input coefficient */
717
0
      sign = (input < 0 ? 1 : 0);         /* sign of input coefficient */
718
719
0
      OutputBit(bs, 1, sign);          /* output the sign bit */
720
0
      CodeGR(&krp, mag ? mag - 1 : 0); /* output GR code for (mag - 1) */
721
722
0
      k = UpdateParam(&kp, -DN_GR);
723
0
    }
724
0
    else
725
0
    {
726
      /* GOLOMB-RICE MODE */
727
728
0
      if (mode == RLGR1)
729
0
      {
730
0
        UINT32 twoMs = 0;
731
732
        /* RLGR1 variant */
733
734
        /* convert input to (2*magnitude - sign), encode using GR code */
735
0
        GetNextInput(input);
736
0
        twoMs = Get2MagSign(input);
737
0
        CodeGR(&krp, twoMs);
738
739
        /* update k, kp */
740
        /* NOTE: as of Aug 2011, the algorithm is still wrongly documented
741
           and the update direction is reversed */
742
0
        if (twoMs)
743
0
        {
744
0
          k = UpdateParam(&kp, -DQ_GR);
745
0
        }
746
0
        else
747
0
        {
748
0
          k = UpdateParam(&kp, UQ_GR);
749
0
        }
750
0
      }
751
0
      else /* mode == RLGR3 */
752
0
      {
753
0
        UINT32 twoMs1 = 0;
754
0
        UINT32 twoMs2 = 0;
755
0
        UINT32 sum2Ms = 0;
756
0
        UINT32 nIdx = 0;
757
758
        /* RLGR3 variant */
759
760
        /* convert the next two input values to (2*magnitude - sign) and */
761
        /* encode their sum using GR code */
762
763
0
        GetNextInput(input);
764
0
        twoMs1 = Get2MagSign(input);
765
0
        GetNextInput(input);
766
0
        twoMs2 = Get2MagSign(input);
767
0
        sum2Ms = twoMs1 + twoMs2;
768
769
0
        CodeGR(&krp, sum2Ms);
770
771
        /* encode binary representation of the first input (twoMs1). */
772
0
        GetMinBits(sum2Ms, nIdx);
773
0
        OutputBits(nIdx, twoMs1);
774
775
        /* update k,kp for the two input values */
776
777
0
        if (twoMs1 && twoMs2)
778
0
        {
779
0
          k = UpdateParam(&kp, -2 * DQ_GR);
780
0
        }
781
0
        else if (!twoMs1 && !twoMs2)
782
0
        {
783
0
          k = UpdateParam(&kp, 2 * UQ_GR);
784
0
        }
785
0
      }
786
0
    }
787
0
  }
788
789
0
  rfx_bitstream_flush(bs);
790
0
  uint32_t processed_size = rfx_bitstream_get_processed_bytes(bs);
791
0
  winpr_aligned_free(bs);
792
793
0
  return WINPR_ASSERTING_INT_CAST(int, processed_size);
794
0
}