vulkan_ffv1: use local RangeCoder struct, refactor overread checking
This commit is contained in:
@@ -41,46 +41,49 @@ layout (set = 1, binding = 3, scalar) buffer slice_state_buf {
|
||||
uint8_t slice_rc_state[];
|
||||
};
|
||||
|
||||
#define READ(c, idx) get_rac_noadapt(c, idx)
|
||||
int get_isymbol(inout RangeCoder c)
|
||||
#define READ(idx) get_rac_noadapt(idx)
|
||||
int get_isymbol(void)
|
||||
{
|
||||
if (READ(c, 0))
|
||||
if (READ(0))
|
||||
return 0;
|
||||
|
||||
uint e = 1;
|
||||
int e = 1;
|
||||
for (; e < 11; e++) {
|
||||
if (!READ(c, e))
|
||||
if (!READ(e))
|
||||
break;
|
||||
}
|
||||
|
||||
int a = 1;
|
||||
uint i = e;
|
||||
int i = e;
|
||||
|
||||
if (bits > 8 && e == 11) {
|
||||
do {
|
||||
rc_state[10] = zero_one_state[rc_state[10] + 256];
|
||||
e++;
|
||||
} while (READ(c, 10));
|
||||
} while (READ(10));
|
||||
|
||||
e--;
|
||||
i = e - 1;
|
||||
|
||||
a += a + int(READ(c, 31));
|
||||
a <<= 1;
|
||||
a |= int(READ(31));
|
||||
for (; i >= 11; i--) {
|
||||
rc_state[31] = zero_one_state[rc_state[31] +
|
||||
(rc_data[31] ? 256 : 0)];
|
||||
a += a + int(READ(c, 31));
|
||||
a <<= 1;
|
||||
a |= int(READ(31));
|
||||
}
|
||||
}
|
||||
|
||||
i += 20;
|
||||
for (; i >= 22; i--)
|
||||
a += a + int(READ(c, i));
|
||||
a <<= i - 1;
|
||||
i -= 2;
|
||||
for (; i >= 0; i--)
|
||||
a |= int(READ(i + 22)) << i;
|
||||
|
||||
return READ(c, min(e + 10, 21)) ? -a : a;
|
||||
return READ(min(e + 10, 21)) ? -a : a;
|
||||
}
|
||||
|
||||
void decode_line_pcm(inout SliceContext sc, ivec2 sp, int w, int y, int p)
|
||||
void decode_line_pcm(ivec2 sp, int w, int y, int p)
|
||||
{
|
||||
if (gl_LocalInvocationID.x > 0)
|
||||
return;
|
||||
@@ -97,13 +100,13 @@ void decode_line_pcm(inout SliceContext sc, ivec2 sp, int w, int y, int p)
|
||||
|
||||
[[unroll]]
|
||||
for (uint i = (rct_offset >> 1); i > 0; i >>= 1)
|
||||
v |= get_rac_equi(sc.c) ? i : 0;
|
||||
v |= get_rac_equi() ? i : 0;
|
||||
|
||||
imageStore(dec[p], sp + LADDR(ivec2(x, y)), uvec4(v));
|
||||
}
|
||||
}
|
||||
|
||||
void decode_line(inout SliceContext sc, ivec2 sp, int w,
|
||||
void decode_line(ivec2 sp, int w,
|
||||
int y, int p, uint state_off,
|
||||
uint8_t quant_table_idx, int run_index)
|
||||
{
|
||||
@@ -126,7 +129,7 @@ void decode_line(inout SliceContext sc, ivec2 sp, int w,
|
||||
|
||||
int diff;
|
||||
if (gl_LocalInvocationID.x == 0)
|
||||
diff = get_isymbol(sc.c);
|
||||
diff = get_isymbol();
|
||||
|
||||
barrier();
|
||||
uint i = gl_LocalInvocationID.x;
|
||||
@@ -155,14 +158,14 @@ GetBitContext gb;
|
||||
void golomb_init(inout SliceContext sc)
|
||||
{
|
||||
if (version == 3 && micro_version > 1 || version > 3)
|
||||
get_rac_internal(sc.c, sc.c.range * 129 >> 8);
|
||||
get_rac_internal(rc.range * 129 >> 8);
|
||||
|
||||
uint64_t ac_byte_count = sc.c.bytestream - sc.c.bytestream_start - 1;
|
||||
init_get_bits(gb, u8buf(sc.c.bytestream_start + ac_byte_count),
|
||||
int(sc.c.bytestream_end - sc.c.bytestream_start - ac_byte_count));
|
||||
uint64_t ac_byte_count = rc.bytestream - rc.bytestream_start - 1;
|
||||
init_get_bits(gb, u8buf(rc.bytestream_start + ac_byte_count),
|
||||
int(rc.bytestream_end - rc.bytestream_start - ac_byte_count));
|
||||
}
|
||||
|
||||
void decode_line(inout SliceContext sc, ivec2 sp, int w,
|
||||
void decode_line(ivec2 sp, int w,
|
||||
int y, int p, uint state_off,
|
||||
uint8_t quant_table_idx, inout int run_index)
|
||||
{
|
||||
@@ -284,7 +287,7 @@ void decode_slice(inout SliceContext sc, const uint slice_idx)
|
||||
#ifdef RGB
|
||||
for (int y = 0; y < sc.slice_dim.y; y++) {
|
||||
for (int p = 0; p < color_planes; p++)
|
||||
decode_line_pcm(sc, sp, w, y, p);
|
||||
decode_line_pcm(sp, w, y, p);
|
||||
|
||||
writeout_rgb(sc, sp, w, y, false);
|
||||
}
|
||||
@@ -295,7 +298,7 @@ void decode_slice(inout SliceContext sc, const uint slice_idx)
|
||||
h = ceil_rshift(h, chroma_shift.y);
|
||||
|
||||
for (int y = 0; y < h; y++)
|
||||
decode_line_pcm(sc, sp, w, y, p);
|
||||
decode_line_pcm(sp, w, y, p);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
@@ -315,7 +318,7 @@ void decode_slice(inout SliceContext sc, const uint slice_idx)
|
||||
int run_index = 0;
|
||||
for (int y = 0; y < sc.slice_dim.y; y++) {
|
||||
for (int p = 0; p < color_planes; p++)
|
||||
decode_line(sc, sp, w, y, p,
|
||||
decode_line(sp, w, y, p,
|
||||
slice_state_off[p], quant_table_idx[p], run_index);
|
||||
|
||||
writeout_rgb(sc, sp, w, y, true);
|
||||
@@ -328,7 +331,7 @@ void decode_slice(inout SliceContext sc, const uint slice_idx)
|
||||
|
||||
int run_index = 0;
|
||||
for (int y = 0; y < h; y++)
|
||||
decode_line(sc, sp, w, y, p,
|
||||
decode_line(sp, w, y, p,
|
||||
slice_state_off[p], quant_table_idx[p], run_index);
|
||||
}
|
||||
#endif
|
||||
@@ -337,9 +340,16 @@ void decode_slice(inout SliceContext sc, const uint slice_idx)
|
||||
void main(void)
|
||||
{
|
||||
uint slice_idx = gl_WorkGroupID.y*gl_NumWorkGroups.x + gl_WorkGroupID.x;
|
||||
|
||||
rc = slice_ctx[slice_idx].c;
|
||||
|
||||
decode_slice(slice_ctx[slice_idx], slice_idx);
|
||||
|
||||
uint32_t status = corrupt ? uint32_t(corrupt) : overread;
|
||||
if (status != 0)
|
||||
slice_status[2*slice_idx + 1] = status;
|
||||
if (gl_LocalInvocationID.x > 0)
|
||||
return;
|
||||
|
||||
uint overread = 0;
|
||||
if (rc.bytestream >= (rc.bytestream_end + MAX_OVERREAD))
|
||||
overread = uint(rc.bytestream - rc.bytestream_end);
|
||||
slice_status[2*slice_idx + 1] = overread;
|
||||
}
|
||||
|
||||
@@ -37,28 +37,22 @@ layout (set = 1, binding = 2, scalar) writeonly buffer slice_status_buf {
|
||||
uint32_t slice_status[];
|
||||
};
|
||||
|
||||
shared uint8_t setup_state[CONTEXT_SIZE];
|
||||
shared uint hdr_sym[4 + 4 + 3];
|
||||
const int nb_hdr_sym = 4 + codec_planes + 3;
|
||||
|
||||
uint get_usymbol(inout RangeCoder c)
|
||||
uint get_usymbol(void)
|
||||
{
|
||||
if (get_rac_direct(c, setup_state[0]))
|
||||
if (get_rac_direct(rc_state[0]))
|
||||
return 0;
|
||||
|
||||
int e = 0;
|
||||
while (get_rac_direct(c, setup_state[1 + min(e, 9)])) { // 1..10
|
||||
while (get_rac_direct(rc_state[1 + min(e, 9)])) // 1..10
|
||||
e++;
|
||||
if (e > 31) {
|
||||
corrupt = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint a = 1;
|
||||
for (int i = e - 1; i >= 0; i--) {
|
||||
a <<= 1;
|
||||
a |= uint(get_rac_direct(c, setup_state[22 + min(i, 9)])); // 22..31
|
||||
a |= uint(get_rac_direct(rc_state[22 + min(i, 9)])); // 22..31
|
||||
}
|
||||
|
||||
return a;
|
||||
@@ -68,10 +62,10 @@ bool decode_slice_header(inout SliceContext sc)
|
||||
{
|
||||
[[unroll]]
|
||||
for (int i = 0; i < CONTEXT_SIZE; i++)
|
||||
setup_state[i] = uint8_t(128);
|
||||
rc_state[i] = uint8_t(128);
|
||||
|
||||
for (int i = 0; i < nb_hdr_sym; i++)
|
||||
hdr_sym[i] = get_usymbol(sc.c);
|
||||
hdr_sym[i] = get_usymbol();
|
||||
|
||||
uint sx = hdr_sym[0];
|
||||
uint sy = hdr_sym[1];
|
||||
@@ -79,10 +73,8 @@ bool decode_slice_header(inout SliceContext sc)
|
||||
uint sh = hdr_sym[3] + 1;
|
||||
|
||||
if (sx < 0 || sy < 0 || sw <= 0 || sh <= 0 ||
|
||||
sx > (gl_NumWorkGroups.x - sw) || sy > (gl_NumWorkGroups.y - sh) ||
|
||||
corrupt) {
|
||||
sx > (gl_NumWorkGroups.x - sw) || sy > (gl_NumWorkGroups.y - sh))
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set coordinates */
|
||||
uint sxs = slice_coord(img_size.x, sx , gl_NumWorkGroups.x, chroma_shift.x);
|
||||
@@ -103,11 +95,11 @@ bool decode_slice_header(inout SliceContext sc)
|
||||
}
|
||||
|
||||
if (version >= 4) {
|
||||
sc.slice_reset_contexts = get_rac_direct(sc.c, setup_state[0]);
|
||||
sc.slice_coding_mode = get_usymbol(sc.c);
|
||||
sc.slice_reset_contexts = get_rac_direct(rc_state[0]);
|
||||
sc.slice_coding_mode = get_usymbol();
|
||||
if (sc.slice_coding_mode != 1 && colorspace == 1) {
|
||||
sc.slice_rct_coef.x = int(get_usymbol(sc.c));
|
||||
sc.slice_rct_coef.y = int(get_usymbol(sc.c));
|
||||
sc.slice_rct_coef.x = int(get_usymbol());
|
||||
sc.slice_rct_coef.y = int(get_usymbol());
|
||||
if (sc.slice_rct_coef.x + sc.slice_rct_coef.y > 4)
|
||||
return true;
|
||||
}
|
||||
@@ -123,14 +115,15 @@ void main(void)
|
||||
u8buf bs = u8buf(slice_data + slice_offsets[slice_idx].x);
|
||||
uint32_t slice_size = slice_offsets[slice_idx].y;
|
||||
|
||||
rac_init_dec(slice_ctx[slice_idx].c,
|
||||
bs, slice_size);
|
||||
rac_init_dec(bs, slice_size);
|
||||
|
||||
if (slice_idx == (gl_NumWorkGroups.x*gl_NumWorkGroups.y - 1))
|
||||
get_rac_equi(slice_ctx[slice_idx].c);
|
||||
get_rac_equi();
|
||||
|
||||
decode_slice_header(slice_ctx[slice_idx]);
|
||||
|
||||
slice_ctx[slice_idx].c = rc;
|
||||
|
||||
if (has_crc) {
|
||||
uint32_t crc = crcref;
|
||||
for (int i = 0; i < slice_size; i++)
|
||||
@@ -139,5 +132,8 @@ void main(void)
|
||||
slice_status[2*slice_idx + 0] = crc;
|
||||
}
|
||||
|
||||
slice_status[2*slice_idx + 1] = corrupt ? uint32_t(corrupt) : overread;
|
||||
uint overread = 0;
|
||||
if (rc.bytestream >= (rc.bytestream_end + MAX_OVERREAD))
|
||||
overread = uint(rc.bytestream - rc.bytestream_end);
|
||||
slice_status[2*slice_idx + 1] = overread;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define VULKAN_RANGECODER_H
|
||||
|
||||
#define CONTEXT_SIZE 32
|
||||
#define MAX_OVERREAD 2
|
||||
|
||||
layout (set = 0, binding = 0, scalar) readonly buffer rangecoder_buf {
|
||||
uint8_t zero_one_state[512];
|
||||
@@ -40,6 +41,7 @@ struct RangeCoder {
|
||||
uint8_t outstanding_byte;
|
||||
};
|
||||
|
||||
shared RangeCoder rc;
|
||||
shared uint8_t rc_state[CONTEXT_SIZE];
|
||||
shared bool rc_data[CONTEXT_SIZE];
|
||||
shared bool rc_dec[CONTEXT_SIZE];
|
||||
@@ -189,74 +191,64 @@ uint rac_terminate(inout RangeCoder c)
|
||||
return uint(uint64_t(c.bytestream) - uint64_t(c.bytestream_start));
|
||||
}
|
||||
|
||||
/* Decoder */
|
||||
uint overread = 0;
|
||||
bool corrupt = false;
|
||||
|
||||
void rac_init_dec(out RangeCoder r, u8buf data, uint buf_size)
|
||||
void rac_init_dec(u8buf data, uint buf_size)
|
||||
{
|
||||
overread = 0;
|
||||
corrupt = false;
|
||||
|
||||
/* Skip priming bytes */
|
||||
rac_init(r, OFFBUF(u8buf, data, 2), buf_size - 2);
|
||||
rac_init(rc, OFFBUF(u8buf, data, 2), buf_size - 2);
|
||||
|
||||
u8vec2 prime = u8vec2buf(data).v;
|
||||
/* Switch endianness of the priming bytes */
|
||||
r.low = pack16(prime.yx);
|
||||
rc.low = pack16(prime.yx);
|
||||
|
||||
if (r.low >= 0xFF00) {
|
||||
r.low = 0xFF00;
|
||||
r.bytestream_end = uint64_t(data) + 2;
|
||||
if (rc.low >= 0xFF00) {
|
||||
rc.low = 0xFF00;
|
||||
rc.bytestream_end = uint64_t(data) + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void refill(inout RangeCoder c)
|
||||
void refill(void)
|
||||
{
|
||||
c.range <<= 8;
|
||||
c.low <<= 8;
|
||||
if (expectEXT(c.bytestream < c.bytestream_end, false)) {
|
||||
c.low |= u8buf(c.bytestream).v;
|
||||
c.bytestream++;
|
||||
} else {
|
||||
overread++;
|
||||
}
|
||||
rc.range <<= 8;
|
||||
rc.low <<= 8;
|
||||
if (expectEXT(rc.bytestream < rc.bytestream_end, true))
|
||||
rc.low |= u8buf(rc.bytestream).v;
|
||||
rc.bytestream++;
|
||||
}
|
||||
|
||||
bool get_rac_internal(inout RangeCoder c, const uint range1)
|
||||
bool get_rac_internal(const uint range1)
|
||||
{
|
||||
uint ranged = c.range - range1;
|
||||
bool bit = c.low >= ranged;
|
||||
c.low -= bit ? ranged : 0;
|
||||
c.range = (bit ? 0 : ranged) + (bit ? range1 : 0);
|
||||
uint ranged = rc.range - range1;
|
||||
bool bit = rc.low >= ranged;
|
||||
rc.low -= bit ? ranged : 0;
|
||||
rc.range = (bit ? 0 : ranged) + (bit ? range1 : 0);
|
||||
|
||||
if (expectEXT(c.range < 0x100, false))
|
||||
refill(c);
|
||||
if (expectEXT(rc.range < 0x100, false))
|
||||
refill();
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
bool get_rac_direct(inout RangeCoder c, inout uint8_t state)
|
||||
bool get_rac_direct(inout uint8_t state)
|
||||
{
|
||||
bool bit = get_rac_internal(c, c.range * state >> 8);
|
||||
bool bit = get_rac_internal(rc.range * state >> 8);
|
||||
state = zero_one_state[state + (bit ? 256 : 0)];
|
||||
return bit;
|
||||
}
|
||||
|
||||
bool get_rac_noadapt(inout RangeCoder c, uint idx)
|
||||
bool get_rac_noadapt(uint idx)
|
||||
{
|
||||
rc_dec[idx] = true;
|
||||
return (rc_data[idx] = get_rac_internal(c, c.range * rc_state[idx] >> 8));
|
||||
return (rc_data[idx] = get_rac_internal(rc.range * rc_state[idx] >> 8));
|
||||
}
|
||||
|
||||
bool get_rac(inout RangeCoder c, uint64_t state)
|
||||
bool get_rac(uint64_t state)
|
||||
{
|
||||
return get_rac_direct(c, u8buf(state).v);
|
||||
return get_rac_direct(u8buf(state).v);
|
||||
}
|
||||
|
||||
bool get_rac_equi(inout RangeCoder c)
|
||||
bool get_rac_equi(void)
|
||||
{
|
||||
return get_rac_internal(c, c.range >> 1);
|
||||
return get_rac_internal(rc.range >> 1);
|
||||
}
|
||||
|
||||
#endif /* VULKAN_RANGECODER_H */
|
||||
|
||||
@@ -887,18 +887,21 @@ static void vk_ffv1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
|
||||
|
||||
int slice_error_cnt = 0;
|
||||
int crc_mismatch_cnt = 0;
|
||||
uint32_t max_overread = 0;
|
||||
for (int i = 0; i < fp->slice_num; i++) {
|
||||
uint32_t crc_res = 0;
|
||||
uint8_t *ssp = slice_status->mapped_mem + 2*i*sizeof(uint32_t);
|
||||
if (fp->crc_checked)
|
||||
crc_res = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 0);
|
||||
uint32_t status = AV_RN32(slice_status->mapped_mem + 2*i*sizeof(uint32_t) + 4);
|
||||
slice_error_cnt += !!status;
|
||||
crc_res = AV_RN32(ssp + 0);
|
||||
uint32_t overread = AV_RN32(ssp + 4);
|
||||
max_overread = FFMAX(overread, max_overread);
|
||||
slice_error_cnt += !!overread;
|
||||
crc_mismatch_cnt += !!crc_res;
|
||||
}
|
||||
if (slice_error_cnt || crc_mismatch_cnt)
|
||||
av_log(dev_ctx, AV_LOG_ERROR, "Decode status: %i slices errored, "
|
||||
av_log(dev_ctx, AV_LOG_ERROR, "Decode status: %i slices overread (%i bytes max), "
|
||||
"%i CRCs mismatched\n",
|
||||
slice_error_cnt, crc_mismatch_cnt);
|
||||
slice_error_cnt, max_overread, crc_mismatch_cnt);
|
||||
|
||||
av_buffer_unref(&fp->slice_state);
|
||||
av_buffer_unref(&fp->slice_offset_buf);
|
||||
|
||||
Reference in New Issue
Block a user