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}