File: video-encoder-h26x-annexb.https.any.js

package info (click to toggle)
firefox 143.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,617,328 kB
  • sloc: cpp: 7,478,492; javascript: 6,417,157; ansic: 3,720,058; python: 1,396,372; xml: 627,523; asm: 438,677; java: 186,156; sh: 63,477; makefile: 19,171; objc: 13,059; perl: 12,983; yacc: 4,583; cs: 3,846; pascal: 3,405; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (369 lines) | stat: -rw-r--r-- 12,140 bytes parent folder | download | duplicates (12)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
// META: global=window,dedicatedworker
// META: script=/webcodecs/video-encoder-utils.js
// META: variant=?h264_annexb_software
// META: variant=?h264_annexb_hardware
// META: variant=?h265_annexb_software
// META: variant=?h265_annexb_hardware

var ENCODER_CONFIG = null;
var ANNEXB_CODEC = ''
promise_setup(async () => {
  const config = {
    '?h264_annexb_software': {
      codec: 'avc1.42001E',
      avc: {format: 'annexb'},
      hardwareAcceleration: 'prefer-software',
    },
    '?h264_annexb_hardware': {
      codec: 'avc1.42001E',
      avc: {format: 'annexb'},
      hardwareAcceleration: 'prefer-hardware',
    },
    '?h265_annexb_software': {
      codec: 'hvc1.1.6.L123.00',
      hevc: {format: 'annexb'},
      hardwareAcceleration: 'prefer-software',
    },
    '?h265_annexb_hardware': {
      codec: 'hvc1.1.6.L123.00',
      hevc: {format: 'annexb'},
      hardwareAcceleration: 'prefer-hardware',
    }
  }[location.search];
  if (config.avc) {
    ANNEXB_CODEC = 'h264'
  }
  if (config.hevc) {
    ANNEXB_CODEC = 'h265'
  }
  config.width = 320;
  config.height = 200;
  config.bitrate = 1000000;
  config.framerate = 30;
  ENCODER_CONFIG = config;
});

// The code is inspired from https://source.chromium.org/chromium/chromium/src/+/main:media/formats/mp4/avc.cc;l=190;drc=a6567f4fac823a8a319652bdb5070b5b72a60f30
// and https://source.chromium.org/chromium/chromium/src/+/main:media/formats/mp4/hevc.cc;l=425;drc=a6567f4fac823a8a319652bdb5070b5b72a60f30?

function checkNaluSyntax(test, chunk) {
  test.step(() => {

    const buffer = new Uint8Array(chunk.byteLength);
    const keyFrame = chunk.type === "key";
    chunk.copyTo(buffer);

    const kAUDAllowed = 1;
    const kBeforeFirstVCL = 2;  // VCL == nal_unit_types 1-5
    const kAfterFirstVCL = 3;
    const kEOStreamAllowed = 4;
    const kNoMoreDataAllowed = 5;
    // Define constants for h264 NALU types
    const kAUD = 9;
    const kSEIMessage = 6;
    const kPrefix = 14;
    const kSubsetSPS = 15;
    const kDPS = 16;
    const kReserved17 = 17;
    const kReserved18 = 18;
    const kPPS = 8;
    const kSPS = 7;
    const kSPSExt = 13;
    const kNonIDRSlice = 1;
    const kSliceDataA = 2;
    const kSliceDataB = 3;
    const kSliceDataC = 4;
    const kIDRSlice = 5;
    const kCodedSliceAux = 19;
    const kEOSeq = 10;
    const kEOStream = 11;
    const kFiller = 12;
    const kUnspecified = 0;
    // Define constants for h265 NALU types
    const AUD_NUT = 35;
    const VPS_NUT = 32;
    const SPS_NUT = 33;
    const PPS_NUT = 34;
    const PREFIX_SEI_NUT = 39;
    const RSV_NVCL41 = 41;
    const RSV_NVCL42 = 42;
    const RSV_NVCL43 = 43;
    const RSV_NVCL44 = 44;
    const UNSPEC48 = 48;
    const UNSPEC49 = 49;
    const UNSPEC50 = 50;
    const UNSPEC51 = 51;
    const UNSPEC52 = 52;
    const UNSPEC53 = 53;
    const UNSPEC54 = 54;
    const UNSPEC55 = 55;
    const FD_NUT = 38;
    const SUFFIX_SEI_NUT = 40;
    const RSV_NVCL45 = 45;
    const RSV_NVCL46 = 46;
    const RSV_NVCL47 = 47;
    const UNSPEC56 = 56;
    const UNSPEC57 = 57;
    const UNSPEC58 = 58;
    const UNSPEC59 = 59;
    const UNSPEC60 = 60;
    const UNSPEC61 = 61;
    const UNSPEC62 = 62;
    const UNSPEC63 = 63;
    const EOS_NUT = 36;
    const EOB_NUT = 37;
    const TRAIL_N = 0;
    const TRAIL_R = 1;
    const TSA_N = 2;
    const TSA_R = 3;
    const STSA_N = 4;
    const STSA_R = 5;
    const RADL_N = 6;
    const RADL_R = 7;
    const RASL_N = 8;
    const RASL_R = 9;
    const RSV_VCL_N10 = 10;
    const RSV_VCL_R11 = 11;
    const RSV_VCL_N12 = 12;
    const RSV_VCL_R13 = 13;
    const RSV_VCL_N14 = 14;
    const RSV_VCL_R15 = 15;
    const RSV_VCL24 = 24;
    const RSV_VCL25 = 25;
    const RSV_VCL26 = 26;
    const RSV_VCL27 = 27;
    const RSV_VCL28 = 28;
    const RSV_VCL29 = 29;
    const RSV_VCL30 = 30;
    const RSV_VCL31 = 31;
    const BLA_W_LP = 16;
    const BLA_W_RADL = 17;
    const BLA_N_LP = 18;
    const IDR_W_RADL = 19;
    const IDR_N_LP = 20;
    const CRA_NUT = 21;
    const RSV_IRAP_VCL22 = 22;
    const RSV_IRAP_VCL23 = 23;

    let order_state = kAUDAllowed;
    let lastBytes = [0xFF, 0xFF, 0xFF];
    for (let pos = 0; pos < buffer.length; pos++) {
      if (lastBytes[0] == 0x00 && lastBytes[1] == 0x00
        && lastBytes[2] == 0x01) {
        let naluType = buffer[pos] & 0x1f;
        if (ANNEXB_CODEC === "h264") {
          switch (naluType) {
            case kAUD:
              assert_less_than_equal(order_state, kAUDAllowed, "Unexpected AUD in order_state " + order_state);
              order_state = kBeforeFirstVCL;
              break;

            case kSEIMessage:
            case kPrefix:
            case kSubsetSPS:
            case kDPS:
            case kReserved17:
            case kReserved18:
            case kPPS:
            case kSPS:
              assert_less_than_equal(order_state, kBeforeFirstVCL, "Unexpected NALU type " + naluType + " in order_state " + order_state);
              order_state = kBeforeFirstVCL;
              break;

            case kSPSExt:
              assert_equals(last_nalu_type, kSPS, "SPS extension does not follow an SPS.");
              break;

            case kNonIDRSlice:
            case kSliceDataA:
            case kSliceDataB:
            case kSliceDataC:
            case kIDRSlice:
              assert_less_than_equal(order_state, kAfterFirstVCL, "Unexpected VCL in order_state " + order_state);
              assert_equals(naluType == kIDRSlice, keyFrame, "Keyframe indicator does not match: " + (naluType == kIDRSlice) + " versus " + keyFrame);
              order_state = kAfterFirstVCL;
              break;

            case kCodedSliceAux:
              assert_equals(order_state, kAfterFirstVCL, "Unexpected extension in order_state " + order_state);
              break;

            case kEOSeq:
              assert_equals(order_state, kAfterFirstVCL, "Unexpected EOSeq in order_state " + order_state);
              order_state = kEOStreamAllowed;
              break;

            case kEOStream:
              assert_greater_than(kAfterFirstVCL, order_state, "Unexpected EOStream in order_state " + order_state);
              order_state = kNoMoreDataAllowed;
              break;
            // These syntax elements are to simply be ignored according to H264
            // Annex B 7.4.2.7
            case kFiller:
            case kUnspecified:
              // These syntax elements are to simply be ignored according to H264 Annex B 7.4.2.7
              break;

            default:
              assert_greater_than(naluType, 19, "NALU TYPE smaller than 20 for unknown type");
              break;
          }
        } else if (ANNEXB_CODEC === 'h265') {
          // When any VPS NAL units, SPS NAL units, PPS NAL units, prefix SEI NAL
          // units, NAL units with nal_unit_type in the range of
          // RSV_NVCL41..RSV_NVCL44, or NAL units with nal_unit_type in the range of
          // UNSPEC48..UNSPEC55 are present, they shall not follow the last VCL NAL
          // unit of the access unit.

          switch (naluType) {
            case AUD_NUT:
              assert_less_than_equal(order_state, kAUDAllowed, "Unexpected AUD in order_state " + order_state);
              order_state = kBeforeFirstVCL;
              break;

            case VPS_NUT:
            case SPS_NUT:
            case PPS_NUT:
            case PREFIX_SEI_NUT:
            case RSV_NVCL41:
            case RSV_NVCL42:
            case RSV_NVCL43:
            case RSV_NVCL44:
            case UNSPEC48:
            case UNSPEC49:
            case UNSPEC50:
            case UNSPEC51:
            case UNSPEC52:
            case UNSPEC53:
            case UNSPEC54:
            case UNSPEC55:
              assert_less_than_equal(order_state, kBeforeFirstVCL, "Unexpected NALU type " + nalu.nal_unit_type + " in order_state " + order_state);
              order_state = kBeforeFirstVCL;
              break;
            // NAL units having nal_unit_type equal to FD_NUT or SUFFIX_SEI_NUT or in
            // the range of RSV_NVCL45..RSV_NVCL47 or UNSPEC56..UNSPEC63 shall not
            // precede the first VCL NAL unit of the access unit.
            case FD_NUT:
            case SUFFIX_SEI_NUT:
            case RSV_NVCL45:
            case RSV_NVCL46:
            case RSV_NVCL47:
            case UNSPEC56:
            case UNSPEC57:
            case UNSPEC58:
            case UNSPEC59:
            case UNSPEC60:
            case UNSPEC61:
            case UNSPEC62:
            case UNSPEC63:
              assert_less_than_equal(order_state, kAfterFirstVC, "Unexpected NALU type " + nalu.nal_unit_type + " in order_state " + order_state);
              break;

            // When an end of sequence NAL unit is present, it shall be the last NAL
            // unit among all NAL units in the access unit other than an end of
            // bitstream NAL unit (when present).
            case EOS_NUT:
              assert_equals(order_state, kAfterFirstVCL, "Unexpected EOS in order_state " + order_state);
              order_state = kEOBitstreamAllowed;
              break;
            // When an end of bitstream NAL unit is present, it shall be the last NAL
            // unit in the access unit.
            case EOB_NUT:
              assert_less_than_equal(order_state, kAfterFirstVCL, "Unexpected EOB in order_state " + order_state);
              order_state = kNoMoreDataAllowed;
              break;
            // VCL, non-IRAP
            case TRAIL_N:
            case TRAIL_R:
            case TSA_N:
            case TSA_R:
            case STSA_N:
            case STSA_R:
            case RADL_N:
            case RADL_R:
            case RASL_N:
            case RASL_R:
            case RSV_VCL_N10:
            case RSV_VCL_R11:
            case RSV_VCL_N12:
            case RSV_VCL_R13:
            case RSV_VCL_N14:
            case RSV_VCL_R15:
            case RSV_VCL24:
            case RSV_VCL25:
            case RSV_VCL26:
            case RSV_VCL27:
            case RSV_VCL28:
            case RSV_VCL29:
            case RSV_VCL30:
            case RSV_VCL31:
              assert_less_than_equal(order_state, kAfterFirstVCL, "Unexpected VCL in order_state " + order_state);
              order_state = kAfterFirstVCL;
              break;
            // VCL, IRAP
            case BLA_W_LP:
            case BLA_W_RADL:
            case BLA_N_LP:
            case IDR_W_RADL:
            case IDR_N_LP:
            case CRA_NUT:
            case RSV_IRAP_VCL22:
            case RSV_IRAP_VCL23:
              assert_less_than_equal(order_state, kAfterFirstVCL, "Unexpected VCL in order_state " + order_state);
              assert_equals(keyFrame, true, "The frame is coded as Keyframe, but indicator does not match");
              order_state = kAfterFirstVCL;
              break;

            default:
              assert_true(false, "Unsupported NALU type " + naluType);
              break;
          };

        }
        last_nalu_type = naluType;
      }
      lastBytes.push(buffer[pos]);
      lastBytes.shift(); // advance reading
    }
  })
}

async function runAnnexBTest(t) {
  let encoder_config = { ...ENCODER_CONFIG };
  const w = encoder_config.width;
  const h = encoder_config.height;
  let frames_to_encode = 16;

  await checkEncoderSupport(t, encoder_config);

  const encodedResults = [];
  const encoder_init = {
    output(chunk, metadata) {
      encodedResults.push(chunk);
    },
    error(e) {
      assert_unreached(e.message);
    }
  };

  let encoder = new VideoEncoder(encoder_init);
  encoder.configure(encoder_config);

  for (let i = 0; i < frames_to_encode; i++) {
    let frame = createDottedFrame(w, h, i);
    let keyframe = (i % 5 == 0);
    encoder.encode(frame, { keyFrame: keyframe });
    frame.close();
  }

  await encoder.flush();
  encoder.close();

  encodedResults.forEach((chunk) => checkNaluSyntax(t, chunk));

  assert_greater_than(encodedResults.length, 0, "frames_encoded");
}

promise_test(async t => {
  return runAnnexBTest(t);
}, 'Verify stream compliance h26x annexb');