- commit
- ba151294f391dcbd3cb7a7ae42d922f28af0eaa1
- parent
- 80eafedd5d92d6200ce5348331addc453060abaf
- author
- Dami <dami.etoile@gmail.com>
| M | portal/ | 83 | ++++++++++++++++++++++++++++++ |
@@ -18,6 +18,20 @@ const h264Delta = () => new Uint8Array([
1818 0, 0, 0, 1, 0x41, 0x9a,1919 ]);2020 21+const h265Keyframe = () => new Uint8Array([22+ 0, 0, 0, 1, 0x40, 0x01, 0x0c,23+ 0, 0, 0, 1, 0x42, 0x01, 0x01, 0x60, 0, 0, 0, 0, 0, 0, 0, 0, 0x5d, 0x78,24+ 0, 0, 0, 1, 0x44, 0x01, 0xc0,25+ 0, 0, 0, 1, 0x46, 0x01,26+ 0, 0, 0, 1, 0x26, 0x01, 0xaa,27+]);28+29+const av1Keyframe = () => new Uint8Array([30+ 0x62, 0x02, 0x20, 0x00,31+ 0x12, 0x00,32+ 0x32, 0x02, 0xaa, 0xbb,33+]);34+2135 function harness({ hasWebCodecs = true } = {}) {2236 let clock = 10;2337 const decoders = [];@@ -137,6 +151,75 @@ test('configured H.264 keyframes commit format only after decode enqueue', () =>
137151 assert.equal(stats.decoderQueueCapacity, MAX_DECODE_QUEUE_SIZE);138152 });139153 154+test('configured H.265 keyframes keep parameter sets out of the decoded chunk', () => {155+ const subject = harness();156+ subject.pipeline.processFramePayload({157+ width: 1920,158+ height: 1080,159+ codec: 'h265',160+ keyframe: true,161+ codecConfig: true,162+ sequence: 1,163+ pts_micros: 2_000,164+ discontinuity: false,165+ data: null,166+ }, h265Keyframe());167+168+ assert.equal(subject.decoders.length, 1);169+ assert.deepEqual(subject.decoders[0].configureCalls[0], {170+ codec: 'hvc1.01.4.L120.B0',171+ codedWidth: 1920,172+ codedHeight: 1080,173+ description: subject.decoders[0].configureCalls[0].description,174+ optimizeForLatency: true,175+ });176+ assert.equal(subject.decoders[0].configureCalls[0].description.byteLength, 58);177+ assert.deepEqual(subject.pipeline.format, {178+ codec: 'h265', width: 1920, height: 1080, epoch: 1,179+ });180+ assert.deepEqual(subject.formats, [subject.pipeline.format]);181+ assert.equal(subject.chunks.length, 1);182+ assert.equal(subject.chunks[0].type, 'key');183+ assert.equal(subject.chunks[0].timestamp, 2_000);184+ assert.deepEqual([...subject.chunks[0].data], [0, 0, 0, 3, 0x26, 0x01, 0xaa]);185+});186+187+test('configured AV1 keyframes keep sequence and temporal headers out of the decoded chunk', () => {188+ const subject = harness();189+ subject.pipeline.processFramePayload({190+ width: 1280,191+ height: 720,192+ codec: 'av1',193+ keyframe: true,194+ codecConfig: true,195+ sequence: 1,196+ pts_micros: 3_000,197+ discontinuity: false,198+ data: null,199+ }, av1Keyframe());200+201+ assert.equal(subject.decoders.length, 1);202+ assert.deepEqual(subject.decoders[0].configureCalls[0], {203+ codec: 'av01.1.00M.08',204+ codedWidth: 1280,205+ codedHeight: 720,206+ description: subject.decoders[0].configureCalls[0].description,207+ optimizeForLatency: true,208+ });209+ assert.deepEqual(210+ [...new Uint8Array(subject.decoders[0].configureCalls[0].description)],211+ [0x62, 0x02, 0x20, 0x00],212+ );213+ assert.deepEqual(subject.pipeline.format, {214+ codec: 'av1', width: 1280, height: 720, epoch: 1,215+ });216+ assert.deepEqual(subject.formats, [subject.pipeline.format]);217+ assert.equal(subject.chunks.length, 1);218+ assert.equal(subject.chunks[0].type, 'key');219+ assert.equal(subject.chunks[0].timestamp, 3_000);220+ assert.deepEqual([...subject.chunks[0].data], [0x32, 0x02, 0xaa, 0xbb]);221+});222+140223 test('stale decoder callbacks cannot mutate a replacement decoder session', () => {141224 const subject = harness();142225 processH264Keyframe(subject);