@invintusmedia/tomp4 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tomp4.js +2 -2
- package/package.json +1 -1
- package/src/codecs/smart-render.js +374 -96
- package/src/hls-clip.js +177 -429
- package/src/index.js +1 -6
- package/src/codecs/REFERENCE.md +0 -885
- package/src/codecs/h264-cabac-init.js +0 -546
- package/src/codecs/h264-cabac.js +0 -322
- package/src/codecs/h264-cavlc-tables.js +0 -628
- package/src/codecs/h264-decoder.js +0 -940
- package/src/codecs/h264-encoder.js +0 -502
- package/src/codecs/h264-intra.js +0 -292
- package/src/codecs/h264-sps-pps.js +0 -483
- package/src/codecs/h264-tables.js +0 -217
- package/src/codecs/h264-transform.js +0 -268
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* H.264 CAVLC (Context-Adaptive Variable-Length Coding) Encoding Tables
|
|
3
|
-
*
|
|
4
|
-
* Complete VLC tables from ITU-T H.264 specification:
|
|
5
|
-
* - Table 9-5: coeff_token VLC tables (5 nC ranges + ChromaDC variants)
|
|
6
|
-
* - Table 9-7: total_zeros for 4x4 blocks (TotalCoeff 1-15)
|
|
7
|
-
* - Table 9-8: total_zeros for chroma DC 2x2 (TotalCoeff 1-3)
|
|
8
|
-
* - Table 9-9: total_zeros for chroma DC 2x4 (TotalCoeff 1-7)
|
|
9
|
-
* - Table 9-10: run_before (zerosLeft 1-7+)
|
|
10
|
-
*
|
|
11
|
-
* Each entry is [bits, length] where:
|
|
12
|
-
* - bits: the VLC codeword value (MSB-first integer)
|
|
13
|
-
* - length: number of bits in the codeword
|
|
14
|
-
*
|
|
15
|
-
* Source: Verified against x264 (common/tables.c) and FFmpeg (libavcodec/h264_cavlc.c).
|
|
16
|
-
*
|
|
17
|
-
* @module codecs/h264-cavlc-tables
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
21
|
-
// coeff_token for TotalCoeff=0 (no coefficients)
|
|
22
|
-
// Indexed by nC table index (0-5):
|
|
23
|
-
// 0: nC 0-1, 1: nC 2-3, 2: nC 4-7, 3: nC 8+, 4: nC=-1 (ChromaDC 2x2), 5: nC=-2 (ChromaDC 2x4)
|
|
24
|
-
// Table 9-5 in the spec
|
|
25
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
26
|
-
|
|
27
|
-
export const coeff0Token = [
|
|
28
|
-
[0x01, 1], // nC 0-1: "1"
|
|
29
|
-
[0x03, 2], // nC 2-3: "11"
|
|
30
|
-
[0x0f, 4], // nC 4-7: "1111"
|
|
31
|
-
[0x03, 6], // nC 8+: "000011"
|
|
32
|
-
[0x01, 2], // ChromaDC 2x2: "01"
|
|
33
|
-
[0x01, 1], // ChromaDC 2x4: "1"
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
37
|
-
// coeff_token VLC tables
|
|
38
|
-
// coeffTokenTable[nC_table][totalCoeff-1][trailingOnes] = [bits, length]
|
|
39
|
-
//
|
|
40
|
-
// nC table index mapping:
|
|
41
|
-
// 0: nC = 0,1 (Table 9-5a)
|
|
42
|
-
// 1: nC = 2,3 (Table 9-5b)
|
|
43
|
-
// 2: nC = 4,5,6,7 (Table 9-5c)
|
|
44
|
-
// 3: nC >= 8 (Table 9-5d) -- fixed 6-bit codes
|
|
45
|
-
// 4: nC = -1 (Chroma DC 2x2, Table 9-5e)
|
|
46
|
-
// 5: nC = -2 (Chroma DC 2x4/4x2, for 4:2:2)
|
|
47
|
-
//
|
|
48
|
-
// trailingOnes: 0..3 (but only 0..min(totalCoeff,3) are valid)
|
|
49
|
-
// Invalid combinations have [0, 0] placeholder
|
|
50
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
51
|
-
|
|
52
|
-
export const coeffTokenTable = [
|
|
53
|
-
// ── nC = 0,1 (table 0) ──
|
|
54
|
-
[
|
|
55
|
-
// totalCoeff=1
|
|
56
|
-
[[0x05, 6], [0x01, 2], [0, 0], [0, 0]],
|
|
57
|
-
// totalCoeff=2
|
|
58
|
-
[[0x07, 8], [0x04, 6], [0x01, 3], [0, 0]],
|
|
59
|
-
// totalCoeff=3
|
|
60
|
-
[[0x07, 9], [0x06, 8], [0x05, 7], [0x03, 5]],
|
|
61
|
-
// totalCoeff=4
|
|
62
|
-
[[0x07, 10], [0x06, 9], [0x05, 8], [0x03, 6]],
|
|
63
|
-
// totalCoeff=5
|
|
64
|
-
[[0x07, 11], [0x06, 10], [0x05, 9], [0x04, 7]],
|
|
65
|
-
// totalCoeff=6
|
|
66
|
-
[[0x0f, 13], [0x06, 11], [0x05, 10], [0x04, 8]],
|
|
67
|
-
// totalCoeff=7
|
|
68
|
-
[[0x0b, 13], [0x0e, 13], [0x05, 11], [0x04, 9]],
|
|
69
|
-
// totalCoeff=8
|
|
70
|
-
[[0x08, 13], [0x0a, 13], [0x0d, 13], [0x04, 10]],
|
|
71
|
-
// totalCoeff=9
|
|
72
|
-
[[0x0f, 14], [0x0e, 14], [0x09, 13], [0x04, 11]],
|
|
73
|
-
// totalCoeff=10
|
|
74
|
-
[[0x0b, 14], [0x0a, 14], [0x0d, 14], [0x0c, 13]],
|
|
75
|
-
// totalCoeff=11
|
|
76
|
-
[[0x0f, 15], [0x0e, 15], [0x09, 14], [0x0c, 14]],
|
|
77
|
-
// totalCoeff=12
|
|
78
|
-
[[0x0b, 15], [0x0a, 15], [0x0d, 15], [0x08, 14]],
|
|
79
|
-
// totalCoeff=13
|
|
80
|
-
[[0x0f, 16], [0x01, 15], [0x09, 15], [0x0c, 15]],
|
|
81
|
-
// totalCoeff=14
|
|
82
|
-
[[0x0b, 16], [0x0e, 16], [0x0d, 16], [0x08, 15]],
|
|
83
|
-
// totalCoeff=15
|
|
84
|
-
[[0x07, 16], [0x0a, 16], [0x09, 16], [0x0c, 16]],
|
|
85
|
-
// totalCoeff=16
|
|
86
|
-
[[0x04, 16], [0x06, 16], [0x05, 16], [0x08, 16]],
|
|
87
|
-
],
|
|
88
|
-
|
|
89
|
-
// ── nC = 2,3 (table 1) ──
|
|
90
|
-
[
|
|
91
|
-
// totalCoeff=1
|
|
92
|
-
[[0x0b, 6], [0x02, 2], [0, 0], [0, 0]],
|
|
93
|
-
// totalCoeff=2
|
|
94
|
-
[[0x07, 6], [0x07, 5], [0x03, 3], [0, 0]],
|
|
95
|
-
// totalCoeff=3
|
|
96
|
-
[[0x07, 7], [0x0a, 6], [0x09, 6], [0x05, 4]],
|
|
97
|
-
// totalCoeff=4
|
|
98
|
-
[[0x07, 8], [0x06, 6], [0x05, 6], [0x04, 4]],
|
|
99
|
-
// totalCoeff=5
|
|
100
|
-
[[0x04, 8], [0x06, 7], [0x05, 7], [0x06, 5]],
|
|
101
|
-
// totalCoeff=6
|
|
102
|
-
[[0x07, 9], [0x06, 8], [0x05, 8], [0x08, 6]],
|
|
103
|
-
// totalCoeff=7
|
|
104
|
-
[[0x0f, 11], [0x06, 9], [0x05, 9], [0x04, 6]],
|
|
105
|
-
// totalCoeff=8
|
|
106
|
-
[[0x0b, 11], [0x0e, 11], [0x0d, 11], [0x04, 7]],
|
|
107
|
-
// totalCoeff=9
|
|
108
|
-
[[0x0f, 12], [0x0a, 11], [0x09, 11], [0x04, 9]],
|
|
109
|
-
// totalCoeff=10
|
|
110
|
-
[[0x0b, 12], [0x0e, 12], [0x0d, 12], [0x0c, 11]],
|
|
111
|
-
// totalCoeff=11
|
|
112
|
-
[[0x08, 12], [0x0a, 12], [0x09, 12], [0x08, 11]],
|
|
113
|
-
// totalCoeff=12
|
|
114
|
-
[[0x0f, 13], [0x0e, 13], [0x0d, 13], [0x0c, 12]],
|
|
115
|
-
// totalCoeff=13
|
|
116
|
-
[[0x0b, 13], [0x0a, 13], [0x09, 13], [0x0c, 13]],
|
|
117
|
-
// totalCoeff=14
|
|
118
|
-
[[0x07, 13], [0x0b, 14], [0x06, 13], [0x08, 13]],
|
|
119
|
-
// totalCoeff=15
|
|
120
|
-
[[0x09, 14], [0x08, 14], [0x0a, 14], [0x01, 13]],
|
|
121
|
-
// totalCoeff=16
|
|
122
|
-
[[0x07, 14], [0x06, 14], [0x05, 14], [0x04, 14]],
|
|
123
|
-
],
|
|
124
|
-
|
|
125
|
-
// ── nC = 4,5,6,7 (table 2) ──
|
|
126
|
-
[
|
|
127
|
-
// totalCoeff=1
|
|
128
|
-
[[0x0f, 6], [0x0e, 4], [0, 0], [0, 0]],
|
|
129
|
-
// totalCoeff=2
|
|
130
|
-
[[0x0b, 6], [0x0f, 5], [0x0d, 4], [0, 0]],
|
|
131
|
-
// totalCoeff=3
|
|
132
|
-
[[0x08, 6], [0x0c, 5], [0x0e, 5], [0x0c, 4]],
|
|
133
|
-
// totalCoeff=4
|
|
134
|
-
[[0x0f, 7], [0x0a, 5], [0x0b, 5], [0x0b, 4]],
|
|
135
|
-
// totalCoeff=5
|
|
136
|
-
[[0x0b, 7], [0x08, 5], [0x09, 5], [0x0a, 4]],
|
|
137
|
-
// totalCoeff=6
|
|
138
|
-
[[0x09, 7], [0x0e, 6], [0x0d, 6], [0x09, 4]],
|
|
139
|
-
// totalCoeff=7
|
|
140
|
-
[[0x08, 7], [0x0a, 6], [0x09, 6], [0x08, 4]],
|
|
141
|
-
// totalCoeff=8
|
|
142
|
-
[[0x0f, 8], [0x0e, 7], [0x0d, 7], [0x0d, 5]],
|
|
143
|
-
// totalCoeff=9
|
|
144
|
-
[[0x0b, 8], [0x0e, 8], [0x0a, 7], [0x0c, 6]],
|
|
145
|
-
// totalCoeff=10
|
|
146
|
-
[[0x0f, 9], [0x0a, 8], [0x0d, 8], [0x0c, 7]],
|
|
147
|
-
// totalCoeff=11
|
|
148
|
-
[[0x0b, 9], [0x0e, 9], [0x09, 8], [0x0c, 8]],
|
|
149
|
-
// totalCoeff=12
|
|
150
|
-
[[0x08, 9], [0x0a, 9], [0x0d, 9], [0x08, 8]],
|
|
151
|
-
// totalCoeff=13
|
|
152
|
-
[[0x0d, 10], [0x07, 9], [0x09, 9], [0x0c, 9]],
|
|
153
|
-
// totalCoeff=14
|
|
154
|
-
[[0x09, 10], [0x0c, 10], [0x0b, 10], [0x0a, 10]],
|
|
155
|
-
// totalCoeff=15
|
|
156
|
-
[[0x05, 10], [0x08, 10], [0x07, 10], [0x06, 10]],
|
|
157
|
-
// totalCoeff=16
|
|
158
|
-
[[0x01, 10], [0x04, 10], [0x03, 10], [0x02, 10]],
|
|
159
|
-
],
|
|
160
|
-
|
|
161
|
-
// ── nC >= 8 (table 3) ── fixed-length 6-bit codes
|
|
162
|
-
[
|
|
163
|
-
// totalCoeff=1
|
|
164
|
-
[[0x00, 6], [0x01, 6], [0, 0], [0, 0]],
|
|
165
|
-
// totalCoeff=2
|
|
166
|
-
[[0x04, 6], [0x05, 6], [0x06, 6], [0, 0]],
|
|
167
|
-
// totalCoeff=3
|
|
168
|
-
[[0x08, 6], [0x09, 6], [0x0a, 6], [0x0b, 6]],
|
|
169
|
-
// totalCoeff=4
|
|
170
|
-
[[0x0c, 6], [0x0d, 6], [0x0e, 6], [0x0f, 6]],
|
|
171
|
-
// totalCoeff=5
|
|
172
|
-
[[0x10, 6], [0x11, 6], [0x12, 6], [0x13, 6]],
|
|
173
|
-
// totalCoeff=6
|
|
174
|
-
[[0x14, 6], [0x15, 6], [0x16, 6], [0x17, 6]],
|
|
175
|
-
// totalCoeff=7
|
|
176
|
-
[[0x18, 6], [0x19, 6], [0x1a, 6], [0x1b, 6]],
|
|
177
|
-
// totalCoeff=8
|
|
178
|
-
[[0x1c, 6], [0x1d, 6], [0x1e, 6], [0x1f, 6]],
|
|
179
|
-
// totalCoeff=9
|
|
180
|
-
[[0x20, 6], [0x21, 6], [0x22, 6], [0x23, 6]],
|
|
181
|
-
// totalCoeff=10
|
|
182
|
-
[[0x24, 6], [0x25, 6], [0x26, 6], [0x27, 6]],
|
|
183
|
-
// totalCoeff=11
|
|
184
|
-
[[0x28, 6], [0x29, 6], [0x2a, 6], [0x2b, 6]],
|
|
185
|
-
// totalCoeff=12
|
|
186
|
-
[[0x2c, 6], [0x2d, 6], [0x2e, 6], [0x2f, 6]],
|
|
187
|
-
// totalCoeff=13
|
|
188
|
-
[[0x30, 6], [0x31, 6], [0x32, 6], [0x33, 6]],
|
|
189
|
-
// totalCoeff=14
|
|
190
|
-
[[0x34, 6], [0x35, 6], [0x36, 6], [0x37, 6]],
|
|
191
|
-
// totalCoeff=15
|
|
192
|
-
[[0x38, 6], [0x39, 6], [0x3a, 6], [0x3b, 6]],
|
|
193
|
-
// totalCoeff=16
|
|
194
|
-
[[0x3c, 6], [0x3d, 6], [0x3e, 6], [0x3f, 6]],
|
|
195
|
-
],
|
|
196
|
-
|
|
197
|
-
// ── nC = -1: Chroma DC 2x2 (4:2:0) (table 4) ── maxCoeff=4
|
|
198
|
-
[
|
|
199
|
-
// totalCoeff=1
|
|
200
|
-
[[0x07, 6], [0x01, 1], [0, 0], [0, 0]],
|
|
201
|
-
// totalCoeff=2
|
|
202
|
-
[[0x04, 6], [0x06, 6], [0x01, 3], [0, 0]],
|
|
203
|
-
// totalCoeff=3
|
|
204
|
-
[[0x03, 6], [0x03, 7], [0x02, 7], [0x05, 6]],
|
|
205
|
-
// totalCoeff=4
|
|
206
|
-
[[0x02, 6], [0x03, 8], [0x02, 8], [0x00, 7]],
|
|
207
|
-
],
|
|
208
|
-
|
|
209
|
-
// ── nC = -2: Chroma DC 2x4 (4:2:2) (table 5) ── maxCoeff=8
|
|
210
|
-
[
|
|
211
|
-
// totalCoeff=1
|
|
212
|
-
[[0x0f, 7], [0x01, 2], [0, 0], [0, 0]],
|
|
213
|
-
// totalCoeff=2
|
|
214
|
-
[[0x0e, 7], [0x0d, 7], [0x01, 3], [0, 0]],
|
|
215
|
-
// totalCoeff=3
|
|
216
|
-
[[0x07, 9], [0x0c, 7], [0x0b, 7], [0x01, 5]],
|
|
217
|
-
// totalCoeff=4
|
|
218
|
-
[[0x06, 9], [0x05, 9], [0x0a, 7], [0x01, 6]],
|
|
219
|
-
// totalCoeff=5
|
|
220
|
-
[[0x07, 10], [0x06, 10], [0x04, 9], [0x09, 7]],
|
|
221
|
-
// totalCoeff=6
|
|
222
|
-
[[0x07, 11], [0x06, 11], [0x05, 10], [0x08, 7]],
|
|
223
|
-
// totalCoeff=7
|
|
224
|
-
[[0x07, 12], [0x06, 12], [0x05, 11], [0x04, 10]],
|
|
225
|
-
// totalCoeff=8
|
|
226
|
-
[[0x07, 13], [0x05, 12], [0x04, 12], [0x04, 11]],
|
|
227
|
-
],
|
|
228
|
-
];
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Maps nC (predicted number of non-zero coefficients) to table index.
|
|
232
|
-
* nC < 0: use -1 → index 4 (ChromaDC 2x2) or -2 → index 5 (ChromaDC 2x4)
|
|
233
|
-
* nC 0-1: index 0
|
|
234
|
-
* nC 2-3: index 1
|
|
235
|
-
* nC 4-7: index 2
|
|
236
|
-
* nC >= 8: index 3
|
|
237
|
-
*/
|
|
238
|
-
export function nCtoTableIndex(nC) {
|
|
239
|
-
if (nC < 0) return nC === -1 ? 4 : 5;
|
|
240
|
-
if (nC <= 1) return 0;
|
|
241
|
-
if (nC <= 3) return 1;
|
|
242
|
-
if (nC <= 7) return 2;
|
|
243
|
-
return 3;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
247
|
-
// total_zeros VLC tables (Table 9-7 in the spec)
|
|
248
|
-
// totalZerosTable[totalCoeff-1][totalZeros] = [bits, length]
|
|
249
|
-
// For 4x4 blocks, TotalCoeff = 1..15
|
|
250
|
-
// totalZeros range: 0..(16-TotalCoeff)
|
|
251
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
252
|
-
|
|
253
|
-
export const totalZerosTable = [
|
|
254
|
-
// totalCoeff=1: totalZeros 0..15
|
|
255
|
-
[
|
|
256
|
-
[0x01, 1], [0x03, 3], [0x02, 3], [0x03, 4],
|
|
257
|
-
[0x02, 4], [0x03, 5], [0x02, 5], [0x03, 6],
|
|
258
|
-
[0x02, 6], [0x03, 7], [0x02, 7], [0x03, 8],
|
|
259
|
-
[0x02, 8], [0x03, 9], [0x02, 9], [0x01, 9],
|
|
260
|
-
],
|
|
261
|
-
// totalCoeff=2: totalZeros 0..14
|
|
262
|
-
[
|
|
263
|
-
[0x07, 3], [0x06, 3], [0x05, 3], [0x04, 3],
|
|
264
|
-
[0x03, 3], [0x05, 4], [0x04, 4], [0x03, 4],
|
|
265
|
-
[0x02, 4], [0x03, 5], [0x02, 5], [0x03, 6],
|
|
266
|
-
[0x02, 6], [0x01, 6], [0x00, 6],
|
|
267
|
-
],
|
|
268
|
-
// totalCoeff=3: totalZeros 0..13
|
|
269
|
-
[
|
|
270
|
-
[0x05, 4], [0x07, 3], [0x06, 3], [0x05, 3],
|
|
271
|
-
[0x04, 4], [0x03, 4], [0x04, 3], [0x03, 3],
|
|
272
|
-
[0x02, 4], [0x03, 5], [0x02, 5], [0x01, 6],
|
|
273
|
-
[0x01, 5], [0x00, 6],
|
|
274
|
-
],
|
|
275
|
-
// totalCoeff=4: totalZeros 0..12
|
|
276
|
-
[
|
|
277
|
-
[0x03, 5], [0x07, 3], [0x05, 4], [0x04, 4],
|
|
278
|
-
[0x06, 3], [0x05, 3], [0x04, 3], [0x03, 4],
|
|
279
|
-
[0x03, 3], [0x02, 4], [0x02, 5], [0x01, 5],
|
|
280
|
-
[0x00, 5],
|
|
281
|
-
],
|
|
282
|
-
// totalCoeff=5: totalZeros 0..11
|
|
283
|
-
[
|
|
284
|
-
[0x05, 4], [0x04, 4], [0x03, 4], [0x07, 3],
|
|
285
|
-
[0x06, 3], [0x05, 3], [0x04, 3], [0x03, 3],
|
|
286
|
-
[0x02, 4], [0x01, 5], [0x01, 4], [0x00, 5],
|
|
287
|
-
],
|
|
288
|
-
// totalCoeff=6: totalZeros 0..10
|
|
289
|
-
[
|
|
290
|
-
[0x01, 6], [0x01, 5], [0x07, 3], [0x06, 3],
|
|
291
|
-
[0x05, 3], [0x04, 3], [0x03, 3], [0x02, 3],
|
|
292
|
-
[0x01, 4], [0x01, 3], [0x00, 6],
|
|
293
|
-
],
|
|
294
|
-
// totalCoeff=7: totalZeros 0..9
|
|
295
|
-
[
|
|
296
|
-
[0x01, 6], [0x01, 5], [0x05, 3], [0x04, 3],
|
|
297
|
-
[0x03, 3], [0x03, 2], [0x02, 3], [0x01, 4],
|
|
298
|
-
[0x01, 3], [0x00, 6],
|
|
299
|
-
],
|
|
300
|
-
// totalCoeff=8: totalZeros 0..8
|
|
301
|
-
[
|
|
302
|
-
[0x01, 6], [0x01, 4], [0x01, 5], [0x03, 3],
|
|
303
|
-
[0x03, 2], [0x02, 2], [0x02, 3], [0x01, 3],
|
|
304
|
-
[0x00, 6],
|
|
305
|
-
],
|
|
306
|
-
// totalCoeff=9: totalZeros 0..7
|
|
307
|
-
[
|
|
308
|
-
[0x01, 6], [0x00, 6], [0x01, 4], [0x03, 2],
|
|
309
|
-
[0x02, 2], [0x01, 3], [0x01, 2], [0x01, 5],
|
|
310
|
-
],
|
|
311
|
-
// totalCoeff=10: totalZeros 0..6
|
|
312
|
-
[
|
|
313
|
-
[0x01, 5], [0x00, 5], [0x01, 3], [0x03, 2],
|
|
314
|
-
[0x02, 2], [0x01, 2], [0x01, 4],
|
|
315
|
-
],
|
|
316
|
-
// totalCoeff=11: totalZeros 0..5
|
|
317
|
-
[
|
|
318
|
-
[0x00, 4], [0x01, 4], [0x01, 3], [0x02, 3],
|
|
319
|
-
[0x01, 1], [0x03, 3],
|
|
320
|
-
],
|
|
321
|
-
// totalCoeff=12: totalZeros 0..4
|
|
322
|
-
[
|
|
323
|
-
[0x00, 4], [0x01, 4], [0x01, 2], [0x01, 1],
|
|
324
|
-
[0x01, 3],
|
|
325
|
-
],
|
|
326
|
-
// totalCoeff=13: totalZeros 0..3
|
|
327
|
-
[
|
|
328
|
-
[0x00, 3], [0x01, 3], [0x01, 1], [0x01, 2],
|
|
329
|
-
],
|
|
330
|
-
// totalCoeff=14: totalZeros 0..2
|
|
331
|
-
[
|
|
332
|
-
[0x00, 2], [0x01, 2], [0x01, 1],
|
|
333
|
-
],
|
|
334
|
-
// totalCoeff=15: totalZeros 0..1
|
|
335
|
-
[
|
|
336
|
-
[0x00, 1], [0x01, 1],
|
|
337
|
-
],
|
|
338
|
-
];
|
|
339
|
-
|
|
340
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
341
|
-
// total_zeros for Chroma DC 2x2 (4:2:0) — Table 9-8 in the spec
|
|
342
|
-
// totalZerosChromaDC2x2[totalCoeff-1][totalZeros] = [bits, length]
|
|
343
|
-
// maxCoeff = 4, so totalCoeff = 1..3
|
|
344
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
345
|
-
|
|
346
|
-
export const totalZerosChromaDC2x2 = [
|
|
347
|
-
// totalCoeff=1: totalZeros 0..3
|
|
348
|
-
[
|
|
349
|
-
[0x01, 1], [0x01, 2], [0x01, 3], [0x00, 3],
|
|
350
|
-
],
|
|
351
|
-
// totalCoeff=2: totalZeros 0..2
|
|
352
|
-
[
|
|
353
|
-
[0x01, 1], [0x01, 2], [0x00, 2],
|
|
354
|
-
],
|
|
355
|
-
// totalCoeff=3: totalZeros 0..1
|
|
356
|
-
[
|
|
357
|
-
[0x01, 1], [0x00, 1],
|
|
358
|
-
],
|
|
359
|
-
];
|
|
360
|
-
|
|
361
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
362
|
-
// total_zeros for Chroma DC 2x4 (4:2:2) — Table 9-9 in the spec
|
|
363
|
-
// totalZerosChromaDC2x4[totalCoeff-1][totalZeros] = [bits, length]
|
|
364
|
-
// maxCoeff = 8, so totalCoeff = 1..7
|
|
365
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
366
|
-
|
|
367
|
-
export const totalZerosChromaDC2x4 = [
|
|
368
|
-
// totalCoeff=1: totalZeros 0..7
|
|
369
|
-
[
|
|
370
|
-
[0x01, 1], [0x02, 3], [0x03, 3], [0x02, 4],
|
|
371
|
-
[0x03, 4], [0x01, 4], [0x01, 5], [0x00, 5],
|
|
372
|
-
],
|
|
373
|
-
// totalCoeff=2: totalZeros 0..6
|
|
374
|
-
[
|
|
375
|
-
[0x00, 3], [0x01, 2], [0x01, 3], [0x04, 3],
|
|
376
|
-
[0x05, 3], [0x06, 3], [0x07, 3],
|
|
377
|
-
],
|
|
378
|
-
// totalCoeff=3: totalZeros 0..5
|
|
379
|
-
[
|
|
380
|
-
[0x00, 3], [0x01, 3], [0x01, 2], [0x02, 2],
|
|
381
|
-
[0x06, 3], [0x07, 3],
|
|
382
|
-
],
|
|
383
|
-
// totalCoeff=4: totalZeros 0..4
|
|
384
|
-
[
|
|
385
|
-
[0x06, 3], [0x00, 2], [0x01, 2], [0x02, 2],
|
|
386
|
-
[0x07, 3],
|
|
387
|
-
],
|
|
388
|
-
// totalCoeff=5: totalZeros 0..3
|
|
389
|
-
[
|
|
390
|
-
[0x00, 2], [0x01, 2], [0x02, 2], [0x03, 2],
|
|
391
|
-
],
|
|
392
|
-
// totalCoeff=6: totalZeros 0..2
|
|
393
|
-
[
|
|
394
|
-
[0x00, 2], [0x01, 2], [0x01, 1],
|
|
395
|
-
],
|
|
396
|
-
// totalCoeff=7: totalZeros 0..1
|
|
397
|
-
[
|
|
398
|
-
[0x00, 1], [0x01, 1],
|
|
399
|
-
],
|
|
400
|
-
];
|
|
401
|
-
|
|
402
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
403
|
-
// run_before VLC tables — Table 9-10 in the spec
|
|
404
|
-
// runBeforeTable[min(zerosLeft,7)-1][runBefore] = [bits, length]
|
|
405
|
-
//
|
|
406
|
-
// zerosLeft=1..6 have individual tables
|
|
407
|
-
// zerosLeft>=7 shares one table (index 6)
|
|
408
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
409
|
-
|
|
410
|
-
export const runBeforeTable = [
|
|
411
|
-
// zerosLeft=1: runBefore 0..1
|
|
412
|
-
[
|
|
413
|
-
[0x01, 1], [0x00, 1],
|
|
414
|
-
],
|
|
415
|
-
// zerosLeft=2: runBefore 0..2
|
|
416
|
-
[
|
|
417
|
-
[0x01, 1], [0x01, 2], [0x00, 2],
|
|
418
|
-
],
|
|
419
|
-
// zerosLeft=3: runBefore 0..3
|
|
420
|
-
[
|
|
421
|
-
[0x03, 2], [0x02, 2], [0x01, 2], [0x00, 2],
|
|
422
|
-
],
|
|
423
|
-
// zerosLeft=4: runBefore 0..4
|
|
424
|
-
[
|
|
425
|
-
[0x03, 2], [0x02, 2], [0x01, 2], [0x01, 3], [0x00, 3],
|
|
426
|
-
],
|
|
427
|
-
// zerosLeft=5: runBefore 0..5
|
|
428
|
-
[
|
|
429
|
-
[0x03, 2], [0x02, 2], [0x03, 3], [0x02, 3], [0x01, 3], [0x00, 3],
|
|
430
|
-
],
|
|
431
|
-
// zerosLeft=6: runBefore 0..6
|
|
432
|
-
[
|
|
433
|
-
[0x03, 2], [0x00, 3], [0x01, 3], [0x03, 3], [0x02, 3], [0x05, 3], [0x04, 3],
|
|
434
|
-
],
|
|
435
|
-
// zerosLeft>=7: runBefore 0..14
|
|
436
|
-
[
|
|
437
|
-
[0x07, 3], [0x06, 3], [0x05, 3], [0x04, 3],
|
|
438
|
-
[0x03, 3], [0x02, 3], [0x01, 3], [0x01, 4],
|
|
439
|
-
[0x01, 5], [0x01, 6], [0x01, 7], [0x01, 8],
|
|
440
|
-
[0x01, 9], [0x01, 10], [0x01, 11],
|
|
441
|
-
],
|
|
442
|
-
];
|
|
443
|
-
|
|
444
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
445
|
-
// Level encoding (coefficient magnitude/sign)
|
|
446
|
-
//
|
|
447
|
-
// The H.264 CAVLC level encoding uses:
|
|
448
|
-
// 1) level_prefix: unary code (N zeros followed by a 1)
|
|
449
|
-
// 2) level_suffix: fixed-length code of length suffixLength
|
|
450
|
-
//
|
|
451
|
-
// The suffixLength starts at 0 (or 1 if totalCoeff>10 && trailingOnes<3)
|
|
452
|
-
// and increases as larger levels are encountered.
|
|
453
|
-
//
|
|
454
|
-
// This function encodes a single coefficient level and returns
|
|
455
|
-
// [bits, length, newSuffixLength].
|
|
456
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Thresholds for incrementing suffixLength.
|
|
460
|
-
* After encoding a level, if |level| > nextSuffix[suffixLength],
|
|
461
|
-
* increment suffixLength.
|
|
462
|
-
* From x264: {0, 3, 6, 12, 24, 48, 0xffff}
|
|
463
|
-
*/
|
|
464
|
-
const SUFFIX_THRESHOLD = [0, 3, 6, 12, 24, 48, 0x7fffffff];
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Encode a single coefficient level value using CAVLC level VLC.
|
|
468
|
-
*
|
|
469
|
-
* Algorithm from ITU-T H.264 Section 9.2.2 and verified against
|
|
470
|
-
* x264 (common/vlc.c x264_level_token / encoder/cavlc.c cavlc_block_residual_escape).
|
|
471
|
-
*
|
|
472
|
-
* @param {number} level - Signed coefficient level (non-zero)
|
|
473
|
-
* @param {number} suffixLength - Current suffix length (0-6)
|
|
474
|
-
* @param {boolean} firstAfterTrailing - True if this is the first level after
|
|
475
|
-
* trailing ones and trailingOnes < 3. The spec says to subtract 1 from the
|
|
476
|
-
* magnitude (since we know it must be > 1 in this case).
|
|
477
|
-
* @returns {{ bits: number, length: number, suffixLength: number }}
|
|
478
|
-
*/
|
|
479
|
-
export function encodeLevel(level, suffixLength, firstAfterTrailing) {
|
|
480
|
-
const sign = level < 0 ? 1 : 0;
|
|
481
|
-
let absLevel = Math.abs(level);
|
|
482
|
-
|
|
483
|
-
// level_code = 2*|level| - 2 + sign
|
|
484
|
-
// If firstAfterTrailing, the decoded level is offset by 1
|
|
485
|
-
// (since |level| > 1 is guaranteed), so we adjust:
|
|
486
|
-
let levelCode = (absLevel << 1) - 2 + sign;
|
|
487
|
-
if (firstAfterTrailing) {
|
|
488
|
-
levelCode -= 2;
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
let bits, length;
|
|
492
|
-
|
|
493
|
-
const prefix = levelCode >> suffixLength;
|
|
494
|
-
|
|
495
|
-
if (prefix < 14) {
|
|
496
|
-
// Normal case: prefix zeros + 1 + suffix bits
|
|
497
|
-
length = prefix + 1 + suffixLength;
|
|
498
|
-
bits = (1 << suffixLength) | (levelCode & ((1 << suffixLength) - 1));
|
|
499
|
-
} else if (suffixLength === 0 && prefix === 14) {
|
|
500
|
-
// Special case: suffixLength=0, prefix=14 uses 4-bit suffix
|
|
501
|
-
length = 15 + 4; // 19 bits total (14 zeros + 1 + 4 suffix bits)
|
|
502
|
-
bits = (1 << 4) | (levelCode - 14);
|
|
503
|
-
} else if (prefix === 14) {
|
|
504
|
-
// suffixLength > 0, prefix=14: normal encoding still applies
|
|
505
|
-
length = 14 + 1 + suffixLength;
|
|
506
|
-
bits = (1 << suffixLength) | (levelCode & ((1 << suffixLength) - 1));
|
|
507
|
-
} else {
|
|
508
|
-
// prefix >= 15: escape code (High Profile level codes)
|
|
509
|
-
let escapeLevelCode = levelCode;
|
|
510
|
-
escapeLevelCode -= 15 << suffixLength;
|
|
511
|
-
if (suffixLength === 0) {
|
|
512
|
-
escapeLevelCode -= 15;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
let levelPrefix = 15;
|
|
516
|
-
// For very large values, extend the prefix (High Profile)
|
|
517
|
-
while (escapeLevelCode >= (1 << (levelPrefix - 3))) {
|
|
518
|
-
escapeLevelCode -= 1 << (levelPrefix - 3);
|
|
519
|
-
levelPrefix++;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// prefix unary code (levelPrefix zeros + 1) + (levelPrefix-3) suffix bits
|
|
523
|
-
length = levelPrefix + 1 + (levelPrefix - 3);
|
|
524
|
-
bits = (1 << (levelPrefix - 3)) | (escapeLevelCode & ((1 << (levelPrefix - 3)) - 1));
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// Update suffixLength
|
|
528
|
-
let newSuffixLength = suffixLength;
|
|
529
|
-
if (newSuffixLength === 0) {
|
|
530
|
-
newSuffixLength = 1;
|
|
531
|
-
}
|
|
532
|
-
if (absLevel > SUFFIX_THRESHOLD[newSuffixLength]) {
|
|
533
|
-
newSuffixLength++;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
return { bits, length, suffixLength: newSuffixLength };
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* Encode the full set of non-trailing-one levels for a residual block.
|
|
541
|
-
*
|
|
542
|
-
* @param {number[]} levels - Array of signed level values (non-trailing, in reverse scan order)
|
|
543
|
-
* @param {number} trailingOnes - Number of trailing ones (0-3)
|
|
544
|
-
* @param {number} totalCoeff - Total number of non-zero coefficients
|
|
545
|
-
* @returns {{ bits: number[], lengths: number[] }} - Arrays of VLC codewords
|
|
546
|
-
*/
|
|
547
|
-
export function encodeLevels(levels, trailingOnes, totalCoeff) {
|
|
548
|
-
const bits = [];
|
|
549
|
-
const lengths = [];
|
|
550
|
-
|
|
551
|
-
// Initial suffix length
|
|
552
|
-
let suffixLength = (totalCoeff > 10 && trailingOnes < 3) ? 1 : 0;
|
|
553
|
-
|
|
554
|
-
for (let i = 0; i < levels.length; i++) {
|
|
555
|
-
const firstAfterTrailing = (i === 0 && trailingOnes < 3);
|
|
556
|
-
const result = encodeLevel(levels[i], suffixLength, firstAfterTrailing);
|
|
557
|
-
bits.push(result.bits);
|
|
558
|
-
lengths.push(result.length);
|
|
559
|
-
suffixLength = result.suffixLength;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return { bits, lengths };
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
566
|
-
// Convenience: encode a full CAVLC residual block
|
|
567
|
-
// ══════════════════════════════════════════════════════════════════════════════
|
|
568
|
-
|
|
569
|
-
/**
|
|
570
|
-
* Write coeff_token to a bitstream writer.
|
|
571
|
-
*
|
|
572
|
-
* @param {number} totalCoeff - Total non-zero coefficients (0-16)
|
|
573
|
-
* @param {number} trailingOnes - Number of trailing +/-1 coefficients (0-3)
|
|
574
|
-
* @param {number} nC - Predicted number of non-zero coefficients
|
|
575
|
-
* @returns {[number, number]} [bits, length] for the coeff_token VLC
|
|
576
|
-
*/
|
|
577
|
-
export function getCoeffToken(totalCoeff, trailingOnes, nC) {
|
|
578
|
-
const tableIdx = nCtoTableIndex(nC);
|
|
579
|
-
if (totalCoeff === 0) {
|
|
580
|
-
return coeff0Token[tableIdx];
|
|
581
|
-
}
|
|
582
|
-
return coeffTokenTable[tableIdx][totalCoeff - 1][trailingOnes];
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* Get total_zeros VLC for a 4x4 block.
|
|
587
|
-
*
|
|
588
|
-
* @param {number} totalCoeff - 1..15
|
|
589
|
-
* @param {number} totalZeros - 0..(16-totalCoeff)
|
|
590
|
-
* @returns {[number, number]} [bits, length]
|
|
591
|
-
*/
|
|
592
|
-
export function getTotalZeros(totalCoeff, totalZeros) {
|
|
593
|
-
return totalZerosTable[totalCoeff - 1][totalZeros];
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
/**
|
|
597
|
-
* Get total_zeros VLC for chroma DC 2x2 block.
|
|
598
|
-
*
|
|
599
|
-
* @param {number} totalCoeff - 1..3
|
|
600
|
-
* @param {number} totalZeros - 0..(4-totalCoeff)
|
|
601
|
-
* @returns {[number, number]} [bits, length]
|
|
602
|
-
*/
|
|
603
|
-
export function getTotalZerosChromaDC(totalCoeff, totalZeros) {
|
|
604
|
-
return totalZerosChromaDC2x2[totalCoeff - 1][totalZeros];
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
/**
|
|
608
|
-
* Get total_zeros VLC for chroma DC 2x4 block (4:2:2).
|
|
609
|
-
*
|
|
610
|
-
* @param {number} totalCoeff - 1..7
|
|
611
|
-
* @param {number} totalZeros - 0..(8-totalCoeff)
|
|
612
|
-
* @returns {[number, number]} [bits, length]
|
|
613
|
-
*/
|
|
614
|
-
export function getTotalZerosChromaDC422(totalCoeff, totalZeros) {
|
|
615
|
-
return totalZerosChromaDC2x4[totalCoeff - 1][totalZeros];
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Get run_before VLC.
|
|
620
|
-
*
|
|
621
|
-
* @param {number} zerosLeft - Remaining zeros to distribute (>= 1)
|
|
622
|
-
* @param {number} runBefore - Run of zeros before this coefficient
|
|
623
|
-
* @returns {[number, number]} [bits, length]
|
|
624
|
-
*/
|
|
625
|
-
export function getRunBefore(zerosLeft, runBefore) {
|
|
626
|
-
const idx = Math.min(zerosLeft, 7) - 1;
|
|
627
|
-
return runBeforeTable[idx][runBefore];
|
|
628
|
-
}
|