Skip to content

Commit 04c1391

Browse files
wolenetzchromium-wpt-export-bot
authored andcommitted
MSE: Fix rare flaky changeType-play-* failures
Unless the app explicitly sets `mediaSource.duration`, `HTMLMediaElement.duration` remains NaN until initial HAVE_METADATA is reached, even if the attached mediaSource has already buffered media well beyond the initialization segment(s) necessary to begin transition to HAVE_METADATA. In Chromium, that transition is begun asynchronously, letting thread hop through the pipeline thread complete while letting the app continue. Eventually, the media element transitions, but in the interim, its value for duration could still be NaN, even if mediaSource has a duration value. This change relaxes the changeType-play-* utility's reliance on strict matching of mediaElement.duration and mediaSource.duration, instead relying on the latter for use in trimming the buffered duration. I've filed MSE spec issue #275 to discuss this behavior: w3c/media-source#275 This change also reports more details in changeType web-test assertion failures, which also enabled finding the suspected root cause of the tests' flakiness. Bug: 1184745 Change-Id: I208cbfbbc60776366a16b6a3e79f52480df5be37 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2906776 Auto-Submit: Matthew Wolenetz <[email protected]> Reviewed-by: Ted Meyer <[email protected]> Commit-Queue: Ted Meyer <[email protected]> Cr-Commit-Position: refs/heads/master@{#886148}
1 parent 3d3e869 commit 04c1391

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

media-source/mediasource-changetype-util.js

+19-11
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ function appendBuffer(test, sourceBuffer, data) {
116116
sourceBuffer.appendBuffer(data);
117117
}
118118

119-
function trimBuffered(test, mediaElement, sourceBuffer, minimumPreviousDuration, newDuration, skip_duration_prechecks) {
119+
function trimBuffered(test, mediaSource, sourceBuffer, minimumPreviousDuration, newDuration, skip_duration_prechecks) {
120120
if (!skip_duration_prechecks) {
121-
assert_less_than(newDuration, minimumPreviousDuration);
122-
assert_less_than(minimumPreviousDuration, mediaElement.duration);
121+
assert_less_than(newDuration, minimumPreviousDuration,
122+
"trimBuffered newDuration must be less than minimumPreviousDuration");
123+
assert_less_than(minimumPreviousDuration, mediaSource.duration,
124+
"trimBuffered minimumPreviousDuration must be less than mediaSource.duration");
123125
}
124126
test.expectEvent(sourceBuffer, "update");
125127
test.expectEvent(sourceBuffer, "updateend");
@@ -128,7 +130,8 @@ function trimBuffered(test, mediaElement, sourceBuffer, minimumPreviousDuration,
128130

129131
function trimDuration(test, mediaElement, mediaSource, newDuration, skip_duration_prechecks) {
130132
if (!skip_duration_prechecks) {
131-
assert_less_than(newDuration, mediaElement.duration);
133+
assert_less_than(newDuration, mediaSource.duration,
134+
"trimDuration newDuration must be less than mediaSource.duration");
132135
}
133136
test.expectEvent(mediaElement, "durationchange");
134137
mediaSource.duration = newDuration;
@@ -158,7 +161,8 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
158161
// implicit_changetype and negative_test.
159162

160163
function findSafeOffset(targetTime, overlappedMediaMetadata, overlappedStartTime, overlappingMediaMetadata) {
161-
assert_greater_than_equal(targetTime, overlappedStartTime);
164+
assert_greater_than_equal(targetTime, overlappedStartTime,
165+
"findSafeOffset targetTime must be greater than or equal to overlappedStartTime");
162166

163167
let offset = targetTime;
164168
if ("start_time" in overlappingMediaMetadata) {
@@ -177,7 +181,8 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
177181
let gopsToRetain = Math.ceil((targetTime - overlappedStartTime) / overlappedMediaMetadata["keyframe_interval"]);
178182
let adjustedTime = overlappedStartTime + gopsToRetain * overlappedMediaMetadata["keyframe_interval"];
179183

180-
assert_greater_than_equal(adjustedTime, targetTime);
184+
assert_greater_than_equal(adjustedTime, targetTime,
185+
"findSafeOffset adjustedTime must be greater than or equal to targetTime");
181186
offset += adjustedTime - targetTime;
182187
return { "offset": offset, "adjustedTime": adjustedTime };
183188
}
@@ -221,7 +226,8 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
221226
// changeType B->B and append B starting at 1.0 seconds (or at the first
222227
// keyframe in B at or after 1.0 seconds if it has keyframe_interval defined).
223228
test.waitForExpectedEvents(() => {
224-
assert_less_than(lastStart, 1.0);
229+
assert_less_than(lastStart, 1.0,
230+
"changeType B->B lastStart must be less than 1.0");
225231
let safeOffset = findSafeOffset(1.0, metadataB, lastStart, metadataB);
226232
lastStart = safeOffset["adjustedTime"];
227233
if (!implicit_changetype) {
@@ -239,7 +245,8 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
239245
// changeType B->A and append A starting at 1.5 seconds (or at the first
240246
// keyframe in B at or after 1.5 seconds if it has keyframe_interval defined).
241247
test.waitForExpectedEvents(() => {
242-
assert_less_than(lastStart, 1.5);
248+
assert_less_than(lastStart, 1.5,
249+
"changeType B->A lastStart must be less than 1.5");
243250
let safeOffset = findSafeOffset(1.5, metadataB, lastStart, metadataA);
244251
// Retain the previous lastStart because the next block will append data
245252
// which begins between that start time and this block's start time.
@@ -258,7 +265,8 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
258265
// changeType A->A and append A starting at 1.3 seconds (or at the first
259266
// keyframe in B at or after 1.3 seconds if it has keyframe_interval defined).
260267
test.waitForExpectedEvents(() => {
261-
assert_less_than(lastStart, 1.3);
268+
assert_less_than(lastStart, 1.3,
269+
"changeType A->A lastStart must be less than 1.3");
262270
// Our next append will begin by overlapping some of metadataB, then some of
263271
// metadataA.
264272
let safeOffset = findSafeOffset(1.3, metadataB, lastStart, metadataA);
@@ -277,7 +285,7 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
277285
// Trim duration to 2 seconds, then play through to end.
278286
test.waitForExpectedEvents(() => {
279287
// If negative testing, then skip fragile assertions.
280-
trimBuffered(test, mediaElement, sourceBuffer, 2.1, 2, negative_test);
288+
trimBuffered(test, mediaSource, sourceBuffer, 2.1, 2, negative_test);
281289
});
282290

283291
test.waitForExpectedEvents(() => {
@@ -286,7 +294,7 @@ function runChangeTypeTest(test, mediaElement, mediaSource, metadataA, typeA, da
286294
});
287295

288296
test.waitForExpectedEvents(() => {
289-
assert_equals(mediaElement.currentTime, 0);
297+
assert_equals(mediaElement.currentTime, 0, "currentTime must be 0");
290298
test.expectEvent(mediaSource, "sourceended");
291299
test.expectEvent(mediaElement, "play");
292300
test.expectEvent(mediaElement, "ended");

0 commit comments

Comments
 (0)