code wiki / (root) / nx_av1_frame.nx

nx_av1_frame.nx source

↩ module page · 236 lines · 7960 B

1// nx_av1_frame.nx -- AV1/AV2 frame-header parameter blocks, writer and reader. 2// 3// Layer five. quantization_params() and cdef_params() are the two blocks that 4// decide, respectively, how coefficients are scaled and how the constrained 5// directional enhancement filter is applied. Both are read straight off the 6// uncompressed header, both are shared verbatim with AV2, and both are 7// self-contained enough to prove by round-trip. 8// 9// su() IS TWO'S COMPLEMENT AT AN ARBITRARY WIDTH. A delta-Q is su(1+6) -- a 10// SEVEN bit signed field, not eight. Sign-extending from the wrong bit turns 11// -1 into +63 and every negative delta into a large positive one, which does 12// not error: it just makes the whole frame come out at the wrong quantiser. 13// 14// THE CDEF SECONDARY STRENGTH SKIPS 3. The field is two bits, and a coded 3 15// means strength FOUR -- the set is {0, 1, 2, 4} and strength 3 does not 16// exist. A writer that stores 4 verbatim overflows the field; one that stores 17// 3 silently means 4. This module maps on write and remaps on read, and 18// REFUSES an attempt to encode strength 3, which is unrepresentable rather 19// than merely unusual. 20// 21// genealogy_id: av1_spec_5_9_12_quantization_params 22// lineage_id: nx_av1_frame_v1 23// license_tier: ORIGINAL 24 25import "nx_syscalls.nx" 26import "nx_bitstream.nx" 27import "nx_av1_seq.nx" 28 29const NX_QP_BASE: i64 = 0 30const NX_QP_YDC: i64 = 1 31const NX_QP_UDC: i64 = 2 32const NX_QP_UAC: i64 = 3 33const NX_QP_VDC: i64 = 4 34const NX_QP_VAC: i64 = 5 35const NX_QP_USEQM: i64 = 6 36const NX_QP_QMY: i64 = 7 37const NX_QP_QMU: i64 = 8 38const NX_QP_QMV: i64 = 9 39 40const NX_CDEF_DAMPING: i64 = 0 41const NX_CDEF_BITS: i64 = 1 42const NX_CDEF_YPRI: i64 = 2 43const NX_CDEF_YSEC: i64 = 10 44const NX_CDEF_UVPRI: i64 = 18 45const NX_CDEF_UVSEC: i64 = 26 46 47// ===== su(n): signed, two's complement at width n ================= 48 49func nx_av1_su_read(bs: *NxBitStream, n: i64) -> i64 { 50 if n <= 0 { return 0 } 51 if n > 32 { return 0 } 52 let v: i64 = nx_bitstream_read_msb(bs, n) 53 let sign: i64 = 1 << (n - 1) 54 if (v & sign) != 0 { return v - (sign << 1) } 55 return v 56} 57 58func nx_av1_su_write(w: *NxAv1Bw, v: i64, n: i64) -> i64 { 59 if n <= 0 { return 0 } 60 if n > 32 { return 0 } 61 let lo: i64 = 0 - (1 << (n - 1)) 62 let hi: i64 = (1 << (n - 1)) - 1 63 if v < lo { return 0 } 64 if v > hi { return 0 } 65 let mask: i64 = (1 << n) - 1 66 nx_av1_bw_put(w, v & mask, n) 67 return 1 68} 69 70// ===== read_delta_q(): a flag then su(1+6) ======================== 71 72func nx_av1_delta_q_read(bs: *NxBitStream) -> i64 { 73 if nx_bitstream_read_msb(bs, 1) == 1 { return nx_av1_su_read(bs, 7) } 74 return 0 75} 76 77func nx_av1_delta_q_write(w: *NxAv1Bw, v: i64) -> i64 { 78 if v == 0 { 79 nx_av1_bw_put(w, 0, 1) 80 return 1 81 } 82 if v < (0 - 64) { return 0 } 83 if v > 63 { return 0 } 84 nx_av1_bw_put(w, 1, 1) 85 return nx_av1_su_write(w, v, 7) 86} 87 88// ===== quantization_params ======================================== 89 90func nx_av1_quant_write(w: *NxAv1Bw, mono: i64, separate_uv: i64, fld: *i64) -> i64 { 91 let base: i64 = fld[NX_QP_BASE] 92 if base < 0 { return 0 } 93 if base > 255 { return 0 } 94 nx_av1_bw_put(w, base, 8) 95 if nx_av1_delta_q_write(w, fld[NX_QP_YDC]) == 0 { return 0 } 96 97 if mono == 0 { 98 var diff: i64 = 0 99 if separate_uv == 1 { 100 if fld[NX_QP_UDC] != fld[NX_QP_VDC] { diff = 1 } 101 if fld[NX_QP_UAC] != fld[NX_QP_VAC] { diff = 1 } 102 nx_av1_bw_put(w, diff, 1) 103 } 104 if nx_av1_delta_q_write(w, fld[NX_QP_UDC]) == 0 { return 0 } 105 if nx_av1_delta_q_write(w, fld[NX_QP_UAC]) == 0 { return 0 } 106 if diff == 1 { 107 if nx_av1_delta_q_write(w, fld[NX_QP_VDC]) == 0 { return 0 } 108 if nx_av1_delta_q_write(w, fld[NX_QP_VAC]) == 0 { return 0 } 109 } 110 } 111 112 let useqm: i64 = fld[NX_QP_USEQM] 113 nx_av1_bw_put(w, useqm, 1) 114 if useqm == 1 { 115 if fld[NX_QP_QMY] > 15 { return 0 } 116 nx_av1_bw_put(w, fld[NX_QP_QMY], 4) 117 if mono == 0 { 118 nx_av1_bw_put(w, fld[NX_QP_QMU], 4) 119 if separate_uv == 1 { nx_av1_bw_put(w, fld[NX_QP_QMV], 4) } 120 } 121 } 122 return 1 123} 124 125func nx_av1_quant_read(bs: *NxBitStream, mono: i64, separate_uv: i64, fld: *i64) -> i64 { 126 fld[NX_QP_BASE] = nx_bitstream_read_msb(bs, 8) 127 fld[NX_QP_YDC] = nx_av1_delta_q_read(bs) 128 fld[NX_QP_UDC] = 0; fld[NX_QP_UAC] = 0 129 fld[NX_QP_VDC] = 0; fld[NX_QP_VAC] = 0 130 131 if mono == 0 { 132 var diff: i64 = 0 133 if separate_uv == 1 { diff = nx_bitstream_read_msb(bs, 1) } 134 fld[NX_QP_UDC] = nx_av1_delta_q_read(bs) 135 fld[NX_QP_UAC] = nx_av1_delta_q_read(bs) 136 if diff == 1 { 137 fld[NX_QP_VDC] = nx_av1_delta_q_read(bs) 138 fld[NX_QP_VAC] = nx_av1_delta_q_read(bs) 139 } else { 140 fld[NX_QP_VDC] = fld[NX_QP_UDC] 141 fld[NX_QP_VAC] = fld[NX_QP_UAC] 142 } 143 } 144 145 let useqm: i64 = nx_bitstream_read_msb(bs, 1) 146 fld[NX_QP_USEQM] = useqm 147 fld[NX_QP_QMY] = 0; fld[NX_QP_QMU] = 0; fld[NX_QP_QMV] = 0 148 if useqm == 1 { 149 fld[NX_QP_QMY] = nx_bitstream_read_msb(bs, 4) 150 if mono == 0 { 151 fld[NX_QP_QMU] = nx_bitstream_read_msb(bs, 4) 152 if separate_uv == 1 { 153 fld[NX_QP_QMV] = nx_bitstream_read_msb(bs, 4) 154 } else { 155 fld[NX_QP_QMV] = fld[NX_QP_QMU] 156 } 157 } 158 } 159 if bs.overflow == 1 { return 0 } 160 return 1 161} 162 163// ===== the CDEF secondary-strength mapping ======================== 164// 165// Coded 0,1,2,3 means strength 0,1,2,4. Strength 3 is UNREPRESENTABLE. 166 167func nx_av1_cdef_sec_decode(coded: i64) -> i64 { 168 if coded == 3 { return 4 } 169 return coded 170} 171 172func nx_av1_cdef_sec_encode(strength: i64) -> i64 { 173 if strength == 4 { return 3 } 174 if strength == 3 { return 0 - 1 } 175 if strength < 0 { return 0 - 1 } 176 if strength > 4 { return 0 - 1 } 177 return strength 178} 179 180// ===== cdef_params ================================================ 181 182func nx_av1_cdef_write(w: *NxAv1Bw, num_planes: i64, fld: *i64) -> i64 { 183 let damping: i64 = fld[NX_CDEF_DAMPING] 184 if damping < 3 { return 0 } 185 if damping > 6 { return 0 } 186 let bits: i64 = fld[NX_CDEF_BITS] 187 if bits < 0 { return 0 } 188 if bits > 3 { return 0 } 189 nx_av1_bw_put(w, damping - 3, 2) 190 nx_av1_bw_put(w, bits, 2) 191 let count: i64 = 1 << bits 192 var i: i64 = 0 193 while i < count { 194 let ypri: i64 = fld[NX_CDEF_YPRI + i] 195 if ypri < 0 { return 0 } 196 if ypri > 15 { return 0 } 197 let ysec: i64 = nx_av1_cdef_sec_encode(fld[NX_CDEF_YSEC + i]) 198 if ysec < 0 { return 0 } 199 nx_av1_bw_put(w, ypri, 4) 200 nx_av1_bw_put(w, ysec, 2) 201 if num_planes > 1 { 202 let upri: i64 = fld[NX_CDEF_UVPRI + i] 203 if upri < 0 { return 0 } 204 if upri > 15 { return 0 } 205 let usec: i64 = nx_av1_cdef_sec_encode(fld[NX_CDEF_UVSEC + i]) 206 if usec < 0 { return 0 } 207 nx_av1_bw_put(w, upri, 4) 208 nx_av1_bw_put(w, usec, 2) 209 } 210 i = i + 1 211 } 212 return 1 213} 214 215func nx_av1_cdef_read(bs: *NxBitStream, num_planes: i64, fld: *i64) -> i64 { 216 let damping: i64 = nx_bitstream_read_msb(bs, 2) + 3 217 let bits: i64 = nx_bitstream_read_msb(bs, 2) 218 fld[NX_CDEF_DAMPING] = damping 219 fld[NX_CDEF_BITS] = bits 220 let count: i64 = 1 << bits 221 var i: i64 = 0 222 while i < count { 223 fld[NX_CDEF_YPRI + i] = nx_bitstream_read_msb(bs, 4) 224 fld[NX_CDEF_YSEC + i] = nx_av1_cdef_sec_decode(nx_bitstream_read_msb(bs, 2)) 225 if num_planes > 1 { 226 fld[NX_CDEF_UVPRI + i] = nx_bitstream_read_msb(bs, 4) 227 fld[NX_CDEF_UVSEC + i] = nx_av1_cdef_sec_decode(nx_bitstream_read_msb(bs, 2)) 228 } else { 229 fld[NX_CDEF_UVPRI + i] = 0 230 fld[NX_CDEF_UVSEC + i] = 0 231 } 232 i = i + 1 233 } 234 if bs.overflow == 1 { return 0 } 235 return 1 236}