Add a BUILD file with mobile harness target to playbacktests/src/androidTest folder
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=145267137
This commit is contained in:
parent
d303db975e
commit
9ac0add4be
@ -1,42 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
package="com.google.android.exoplayer2.playbacktests">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/>
|
|
||||||
|
|
||||||
<application android:debuggable="true"
|
|
||||||
android:allowBackup="false"
|
|
||||||
tools:ignore="MissingApplicationIcon,HardcodedDebugMode">
|
|
||||||
<uses-library android:name="android.test.runner"/>
|
|
||||||
|
|
||||||
<activity android:name="com.google.android.exoplayer2.playbacktests.util.HostActivity"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
|
||||||
android:label="ExoPlayerTest"/>
|
|
||||||
|
|
||||||
</application>
|
|
||||||
|
|
||||||
<instrumentation
|
|
||||||
android:targetPackage="com.google.android.exoplayer2.playbacktests"
|
|
||||||
android:name="android.test.InstrumentationTestRunner"
|
|
||||||
tools:replace="android:targetPackage"/>
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -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<HostActivity> {
|
|
||||||
|
|
||||||
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<FrameworkMediaCrypto> buildDrmSessionManager(
|
|
||||||
final String userAgent) {
|
|
||||||
DefaultDrmSessionManager<FrameworkMediaCrypto> 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<FrameworkMediaCrypto> drmSessionManager) {
|
|
||||||
SimpleExoPlayer player = new DebugSimpleExoPlayer(host, trackSelector,
|
|
||||||
new DefaultLoadControl(), drmSessionManager);
|
|
||||||
player.setVideoSurface(surface);
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected MediaSource buildSource(HostActivity host, String userAgent,
|
|
||||||
TransferListener<? super DataSource> 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<Integer> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user