SourceBuffer-short-frame-endOfStream.html (3368B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Test endOfStream() with short frame duration</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="mediasource-util.js"></script> 8 </head> 9 <body> 10 </body> 11 <script> 12 const frames_per_keyframe = 8; 13 const default_sample_duration = 512; 14 // Frame duration is much less than half a microsecond, but timescale is 15 // representable with an unsigned 32-bit integer. 16 // The last frame's start and end times would both round down if rounded to 17 // the nearest microsecond. 18 const fps = 8e6; 19 const timescale = default_sample_duration * fps; 20 const earliest_presentation_time = 1024; 21 const frame0_offset = earliest_presentation_time / default_sample_duration; 22 23 let media; 24 promise_test(async t => { 25 media = await new Promise( 26 r => MediaSourceUtil.fetchManifestAndData( 27 t, 28 `mp4/test-v-128k-320x240-24fps-${frames_per_keyframe}kfr-manifest.json`, 29 (type, data) => r({type, data}))); 30 // Truncate at end of first segment, which is also the end of 8 frames. 31 const segment0_end = 0x1b1a; 32 media.data = media.data.subarray(0, segment0_end); 33 // Overwrite timescale to shorten frame durations. 34 const media_timescale_start = 0x182; 35 MediaSourceUtil.WriteBigEndianInteger32ToUint8Array( 36 timescale, media.data.subarray(media_timescale_start)); 37 const segment_index_timescale_start = 0x353; 38 MediaSourceUtil.WriteBigEndianInteger32ToUint8Array( 39 timescale, media.data.subarray(segment_index_timescale_start)); 40 }, 'setup'); 41 42 promise_test(async t => { 43 assert_implements_optional(MediaSource.isTypeSupported(media.type), 44 'type supported'); 45 46 const v = document.createElement('video'); 47 const v_watcher = new EventWatcher(t, v, ['error', 'ended']); 48 document.body.appendChild(v); 49 const media_source = new MediaSource(); 50 const media_source_watcher = 51 new EventWatcher(t, media_source, ['sourceopen']); 52 v.src = URL.createObjectURL(media_source); 53 await media_source_watcher.wait_for('sourceopen'); 54 55 const source_buffer = media_source.addSourceBuffer(media.type); 56 assert_equals(source_buffer.mode, 'segments', 'source_buffer.mode'); 57 const source_buffer_watcher = 58 new EventWatcher(t, source_buffer, ['updateend']); 59 60 source_buffer.appendBuffer(media.data); 61 await source_buffer_watcher.wait_for('updateend'); 62 assert_equals(source_buffer.buffered.length, 1, 63 'source_buffer.buffered.length after first append'); 64 assert_approx_equals(source_buffer.buffered.start(0), 65 frame0_offset / fps, 66 1e-6, 67 'source_buffer.buffered.start(0) after first append'); 68 const bufferEnd = source_buffer.buffered.end(0); 69 assert_approx_equals(bufferEnd, 70 (frame0_offset + frames_per_keyframe) / fps, 71 1e-6, 72 'source_buffer.buffered.end(0) after first append'); 73 74 media_source.endOfStream(); 75 assert_equals(media_source.duration, bufferEnd, 'media_source.duration'); 76 assert_equals(v.duration, media_source.duration, 77 'v.duration == media_source.duration'); 78 79 v.play(); 80 await v_watcher.wait_for('ended'); 81 assert_equals(v.currentTime, media_source.duration, 'v.currentTime'); 82 }, 'endOfStream() with short frame duration'); 83 </script> 84 </html>