Coverage Report

Created: 2024-05-20 06:11

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