You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-11-23 21:54:53 +02:00
242 lines
6.1 KiB
Plaintext
242 lines
6.1 KiB
Plaintext
/*
|
|
* 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;
|
|
};
|
|
|
|
#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));
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
/* 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);
|
|
}
|