From 4871619b15253af103de819500e2e38bb00fecf6 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 26 Jan 2019 20:36:24 +0100 Subject: [PATCH] openvidu-test-e2e: jave integration for media file analysis --- openvidu-test-e2e/pom.xml | 11 +- .../test/e2e/OpenViduTestAppE2eTest.java | 106 ++++++++++++++- .../e2e/utils/MultimediaFileMetadata.java | 123 ++++++++++++++++++ 3 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java diff --git a/openvidu-test-e2e/pom.xml b/openvidu-test-e2e/pom.xml index 75fa6ec6..d3c5e571 100644 --- a/openvidu-test-e2e/pom.xml +++ b/openvidu-test-e2e/pom.xml @@ -156,7 +156,16 @@ jcodec-javase 0.2.3 - + + ws.schild + jave-core + 2.4.5 + + + ws.schild + jave-native-linux64 + 2.4.5 + io.openvidu diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 24486e16..e3ac8f92 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -81,6 +81,7 @@ import io.openvidu.test.e2e.browser.ChromeAndroidUser; import io.openvidu.test.e2e.browser.ChromeUser; import io.openvidu.test.e2e.browser.FirefoxUser; import io.openvidu.test.e2e.browser.OperaUser; +import io.openvidu.test.e2e.utils.MultimediaFileMetadata; /** * E2E tests for openvidu-testapp. @@ -1233,6 +1234,82 @@ public class OpenViduTestAppE2eTest { gracefullyLeaveParticipants(2); } + /*@Test + @DisplayName("Remote record cross-browser audio-only and video-only") + void remoteRecordAudioOnlyVideoOnlyTest() throws Exception { + + setupBrowser("chrome"); + + log.info("Remote record cross-browser audio-only and video-only"); + + Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread th, Throwable ex) { + System.out.println("Uncaught exception: " + ex); + synchronized (lock) { + OpenViduTestAppE2eTest.ex = new Exception(ex); + } + } + }; + + Thread t = new Thread(() -> { + BrowserUser user2 = new FirefoxUser("FirefoxUser", 30); + user2.getDriver().get(APP_URL); + WebElement urlInput = user2.getDriver().findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + WebElement secretInput = user2.getDriver().findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + + user2.getEventManager().startPolling(); + + user2.getDriver().findElement(By.id("add-user-btn")).click(); + user2.getDriver().findElement(By.className("join-btn")).click(); + try { + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("accessAllowed", 2); + user.getEventManager().waitUntilEventReaches("streamCreated", 8); + user.getEventManager().waitUntilEventReaches("streamPlaying", 8); + + Assert.assertTrue(user2.getEventManager() + .assertMediaTracks(user2.getDriver().findElements(By.tagName("video")), true, true)); + + user2.getEventManager().waitUntilEventReaches("streamDestroyed", 1); + user2.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); + user2.getDriver().findElement(By.id("remove-user-btn")).click(); + user2.getEventManager().waitUntilEventReaches("sessionDisconnected", 1); + } catch (Exception e) { + e.printStackTrace(); + Thread.currentThread().interrupt(); + } + user2.dispose(); + }); + t.setUncaughtExceptionHandler(h); + t.start(); + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.className("join-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("accessAllowed", 2); + user.getEventManager().waitUntilEventReaches("streamCreated", 8); + user.getEventManager().waitUntilEventReaches("streamPlaying", 8); + + Assert.assertEquals(user.getDriver().findElements(By.tagName("video")).size(), 2); + Assert.assertTrue(user.getEventManager().assertMediaTracks(user.getDriver().findElements(By.tagName("video")), + true, true)); + + gracefullyLeaveParticipants(1); + + t.join(); + + synchronized (lock) { + if (OpenViduTestAppE2eTest.ex != null) { + throw OpenViduTestAppE2eTest.ex; + } + } + }*/ + @Test @DisplayName("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session") void restApiFetchForce() throws Exception { @@ -1643,10 +1720,13 @@ public class OpenViduTestAppE2eTest { } private boolean recordedFileFine(File file, Recording recording) { + this.checkMultimediaFile(file, true, true, recording.getDuration(), recording.getResolution(), 30, "h264", + "aac"); + boolean isFine = false; Picture frame; try { - // Get a frame at 75% duration + // Get a frame at 75% duration and check that it has the expected color frame = FrameGrab.getFrameAtSec(file, (double) (recording.getDuration() * 0.75)); BufferedImage image = AWTUtil.toBufferedImage(frame); Map colorMap = this.averageColor(image); @@ -1662,6 +1742,30 @@ public class OpenViduTestAppE2eTest { return isFine; } + private void checkMultimediaFile(File file, boolean hasAudio, boolean hasVideo, double duration, String resolution, + int framerate, String videoDecoder, String audioDecoder) { + // Check tracks, duration, resolution, framerate and decoders + MultimediaFileMetadata metadata = new MultimediaFileMetadata(file); + + if (hasVideo) { + if (hasAudio) { + Assert.assertTrue(metadata.hasAudioAndVideo()); + Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); + } else { + Assert.assertTrue(metadata.hasVideo()); + } + Assert.assertEquals(resolution, metadata.getVideoWidth() + "x" + metadata.getVideoHeight()); + Assert.assertEquals(metadata.getFrameRate(), new Integer(30)); + Assert.assertTrue(metadata.getVideoDecoder().toLowerCase().contains(videoDecoder)); + } else if (hasAudio) { + Assert.assertTrue(metadata.hasAudio()); + Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); + } else { + Assert.fail("Cannot check a file witho no audio and no video"); + } + Assert.assertTrue((double) metadata.getDuration() / 1000 == duration); + } + private boolean thumbnailIsFine(File file) { boolean isFine = false; BufferedImage image = null; diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java new file mode 100644 index 00000000..7cdf9f06 --- /dev/null +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2017-2019 OpenVidu (https://openvidu.io/) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.openvidu.test.e2e.utils; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ws.schild.jave.AudioInfo; +import ws.schild.jave.EncoderException; +import ws.schild.jave.MultimediaInfo; +import ws.schild.jave.MultimediaObject; +import ws.schild.jave.VideoInfo; +import ws.schild.jave.VideoSize; + +public class MultimediaFileMetadata { + + private static final Logger log = LoggerFactory.getLogger(MultimediaFileMetadata.class); + + private MultimediaInfo mediaInfo; + private AudioInfo audioInfo; + private VideoInfo videoInfo; + private VideoSize videoSize; + + public MultimediaFileMetadata(File f) { + try { + this.mediaInfo = new MultimediaObject(f).getInfo(); + this.audioInfo = mediaInfo.getAudio(); + this.videoInfo = mediaInfo.getVideo(); + if (videoInfo != null) { + this.videoSize = videoInfo.getSize(); + } + } catch (EncoderException e) { + log.error("Error getting multimedia information from file {}. Error: ", f.getAbsolutePath(), + e.getMessage()); + } + } + + public long getDuration() { + return mediaInfo.getDuration(); + } + + public String getFormat(String format) { + return mediaInfo.getFormat(); + } + + public boolean hasAudio() { + return audioInfo != null; + } + + public boolean hasVideo() { + return videoInfo != null; + } + + public boolean hasAudioAndVideo() { + return this.hasAudio() && this.hasVideo(); + } + + public Integer getAudioBitrate() { + if (audioInfo != null) { + return audioInfo.getBitRate(); + } else { + return null; + } + } + + public Integer getVideoBitrate() { + if (videoInfo != null) { + return videoInfo.getBitRate(); + } else { + return null; + } + } + + public String getAudioDecoder() { + return audioInfo.getDecoder(); + } + + public String getVideoDecoder() { + return videoInfo.getDecoder(); + } + + public Integer getVideoWidth() { + if (videoSize != null) { + return videoSize.getWidth(); + } else { + return null; + } + } + + public Integer getVideoHeight() { + if (videoSize != null) { + return videoSize.getHeight(); + } else { + return null; + } + } + + public Integer getFrameRate() { + if (videoInfo != null) { + return Math.round(videoInfo.getFrameRate()); + } else { + return null; + } + } + +}