/* * FFv1 codec * * Copyright (c) 2026 Lynne * * 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 */ #ifndef VULKAN_RANGECODER_SUBGROUP_H #define VULKAN_RANGECODER_SUBGROUP_H #extension GL_KHR_shader_subgroup_basic : require #extension GL_KHR_shader_subgroup_ballot : require #extension GL_KHR_shader_subgroup_shuffle : require #extension GL_KHR_shader_subgroup_shuffle_relative : require #define CONTEXT_SIZE 32 #define MAX_OVERREAD 2 #define RC_LANES gl_WorkGroupSize.x #define RC_K (CONTEXT_SIZE/RC_LANES) struct RCStates { uint v[RC_K]; }; #ifdef DECODE #define RC_BTYPE readonly buffer #else #define RC_BTYPE uniform #endif layout (set = 0, binding = 0, scalar) RC_BTYPE rangecoder_buf { uint8_t rangecoder_state[512]; }; shared uint8_t zero_one_state[512]; struct RangeCoder { uint bs_start; uint bs_off; uint bs_end; uint low; uint range; uint16_t outstanding_count; int16_t outstanding_byte; }; RangeCoder rc; uint rac_range1(uint range, uint state24) { uint hi, lo; umulExtended(range, state24, hi, lo); return hi; } #ifdef ENCODE uint rc_top; uint rc_oc; int rc_ob; uint rc_nev; uint rc_ev[64/RC_LANES]; void rac_init_enc(in RangeCoder c) { for (uint i = gl_SubgroupInvocationID; i < 512; i += RC_LANES) zero_one_state[i] = rangecoder_state[i]; barrier(); rc = c; rc_top = rc.low + rc.range; rc_oc = uint(rc.outstanding_count); rc_ob = int(rc.outstanding_byte); rc_nev = 0; [[unroll]] for (uint k = 0; k < 64/RC_LANES; k++) rc_ev[k] = 0; } void rac_emit_block(uint low, uint cnt) { uint lane = gl_SubgroupInvocationID; bool deferred = lane < cnt && low - 0xFF01u < 0xFFu; if (rc_ob >= 0 && rc_oc == 0 && subgroupBallot(deferred).x == 0) { uint digit = (low >> 8) & 0xFFu; uint prev = subgroupShuffleUp(digit, 1); uint b = ((lane == 0 ? uint(rc_ob) : prev) + (low >> 16)) & 0xFFu; if (lane < cnt) slice_data[rc.bs_off + lane].v = uint8_t(b); rc.bs_off += cnt; rc_ob = int(subgroupBroadcast(digit, cnt - 1)); } else { for (uint i = 0; i < cnt; i++) { uint l = subgroupBroadcast(low, i); if (rc_ob < 0) { rc_ob = int(l >> 8); } else if (l - 0xFF01u < 0xFFu) { rc_oc++; } else { uint carry = l >> 16; if (lane == 0) slice_data[rc.bs_off].v = uint8_t(uint(rc_ob) + carry); for (uint k = 0; k < rc_oc; k += RC_LANES) if (lane < rc_oc - k) slice_data[rc.bs_off + 1 + k + lane].v = uint8_t(carry - 1u); rc.bs_off += 1 + rc_oc; rc_oc = 0; rc_ob = int((l >> 8) & 0xFFu); } } } } void rac_emit(void) { [[unroll]] for (uint k = 0; k < 64/RC_LANES; k++) if (rc_nev > k*RC_LANES) rac_emit_block(rc_ev[k], min(rc_nev - k*RC_LANES, RC_LANES)); rc_nev = 0; } void rac_renorm_enc(void) { uint low = rc_top - rc.range; rc.range <<= 8; rc_top = ((low & 0xFFu) << 8) + rc.range; [[unroll]] for (uint k = 0; k < 64/RC_LANES; k++) rc_ev[k] = gl_SubgroupInvocationID + k*RC_LANES == rc_nev ? low : rc_ev[k]; rc_nev++; } void put_rac_range1(uint range1, bool bit) { rc_top = bit ? rc_top : rc_top - range1; rc.range = bit ? range1 : rc.range - range1; [[dont_flatten]] if (rc.range < 0x100) rac_renorm_enc(); } void put_rac(uint state24, bool bit) { put_rac_range1(rac_range1(rc.range, state24), bit); } void put_rac_equi(bool bit) { put_rac_range1(rc.range >> 1, bit); } uint rac_terminate(void) { rac_emit(); uint range1 = (rc.range * 129) >> 8; rc.range -= range1; rc_top -= range1; if (rc.range < 0x100) rac_renorm_enc(); rc_top = rc_top - rc.range + 0x1FEu; rc.range = 0xFFu; rac_renorm_enc(); rc_top = rc_top - rc.range + 0xFFu; rc.range = 0xFFu; rac_renorm_enc(); rac_emit(); rc.low = rc_top - rc.range; rc.outstanding_count = uint16_t(rc_oc); rc.outstanding_byte = int16_t(rc_ob); return rc.bs_off - rc.bs_start; } void put_isymbol_tail(int e, RCStates st24, uint a, bool neg) { uint s[21]; [[unroll]] for (uint i = 0; i < 11; i++) if (i <= e + 1) s[i] = subgroupBroadcast(st24.v[i/RC_LANES], i % RC_LANES); [[unroll]] for (uint i = 0; i < 9; i++) if (i < e) s[11 + i] = subgroupBroadcast(st24.v[(22 + i)/RC_LANES], (22 + i) % RC_LANES); s[20] = subgroupBroadcast(st24.v[(11 + e)/RC_LANES], (11 + e) % RC_LANES); uint range = rc.range; uint top = rc_top; uint r = rac_range1(rc.range, s[0]); rc.range -= r; rc_top -= r; [[unroll]] for (int i = 0; i < 9; i++) if (i < e) rc.range = rac_range1(rc.range, s[1 + i]); r = rac_range1(rc.range, s[1 + e]); rc.range -= r; rc_top -= r; [[dont_flatten]] if (rc.range < 0x100) { rc.range = range; rc_top = top; put_rac(s[0], false); [[unroll]] for (int i = 0; i < 9; i++) if (i < e) put_rac(s[1 + i], true); put_rac(s[1 + e], false); } [[unroll]] for (int i = 8; i >= 0; i--) if (i < e) put_rac(s[11 + i], bitfieldExtract(a, i, 1) != 0); put_rac(s[20], neg); } void put_isymbol_esc(int e, RCStates st, RCStates st24, uint a, bool neg, out uint s10, out uint s31) { uint s[10]; [[unroll]] for (uint i = 0; i < 10; i++) s[i] = subgroupBroadcast(st24.v[i/RC_LANES], i % RC_LANES); s10 = subgroupBroadcast(st.v[10/RC_LANES], 10 % RC_LANES); s31 = subgroupBroadcast(st.v[31/RC_LANES], 31 % RC_LANES); put_rac(s[0], false); [[unroll]] for (int i = 1; i < 10; i++) put_rac(s[i], true); if (rc_nev > 40) rac_emit(); for (int i = 9; i < e; i++) { uint nx = rangecoder_state[256 + s10]; put_rac(s10 << 24, true); if (rc_nev > 60) rac_emit(); s10 = nx; } uint nx = rangecoder_state[s10]; put_rac(s10 << 24, false); s10 = nx; for (int i = e - 1; i >= 9; i--) { bool b = bitfieldExtract(a, i, 1) != 0; uint n0 = rangecoder_state[s31]; uint n1 = rangecoder_state[256 + s31]; put_rac(s31 << 24, b); if (rc_nev > 60) rac_emit(); s31 = b ? n1 : n0; } if (rc_nev > 50) rac_emit(); [[unroll]] for (int i = 8; i >= 0; i--) s[i] = subgroupBroadcast(st24.v[(22 + i)/RC_LANES], (22 + i) % RC_LANES); uint ss = subgroupBroadcast(st24.v[21/RC_LANES], 21 % RC_LANES); [[unroll]] for (int i = 8; i >= 0; i--) put_rac(s[i], bitfieldExtract(a, i, 1) != 0); put_rac(ss, neg); } void put_isymbol(RCStates st, int v, out uint s10, out uint s31) { RCStates st24; [[unroll]] for (uint k = 0; k < RC_K; k++) st24.v[k] = st.v[k] << 24; uint a = abs(v); int e = findMSB(a); bool neg = v < 0; s10 = 0; s31 = 0; if (v != 0) { if (e < 4) { if (e < 2) { if (e == 1) put_isymbol_tail(1, st24, a, neg); else put_isymbol_tail(0, st24, a, neg); } else if (e == 3) { put_isymbol_tail(3, st24, a, neg); } else { put_isymbol_tail(2, st24, a, neg); } } else if (e < 7) { if (e == 4) put_isymbol_tail(4, st24, a, neg); else if (e == 5) put_isymbol_tail(5, st24, a, neg); else put_isymbol_tail(6, st24, a, neg); } else if (e < 10) { if (e == 7) put_isymbol_tail(7, st24, a, neg); else if (e == 8) put_isymbol_tail(8, st24, a, neg); else put_isymbol_tail(9, st24, a, neg); } else { put_isymbol_esc(e, st, st24, a, neg, s10, s31); } } else { put_rac(subgroupBroadcast(st24.v[0], 0), true); } } #endif #ifdef DECODE uint rc_win; uint rc_winx[RC_K]; uint rc_dist; uint rc_next; uint rc_pos; void rac_load_window(void) { rc.bs_off += rc_pos; rc_pos &= ~31u; uint o = rc.bs_off + gl_SubgroupInvocationID; rc_win = uint(~(o < rc.bs_end ? u8buf(uint64_t(slice_data) + o).v : uint8_t(0))); [[unroll]] for (uint k = 1; k < RC_K; k++) { o += RC_LANES; rc_winx[k] = uint(~(o < rc.bs_end ? u8buf(uint64_t(slice_data) + o).v : uint8_t(0))); } } void rac_init_dec(in RangeCoder c) { for (uint i = gl_SubgroupInvocationID; i < 512; i += RC_LANES) zero_one_state[i] = rangecoder_state[i]; barrier(); rc = c; rc_dist = rc.range - rc.low - 1; rc_pos = 0; rac_load_window(); rc_next = subgroupBroadcast(rc_win, 0); } void rac_check_window(void) { if (rc_pos > 10) rac_load_window(); } void refill(void) { rc.range <<= 8; rc_dist = (rc_dist << 8) | rc_next; if (RC_K == 1) rc_next = subgroupBroadcast(rc_win, ++rc_pos); else if (++rc_pos < RC_LANES) rc_next = subgroupBroadcast(rc_win, rc_pos); else rc_next = subgroupBroadcast(rc_winx[rc_pos/RC_LANES], rc_pos % RC_LANES); } void rac_renorm(void) { if (expectEXT(rc.range < 0x100, false)) refill(); } bool get_rac_internal(uint range1) { bool bit = rc_dist < range1; uint ranged = rc.range - range1; uint distd = rc_dist - range1; rc.range = bit ? range1 : ranged; rc_dist = bit ? rc_dist : distd; return bit; } bool get_rac(uint state24) { bool bit = get_rac_internal(rac_range1(rc.range, state24)); rac_renorm(); return bit; } bool get_rac_equi(void) { rac_check_window(); bool bit = get_rac_internal(rc.range >> 1); rac_renorm(); return bit; } int get_isymbol_tail(int e, uint range, uint range1, RCStates sx, int pred, int sgn, out uint read, out uint bits) { uint m[9]; [[unroll]] for (int k = 8; k >= 0; k--) if (k + 1 < e) m[k] = subgroupBroadcast(sx.v[(22 + k)/RC_LANES], (22 + k) % RC_LANES); uint ss = subgroupBroadcast(sx.v[(10 + e)/RC_LANES], (10 + e) % RC_LANES); rc.range = range - range1; rc_dist -= range1; rac_renorm(); uint a = 0; [[unroll]] for (int k = 8; k >= 0; k--) { if (k + 1 < e) { a = (a << 1) + uint(get_rac_internal(rac_range1(rc.range, m[k]))); rac_renorm(); } } a += 1u << (e - 1); int sa = int(a)*sgn; int vp = pred + sa; int vn = vp - 2*sa; bool neg = get_rac_internal(rac_range1(rc.range, ss)); int v = neg ? vn : vp; read = (2u << e) - 1u + (((1u << (e - 1)) - 1u) << 22) + (1u << (10 + e)); bits = (a << 22) + (1u << e) - 2u - (1u << (21 + e)) + (neg ? 1u << (10 + e) : 0u); return v; } const int AVERROR_INVALIDDATA = -0x41444E49; int get_isymbol_esc(inout RCStates st, RCStates sx, int pred, int sgn, out uint read, out uint bits) { bool esc = c_bits > 10; int n = 11; if (esc) { uint s10 = subgroupBroadcast(st.v[10/RC_LANES], 10 % RC_LANES); bool one; [[dont_unroll]] do { s10 = rangecoder_state[s10 + 256]; n++; rac_check_window(); one = get_rac(s10 << 24); } while (one && n < 33); st.v[10/RC_LANES] = gl_SubgroupInvocationID == 10 % RC_LANES ? s10 : st.v[10/RC_LANES]; if (one) { read = 0x7FFu; bits = 0x7FEu; return pred + sgn*AVERROR_INVALIDDATA; } } uint s31 = subgroupBroadcast(st.v[31/RC_LANES], 31 % RC_LANES); rac_check_window(); bool b = get_rac(s31 << 24); uint a = b ? 0x3 : 0x2; for (n -= 2; n >= 11; n--) { s31 = rangecoder_state[s31 + (b ? 256 : 0)]; rac_check_window(); b = get_rac(s31 << 24); a = (a << 1) | uint(b); } st.v[31/RC_LANES] = gl_SubgroupInvocationID == 31 % RC_LANES ? s31 : st.v[31/RC_LANES]; rac_check_window(); [[unroll]] for (int k = 8; k >= 0; k--) { uint sk = subgroupBroadcast(sx.v[(22 + k)/RC_LANES], (22 + k) % RC_LANES); a = (a << 1) | uint(get_rac(sk)); } uint ss = subgroupBroadcast(sx.v[21/RC_LANES], 21 % RC_LANES); bool neg = get_rac_internal(rac_range1(rc.range, ss)); int sa = int(a)*sgn; read = 0xFFE007FFu; bits = ((esc ? 0x1FFu : 0x3FFu) << 1) | ((a & 0x3FFu) << 22) | (uint(neg) << 21); return neg ? pred - sa : pred + sa; } int get_isymbol(inout RCStates st, int pred, int sgn, out uint read, out uint bits) { RCStates sx; [[unroll]] for (uint k = 0; k < RC_K; k++) sx.v[k] = st.v[k] << 24; uint s[11]; [[unroll]] for (uint i = 0; i < 11; i++) s[i] = subgroupBroadcast(sx.v[i/RC_LANES], i % RC_LANES); read = 1u; bits = 1u; uint range = rc.range; uint dist = rc_dist; uint range0 = rac_range1(range, s[0]); uint r[11]; r[0] = range - range0; r[1] = rac_range1(r[0], s[1]); rc.range = r[0]; rc_dist = dist - range0; uint lim = max(rc_dist, 0xffu); int v; while (true) { uint skip; [[unroll]] for (int i = 2; i < 6; i++) r[i] = rac_range1(r[i - 1], s[i]); if (r[5] > lim) { [[unroll]] for (int i = 6; i < 11; i++) r[i] = rac_range1(r[i - 1], s[i]); if (r[6] > lim) { if (r[7] > lim) { if (r[8] > lim) { if (r[9] > lim) { if (r[10] > lim) { rc.range = r[10]; v = get_isymbol_esc(st, sx, pred, sgn, read, bits); break; } else if (r[10] <= rc_dist) { v = get_isymbol_tail(10, r[9], r[10], sx, pred, sgn, read, bits); break; } else { skip = 10; rc.range = r[10]; } } else if (r[9] <= rc_dist) { v = get_isymbol_tail(9, r[8], r[9], sx, pred, sgn, read, bits); break; } else { skip = 9; rc.range = r[9]; } } else if (r[8] <= rc_dist) { v = get_isymbol_tail(8, r[7], r[8], sx, pred, sgn, read, bits); break; } else { skip = 8; rc.range = r[8]; } } else if (r[7] <= rc_dist) { v = get_isymbol_tail(7, r[6], r[7], sx, pred, sgn, read, bits); break; } else { skip = 7; rc.range = r[7]; } } else if (r[6] <= rc_dist) { v = get_isymbol_tail(6, r[5], r[6], sx, pred, sgn, read, bits); break; } else { skip = 6; rc.range = r[6]; } } else if (r[4] > lim) { if (r[5] <= rc_dist) { v = get_isymbol_tail(5, r[4], r[5], sx, pred, sgn, read, bits); break; } else { skip = 5; rc.range = r[5]; } } else if (r[3] > lim) { if (r[4] <= rc_dist) { v = get_isymbol_tail(4, r[3], r[4], sx, pred, sgn, read, bits); break; } else { skip = 4; rc.range = r[4]; } } else if (r[2] > lim) { if (r[3] <= rc_dist) { v = get_isymbol_tail(3, r[2], r[3], sx, pred, sgn, read, bits); break; } else { skip = 3; rc.range = r[3]; } } else if (r[1] > lim) { if (r[2] <= rc_dist) { v = get_isymbol_tail(2, r[1], r[2], sx, pred, sgn, read, bits); break; } else { skip = 2; rc.range = r[2]; } } else if (range0 > min(dist, range - 0x100)) { if (dist < range0) { rc.range = range0; rc_dist = dist; v = pred; break; } skip = 0; rc.range = r[0]; } else if (r[1] <= rc_dist) { v = get_isymbol_tail(1, r[0], r[1], sx, pred, sgn, read, bits); break; } else { skip = 1; rc.range = r[1]; } refill(); lim = max(rc_dist, 0xffu); r[0] = rc.range; r[1] = skip > 0 ? rc.range + skip - 1 : rac_range1(rc.range, s[1]); range0 = 0; uint skipped = (2u << skip) - 2u; [[unroll]] for (uint k = 0; k < RC_K; k++) sx.v[k] = subgroupInverseBallot(uvec4(skipped >> (k*RC_LANES), 0, 0, 0)) ? ~0u : sx.v[k]; [[unroll]] for (uint i = 2; i < 11; i++) s[i] = subgroupBroadcast(sx.v[i/RC_LANES], i % RC_LANES); } return v; } #endif #endif /* VULKAN_RANGECODER_SUBGROUP_H */