Skip to content
Permalink
Browse files
[MSE] Improved coded frame eviction algorithm
https://bugs.webkit.org/show_bug.cgi?id=246144

Reviewed by Alicia Boya Garcia.

I made it in two aspects, first is that now it does not begin at 0, it
begins at the first buffered range.

A fix would be that sometimes you need to evict frames but a window of
30s is too much and it can easily happen it does not evict anything,
so we need to reduce the partition to be able to effectively evict
something. We do it in windows from 30 to 3s.

This is tested by several tests that needed a rebase line or small tweaks.

* LayoutTests/media/media-source/media-source-append-before-last-range-no-quota-exceeded-expected.txt:
* LayoutTests/media/media-source/media-source-append-before-last-range-no-quota-exceeded.html:
* LayoutTests/media/media-source/media-source-append-buffer-full-quota-exceeded-error-expected.txt:
* LayoutTests/media/media-source/media-source-append-buffer-full-quota-exceeded-error.html:
* LayoutTests/media/media-source/media-source-evict-codedframe-after-seek-expected.txt:
* Source/WebCore/Modules/mediasource/SourceBuffer.cpp:
(WebCore::SourceBuffer::appendBufferInternal):
* Source/WebCore/platform/graphics/PlatformTimeRanges.cpp:
(WebCore::PlatformTimeRanges::minimumBufferedTime const):
* Source/WebCore/platform/graphics/PlatformTimeRanges.h:
* Source/WebCore/platform/graphics/SourceBufferPrivate.cpp:
(WebCore::SourceBufferPrivate::evictCodedFrames):
* Source/WebCore/platform/graphics/SourceBufferPrivate.h:
* Source/WebKit/GPUProcess/media/RemoteSourceBufferProxy.cpp:
(WebKit::RemoteSourceBufferProxy::evictCodedFrames):
* Source/WebKit/GPUProcess/media/RemoteSourceBufferProxy.h:
* Source/WebKit/GPUProcess/media/RemoteSourceBufferProxy.messages.in:
* Source/WebKit/WebProcess/GPU/media/SourceBufferPrivateRemote.cpp:
(WebKit::SourceBufferPrivateRemote::evictCodedFrames):
* Source/WebKit/WebProcess/GPU/media/SourceBufferPrivateRemote.h:

Canonical link: https://commits.webkit.org/256441@main
  • Loading branch information
calvaris committed Nov 8, 2022
1 parent 6f536b7 commit 48b51f0536c90a12e3acd596d36ef82324acd3a5
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 158 deletions.
@@ -127,6 +127,6 @@ EVENT(updateend)
Appending PTS=118
EVENT(updateend)
EXPECTED (exception != 'QuotaExceededError: The quota has been exceeded.') OK
EXPECTED (bufferedRanges() == '[ 115...119, 120...170 ]') OK
EXPECTED (bufferedRanges() == '[ 115...119, 120...146 ]') OK
END OF TEST

@@ -76,7 +76,7 @@
exception = await appendPtsRange(115, 118);

testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '!=');
testExpected('bufferedRanges()', '[ 115...119, 120...170 ]', '==');
testExpected('bufferedRanges()', '[ 115...119, 120...146 ]', '==');

endTest();
});
@@ -85,4 +85,4 @@
<body>
<video></video>
</body>
</html>
</html>
@@ -117,7 +117,7 @@ Appending PTS=41
EVENT(updateend)
Appending PTS=42
EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.') OK
EXPECTED (1 == '1') OK
EXPECTED (sourceBuffer.buffered.length == '1') OK
EVENT(updateend)
Appending PTS=0.002
EVENT(updateend)
@@ -141,70 +141,10 @@ Appending PTS=9.002
EVENT(updateend)
Appending PTS=10.002
EVENT(updateend)
Appending PTS=11.002
EVENT(updateend)
Appending PTS=12.002
EVENT(updateend)
Appending PTS=13.002
EVENT(updateend)
Appending PTS=14.002
EVENT(updateend)
Appending PTS=15.002
EVENT(updateend)
Appending PTS=16.002
EVENT(updateend)
Appending PTS=17.002
EVENT(updateend)
Appending PTS=18.002
EVENT(updateend)
Appending PTS=19.002
EVENT(updateend)
Appending PTS=20.002
EVENT(updateend)
Appending PTS=21.002
EVENT(updateend)
Appending PTS=22.002
EVENT(updateend)
Appending PTS=23.002
EVENT(updateend)
Appending PTS=24.002
EVENT(updateend)
Appending PTS=25.002
EVENT(updateend)
Appending PTS=26.002
EVENT(updateend)
Appending PTS=27.002
EVENT(updateend)
Appending PTS=28.002
EVENT(updateend)
Appending PTS=29.002
EVENT(updateend)
Appending PTS=30.002
EVENT(updateend)
Appending PTS=31.002
EVENT(updateend)
Appending PTS=32.002
EVENT(updateend)
Appending PTS=33.002
EVENT(updateend)
Appending PTS=34.002
EVENT(updateend)
Appending PTS=35.002
EVENT(updateend)
Appending PTS=36.002
EVENT(updateend)
Appending PTS=37.002
EVENT(updateend)
Appending PTS=38.002
EVENT(updateend)
Appending PTS=39.002
EVENT(updateend)
Appending PTS=40.002
EVENT(updateend)
Appending PTS=41.002
EVENT(updateend)
Appending PTS=42.002
EXPECTED (exception != 'QuotaExceededError: The quota has been exceeded.') OK
Appending PTS=11002-60002
EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.') OK
EXPECTED (sourceBuffer.buffered.length == '1') OK
EVENT(updateend)
Appending PTS=0
EVENT(updateend)
@@ -316,16 +256,11 @@ EVENT(updateend)
Appending PTS=31.916666666666668
EVENT(updateend)
EXPECTED (exception != 'QuotaExceededError: The quota has been exceeded.') OK
EXPECTED (1 == '1') OK
EXPECTED (sourceBuffer.buffered.length == '1') OK
Create a small 2000/24000 gap in the data at 31s.
EVENT(updateend)
EXPECTED (2 == '2') OK
Appending PTS=32
EVENT(updateend)
Appending PTS=33
EVENT(updateend)
Appending PTS=34
EVENT(updateend)
Appending PTS=35
EXPECTED (sourceBuffer.buffered.length == '2') OK
Appending PTS=32-100
EXPECTED (exception == 'QuotaExceededError: The quota has been exceeded.') OK
END OF TEST

@@ -28,11 +28,13 @@
return resultException;
}

async function appendConcatenateSamples(start, end) {
async function appendConcatenateSamples(start, end, timescale = 1, gap = 0, step = null) {
var resultException = null;
if (step == null)
step = timescale;
const samples = [];
for (let time = start; time <= end; time++)
samples.push(makeASample(time, time, 1, 1, 1, time === start ? SAMPLE_FLAG.SYNC : SAMPLE_FLAG.NONE));
for (let time = start; time <= end; time += step)
samples.push(makeASample(time, time, step - gap, timescale, 1, time === start ? SAMPLE_FLAG.SYNC : SAMPLE_FLAG.NONE, 1));

try {
consoleWrite('Appending PTS='+start+'-'+end );
@@ -82,13 +84,17 @@
exception = await appendPtsRange(0, 60000, 1000, 2);
testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '==');
// Check that appendBuffer removed all the small gaps in the data less than the threshold.
testExpected(sourceBuffer.buffered.length, '1', '==');
testExpected('sourceBuffer.buffered.length', '1', '==');

internals.settings.setMaximumSourceBufferSize(1500);
// Ensure that if current time is close enough to the buffered data that the nearest range isn't evicted.
sourceBuffer.remove(0, Infinity);
await waitFor(sourceBuffer, 'updateend');
exception = await appendPtsRange(2, 60002, 1000);
exception = await appendPtsRange(2, 10002, 1000);
testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '!=');
exception = await appendConcatenateSamples(11002, 60002, 1000);
testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '==');
testExpected('sourceBuffer.buffered.length', '1', '==');

internals.settings.setMaximumSourceBufferSize(4000);
// Ensure that small gaps that would be ignored during playback are also ignored by eviction.
@@ -101,12 +107,12 @@
// Add 30 to 32s in smaller granularity.
exception = await appendPtsRange(720000, 768000 - 1, 24000, 0, 2000);
testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '!=');
testExpected(sourceBuffer.buffered.length, '1', '==');
// Create a small 2000/24000 gap in the data at 31s.
testExpected('sourceBuffer.buffered.length', '1', '==');
consoleWrite("Create a small 2000/24000 gap in the data at 31s.");
sourceBuffer.remove(744000 / 24000, (744000 + 2000) / 24000);
await waitFor(sourceBuffer, 'updateend');
testExpected(sourceBuffer.buffered.length, '2', '==');
exception = await appendPtsRange(32, 60);
testExpected('sourceBuffer.buffered.length', '2', '==');
exception = await appendConcatenateSamples(32, 100);
testExpected('exception', 'QuotaExceededError: The quota has been exceeded.', '==');

endTest();
@@ -102,6 +102,6 @@ EVENT(updateend)
Appending PTS=45
EVENT(updateend)
EXPECTED (exception != 'QuotaExceededError: The quota has been exceeded.') OK
bufferedRanges()=[ 0...12, 13...46 ]
bufferedRanges()=[ 6...12, 13...48 ]
END OF TEST

@@ -501,7 +501,7 @@ ExceptionOr<void> SourceBuffer::appendBufferInternal(const unsigned char* data,
m_source->openIfInEndedState();

// 4. Run the coded frame eviction algorithm.
m_private->evictCodedFrames(size, maximumBufferSize(), m_source->currentTime(), m_source->duration(), m_source->isEnded());
m_private->evictCodedFrames(size, maximumBufferSize(), m_source->currentTime(), m_source->isEnded());

// 5. If the buffer full flag equals true, then throw a QuotaExceededError exception and abort these step.
if (m_private->isBufferFullFor(size, maximumBufferSize())) {
@@ -138,6 +138,14 @@ MediaTime PlatformTimeRanges::maximumBufferedTime() const
return m_ranges[length() - 1].m_end;
}

MediaTime PlatformTimeRanges::minimumBufferedTime() const
{
if (!length())
return MediaTime::invalidTime();

return m_ranges[0].m_start;
}

void PlatformTimeRanges::add(const MediaTime& start, const MediaTime& end)
{
#if !PLATFORM(MAC) // https://bugs.webkit.org/show_bug.cgi?id=180253
@@ -50,6 +50,7 @@ class WEBCORE_EXPORT PlatformTimeRanges {
MediaTime end(unsigned index, bool& valid) const;
MediaTime duration(unsigned index) const;
MediaTime maximumBufferedTime() const;
MediaTime minimumBufferedTime() const;

void invert();
void intersectWith(const PlatformTimeRanges&);

0 comments on commit 48b51f0

Please sign in to comment.