1 /* 2 * Copyright 2019 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.cts; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.media.MediaCasException; 23 import android.media.MediaCodecList; 24 import android.media.MediaCryptoException; 25 import android.media.MediaFormat; 26 import android.net.Uri; 27 import android.test.ActivityInstrumentationTestCase2; 28 import android.util.Log; 29 import android.view.Surface; 30 31 import java.io.IOException; 32 import java.util.List; 33 import java.util.concurrent.TimeUnit; 34 35 public class MediaCodecPlayerTestBase<T extends Activity> extends ActivityInstrumentationTestCase2<T> { 36 37 private static final String TAG = MediaCodecPlayerTestBase.class.getSimpleName(); 38 private static final int CONNECTION_RETRIES = 10; 39 private static final int SLEEP_TIME_MS = 1000; 40 // The first ten seconds in PLAY_TIME_MS plays the clear lead, 41 // the next ten seconds verifies encrypted playback. 42 // This applies to both streaming and offline tests. 43 private static final long PLAY_TIME_MS = TimeUnit.MILLISECONDS.convert(20, TimeUnit.SECONDS); 44 45 protected Context mContext; 46 protected MediaCodecClearKeyPlayer mMediaCodecPlayer; 47 MediaCodecPlayerTestBase(Class<T> clz)48 public MediaCodecPlayerTestBase(Class<T> clz) { 49 super(clz); 50 } 51 52 @Override setUp()53 protected void setUp() throws Exception { 54 super.setUp(); 55 mContext = getInstrumentation().getTargetContext(); 56 } 57 58 /** 59 * Tests clear content playback. 60 */ testPlayback( String videoMime, String[] videoFeatures, Uri audioUrl, Uri videoUrl, int videoWidth, int videoHeight, List<Surface> surfaces)61 protected void testPlayback( 62 String videoMime, String[] videoFeatures, 63 Uri audioUrl, 64 Uri videoUrl, 65 int videoWidth, int videoHeight, 66 List<Surface> surfaces) throws Exception { 67 68 if (isWatchDevice()) { 69 return; 70 } 71 72 if (!preparePlayback(videoMime, videoFeatures, 73 audioUrl, false /* audioEncrypted */, 74 videoUrl, false /* videoEncrypted */, videoWidth, videoHeight, 75 false /* scrambled */, null /* sessionId */, surfaces)) { 76 return; 77 } 78 79 // starts video playback 80 playUntilEnd(); 81 } 82 isWatchDevice()83 protected boolean isWatchDevice() { 84 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH); 85 } 86 preparePlayback(String videoMime, String[] videoFeatures, Uri audioUrl, boolean audioEncrypted, Uri videoUrl, boolean videoEncrypted, int videoWidth, int videoHeight, boolean scrambled, byte[] sessionId, List<Surface> surfaces)87 protected boolean preparePlayback(String videoMime, String[] videoFeatures, Uri audioUrl, 88 boolean audioEncrypted, Uri videoUrl, boolean videoEncrypted, int videoWidth, 89 int videoHeight, boolean scrambled, byte[] sessionId, List<Surface> surfaces) 90 throws IOException, MediaCryptoException, MediaCasException { 91 if (false == playbackPreCheck(videoMime, videoFeatures, videoUrl, 92 videoWidth, videoHeight)) { 93 Log.e(TAG, "Failed playback precheck"); 94 return false; 95 } 96 97 mMediaCodecPlayer = new MediaCodecClearKeyPlayer( 98 surfaces, 99 sessionId, scrambled, 100 mContext); 101 102 mMediaCodecPlayer.setAudioDataSource(audioUrl, null, audioEncrypted); 103 mMediaCodecPlayer.setVideoDataSource(videoUrl, null, videoEncrypted); 104 mMediaCodecPlayer.start(); 105 if (!mMediaCodecPlayer.prepare()) { 106 Log.i(TAG, "Media Player could not be prepared."); 107 return false; 108 } 109 return true; 110 } 111 playUntilEnd()112 protected void playUntilEnd() throws InterruptedException { 113 mMediaCodecPlayer.startThread(); 114 115 long timeOut = System.currentTimeMillis() + PLAY_TIME_MS; 116 while (timeOut > System.currentTimeMillis() && !mMediaCodecPlayer.isEnded()) { 117 Thread.sleep(SLEEP_TIME_MS); 118 if (mMediaCodecPlayer.getCurrentPosition() >= mMediaCodecPlayer.getDuration() ) { 119 Log.d(TAG, "current pos = " + mMediaCodecPlayer.getCurrentPosition() + 120 ">= duration = " + mMediaCodecPlayer.getDuration()); 121 break; 122 } 123 } 124 125 Log.d(TAG, "playVideo player.reset()"); 126 mMediaCodecPlayer.reset(); 127 } 128 129 /** 130 * Verify if we can support playback resolution 131 */ playbackPreCheck(String videoMime, String[] videoFeatures, Uri videoUrl, int videoWidth, int videoHeight)132 public boolean playbackPreCheck(String videoMime, String[] videoFeatures, 133 Uri videoUrl, int videoWidth, int videoHeight) { 134 if (!isResolutionSupported(videoMime, videoFeatures, videoWidth, videoHeight)) { 135 Log.i(TAG, "Device does not support " + 136 videoWidth + "x" + videoHeight + " resolution for " + videoMime); 137 return false; 138 } 139 return true; 140 } 141 isResolutionSupported(String mime, String[] features, int videoWidth, int videoHeight)142 protected boolean isResolutionSupported(String mime, String[] features, 143 int videoWidth, int videoHeight) { 144 MediaFormat format = MediaFormat.createVideoFormat(mime, videoWidth, videoHeight); 145 for (String feature: features) { 146 format.setFeatureEnabled(feature, true); 147 } 148 MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS); 149 if (mcl.findDecoderForFormat(format) == null) { 150 Log.i(TAG, "could not find codec for " + format); 151 return false; 152 } 153 return true; 154 } 155 156 } 157