Merge widevine playback tests to v2.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=127825954
This commit is contained in:
mishragaurav 2016-07-19 06:44:26 -07:00 committed by Oliver Woodman
parent 2ed55d97d1
commit a61828a675
5 changed files with 481 additions and 45 deletions

View file

@ -20,6 +20,8 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
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;
@ -28,6 +30,7 @@ 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.playbacktests.util.TestMediaDrmCallback;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -45,6 +48,8 @@ import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import android.annotation.TargetApi;
import android.media.MediaDrm;
import android.media.UnsupportedSchemeException;
import android.net.Uri;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
@ -53,6 +58,7 @@ import junit.framework.AssertionFailedError;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* Tests DASH playbacks using {@link ExoPlayer}.
@ -63,6 +69,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
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;
@ -73,12 +80,22 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
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";
@ -129,6 +146,63 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
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_PROVIDER = "widevine_test";
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;
@ -184,7 +258,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h264_fixed";
testDashPlayback(getActivity(), streamName, H264_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false,
H264_CDD_FIXED);
MimeTypes.VIDEO_H264, false, H264_CDD_FIXED);
}
public void testH264Adaptive() throws DecoderQueryException {
@ -193,8 +267,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
return;
}
String streamName = "test_h264_adaptive";
testDashPlayback(getActivity(), streamName, H264_MANIFEST, AAC_AUDIO_REPRESENTATION_ID,
ALLOW_ADDITIONAL_VIDEO_FORMATS, H264_CDD_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 {
@ -204,7 +278,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h264_adaptive_with_seeking";
testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, H264_MANIFEST,
AAC_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS, H264_CDD_ADAPTIVE);
AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS,
H264_CDD_ADAPTIVE);
}
public void testH264AdaptiveWithRendererDisabling() throws DecoderQueryException {
@ -214,7 +289,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h264_adaptive_with_renderer_disabling";
testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false, H264_MANIFEST,
AAC_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS, H264_CDD_ADAPTIVE);
AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H264, ALLOW_ADDITIONAL_VIDEO_FORMATS,
H264_CDD_ADAPTIVE);
}
// H265 CDD.
@ -226,7 +302,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h265_fixed";
testDashPlayback(getActivity(), streamName, H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false,
H265_CDD_FIXED);
MimeTypes.VIDEO_H265, false, H265_CDD_FIXED);
}
public void testH265Adaptive() throws DecoderQueryException {
@ -235,8 +311,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
return;
}
String streamName = "test_h265_adaptive";
testDashPlayback(getActivity(), streamName, H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID,
ALLOW_ADDITIONAL_VIDEO_FORMATS, H265_CDD_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 {
@ -246,7 +322,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h265_adaptive_with_seeking";
testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, H265_MANIFEST,
AAC_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS, H265_CDD_ADAPTIVE);
AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H265, ALLOW_ADDITIONAL_VIDEO_FORMATS,
H265_CDD_ADAPTIVE);
}
public void testH265AdaptiveWithRendererDisabling() throws DecoderQueryException {
@ -256,8 +333,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_h265_adaptive_with_renderer_disabling";
testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false,
H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS,
H265_CDD_ADAPTIVE);
H265_MANIFEST, AAC_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_H265,
ALLOW_ADDITIONAL_VIDEO_FORMATS, H265_CDD_ADAPTIVE);
}
// VP9 (CDD).
@ -269,7 +346,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_vp9_fixed_360p";
testDashPlayback(getActivity(), streamName, VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID, false,
VP9_CDD_FIXED);
MimeTypes.VIDEO_VP9, false, VP9_CDD_FIXED);
}
public void testVp9Adaptive() throws DecoderQueryException {
@ -278,8 +355,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
return;
}
String streamName = "test_vp9_adaptive";
testDashPlayback(getActivity(), streamName, VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID,
ALLOW_ADDITIONAL_VIDEO_FORMATS, VP9_CDD_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 {
@ -289,7 +366,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_vp9_adaptive_with_seeking";
testDashPlayback(getActivity(), streamName, SEEKING_SCHEDULE, false, VP9_MANIFEST,
VORBIS_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS, VP9_CDD_ADAPTIVE);
VORBIS_AUDIO_REPRESENTATION_ID, false, MimeTypes.VIDEO_VP9, ALLOW_ADDITIONAL_VIDEO_FORMATS,
VP9_CDD_ADAPTIVE);
}
public void testVp9AdaptiveWithRendererDisabling() throws DecoderQueryException {
@ -299,8 +377,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_vp9_adaptive_with_renderer_disabling";
testDashPlayback(getActivity(), streamName, RENDERER_DISABLING_SCHEDULE, false,
VP9_MANIFEST, VORBIS_AUDIO_REPRESENTATION_ID, ALLOW_ADDITIONAL_VIDEO_FORMATS,
VP9_CDD_ADAPTIVE);
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.
@ -313,7 +391,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_23fps_h264_fixed";
testDashPlayback(getActivity(), streamName, H264_23_MANIFEST, AAC_AUDIO_REPRESENTATION_ID,
false, H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID);
false, MimeTypes.VIDEO_H264, false, H264_BASELINE_480P_23FPS_VIDEO_REPRESENTATION_ID);
}
// 24 fps.
@ -324,7 +402,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_24fps_h264_fixed";
testDashPlayback(getActivity(), streamName, H264_24_MANIFEST, AAC_AUDIO_REPRESENTATION_ID,
false, H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID);
false, MimeTypes.VIDEO_H264, false, H264_BASELINE_480P_24FPS_VIDEO_REPRESENTATION_ID);
}
// 29.97 fps.
@ -335,39 +413,219 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
String streamName = "test_29fps_h264_fixed";
testDashPlayback(getActivity(), streamName, H264_29_MANIFEST, AAC_AUDIO_REPRESENTATION_ID,
false, H264_BASELINE_480P_29FPS_VIDEO_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 canIncludeAdditionalVideoFormats, String... videoFormats) {
String audioFormat, boolean isWidevineEncrypted, String videoMimeType,
boolean canIncludeAdditionalVideoFormats, String... videoFormats) {
testDashPlayback(activity, streamName, null, true, manifestFileName, audioFormat,
canIncludeAdditionalVideoFormats, videoFormats);
isWidevineEncrypted, videoMimeType, canIncludeAdditionalVideoFormats, videoFormats);
}
private void testDashPlayback(HostActivity activity, String streamName,
ActionSchedule actionSchedule, boolean fullPlaybackNoSeeking, String manifestFileName,
String audioFormat, boolean canIncludeAdditionalVideoFormats, String... videoFormats) {
Uri manifestUri = Uri.parse(MANIFEST_URL_PREFIX + manifestFileName);
String audioFormat, boolean isWidevineEncrypted, String videoMimeType,
boolean canIncludeAdditionalVideoFormats, String... videoFormats) {
MetricsLogger metricsLogger = MetricsLogger.Factory.createDefault(getInstrumentation(), TAG,
REPORT_NAME, streamName);
DashHostedTest test = new DashHostedTest(streamName, manifestUri, metricsLogger,
fullPlaybackNoSeeking, audioFormat, canIncludeAdditionalVideoFormats, false, actionSchedule,
videoFormats);
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,
streamName + "_cdd_limited_retry");
test = new DashHostedTest(streamName, manifestUri, metricsLogger, fullPlaybackNoSeeking,
audioFormat, false, true, actionSchedule, videoFormats);
REPORT_OBJECT_NAME);
test = new DashHostedTest(streamName, manifestPath, metricsLogger, fullPlaybackNoSeeking,
audioFormat, isWidevineEncrypted, videoMimeType, false, true, actionSchedule,
videoFormats);
activity.runTest(test, TEST_TIMEOUT_MS);
}
}
private boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false);
assertNotNull(decoderInfo);
if (decoderInfo.adaptive) {
@ -381,34 +639,45 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
private static class DashHostedTest extends ExoHostedTest {
private final String streamName;
private final Uri manifestUri;
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 manifestUri The manifest uri.
* @param manifestPath The manifest path.
* @param metricsLogger Logger to log metrics from the test.
* @param fullPlaybackNoSeeking True if the test will play the entire source with no seeking.
* False otherwise.
* @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, Uri manifestUri, MetricsLogger metricsLogger,
boolean fullPlaybackNoSeeking, String audioFormat, boolean canIncludeAdditionalVideoFormats,
boolean isCddLimitedRetry, ActionSchedule actionSchedule, String... videoFormats) {
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.manifestUri = manifestUri;
this.manifestPath = manifestPath;
this.metricsLogger = metricsLogger;
this.fullPlaybackNoSeeking = fullPlaybackNoSeeking;
this.isWidevineEncrypted = isWidevineEncrypted;
this.videoMimeType = videoMimeType;
this.isCddLimitedRetry = isCddLimitedRetry;
trackSelector = new DashTestTrackSelector(new String[] {audioFormat},
videoFormats, canIncludeAdditionalVideoFormats);
if (actionSchedule != null) {
@ -421,6 +690,37 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
return trackSelector;
}
@Override
@TargetApi(18)
protected final StreamingDrmSessionManager buildDrmSessionManager() {
StreamingDrmSessionManager 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;
TestMediaDrmCallback drmCallback = TestMediaDrmCallback.newWidevineInstance(
widevineContentId, WIDEVINE_PROVIDER);
drmSessionManager = StreamingDrmSessionManager.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
public MediaSource buildSource(HostActivity host, String userAgent) {
DataSource.Factory manifestDataSourceFactory = new DefaultDataSourceFactory(host, userAgent);
@ -429,6 +729,10 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
bandwidthMeter);
FormatEvaluator.Factory formatEvaluatorFactory = new AdaptiveEvaluator.Factory(
bandwidthMeter);
String manifestUrl = manifestPath;
manifestUrl += isWidevineEncrypted ? (needsSecureVideoDecoder ? WIDEVINE_L1_SUFFIX
: WIDEVINE_L3_SUFFIX) : "";
Uri manifestUri = Uri.parse(manifestUrl);
DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory(
mediaDataSourceFactory, formatEvaluatorFactory);
return new DashMediaSource(manifestUri, manifestDataSourceFactory, chunkSourceFactory,
@ -438,6 +742,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
@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,

View file

@ -15,6 +15,11 @@
*/
package com.google.android.exoplayer2.playbacktests.util;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.Surface;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
@ -22,18 +27,16 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioTrack;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.playbacktests.util.HostActivity.HostedTest;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.util.Util;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.Surface;
import junit.framework.Assert;
/**
* A {@link HostedTest} for {@link ExoPlayer} playback tests.
*/
@ -120,7 +123,8 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
public final void onStart(HostActivity host, Surface surface) {
// Build the player.
trackSelector = buildTrackSelector(host);
player = buildExoPlayer(host, surface, trackSelector);
DrmSessionManager drmSessionManager = buildDrmSessionManager();
player = buildExoPlayer(host, surface, trackSelector, drmSessionManager);
player.setMediaSource(buildSource(host, Util.getUserAgent(host, "ExoPlayerPlaybackTests")));
player.addListener(this);
player.setDebugListener(this);
@ -271,6 +275,11 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
// Internal logic
protected DrmSessionManager buildDrmSessionManager() {
// Do nothing. Interested subclasses may override.
return null;
}
@SuppressWarnings("unused")
protected MappingTrackSelector buildTrackSelector(HostActivity host) {
return new DefaultTrackSelector(null);
@ -278,8 +287,9 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
@SuppressWarnings("unused")
protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface,
MappingTrackSelector trackSelector) {
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(host, trackSelector);
MappingTrackSelector trackSelector, DrmSessionManager drmSessionManager) {
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(host, trackSelector,
new DefaultLoadControl(), drmSessionManager);
player.setSurface(surface);
return player;
}

View file

@ -43,6 +43,11 @@ public final class LogcatMetricsLogger implements MetricsLogger {
Log.d(tag, key + ": " + value);
}
@Override
public void logMetric(String key, boolean value) {
Log.d(tag, key + ": " + value);
}
@Override
public void close() {
// Do nothing.

View file

@ -27,6 +27,7 @@ public interface MetricsLogger {
String KEY_FRAMES_SKIPPED_COUNT = "frames_skipped_count";
String KEY_MAX_CONSECUTIVE_FRAMES_DROPPED_COUNT = "maximum_consecutive_frames_dropped_count";
String KEY_TEST_NAME = "test_name";
String KEY_IS_CDD_LIMITED_RETRY = "is_cdd_limited_retry";
/**
* Logs an int metric provided from a test.
@ -52,6 +53,14 @@ public interface MetricsLogger {
*/
void logMetric(String key, String value);
/**
* Logs a boolean metric provided from a test.
*
* @param key The key of the metric to be logged.
* @param value The value of the metric to be logged.
*/
void logMetric(String key, boolean value);
/**
* Closes the logger.
*/

View file

@ -0,0 +1,107 @@
/*
* 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.util;
import android.annotation.TargetApi;
import android.media.MediaDrm;
import android.text.TextUtils;
import com.google.android.exoplayer2.drm.MediaDrmCallback;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.UUID;
/**
* A {@link MediaDrmCallback} for Widevine test content.
*/
@TargetApi(18)
public final class TestMediaDrmCallback implements MediaDrmCallback {
private static final String WIDEVINE_BASE_URL = "https://proxy.uat.widevine.com/proxy";
private final String defaultUrl;
private final Map<String, String> keyRequestProperties;
public static TestMediaDrmCallback newWidevineInstance(String contentId, String provider) {
String defaultUrl = WIDEVINE_BASE_URL + "?video_id=" + contentId + "&provider=" + provider;
return new TestMediaDrmCallback(defaultUrl, null);
}
private TestMediaDrmCallback(String defaultUrl, Map<String, String> keyRequestProperties) {
this.defaultUrl = defaultUrl;
this.keyRequestProperties = keyRequestProperties;
}
@Override
public byte[] executeProvisionRequest(UUID uuid, MediaDrm.ProvisionRequest request)
throws IOException {
String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData(),
Charset.defaultCharset());
return executePost(url, null, null);
}
@Override
public byte[] executeKeyRequest(UUID uuid, MediaDrm.KeyRequest request) throws Exception {
String url = request.getDefaultUrl();
if (TextUtils.isEmpty(url)) {
url = defaultUrl;
}
return executePost(url, request.getData(), keyRequestProperties);
}
private static byte[] executePost(String url, byte[] data, Map<String, String> requestProperties)
throws IOException {
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(url).openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(data != null);
urlConnection.setDoInput(true);
if (requestProperties != null) {
for (Map.Entry<String, String> requestProperty : requestProperties.entrySet()) {
urlConnection.setRequestProperty(requestProperty.getKey(), requestProperty.getValue());
}
}
// Write the request body, if there is one.
if (data != null) {
OutputStream out = urlConnection.getOutputStream();
try {
out.write(data);
} finally {
out.close();
}
}
// Read and return the response body.
InputStream inputStream = urlConnection.getInputStream();
try {
return Util.toByteArray(inputStream);
} finally {
inputStream.close();
}
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
}