openvidu-test-e2e: let the camera-mute BWE test start below the top layer

After a camera unmute the publisher restarts every simulcast layer at
once. When the top layer arrives last, the mediasoup worker starts the
subscriber on the lowest one and moves it up at its next layer decision,
about a second later, even with its bandwidth estimate kept.

The test now requires the top layer within 5 s of the video resuming,
and keeps its check that no probe reaches the subscriber during the
mute. The subscriber-disable and unpublish tests keep the first-frame
check, because the publisher's layers keep flowing there: 6 of 6 each
under the same load, with the first layer decision already on the top
layer every time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pull/926/merge
pabloFuente 2026-11-02 17:26:50 +01:00
parent 50c4778c12
commit acb1139c9e
1 changed files with 35 additions and 3 deletions

View File

@ -3226,7 +3226,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// bandwidth (nothing can host the probes), and its estimate must survive the // bandwidth (nothing can host the probes), and its estimate must survive the
// pause so that the video comes back on its top layer. The three tests below // pause so that the video comes back on its top layer. The three tests below
// drive the ways a connection gets there: the publisher mutes the camera, the // drive the ways a connection gets there: the publisher mutes the camera, the
// subscriber disables the video, and the camera is unpublished // subscriber disables the video, and the camera is unpublished. The first two
// check that no probe reaches the subscriber during the pause. The last two
// check that the first frames after it are already the top layer
// The top simulcast layer of the fake camera // The top simulcast layer of the fake camera
private static final int CAMERA_TOP_LAYER_WIDTH = 640; private static final int CAMERA_TOP_LAYER_WIDTH = 640;
@ -3313,6 +3315,33 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
"The video left its top layer after resuming"); "The video left its top layer after resuming");
} }
/**
* With the video just resumed by its publisher: it must reach its top layer
* within maxMillis. The first frames may come from a lower layer even with the
* estimate kept: the publisher restarts every simulcast layer at once, and when
* the top one arrives last the server only moves the subscriber up at its next
* layer decision, about a second later.
*/
private void assertVideoResumesAndReachesTopLayer(OpenViduTestappUser user, WebElement subscriberVideo,
long framesDecodedBefore, long maxMillis) throws Exception {
this.waitUntilAux(user, subscriberVideo,
() -> this.getLayerCounter(this.getSubscriberVideoLayer(user, subscriberVideo),
"framesDecoded") > framesDecodedBefore,
"Timeout waiting for the video to resume");
final long resumedAt = System.currentTimeMillis();
JsonObject layer = new JsonObject();
while (System.currentTimeMillis() - resumedAt < maxMillis) {
layer = this.getSubscriberVideoLayer(user, subscriberVideo);
if (this.getLayerCounter(layer, "frameWidth") == CAMERA_TOP_LAYER_WIDTH) {
break;
}
Thread.sleep(250);
}
Assertions.assertEquals(CAMERA_TOP_LAYER_WIDTH, this.getLayerCounter(layer, "frameWidth"),
"The video did not reach its top layer within " + maxMillis + " ms of resuming. "
+ describeSubscriberVideoLayer(layer));
}
@Test @Test
@DisplayName("Camera mute keeps the subscriber bandwidth estimate") @DisplayName("Camera mute keeps the subscriber bandwidth estimate")
void cameraMuteKeepsSubscriberBweTest() throws Exception { void cameraMuteKeepsSubscriberBweTest() throws Exception {
@ -3329,11 +3358,14 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
long framesDecodedPaused = assertOnlyAudioWhilePaused(user, subscriberVideo); long framesDecodedPaused = assertOnlyAudioWhilePaused(user, subscriberVideo);
// The publisher unmutes // The publisher unmutes. Its simulcast layers restart together, so the first
// frames may come from a lower one (see assertVideoResumesAndReachesTopLayer).
// Whether the estimate survived is checked by the subscriber-side pauses below,
// where every layer keeps flowing
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .mute-unmute-video")).sendKeys(Keys.ENTER); user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .mute-unmute-video")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches("trackUnmuted", "RoomEvent", 1); user.getEventManager().waitUntilEventReaches("trackUnmuted", "RoomEvent", 1);
assertVideoResumesOnTopLayer(user, subscriberVideo, framesDecodedPaused); assertVideoResumesAndReachesTopLayer(user, subscriberVideo, framesDecodedPaused, 5000);
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }