| /* |
| * FFv1 codec |
| * |
| * Copyright (c) 2024 Lynne <dev@lynne.ee> |
| * |
| * This file is part of FFmpeg. |
| * |
| * FFmpeg is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * FFmpeg is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with FFmpeg; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| struct RangeCoder { |
| uint64_t bytestream_start; |
| uint64_t bytestream; |
| uint64_t bytestream_end; |
| |
| int low; |
| int range; |
| uint16_t outstanding_count; |
| uint8_t outstanding_byte; |
| }; |
| |
| void rac_init(out RangeCoder r, u8buf data, uint buf_size) |
| { |
| r.bytestream_start = uint64_t(data); |
| r.bytestream = uint64_t(data); |
| r.bytestream_end = uint64_t(data) + buf_size; |
| r.low = 0; |
| r.range = 0xFF00; |
| r.outstanding_count = uint16_t(0); |
| r.outstanding_byte = uint8_t(0xFF); |
| } |
| |
| #if !defined(DECODE) |
| |
| #ifdef FULL_RENORM |
| /* Full renorm version that can handle outstanding_byte == 0xFF */ |
| void renorm_encoder(inout RangeCoder c) |
| { |
| int bs_cnt = 0; |
| u8buf bytestream = u8buf(c.bytestream); |
| |
| if (c.outstanding_byte == 0xFF) { |
| c.outstanding_byte = uint8_t(c.low >> 8); |
| } else if (c.low <= 0xFF00) { |
| bytestream[bs_cnt++].v = c.outstanding_byte; |
| uint16_t cnt = c.outstanding_count; |
| for (; cnt > 0; cnt--) |
| bytestream[bs_cnt++].v = uint8_t(0xFF); |
| c.outstanding_count = uint16_t(0); |
| c.outstanding_byte = uint8_t(c.low >> 8); |
| } else if (c.low >= 0x10000) { |
| bytestream[bs_cnt++].v = c.outstanding_byte + uint8_t(1); |
| uint16_t cnt = c.outstanding_count; |
| for (; cnt > 0; cnt--) |
| bytestream[bs_cnt++].v = uint8_t(0x00); |
| c.outstanding_count = uint16_t(0); |
| c.outstanding_byte = uint8_t(bitfieldExtract(c.low, 8, 8)); |
| } else { |
| c.outstanding_count++; |
| } |
| |
| c.bytestream += bs_cnt; |
| c.range <<= 8; |
| c.low = bitfieldInsert(0, c.low, 8, 8); |
| } |
| |
| #else |
| |
| /* Cannot deal with outstanding_byte == -1 in the name of speed */ |
| void renorm_encoder(inout RangeCoder c) |
| { |
| uint16_t oc = c.outstanding_count + uint16_t(1); |
| int low = c.low; |
| |
| c.range <<= 8; |
| c.low = bitfieldInsert(0, low, 8, 8); |
| |
| if (low > 0xFF00 && low < 0x10000) { |
| c.outstanding_count = oc; |
| return; |
| } |
| |
| u8buf bs = u8buf(c.bytestream); |
| uint8_t outstanding_byte = c.outstanding_byte; |
| |
| c.bytestream = uint64_t(bs) + oc; |
| c.outstanding_count = uint16_t(0); |
| c.outstanding_byte = uint8_t(low >> 8); |
| |
| uint8_t obs = uint8_t(low > 0xFF00); |
| uint8_t fill = obs - uint8_t(1); /* unsigned underflow */ |
| |
| bs[0].v = outstanding_byte + obs; |
| for (int i = 1; i < oc; i++) |
| bs[i].v = fill; |
| } |
| #endif |
| |
| void put_rac_internal(inout RangeCoder c, const int range1, bool bit) |
| { |
| #ifdef DEBUG |
| if (range1 >= c.range) |
| debugPrintfEXT("Error: range1 >= c.range"); |
| if (range1 <= 0) |
| debugPrintfEXT("Error: range1 <= 0"); |
| #endif |
| |
| int ranged = c.range - range1; |
| c.low += bit ? ranged : 0; |
| c.range = bit ? range1 : ranged; |
| |
| if (expectEXT(c.range < 0x100, false)) |
| renorm_encoder(c); |
| } |
| |
| void put_rac_direct(inout RangeCoder c, inout uint8_t state, bool bit) |
| { |
| put_rac_internal(c, (c.range * state) >> 8, bit); |
| state = zero_one_state[(uint(bit) << 8) + state]; |
| } |
| |
| void put_rac(inout RangeCoder c, uint64_t state, bool bit) |
| { |
| put_rac_direct(c, u8buf(state).v, bit); |
| } |
| |
| /* Equiprobable bit */ |
| void put_rac_equi(inout RangeCoder c, bool bit) |
| { |
| put_rac_internal(c, c.range >> 1, bit); |
| } |
| |
| void put_rac_terminate(inout RangeCoder c) |
| { |
| int range1 = (c.range * 129) >> 8; |
| |
| #ifdef DEBUG |
| if (range1 >= c.range) |
| debugPrintfEXT("Error: range1 >= c.range"); |
| if (range1 <= 0) |
| debugPrintfEXT("Error: range1 <= 0"); |
| #endif |
| |
| c.range -= range1; |
| if (expectEXT(c.range < 0x100, false)) |
| renorm_encoder(c); |
| } |
| |
| /* Return the number of bytes written. */ |
| uint32_t rac_terminate(inout RangeCoder c) |
| { |
| put_rac_terminate(c); |
| c.range = uint16_t(0xFF); |
| c.low += 0xFF; |
| renorm_encoder(c); |
| c.range = uint16_t(0xFF); |
| renorm_encoder(c); |
| |
| #ifdef DEBUG |
| if (c.low != 0) |
| debugPrintfEXT("Error: c.low != 0"); |
| if (c.range < 0x100) |
| debugPrintfEXT("Error: range < 0x100"); |
| #endif |
| |
| return uint32_t(uint64_t(c.bytestream) - uint64_t(c.bytestream_start)); |
| } |
| |
| #else |
| |
| /* Decoder */ |
| uint overread = 0; |
| bool corrupt = false; |
| |
| void rac_init_dec(out RangeCoder r, u8buf data, uint buf_size) |
| { |
| overread = 0; |
| corrupt = false; |
| |
| /* Skip priming bytes */ |
| rac_init(r, OFFBUF(u8buf, data, 2), buf_size - 2); |
| |
| u8vec2 prime = u8vec2buf(data).v; |
| /* Switch endianness of the priming bytes */ |
| r.low = pack16(prime.yx); |
| |
| if (r.low >= 0xFF00) { |
| r.low = 0xFF00; |
| r.bytestream_end = uint64_t(data) + 2; |
| } |
| } |
| |
| void refill(inout RangeCoder c) |
| { |
| c.range <<= 8; |
| c.low <<= 8; |
| if (expectEXT(c.bytestream < c.bytestream_end, false)) { |
| c.low |= u8buf(c.bytestream).v; |
| c.bytestream++; |
| } else { |
| overread++; |
| } |
| } |
| |
| bool get_rac_internal(inout RangeCoder c, const int range1) |
| { |
| int ranged = c.range - range1; |
| bool bit = c.low >= ranged; |
| c.low -= bit ? ranged : 0; |
| c.range = (bit ? 0 : ranged) + (bit ? range1 : 0); |
| |
| if (expectEXT(c.range < 0x100, false)) |
| refill(c); |
| |
| return bit; |
| } |
| |
| bool get_rac_direct(inout RangeCoder c, inout uint8_t state) |
| { |
| bool bit = get_rac_internal(c, c.range * state >> 8); |
| state = zero_one_state[state + (bit ? 256 : 0)]; |
| return bit; |
| } |
| |
| bool get_rac(inout RangeCoder c, uint64_t state) |
| { |
| return get_rac_direct(c, u8buf(state).v); |
| } |
| |
| bool get_rac_equi(inout RangeCoder c) |
| { |
| return get_rac_internal(c, c.range >> 1); |
| } |
| |
| #endif |