diff --git a/playbacktests/src/androidTest/AndroidManifest.xml b/playbacktests/src/androidTest/AndroidManifest.xml deleted file mode 100644 index 2f7bbe6d7c..0000000000 --- a/playbacktests/src/androidTest/AndroidManifest.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java deleted file mode 100644 index 6b561bc81c..0000000000 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * 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 com.google.android.exoplayer2.playbacktests.gts; - -import android.annotation.TargetApi; -import android.media.MediaDrm; -import android.media.UnsupportedSchemeException; -import android.net.Uri; -import android.test.ActivityInstrumentationTestCase2; -import android.util.Log; -import android.view.Surface; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.DefaultLoadControl; -import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.RendererCapabilities; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.decoder.DecoderCounters; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; -import com.google.android.exoplayer2.drm.DrmSessionManager; -import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; -import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; -import com.google.android.exoplayer2.drm.UnsupportedDrmException; -import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; -import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; -import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; -import com.google.android.exoplayer2.playbacktests.util.ActionSchedule; -import com.google.android.exoplayer2.playbacktests.util.DebugSimpleExoPlayer; -import com.google.android.exoplayer2.playbacktests.util.DecoderCountersUtil; -import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest; -import com.google.android.exoplayer2.playbacktests.util.HostActivity; -import com.google.android.exoplayer2.playbacktests.util.MetricsLogger; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.source.dash.DashMediaSource; -import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; -import com.google.android.exoplayer2.trackselection.FixedTrackSelection; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.trackselection.RandomTrackSelection; -import com.google.android.exoplayer2.trackselection.TrackSelection; -import com.google.android.exoplayer2.upstream.BandwidthMeter; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; -import com.google.android.exoplayer2.upstream.TransferListener; -import com.google.android.exoplayer2.util.Assertions; -import com.google.android.exoplayer2.util.MimeTypes; -import com.google.android.exoplayer2.util.Util; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import junit.framework.AssertionFailedError; - -/** - * Tests DASH playbacks using {@link ExoPlayer}. - */ -public final class DashTest extends ActivityInstrumentationTestCase2 { - - private static final String TAG = "DashTest"; - private static final String VIDEO_TAG = TAG + ":Video"; - private static final String AUDIO_TAG = TAG + ":Audio"; - private static final String REPORT_NAME = "GtsExoPlayerTestCases"; - private static final String REPORT_OBJECT_NAME = "playbacktest"; - private static final int VIDEO_RENDERER_INDEX = 0; - private static final int AUDIO_RENDERER_INDEX = 1; - - private static final long TEST_TIMEOUT_MS = 5 * 60 * 1000; - private static final int MIN_LOADABLE_RETRY_COUNT = 10; - private static final int MAX_CONSECUTIVE_DROPPED_VIDEO_FRAMES = 10; - private static final float MAX_DROPPED_VIDEO_FRAME_FRACTION = 0.01f; - - private static final String MANIFEST_URL_PREFIX = "https://storage.googleapis.com/exoplayer-test-" - + "media-1/gen-3/screens/dash-vod-single-segment/"; - // Clear content manifests. - private static final String H264_MANIFEST = "manifest-h264.mpd"; - private static final String H265_MANIFEST = "manifest-h265.mpd"; - private static final String VP9_MANIFEST = "manifest-vp9.mpd"; - private static final String H264_23_MANIFEST = "manifest-h264-23.mpd"; - private static final String H264_24_MANIFEST = "manifest-h264-24.mpd"; - private static final String H264_29_MANIFEST = "manifest-h264-29.mpd"; - // Widevine encrypted content manifests. - private static final String WIDEVINE_H264_MANIFEST_PREFIX = "manifest-h264-enc"; - private static final String WIDEVINE_H265_MANIFEST_PREFIX = "manifest-h265-enc"; - private static final String WIDEVINE_VP9_MANIFEST_PREFIX = "manifest-vp9-enc"; - private static final String WIDEVINE_H264_23_MANIFEST_PREFIX = "manifest-h264-23-enc"; - private static final String WIDEVINE_H264_24_MANIFEST_PREFIX = "manifest-h264-24-enc"; - private static final String WIDEVINE_H264_29_MANIFEST_PREFIX = "manifest-h264-29-enc"; - private static final String WIDEVINE_L1_SUFFIX = "-hw.mpd"; - private static final String WIDEVINE_L3_SUFFIX = "-sw.mpd"; - - private static final String AAC_AUDIO_REPRESENTATION_ID = "141"; - private static final String H264_BASELINE_240P_VIDEO_REPRESENTATION_ID = "avc-baseline-240"; - private static final String H264_BASELINE_480P_VIDEO_REPRESENTATION_ID = "avc-baseline-480"; - private static final String H264_MAIN_240P_VIDEO_REPRESENTATION_ID = "avc-main-240"; - private static final String H264_MAIN_480P_VIDEO_REPRESENTATION_ID = "avc-main-480"; - // The highest quality H264 format mandated by the Android CDD. - private static final String H264_CDD_FIXED = Util.SDK_INT < 23 - ? H264_BASELINE_480P_VIDEO_REPRESENTATION_ID : H264_MAIN_480P_VIDEO_REPRESENTATION_ID; - // Multiple H264 formats mandated by the Android CDD. Note: The CDD actually mandated main profile - // support from API level 23, but we opt to test only from 24 due to known issues on API level 23 - // when switching between baseline and main profiles on certain devices. - private static final String[] H264_CDD_ADAPTIVE = Util.SDK_INT < 24 - ? new String[] { - H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - H264_BASELINE_480P_VIDEO_REPRESENTATION_ID} - : new String[] { - H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, - H264_MAIN_240P_VIDEO_REPRESENTATION_ID, - H264_MAIN_480P_VIDEO_REPRESENTATION_ID}; - - private static final String H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID = - "avc-baseline-480-23"; - private static final String H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID = - "avc-baseline-480-24"; - private static final String H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID = - "avc-baseline-480-29"; - - private static final String H265_BASELINE_288P_VIDEO_REPRESENTATION_ID = "hevc-main-288"; - private static final String H265_BASELINE_360P_VIDEO_REPRESENTATION_ID = "hevc-main-360"; - // The highest quality H265 format mandated by the Android CDD. - private static final String H265_CDD_FIXED = H265_BASELINE_360P_VIDEO_REPRESENTATION_ID; - // Multiple H265 formats mandated by the Android CDD. - private static final String[] H265_CDD_ADAPTIVE = - new String[] { - H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, - H265_BASELINE_360P_VIDEO_REPRESENTATION_ID}; - - private static final String VORBIS_AUDIO_REPRESENTATION_ID = "4"; - private static final String VP9_180P_VIDEO_REPRESENTATION_ID = "0"; - private static final String VP9_360P_VIDEO_REPRESENTATION_ID = "1"; - // The highest quality VP9 format mandated by the Android CDD. - private static final String VP9_CDD_FIXED = VP9_360P_VIDEO_REPRESENTATION_ID; - // Multiple VP9 formats mandated by the Android CDD. - private static final String[] VP9_CDD_ADAPTIVE = - new String[] { - VP9_180P_VIDEO_REPRESENTATION_ID, - VP9_360P_VIDEO_REPRESENTATION_ID}; - - // Widevine encrypted content representation ids. - private static final String WIDEVINE_AAC_AUDIO_REPRESENTATION_ID = "0"; - private static final String WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID = "1"; - private static final String WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID = "2"; - private static final String WIDEVINE_H264_MAIN_240P_VIDEO_REPRESENTATION_ID = "3"; - private static final String WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID = "4"; - // The highest quality H264 format mandated by the Android CDD. - private static final String WIDEVINE_H264_CDD_FIXED = Util.SDK_INT < 23 - ? WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID - : WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID; - // Multiple H264 formats mandated by the Android CDD. Note: The CDD actually mandated main profile - // support from API level 23, but we opt to test only from 24 due to known issues on API level 23 - // when switching between baseline and main profiles on certain devices. - private static final String[] WIDEVINE_H264_CDD_ADAPTIVE = Util.SDK_INT < 24 - ? new String[] { - WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID} - : new String[] { - WIDEVINE_H264_BASELINE_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_BASELINE_480P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_MAIN_240P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H264_MAIN_480P_VIDEO_REPRESENTATION_ID}; - - private static final String WIDEVINE_H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID = "2"; - private static final String WIDEVINE_H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID = "2"; - private static final String WIDEVINE_H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID = "2"; - - private static final String WIDEVINE_H265_BASELINE_288P_VIDEO_REPRESENTATION_ID = "1"; - private static final String WIDEVINE_H265_BASELINE_360P_VIDEO_REPRESENTATION_ID = "2"; - // The highest quality H265 format mandated by the Android CDD. - private static final String WIDEVINE_H265_CDD_FIXED = - WIDEVINE_H265_BASELINE_360P_VIDEO_REPRESENTATION_ID; - // Multiple H265 formats mandated by the Android CDD. - private static final String[] WIDEVINE_H265_CDD_ADAPTIVE = - new String[] { - WIDEVINE_H265_BASELINE_288P_VIDEO_REPRESENTATION_ID, - WIDEVINE_H265_BASELINE_360P_VIDEO_REPRESENTATION_ID}; - - private static final String WIDEVINE_VORBIS_AUDIO_REPRESENTATION_ID = "0"; - private static final String WIDEVINE_VP9_180P_VIDEO_REPRESENTATION_ID = "1"; - private static final String WIDEVINE_VP9_360P_VIDEO_REPRESENTATION_ID = "2"; - // The highest quality VP9 format mandated by the Android CDD. - private static final String WIDEVINE_VP9_CDD_FIXED = VP9_360P_VIDEO_REPRESENTATION_ID; - // Multiple VP9 formats mandated by the Android CDD. - private static final String[] WIDEVINE_VP9_CDD_ADAPTIVE = - new String[] { - WIDEVINE_VP9_180P_VIDEO_REPRESENTATION_ID, - WIDEVINE_VP9_360P_VIDEO_REPRESENTATION_ID}; - - private static final String WIDEVINE_LICENSE_URL = - "https://proxy.uat.widevine.com/proxy?provider=widevine_test&video_id="; - private static final String WIDEVINE_SW_CRYPTO_CONTENT_ID = "exoplayer_test_1"; - private static final String WIDEVINE_HW_SECURE_DECODE_CONTENT_ID = "exoplayer_test_2"; - private static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); - private static final String WIDEVINE_SECURITY_LEVEL_1 = "L1"; - private static final String WIDEVINE_SECURITY_LEVEL_3 = "L3"; - private static final String SECURITY_LEVEL_PROPERTY = "securityLevel"; - - // Whether adaptive tests should enable video formats beyond those mandated by the Android CDD - // if the device advertises support for them. - private static final boolean ALLOW_ADDITIONAL_VIDEO_FORMATS = Util.SDK_INT >= 24; - - private static final ActionSchedule SEEKING_SCHEDULE = new ActionSchedule.Builder(TAG) - .delay(10000).seek(15000) - .delay(10000).seek(30000).seek(31000).seek(32000).seek(33000).seek(34000) - .delay(1000).pause().delay(1000).play() - .delay(1000).pause().seek(120000).delay(1000).play() - .build(); - private static final ActionSchedule RENDERER_DISABLING_SCHEDULE = new ActionSchedule.Builder(TAG) - // Wait 10 seconds, disable the video renderer, wait another 10 seconds and enable it again. - .delay(10000).disableRenderer(VIDEO_RENDERER_INDEX) - .delay(10000).enableRenderer(VIDEO_RENDERER_INDEX) - // Ditto for the audio renderer. - .delay(10000).disableRenderer(AUDIO_RENDERER_INDEX) - .delay(10000).enableRenderer(AUDIO_RENDERER_INDEX) - // Wait 10 seconds, then disable and enable the video renderer 5 times in quick succession. - .delay(10000).disableRenderer(VIDEO_RENDERER_INDEX) - .enableRenderer(VIDEO_RENDERER_INDEX) - .disableRenderer(VIDEO_RENDERER_INDEX) - .enableRenderer(VIDEO_RENDERER_INDEX) - .disableRenderer(VIDEO_RENDERER_INDEX) - .enableRenderer(VIDEO_RENDERER_INDEX) - .disableRenderer(VIDEO_RENDERER_INDEX) - .enableRenderer(VIDEO_RENDERER_INDEX) - .disableRenderer(VIDEO_RENDERER_INDEX) - .enableRenderer(VIDEO_RENDERER_INDEX) - // Ditto for the audio renderer. - .delay(10000).disableRenderer(AUDIO_RENDERER_INDEX) - .enableRenderer(AUDIO_RENDERER_INDEX) - .disableRenderer(AUDIO_RENDERER_INDEX) - .enableRenderer(AUDIO_RENDERER_INDEX) - .disableRenderer(AUDIO_RENDERER_INDEX) - .enableRenderer(AUDIO_RENDERER_INDEX) - .disableRenderer(AUDIO_RENDERER_INDEX) - .enableRenderer(AUDIO_RENDERER_INDEX) - .disableRenderer(AUDIO_RENDERER_INDEX) - .enableRenderer(AUDIO_RENDERER_INDEX) - .delay(10000).seek(120000) - .build(); - - public DashTest() { - super(HostActivity.class); - } - - // H264 CDD. - - public void testH264Fixed() { - if (Util.SDK_INT < 16) { - // Pass. - return; - } - String streamName = "test_h264_fixed"; - testDashPlayback(getActivity(), streamName, H264_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_H264, false, H264_CDD_FIXED); - } - - public void testH264Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 16 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_h264_adaptive"; - testDashPlayback(getActivity(), streamName, H264_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS, H264_CDD_ADAPTIVE); - } - - public void testH264AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 16 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_h264_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, H264_MANIFEST, - AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS, - H264_CDD_ADAPTIVE); - } - - public void testH264AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 16 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_h264_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, H264_MANIFEST, - AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS, - H264_CDD_ADAPTIVE); - } - - // H265 CDD. - - public void testH265Fixed() { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_h265_fixed"; - testDashPlayback(getActivity(), streamName, H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_H265, false, H265_CDD_FIXED); - } - - public void testH265Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_h265_adaptive"; - testDashPlayback(getActivity(), streamName, H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_H265, ALLOW_ADDITIONAL_VIDEO_FORMATS, H265_CDD_ADAPTIVE); - } - - public void testH265AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_h265_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, H265_MANIFEST, - AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H265, ALLOW_ADDITIONAL_VIDEO_FORMATS, - H265_CDD_ADAPTIVE); - } - - public void testH265AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_h265_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, - H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H265, - ALLOW_ADDITIONAL_VIDEO_FORMATS, H265_CDD_ADAPTIVE); - } - - // VP9 (CDD). - - public void testVp9Fixed360p() { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_vp9_fixed_360p"; - testDashPlayback(getActivity(), streamName, VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_VP9, false, VP9_CDD_FIXED); - } - - public void testVp9Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_vp9_adaptive"; - testDashPlayback(getActivity(), streamName, VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID, false, - MimeTypes.VIDEO_VP9, ALLOW_ADDITIONAL_VIDEO_FORMATS, VP9_CDD_ADAPTIVE); - } - - public void testVp9AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_vp9_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, VP9_MANIFEST, - VORBIS_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_VP9, ALLOW_ADDITIONAL_VIDEO_FORMATS, - VP9_CDD_ADAPTIVE); - } - - public void testVp9AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_vp9_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, - VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_VP9, - ALLOW_ADDITIONAL_VIDEO_FORMATS, VP9_CDD_ADAPTIVE); - } - - // H264: Other frame-rates for output buffer count assertions. - - // 23.976 fps. - public void test23FpsH264Fixed() { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_23fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, H264_23_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, - false, MimeTypes.VIDEO_H264, false, H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID); - } - - // 24 fps. - public void test24FpsH264Fixed() { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_24fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, H264_24_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, - false, MimeTypes.VIDEO_H264, false, H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID); - } - - // 29.97 fps. - public void test29FpsH264Fixed() { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_29fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, H264_29_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, - false, MimeTypes.VIDEO_H264, false, H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID); - } - - // Widevine encrypted media tests. - // H264 CDD. - - public void testWidevineH264Fixed() throws DecoderQueryException { - if (Util.SDK_INT < 18) { - // Pass. - return; - } - String streamName = "test_widevine_h264_fixed"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H264_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H264, false, - WIDEVINE_H264_CDD_FIXED); - } - - public void testWidevineH264Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 18 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_widevine_h264_adaptive"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H264_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H264, - ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H264_CDD_ADAPTIVE); - } - - public void testWidevineH264AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 18 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_widevine_h264_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, - WIDEVINE_H264_MANIFEST_PREFIX, WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H264_CDD_ADAPTIVE); - } - - public void testWidevineH264AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 18 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H264)) { - // Pass. - return; - } - String streamName = "test_widevine_h264_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, - WIDEVINE_H264_MANIFEST_PREFIX, WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H264_CDD_ADAPTIVE); - } - - // H265 CDD. - - public void testWidevineH265Fixed() throws DecoderQueryException { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_widevine_h265_fixed"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H265_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H265, false, - WIDEVINE_H265_CDD_FIXED); - } - - public void testWidevineH265Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_widevine_h265_adaptive"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H265_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H265, - ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H265_CDD_ADAPTIVE); - } - - public void testWidevineH265AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_widevine_h265_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, - WIDEVINE_H265_MANIFEST_PREFIX, WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_H265, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H265_CDD_ADAPTIVE); - } - - public void testWidevineH265AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_H265)) { - // Pass. - return; - } - String streamName = "test_widevine_h265_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, - WIDEVINE_H265_MANIFEST_PREFIX, WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_H265, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_H265_CDD_ADAPTIVE); - } - - // VP9 (CDD). - - public void testWidevineVp9Fixed360p() throws DecoderQueryException { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_widevine_vp9_fixed_360p"; - testDashPlayback(getActivity(), streamName, WIDEVINE_VP9_MANIFEST_PREFIX, - WIDEVINE_VORBIS_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_VP9, false, - WIDEVINE_VP9_CDD_FIXED); - } - - public void testWidevineVp9Adaptive() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_widevine_vp9_adaptive"; - testDashPlayback(getActivity(), streamName, WIDEVINE_VP9_MANIFEST_PREFIX, - WIDEVINE_VORBIS_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_VP9, - ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_VP9_CDD_ADAPTIVE); - } - - public void testWidevineVp9AdaptiveWithSeeking() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_widevine_vp9_adaptive_with_seeking"; - testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, - WIDEVINE_VP9_MANIFEST_PREFIX, WIDEVINE_VORBIS_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_VP9, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_VP9_CDD_ADAPTIVE); - } - - public void testWidevineVp9AdaptiveWithRendererDisabling() throws DecoderQueryException { - if (Util.SDK_INT < 24 || shouldSkipAdaptiveTest(MimeTypes.VIDEO_VP9)) { - // Pass. - return; - } - String streamName = "test_widevine_vp9_adaptive_with_renderer_disabling"; - testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, - WIDEVINE_VP9_MANIFEST_PREFIX, WIDEVINE_VORBIS_AUDIO_REPRESENTATION_ID, true, - MimeTypes.VIDEO_VP9, ALLOW_ADDITIONAL_VIDEO_FORMATS, WIDEVINE_VP9_CDD_ADAPTIVE); - } - - // H264: Other frame-rates for output buffer count assertions. - - // 23.976 fps. - public void testWidevine23FpsH264Fixed() throws DecoderQueryException { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_widevine_23fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H264_23_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H264, false, - WIDEVINE_H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID); - } - - // 24 fps. - public void testWidevine24FpsH264Fixed() throws DecoderQueryException { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_widevine_24fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H264_24_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H264, false, - WIDEVINE_H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID); - } - - // 29.97 fps. - public void testWidevine29FpsH264Fixed() throws DecoderQueryException { - if (Util.SDK_INT < 23) { - // Pass. - return; - } - String streamName = "test_widevine_29fps_h264_fixed"; - testDashPlayback(getActivity(), streamName, WIDEVINE_H264_29_MANIFEST_PREFIX, - WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, true, MimeTypes.VIDEO_H264, false, - WIDEVINE_H264_BASELINE_480P_29FPS_VIDEO_REPRESENTATION_ID); - } - - // Internal. - - private void testDashPlayback(HostActivity activity, String streamName, String manifestFileName, - String audioFormat, boolean isWidevineEncrypted, String videoMimeType, - boolean canIncludeAdditionalVideoFormats, String... videoFormats) { - testDashPlayback(activity, streamName, null, true, manifestFileName, audioFormat, - isWidevineEncrypted, videoMimeType, canIncludeAdditionalVideoFormats, videoFormats); - } - - private void testDashPlayback(HostActivity activity, String streamName, - ActionSchedule actionSchedule, boolean fullPlaybackNoSeeking, String manifestFileName, - String audioFormat, boolean isWidevineEncrypted, String videoMimeType, - boolean canIncludeAdditionalVideoFormats, String... videoFormats) { - MetricsLogger metricsLogger = MetricsLogger.Factory.createDefault(getInstrumentation(), TAG, - REPORT_NAME, REPORT_OBJECT_NAME); - String manifestPath = MANIFEST_URL_PREFIX + manifestFileName; - DashHostedTest test = new DashHostedTest(streamName, manifestPath, metricsLogger, - fullPlaybackNoSeeking, audioFormat, isWidevineEncrypted, videoMimeType, - canIncludeAdditionalVideoFormats, false, actionSchedule, videoFormats); - activity.runTest(test, TEST_TIMEOUT_MS); - // Retry test exactly once if adaptive test fails due to excessive dropped buffers when playing - // non-CDD required formats (b/28220076). - if (test.needsCddLimitedRetry) { - metricsLogger = MetricsLogger.Factory.createDefault(getInstrumentation(), TAG, REPORT_NAME, - REPORT_OBJECT_NAME); - test = new DashHostedTest(streamName, manifestPath, metricsLogger, fullPlaybackNoSeeking, - audioFormat, isWidevineEncrypted, videoMimeType, false, true, actionSchedule, - videoFormats); - activity.runTest(test, TEST_TIMEOUT_MS); - } - } - - private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException { - MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false); - assertNotNull(decoderInfo); - if (decoderInfo.adaptive) { - return false; - } - assertTrue(Util.SDK_INT < 21); - return true; - } - - @TargetApi(16) - private static class DashHostedTest extends ExoHostedTest { - - private final String streamName; - private final String videoMimeType; - private final String manifestPath; - private final MetricsLogger metricsLogger; - private final boolean fullPlaybackNoSeeking; - private final boolean isCddLimitedRetry; - private final boolean isWidevineEncrypted; - private final DashTestTrackSelector trackSelector; - - private boolean needsCddLimitedRetry; - private boolean needsSecureVideoDecoder; - - /** - * @param streamName The name of the test stream for metric logging. - * @param manifestPath The manifest path. - * @param metricsLogger Logger to log metrics from the test. - * @param fullPlaybackNoSeeking Whether the test will play the entire source with no seeking. - * @param audioFormat The audio format. - * @param isWidevineEncrypted Whether the video is Widevine encrypted. - * @param videoMimeType The video mime type. - * @param canIncludeAdditionalVideoFormats Whether to use video formats in addition to those - * listed in the videoFormats argument, if the device is capable of playing them. - * @param isCddLimitedRetry Whether this is a CDD limited retry following a previous failure. - * @param actionSchedule The action schedule for the test. - * @param videoFormats The video formats. - */ - public DashHostedTest(String streamName, String manifestPath, MetricsLogger metricsLogger, - boolean fullPlaybackNoSeeking, String audioFormat, boolean isWidevineEncrypted, - String videoMimeType, boolean canIncludeAdditionalVideoFormats, boolean isCddLimitedRetry, - ActionSchedule actionSchedule, String... videoFormats) { - super(TAG, fullPlaybackNoSeeking); - Assertions.checkArgument(!(isCddLimitedRetry && canIncludeAdditionalVideoFormats)); - this.streamName = streamName; - this.manifestPath = manifestPath; - this.metricsLogger = metricsLogger; - this.fullPlaybackNoSeeking = fullPlaybackNoSeeking; - this.isWidevineEncrypted = isWidevineEncrypted; - this.videoMimeType = videoMimeType; - this.isCddLimitedRetry = isCddLimitedRetry; - trackSelector = new DashTestTrackSelector(audioFormat, videoFormats, - canIncludeAdditionalVideoFormats); - if (actionSchedule != null) { - setSchedule(actionSchedule); - } - } - - @Override - protected MappingTrackSelector buildTrackSelector(HostActivity host, - BandwidthMeter bandwidthMeter) { - return trackSelector; - } - - @Override - @TargetApi(18) - @SuppressWarnings("ResourceType") - protected final DefaultDrmSessionManager buildDrmSessionManager( - final String userAgent) { - DefaultDrmSessionManager drmSessionManager = null; - if (isWidevineEncrypted) { - try { - // Force L3 if secure decoder is not available. - boolean forceL3Widevine = MediaCodecUtil.getDecoderInfo(videoMimeType, true) == null; - MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); - String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); - String widevineContentId = forceL3Widevine ? WIDEVINE_SW_CRYPTO_CONTENT_ID - : WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty) - ? WIDEVINE_HW_SECURE_DECODE_CONTENT_ID : WIDEVINE_SW_CRYPTO_CONTENT_ID; - HttpMediaDrmCallback drmCallback = new HttpMediaDrmCallback( - WIDEVINE_LICENSE_URL + widevineContentId, - new DefaultHttpDataSourceFactory(userAgent)); - drmSessionManager = DefaultDrmSessionManager.newWidevineInstance(drmCallback, null, - null, null); - if (forceL3Widevine && !WIDEVINE_SECURITY_LEVEL_3.equals(securityProperty)) { - drmSessionManager.setPropertyString(SECURITY_LEVEL_PROPERTY, WIDEVINE_SECURITY_LEVEL_3); - } - // Check if secure video decoder is required. - securityProperty = drmSessionManager.getPropertyString(SECURITY_LEVEL_PROPERTY); - needsSecureVideoDecoder = WIDEVINE_SECURITY_LEVEL_1.equals(securityProperty); - } catch (MediaCodecUtil.DecoderQueryException | UnsupportedSchemeException - | UnsupportedDrmException e) { - throw new IllegalStateException(e); - } - } - return drmSessionManager; - } - - @Override - protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, - MappingTrackSelector trackSelector, - DrmSessionManager drmSessionManager) { - SimpleExoPlayer player = new DebugSimpleExoPlayer(host, trackSelector, - new DefaultLoadControl(), drmSessionManager); - player.setVideoSurface(surface); - return player; - } - - @Override - protected MediaSource buildSource(HostActivity host, String userAgent, - TransferListener mediaTransferListener) { - DataSource.Factory manifestDataSourceFactory = new DefaultDataSourceFactory(host, userAgent); - DataSource.Factory mediaDataSourceFactory = new DefaultDataSourceFactory(host, userAgent, - mediaTransferListener); - String manifestUrl = manifestPath; - manifestUrl += isWidevineEncrypted ? (needsSecureVideoDecoder ? WIDEVINE_L1_SUFFIX - : WIDEVINE_L3_SUFFIX) : ""; - Uri manifestUri = Uri.parse(manifestUrl); - DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory( - mediaDataSourceFactory); - return new DashMediaSource(manifestUri, manifestDataSourceFactory, chunkSourceFactory, - MIN_LOADABLE_RETRY_COUNT, 0 /* livePresentationDelayMs */, null, null); - } - - @Override - protected void logMetrics(DecoderCounters audioCounters, DecoderCounters videoCounters) { - metricsLogger.logMetric(MetricsLogger.KEY_TEST_NAME, streamName); - metricsLogger.logMetric(MetricsLogger.KEY_IS_CDD_LIMITED_RETRY, isCddLimitedRetry); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_DROPPED_COUNT, - videoCounters.droppedOutputBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_MAX_CONSECUTIVE_FRAMES_DROPPED_COUNT, - videoCounters.maxConsecutiveDroppedOutputBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_SKIPPED_COUNT, - videoCounters.skippedOutputBufferCount); - metricsLogger.logMetric(MetricsLogger.KEY_FRAMES_RENDERED_COUNT, - videoCounters.renderedOutputBufferCount); - metricsLogger.close(); - } - - @Override - protected void assertPassed(DecoderCounters audioCounters, DecoderCounters videoCounters) { - if (fullPlaybackNoSeeking) { - // We shouldn't have skipped any output buffers. - DecoderCountersUtil.assertSkippedOutputBufferCount(AUDIO_TAG, audioCounters, 0); - DecoderCountersUtil.assertSkippedOutputBufferCount(VIDEO_TAG, videoCounters, 0); - // We allow one fewer output buffer due to the way that MediaCodecRenderer and the - // underlying decoders handle the end of stream. This should be tightened up in the future. - DecoderCountersUtil.assertTotalOutputBufferCount(AUDIO_TAG, audioCounters, - audioCounters.inputBufferCount - 1, audioCounters.inputBufferCount); - DecoderCountersUtil.assertTotalOutputBufferCount(VIDEO_TAG, videoCounters, - videoCounters.inputBufferCount - 1, videoCounters.inputBufferCount); - } - try { - int droppedFrameLimit = (int) Math.ceil(MAX_DROPPED_VIDEO_FRAME_FRACTION - * DecoderCountersUtil.getTotalOutputBuffers(videoCounters)); - // Assert that performance is acceptable. - // Assert that total dropped frames were within limit. - DecoderCountersUtil.assertDroppedOutputBufferLimit(VIDEO_TAG, videoCounters, - droppedFrameLimit); - // Assert that consecutive dropped frames were within limit. - DecoderCountersUtil.assertConsecutiveDroppedOutputBufferLimit(VIDEO_TAG, videoCounters, - MAX_CONSECUTIVE_DROPPED_VIDEO_FRAMES); - } catch (AssertionFailedError e) { - if (trackSelector.includedAdditionalVideoFormats) { - // Retry limiting to CDD mandated formats (b/28220076). - Log.e(TAG, "Too many dropped or consecutive dropped frames.", e); - needsCddLimitedRetry = true; - } else { - throw e; - } - } - } - - } - - private static final class DashTestTrackSelector extends MappingTrackSelector { - - private final String audioFormatId; - private final String[] videoFormatIds; - private final boolean canIncludeAdditionalVideoFormats; - - public boolean includedAdditionalVideoFormats; - - private DashTestTrackSelector(String audioFormatId, String[] videoFormatIds, - boolean canIncludeAdditionalVideoFormats) { - this.audioFormatId = audioFormatId; - this.videoFormatIds = videoFormatIds; - this.canIncludeAdditionalVideoFormats = canIncludeAdditionalVideoFormats; - } - - @Override - protected TrackSelection[] selectTracks(RendererCapabilities[] rendererCapabilities, - TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports) - throws ExoPlaybackException { - Assertions.checkState(rendererCapabilities[VIDEO_RENDERER_INDEX].getTrackType() - == C.TRACK_TYPE_VIDEO); - Assertions.checkState(rendererCapabilities[AUDIO_RENDERER_INDEX].getTrackType() - == C.TRACK_TYPE_AUDIO); - Assertions.checkState(rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].length == 1); - Assertions.checkState(rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].length == 1); - TrackSelection[] selections = new TrackSelection[rendererCapabilities.length]; - selections[VIDEO_RENDERER_INDEX] = new RandomTrackSelection( - rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].get(0), - getVideoTrackIndices(rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].get(0), - rendererFormatSupports[VIDEO_RENDERER_INDEX][0], videoFormatIds, - canIncludeAdditionalVideoFormats), - 0 /* seed */); - selections[AUDIO_RENDERER_INDEX] = new FixedTrackSelection( - rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].get(0), - getTrackIndex(rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].get(0), audioFormatId)); - includedAdditionalVideoFormats = - selections[VIDEO_RENDERER_INDEX].length() > videoFormatIds.length; - return selections; - } - - private static int[] getVideoTrackIndices(TrackGroup trackGroup, int[] formatSupport, - String[] formatIds, boolean canIncludeAdditionalFormats) { - List trackIndices = new ArrayList<>(); - - // Always select explicitly listed representations. - for (String formatId : formatIds) { - int trackIndex = getTrackIndex(trackGroup, formatId); - Log.d(TAG, "Adding base video format: " - + Format.toLogString(trackGroup.getFormat(trackIndex))); - trackIndices.add(trackIndex); - } - - // Select additional video representations, if supported by the device. - if (canIncludeAdditionalFormats) { - for (int i = 0; i < trackGroup.length; i++) { - if (!trackIndices.contains(i) && isFormatHandled(formatSupport[i])) { - Log.d(TAG, "Adding extra video format: " - + Format.toLogString(trackGroup.getFormat(i))); - trackIndices.add(i); - } - } - } - - int[] trackIndicesArray = Util.toArray(trackIndices); - Arrays.sort(trackIndicesArray); - return trackIndicesArray; - } - - private static int getTrackIndex(TrackGroup trackGroup, String formatId) { - for (int i = 0; i < trackGroup.length; i++) { - if (trackGroup.getFormat(i).id.equals(formatId)) { - return i; - } - } - throw new IllegalStateException("Format " + formatId + " not found."); - } - - private static boolean isFormatHandled(int formatSupport) { - return (formatSupport & RendererCapabilities.FORMAT_SUPPORT_MASK) - == RendererCapabilities.FORMAT_HANDLED; - } - - } - -}