1 /*
2  *  Copyright (C) 2017-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "BitstreamWriter.h"
10 
CBitstreamWriter(uint8_t * buffer,unsigned int buffer_size,int writer_le)11 CBitstreamWriter::CBitstreamWriter(uint8_t *buffer, unsigned int buffer_size, int writer_le)
12   : writer_le(writer_le)
13   , bit_buf(0)
14   , bit_left(32)
15   , buf(buffer)
16   , buf_ptr(buf)
17 {
18 }
19 
WriteBits(int n,unsigned int value)20 void CBitstreamWriter::WriteBits(int n, unsigned int value)
21 {
22   // Write up to 32 bits into a bitstream.
23   unsigned int bit_buf;
24   int bit_left;
25 
26   if (n == 32)
27   {
28     // Write exactly 32 bits into a bitstream.
29     // danger, recursion in play.
30     int lo = value & 0xffff;
31     int hi = value >> 16;
32     if (writer_le)
33     {
34       WriteBits(16, lo);
35       WriteBits(16, hi);
36     }
37     else
38     {
39       WriteBits(16, hi);
40       WriteBits(16, lo);
41     }
42     return;
43   }
44 
45   bit_buf = this->bit_buf;
46   bit_left = this->bit_left;
47 
48   if (writer_le)
49   {
50     bit_buf |= value << (32 - bit_left);
51     if (n >= bit_left) {
52       BS_WL32(buf_ptr, bit_buf);
53       buf_ptr += 4;
54       bit_buf = (bit_left == 32) ? 0 : value >> bit_left;
55       bit_left += 32;
56     }
57     bit_left -= n;
58   }
59   else
60   {
61     if (n < bit_left) {
62       bit_buf = (bit_buf << n) | value;
63       bit_left -= n;
64     }
65     else {
66       bit_buf <<= bit_left;
67       bit_buf |= value >> (n - bit_left);
68       BS_WB32(buf_ptr, bit_buf);
69       buf_ptr += 4;
70       bit_left += 32 - n;
71       bit_buf = value;
72     }
73   }
74 
75   this->bit_buf = bit_buf;
76   this->bit_left = bit_left;
77 }
78 
SkipBits(int n)79 void CBitstreamWriter::SkipBits(int n)
80 {
81   // Skip the given number of bits.
82   // Must only be used if the actual values in the bitstream do not matter.
83   // If n is 0 the behavior is undefined.
84   bit_left -= n;
85   buf_ptr -= 4 * (bit_left >> 5);
86   bit_left &= 31;
87 }
88 
FlushBits()89 void CBitstreamWriter::FlushBits()
90 {
91   if (!writer_le)
92   {
93     if (bit_left < 32)
94       bit_buf <<= bit_left;
95   }
96   while (bit_left < 32)
97   {
98 
99     if (writer_le)
100     {
101       *buf_ptr++ = bit_buf;
102       bit_buf >>= 8;
103     }
104     else
105     {
106       *buf_ptr++ = bit_buf >> 24;
107       bit_buf <<= 8;
108     }
109     bit_left += 8;
110   }
111   bit_left = 32;
112   bit_buf = 0;
113 }
114