openvidu-test-e2e: check "framesDecoded" rtc stat when confirming subscriber video is received

pull/907/head
pabloFuente 2026-09-01 18:27:22 +02:00
parent 3ff7e14baf
commit 3326bb9614
2 changed files with 43 additions and 1 deletions

View File

@ -2080,6 +2080,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo); String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo);
Assertions.assertEquals(expectedCodec, subscriberCodec); Assertions.assertEquals(expectedCodec, subscriberCodec);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }
@ -2159,7 +2160,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
Assertions.assertEquals(expectedCodec, Assertions.assertEquals(expectedCodec,
getPublisherVideoLayerAttribute(chromeUser, publisherVideo, null, "codec").getAsString()); getPublisherVideoLayerAttribute(chromeUser, publisherVideo, null, "codec").getAsString());
latch.countDown(); latch.countDown();
latch.await(10, TimeUnit.SECONDS); latch.await(60, TimeUnit.SECONDS);
gracefullyLeaveParticipants(chromeUser, 1); gracefullyLeaveParticipants(chromeUser, 1);
} catch (Exception e) { } catch (Exception e) {
Assertions.fail("Error while setting up Chrome publisher", e); Assertions.fail("Error while setting up Chrome publisher", e);
@ -2187,6 +2188,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
.findElement(By.cssSelector("#openvidu-instance-0 video.remote")); .findElement(By.cssSelector("#openvidu-instance-0 video.remote"));
String subscriberCodec = this.getSubscriberVideoCodec(firefoxUser, subscriberVideo); String subscriberCodec = this.getSubscriberVideoCodec(firefoxUser, subscriberVideo);
Assertions.assertEquals(expectedCodec, subscriberCodec); Assertions.assertEquals(expectedCodec, subscriberCodec);
this.waitUntilSubscriberFramesDecodedIncrease(firefoxUser, subscriberVideo);
latch.countDown(); latch.countDown();
latch.await(10, TimeUnit.SECONDS); latch.await(10, TimeUnit.SECONDS);
gracefullyLeaveParticipants(firefoxUser, 1); gracefullyLeaveParticipants(firefoxUser, 1);
@ -2347,6 +2349,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
Assertions.assertTrue(converged, Assertions.assertTrue(converged,
subscriberBrowser + " subscriber BWE did not converge to highest layer. Last frameWidth: " subscriberBrowser + " subscriber BWE did not converge to highest layer. Last frameWidth: "
+ lastWidth + ". Expected: " + EXPECTED_HIGHEST_WIDTH); + lastWidth + ". Expected: " + EXPECTED_HIGHEST_WIDTH);
this.waitUntilSubscriberFramesDecodedIncrease(subscriberUser, subscriberVideo);
latch.countDown(); latch.countDown();
latch.await(10, TimeUnit.SECONDS); latch.await(10, TimeUnit.SECONDS);
@ -2400,6 +2403,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
this.waitUntilVideoLayersNotEmpty(user, subscriberVideo); this.waitUntilVideoLayersNotEmpty(user, subscriberVideo);
long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo); long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// Unsubscribe // Unsubscribe
WebElement toggleSubscriptionBtn = user.getDriver() WebElement toggleSubscriptionBtn = user.getDriver()
@ -2417,6 +2421,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
waitUntilVideoLayersNotEmpty(user, subscriberVideo); waitUntilVideoLayersNotEmpty(user, subscriberVideo);
bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo); bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }
@ -2454,6 +2459,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo); long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// A disabled subscribed track does not increase its bytesReceived over time // A disabled subscribed track does not increase its bytesReceived over time
WebElement enableToggle = user.getDriver() WebElement enableToggle = user.getDriver()
@ -2469,6 +2475,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
enableToggle.click(); enableToggle.click();
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }
@ -2516,6 +2523,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
firstSubscriberToggle.click(); firstSubscriberToggle.click();
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo1, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo1, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo1);
this.waitUntilPublisherLayerActive(user, publisherVideo, "f", true); this.waitUntilPublisherLayerActive(user, publisherVideo, "f", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true); this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true); this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
@ -2548,6 +2556,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo1, q); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo1, q);
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo2, f); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo2, f);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo2);
WebElement secondSubscriberToggle = user.getDriver() WebElement secondSubscriberToggle = user.getDriver()
.findElement(By.cssSelector("#openvidu-instance-2 .toggle-video-enabled")); .findElement(By.cssSelector("#openvidu-instance-2 .toggle-video-enabled"));
@ -2728,6 +2737,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// Video quality of subscriber should be by default f // Video quality of subscriber should be by default f
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, f); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, f);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// Manually change video quality of subscriber to h // Manually change video quality of subscriber to h
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
@ -2784,6 +2794,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
int frameWidth = publishedLayer.get("frameWidth").getAsInt(); int frameWidth = publishedLayer.get("frameWidth").getAsInt();
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, frameWidth); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, frameWidth);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
gracefullyLeaveParticipants(user, 2); gracefullyLeaveParticipants(user, 2);
} }
@ -2823,6 +2834,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// Subscriber should settle in 640p // Subscriber should settle in 640p
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 640); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 640);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
changeElementSize(user, subscriberVideo, 1000, 700); changeElementSize(user, subscriberVideo, 1000, 700);
Thread.sleep(2000); Thread.sleep(2000);
@ -2886,6 +2898,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
"HTMLVideoElements were expected to have only one audio track"); "HTMLVideoElements were expected to have only one audio track");
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
int frameWidth; int frameWidth;
frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo); frameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
@ -2949,6 +2962,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// With adaptive stream disabled, it doesn't matter the subscription video is // With adaptive stream disabled, it doesn't matter the subscription video is
// small. All layers will remain active // small. All layers will remain active
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
changeElementSize(user, subscriberVideo, 100, 30); changeElementSize(user, subscriberVideo, 100, 30);
Thread.sleep(4000); Thread.sleep(4000);
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true); this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
@ -3019,6 +3033,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
int subscriberFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo); int subscriberFrameWidth = this.getSubscriberVideoFrameWidth(user, subscriberVideo);
Assertions.assertEquals(publisherActiveFrameWidth, subscriberFrameWidth, Assertions.assertEquals(publisherActiveFrameWidth, subscriberFrameWidth,
"Wrong publisher and subscriber video frameWidth"); "Wrong publisher and subscriber video frameWidth");
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// All video layers should reach enabled status with a big video in the // All video layers should reach enabled status with a big video in the
// subscriber side // subscriber side
@ -3088,6 +3103,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
Thread.sleep(3000); Thread.sleep(3000);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
this.waitUntilPublisherLayerActive(user, publisherVideo, null, true); this.waitUntilPublisherLayerActive(user, publisherVideo, null, true);
this.waitUntilPublisherBytesSentIncrease(user, publisherVideo, null, bytesSent); this.waitUntilPublisherBytesSentIncrease(user, publisherVideo, null, bytesSent);
@ -3177,6 +3193,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// Subscriber should settle in 1920x1080p // Subscriber should settle in 1920x1080p
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
changeElementSize(user, subscriberVideo, 1000, 700); changeElementSize(user, subscriberVideo, 1000, 700);
Thread.sleep(2000); Thread.sleep(2000);
@ -3240,6 +3257,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
// Subscriber should settle in 960 // Subscriber should settle in 960
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
changeElementSize(user, subscriberVideo, 1000, 700); changeElementSize(user, subscriberVideo, 1000, 700);
Thread.sleep(2000); Thread.sleep(2000);
@ -3313,6 +3331,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
this.waitForBackdropAndClick(user, "mat-option.mode-LOW"); this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960); this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
Thread.sleep(4000); Thread.sleep(4000);
this.waitUntilPublisherLayerActive(user, publisherVideo, null, true); this.waitUntilPublisherLayerActive(user, publisherVideo, null, true);
@ -3405,6 +3424,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote")); WebElement subscriberVideo = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo); String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo);
Assertions.assertEquals("video/" + codecUpperCase, subscriberCodec); Assertions.assertEquals("video/" + codecUpperCase, subscriberCodec);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// Validate SVC by dynamically switching subscriber quality and checking // Validate SVC by dynamically switching subscriber quality and checking
// subscriber frameWidth transitions. // subscriber frameWidth transitions.
@ -4221,6 +4241,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo); long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesPerSecondNotZero(user, subscriberVideo); this.waitUntilSubscriberFramesPerSecondNotZero(user, subscriberVideo);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo); String subscriberCodec = this.getSubscriberVideoCodec(user, subscriberVideo);
String expectedCodec = "video/VP8"; String expectedCodec = "video/VP8";
Assertions.assertEquals(expectedCodec, subscriberCodec); Assertions.assertEquals(expectedCodec, subscriberCodec);
@ -4258,6 +4279,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo); long bytesReceived = this.getSubscriberVideoBytesReceived(user, subscriberVideo);
this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived); this.waitUntilSubscriberBytesReceivedIncrease(user, subscriberVideo, bytesReceived);
this.waitUntilSubscriberFramesPerSecondNotZero(user, subscriberVideo); this.waitUntilSubscriberFramesPerSecondNotZero(user, subscriberVideo);
this.waitUntilSubscriberFramesDecodedIncrease(user, subscriberVideo);
// Check subscriber's codec // Check subscriber's codec
if (codec != null) { if (codec != null) {
@ -4332,6 +4354,10 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
return getSubscriberVideoLayerStat(user, subscriberVideo, "framesPerSecond", JsonElement::getAsInt); return getSubscriberVideoLayerStat(user, subscriberVideo, "framesPerSecond", JsonElement::getAsInt);
} }
private long getSubscriberVideoFramesDecoded(OpenViduTestappUser user, WebElement subscriberVideo) {
return getSubscriberVideoLayerStat(user, subscriberVideo, "framesDecoded", JsonElement::getAsLong);
}
private String getSubscriberVideoCodec(OpenViduTestappUser user, WebElement subscriberVideo) { private String getSubscriberVideoCodec(OpenViduTestappUser user, WebElement subscriberVideo) {
return getSubscriberVideoLayerStat(user, subscriberVideo, "codec", JsonElement::getAsString); return getSubscriberVideoLayerStat(user, subscriberVideo, "codec", JsonElement::getAsString);
} }
@ -4436,6 +4462,21 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
}, "Timeout waiting for subscriber track to increase its bytesReceived from " + previousBytesReceived); }, "Timeout waiting for subscriber track to increase its bytesReceived from " + previousBytesReceived);
} }
// A subscriber video is only properly received AND played if its decoder keeps
// producing new frames. Receiving bytes is not enough: a subscriber may receive
// media that it is not able to decode at all
private void waitUntilSubscriberFramesDecodedIncrease(OpenViduTestappUser user, WebElement videoElement) {
this.waitUntilSubscriberFramesDecodedIncrease(user, videoElement,
this.getSubscriberVideoFramesDecoded(user, videoElement));
}
private void waitUntilSubscriberFramesDecodedIncrease(OpenViduTestappUser user, WebElement videoElement,
final long previousFramesDecoded) {
this.waitUntilAux(user, videoElement, () -> {
return this.getSubscriberVideoFramesDecoded(user, videoElement) > previousFramesDecoded;
}, "Timeout waiting for subscriber track to increase its framesDecoded from " + previousFramesDecoded);
}
private void waitUntilPublisherBytesSentIncrease(OpenViduTestappUser user, WebElement videoElement, String rid, private void waitUntilPublisherBytesSentIncrease(OpenViduTestappUser user, WebElement videoElement, String rid,
final long previousBytesSent) { final long previousBytesSent) {
this.waitUntilAux(user, videoElement, () -> { this.waitUntilAux(user, videoElement, () -> {

View File

@ -110,6 +110,7 @@ export class VideoTrackComponent extends TrackComponent {
frameWidth: report.frameWidth, frameWidth: report.frameWidth,
frameHeight: report.frameHeight, frameHeight: report.frameHeight,
framesPerSecond: report.framesPerSecond, framesPerSecond: report.framesPerSecond,
framesDecoded: report.framesDecoded,
bytesReceived: report.bytesReceived, bytesReceived: report.bytesReceived,
bytesSent: report.bytesSent, bytesSent: report.bytesSent,
}); });