test_eviction_target_not_in_buffered_range.html (3490B)
1 <!DOCTYPE html> 2 <html><head> 3 <title>MSE: Auto eviction for a new playback position not in the current buffered range</title> 4 <script src="/tests/SimpleTest/SimpleTest.js"></script> 5 <script type="text/javascript" src="mediasource.js"></script> 6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 7 </head> 8 <body> 9 <script class="testbody" type="text/javascript"> 10 11 // This test is used to ensure that the auto eviction will kick in after seeking 12 // to a new position which is not in the current buffered range and the buffer 13 // is already near full. If we don't evict enough data for this case, we would 14 // not be able to append new data for the new range which contains the seek 15 // target. 16 SimpleTest.waitForExplicitFinish(); 17 18 addMSEPrefs( 19 // Set this to a low value in order to reproduce the issue quickly. 20 ["media.mediasource.eviction_threshold.video", 200000], 21 ); 22 23 runWithMSE(async (ms, el) => { 24 el.controls = true; 25 await once(ms, "sourceopen"); 26 ok(true, "Receive a sourceopen event"); 27 28 const videosb = ms.addSourceBuffer("video/mp4"); 29 await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4"); 30 31 // After appending those data, the buffered range will be (1.601667, 7.208333) 32 // and the buffer will be almost full (191kB/195kB) 33 for (let idx = 3; idx < 10; idx++) { 34 info(`Loading range [${idx}:${idx+1}]`); 35 await fetchAndLoad(videosb, "bipbop/bipbop_video", range(idx, idx +1), ".m4s"); 36 } 37 38 // Seek to the position which is before the buffer's start time, and it should 39 // trigger the auto eviction in order to allow us to append more data later. 40 info(`Seek to the position which is earlier than the buffer's start`); 41 await seekAndFetchData(el, 0, videosb, range(1, 2)); 42 43 info(`Seek to the position which is later than the buffer's end`); 44 await seekAndFetchData(el, 7.5, videosb, range(10, 11)); 45 46 SimpleTest.finish(); 47 }); 48 49 // Helper functions 50 async function seekAndFetchData(el, seekTime, sb, range) { 51 const promise = once(el, "seeked"); 52 const start = sb.buffered.start(0); 53 const end = sb.buffered.end(sb.buffered.length - 1); 54 55 // We need to wait for the data eviction finish first after seeking. 56 el.currentTime = seekTime; 57 await monitorBufferedChange(sb); 58 const newStart = sb.buffered.start(0); 59 const newEnd = sb.buffered.end(sb.buffered.length - 1); 60 info(`Buffer range is changed from [${start}, ${end}] to [${newStart}, ${newEnd}]`); 61 62 // Check if we evict data from the correct side of the buffer. 63 if (seekTime > end) { 64 ok(newStart > start, "Evicted data from the head"); 65 } else { 66 ok(newEnd < end, "Evicted data from the tail"); 67 } 68 69 try { 70 info(`Append the data containing the seek target`); 71 await fetchAndLoad(sb, "bipbop/bipbop_video", range, ".m4s"); 72 } catch (error) { 73 ok(error.name == "QuotaExceededError", "We shouldn't get other error"); 74 ok(false, "Should be able to append new data due to the auto eviction"); 75 } 76 await promise; 77 info(`Succefully appended new data and seeked to the desired position`); 78 } 79 80 function monitorBufferedChange(sourceBuffer) { 81 return new Promise((resolve) => { 82 const lastBuffered = sourceBuffer.buffered; 83 const checkBufferedChange = () => { 84 if (sourceBuffer.buffered !== lastBuffered) { 85 ok(true, `Source buffered range has changed`); 86 clearInterval(intervalId); 87 resolve(); 88 } 89 }; 90 const intervalId = setInterval(checkBufferedChange, 100); 91 }); 92 } 93 94 </script> 95 </body> 96 </html>