tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SourceBuffer-appendWindowEnd-rounding.html (3866B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <title>Test appendWindowEnd and frame end timestamp rounding</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 fps = 24;
     13 const frames_per_keyframe = 8;
     14 const default_sample_duration = 512;
     15 const earliest_presentation_time = 1024;
     16 const frame0_offset = earliest_presentation_time / default_sample_duration;
     17 
     18 // Presentation positions of the 8 frames in a segment are
     19 // 0, 4, 2, 1, 3, 7, 6, 5.
     20 let media;
     21 promise_test(async t => {
     22  media = await new Promise(
     23    r => MediaSourceUtil.fetchManifestAndData(
     24      t,
     25      `mp4/test-v-128k-320x240-${fps}fps-${frames_per_keyframe}kfr-manifest.json`,
     26      (type, data) => r({type, data})));
     27 }, 'setup');
     28 
     29 async function append_frames({t, last_frame_pos}) {
     30  assert_implements_optional(MediaSource.isTypeSupported(media.type),
     31                             'type supported');
     32 
     33  const v = document.createElement('video');
     34  const v_watcher = new EventWatcher(t, v, ['error']);
     35  document.body.appendChild(v);
     36  const media_source = new MediaSource();
     37  const media_source_watcher =
     38        new EventWatcher(t, media_source, ['sourceopen']);
     39  v.src = URL.createObjectURL(media_source);
     40  await media_source_watcher.wait_for('sourceopen');
     41 
     42  const source_buffer = media_source.addSourceBuffer(media.type);
     43  assert_equals(source_buffer.mode, 'segments', 'source_buffer.mode');
     44  const source_buffer_watcher =
     45        new EventWatcher(t, source_buffer, ['updateend']);
     46 
     47  // This is intentionally a sum of double precision representations of
     48  // "presentation timestamp and frame duration" to match frame end timestamp
     49  // in
     50  // https://w3c.github.io/media-source/#sourcebuffer-coded-frame-processing
     51  source_buffer.appendWindowEnd = last_frame_pos / fps + 1 / fps;
     52 
     53  source_buffer.appendBuffer(media.data);
     54  await source_buffer_watcher.wait_for('updateend');
     55  assert_approx_equals(source_buffer.buffered.start(0),
     56                       frame0_offset / fps,
     57                       1e-6,
     58                       'source_buffer.buffered.start(0) after append');
     59  assert_approx_equals(
     60    source_buffer.buffered.end(source_buffer.buffered.length - 1),
     61    source_buffer.appendWindowEnd,
     62    1e-6,
     63    'source_buffer.buffered.end() after append');
     64 
     65  media_source.endOfStream();
     66  assert_equals(media_source.duration,
     67                source_buffer.buffered.end(source_buffer.buffered.length - 1),
     68                'media_source.duration == buffered.end');
     69  assert_equals(v.duration, media_source.duration,
     70                'v.duration == media_source.duration');
     71 };
     72 
     73 // The first frame has presentation timestamp 2 frame durations after zero.
     74 //
     75 // The ninth frame has presentation timestamp 10 frame durations after zero
     76 // and is a keyframe.  The double precision sum of double presentation
     77 // representations of its timestamp and frame duration is greater than the
     78 // double precision representation of the tenth frame's timestamp.
     79 // i.e 10/24 + 1/24 > 11/24, which would round down if rounded to
     80 // nearest microseconds.
     81 //
     82 // The eighteenth frame has presentation timestamp 22 frame durations after
     83 // zero.  (Frames are not in presentation order.)  It is immediately after a
     84 // keyframe and so is found before the need random access point flag is set to
     85 // true on applying appendWindowEnd.  The double precision sum of double
     86 // presentation representations of its timestamp and frame duration is less
     87 // than the double precision representation of the tenth frame's timestamp.
     88 // i.e 22/24 + 1/24 < 23/24, which would round down if rounded to nearest
     89 // microseconds.
     90 for (const last_frame_pos of [10, 22]) {
     91  promise_test(
     92    t => append_frames({t, last_frame_pos}),
     93    `last frame at ${last_frame_pos}`);
     94 }
     95 </script>
     96 </html>