1use std::io::{Read, Result, Write};
22
23use byteorder::{ReadBytesExt, WriteBytesExt};
24
25use crate::traits::{CabacReader, CabacWriter};
26
27const NEXT_STATE_MPS: [u8; 128] = [
28 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
29 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
30 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
31 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
32 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
33 119, 120, 121, 122, 123, 124, 125, 124, 125, 126, 127,
34];
35
36const NEXT_STATE_LPS: [u8; 128] = [
37 1, 0, 0, 1, 2, 3, 4, 5, 4, 5, 8, 9, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 18, 19, 22,
38 23, 22, 23, 24, 25, 26, 27, 26, 27, 30, 31, 30, 31, 32, 33, 32, 33, 36, 37, 36, 37, 38, 39, 38,
39 39, 42, 43, 42, 43, 44, 45, 44, 45, 46, 47, 48, 49, 48, 49, 50, 51, 52, 53, 52, 53, 54, 55, 54,
40 55, 56, 57, 58, 59, 58, 59, 60, 61, 60, 61, 60, 61, 62, 63, 64, 65, 64, 65, 66, 67, 66, 67, 66,
41 67, 68, 69, 68, 69, 70, 71, 70, 71, 70, 71, 72, 73, 72, 73, 72, 73, 74, 75, 74, 75, 74, 75, 76,
42 77, 76, 77, 126, 127,
43];
44
45const LPST_TABLE: [[u8; 4]; 64] = [
46 [128, 176, 208, 240],
47 [128, 167, 197, 227],
48 [128, 158, 187, 216],
49 [123, 150, 178, 205],
50 [116, 142, 169, 195],
51 [111, 135, 160, 185],
52 [105, 128, 152, 175],
53 [100, 122, 144, 166],
54 [95, 116, 137, 158],
55 [90, 110, 130, 150],
56 [85, 104, 123, 142],
57 [81, 99, 117, 135],
58 [77, 94, 111, 128],
59 [73, 89, 105, 122],
60 [69, 85, 100, 116],
61 [66, 80, 95, 110],
62 [62, 76, 90, 104],
63 [59, 72, 86, 99],
64 [56, 69, 81, 94],
65 [53, 65, 77, 89],
66 [51, 62, 73, 85],
67 [48, 59, 69, 80],
68 [46, 56, 66, 76],
69 [43, 53, 63, 72],
70 [41, 50, 59, 69],
71 [39, 48, 56, 65],
72 [37, 45, 54, 62],
73 [35, 43, 51, 59],
74 [33, 41, 48, 56],
75 [32, 39, 46, 53],
76 [30, 37, 43, 50],
77 [29, 35, 41, 48],
78 [27, 33, 39, 45],
79 [26, 31, 37, 43],
80 [24, 30, 35, 41],
81 [23, 28, 33, 39],
82 [22, 27, 32, 37],
83 [21, 26, 30, 35],
84 [20, 24, 29, 33],
85 [19, 23, 27, 31],
86 [18, 22, 26, 30],
87 [17, 21, 25, 28],
88 [16, 20, 23, 27],
89 [15, 19, 22, 25],
90 [14, 18, 21, 24],
91 [14, 17, 20, 23],
92 [13, 16, 19, 22],
93 [12, 15, 18, 21],
94 [12, 14, 17, 20],
95 [11, 14, 16, 19],
96 [11, 13, 15, 18],
97 [10, 12, 15, 17],
98 [10, 12, 14, 16],
99 [9, 11, 13, 15],
100 [9, 11, 12, 14],
101 [8, 10, 12, 14],
102 [8, 9, 11, 13],
103 [7, 9, 11, 12],
104 [7, 9, 10, 12],
105 [7, 8, 10, 11],
106 [6, 8, 9, 11],
107 [6, 7, 9, 10],
108 [6, 7, 8, 9],
109 [2, 2, 2, 2],
110];
111
112const RENORM_TABLE: [u8; 32] = [
113 6, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
114];
115
116#[derive(Default, Copy, Clone, Eq, PartialEq)]
118pub struct H265Context {
119 uc_state: u8,
120}
121
122impl H265Context {
123 fn get_state(&self) -> u8 {
124 self.uc_state >> 1
125 }
126
127 fn get_mps(&self) -> bool {
128 (self.uc_state & 1) == 1
129 }
130 fn update_lps(&mut self) {
131 self.uc_state = NEXT_STATE_LPS[usize::from(self.uc_state)];
132 }
133 fn update_mps(&mut self) {
134 self.uc_state = NEXT_STATE_MPS[usize::from(self.uc_state)];
135 }
136}
137
138pub struct H265Writer<W> {
140 writer: W,
141 low: u32,
142 range: u32,
143 buffered_byte: u32,
144 num_buffered_bytes: i32,
145 bits_left: i32,
146}
147
148impl<W: Write> CabacWriter<H265Context> for H265Writer<W> {
149 fn put_bypass(&mut self, value: bool) -> Result<()> {
150 self.low <<= 1;
151 if value {
152 self.low += self.range;
153 }
154
155 self.bits_left -= 1;
156
157 if self.bits_left < 12 {
158 self.flush_completed()?;
159 }
160
161 Ok(())
162 }
163
164 fn put(&mut self, value: bool, cur_ctx: &mut H265Context) -> Result<()> {
165 let lps = LPST_TABLE[usize::from(cur_ctx.get_state())][((self.range >> 6) & 3) as usize];
166
167 self.range -= u32::from(lps);
168
169 if value != cur_ctx.get_mps() {
170 let num_bits = RENORM_TABLE[usize::from(lps >> 3)];
171 self.low = (self.low + self.range) << num_bits;
172 self.range = u32::from(lps) << num_bits;
173
174 cur_ctx.update_lps();
175
176 self.bits_left -= i32::from(num_bits);
177 } else {
178 cur_ctx.update_mps();
179
180 if self.range >= 256 {
183 return Ok(());
184 }
185
186 self.low <<= 1;
187 self.range <<= 1;
188 self.bits_left -= 1;
189 }
190
191 if self.bits_left < 12 {
192 self.flush_completed()?;
193 }
194 Ok(())
195 }
196
197 fn finish(&mut self) -> Result<()> {
198 assert!(self.bits_left <= 32);
199
200 if (self.low >> (32 - self.bits_left)) != 0 {
201 self.writer.write_u8((self.buffered_byte + 1) as u8)?;
202 while self.num_buffered_bytes > 1 {
203 self.writer.write_u8(0x00)?;
204 self.num_buffered_bytes -= 1;
205 }
206
207 self.low -= 1 << (32 - self.bits_left);
208 } else {
209 if self.num_buffered_bytes > 0 {
210 self.writer.write_u8(self.buffered_byte as u8)?;
211 }
212
213 while self.num_buffered_bytes > 1 {
214 self.writer.write_u8(0xff)?;
215 self.num_buffered_bytes -= 1;
216 }
217 }
218
219 let mut bits = 32 - self.bits_left;
223
224 let data = self.low;
225
226 while bits >= 8 {
227 self.writer.write_u8((data >> (bits - 8)) as u8)?;
228 bits -= 8;
229 }
230
231 if bits > 0 {
232 self.writer.write_u8((data << (8 - bits)) as u8)?;
233 }
234
235 Ok(())
236 }
237}
238
239impl<W: Write> H265Writer<W> {
240 pub fn new(writer: W) -> Self {
241 H265Writer {
242 writer,
243 low: 0,
244 range: 510,
245 bits_left: 23,
246 num_buffered_bytes: 0,
247 buffered_byte: 0xff,
248 }
249 }
250
251 fn flush_completed(&mut self) -> Result<()> {
252 let lead_byte = self.low >> (24 - self.bits_left);
253 self.bits_left += 8;
254 self.low &= 0xffffffff >> self.bits_left;
255
256 if lead_byte == 0xff {
257 self.num_buffered_bytes += 1;
258 } else if self.num_buffered_bytes > 0 {
259 let carry = lead_byte >> 8;
260 let mut byte = self.buffered_byte + carry;
261 self.buffered_byte = lead_byte & 0xff;
262
263 self.writer.write_u8(byte as u8)?;
264
265 byte = (0xff + carry) & 0xff;
266 while self.num_buffered_bytes > 1 {
267 self.writer.write_u8(byte as u8)?;
268 self.num_buffered_bytes -= 1;
269 }
270 } else {
271 self.num_buffered_bytes = 1;
272 self.buffered_byte = lead_byte;
273 }
274 Ok(())
275 }
276}
277
278pub struct H265Reader<R> {
280 reader: R,
281 value: u32,
282 range: u32,
283 bits_needed: i32,
284}
285
286impl<R: Read> CabacReader<H265Context> for H265Reader<R> {
287 fn get_bypass(&mut self) -> Result<bool> {
288 self.value <<= 1;
289 self.bits_needed += 1;
290
291 if self.bits_needed >= 0 {
292 self.bits_needed = -8;
293 self.value |= u32::from(self.reader.read_u8()?);
294 }
295
296 let scaled_range = self.range << 7;
297
298 let r = self.value.overflowing_sub(scaled_range);
299
300 if r.1 {
301 Ok(false)
302 } else {
303 self.value = r.0;
304 Ok(true)
305 }
306 }
307
308 fn get(&mut self, cur_ctx: &mut H265Context) -> Result<bool> {
309 let mut range = self.range;
310 let mut value = self.value;
311
312 let lps = LPST_TABLE[usize::from(cur_ctx.get_state())][((range >> 6) & 3) as usize];
313
314 range -= u32::from(lps);
315
316 let scaled_range = range << 7;
317
318 let bit;
319
320 let r = value.overflowing_sub(scaled_range);
321
322 if r.1 {
323 bit = cur_ctx.get_mps();
326
327 cur_ctx.update_mps();
328
329 if scaled_range < (256 << 7) {
330 range = scaled_range >> 6; value <<= 1; self.bits_needed += 1;
335
336 if self.bits_needed == 0 {
337 self.bits_needed = -8;
338 value |= u32::from(self.reader.read_u8()?);
339 }
340 }
341 } else {
342 value = r.0;
345
346 let num_bits = RENORM_TABLE[usize::from(lps >> 3)];
347 value <<= num_bits;
348 range = u32::from(lps) << num_bits; bit = !cur_ctx.get_mps();
352
353 cur_ctx.update_lps();
354
355 self.bits_needed += i32::from(num_bits);
356
357 if self.bits_needed >= 0 {
358 value |= u32::from(self.reader.read_u8()?) << self.bits_needed;
359
360 self.bits_needed -= 8;
361 }
362 }
363
364 self.range = range;
365 self.value = value;
366
367 Ok(bit)
368 }
369}
370
371impl<R: Read> H265Reader<R> {
372 pub fn new(reader: R) -> Result<Self> {
373 let mut r = H265Reader {
374 reader: reader,
375 value: 0,
376 range: 510,
377 bits_needed: 8,
378 };
379
380 r.value = (u32::from(r.reader.read_u8()?) << 8) | u32::from(r.reader.read_u8()?);
381 r.bits_needed -= 16;
382
383 Ok(r)
384 }
385}