1 /* 2 * Copyright (C) 2008 The Android Open Source Project 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 com.android.mediaframeworktest.unit; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.graphics.Bitmap; 24 import android.media.MediaMetadataRetriever; 25 import android.platform.test.annotations.RequiresFlagsDisabled; 26 import android.platform.test.annotations.RequiresFlagsEnabled; 27 import android.platform.test.flag.junit.CheckFlagsRule; 28 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 29 import android.util.Log; 30 31 import androidx.test.filters.LargeTest; 32 import androidx.test.filters.MediumTest; 33 import androidx.test.runner.AndroidJUnit4; 34 35 import com.android.media.playback.flags.Flags; 36 import com.android.mediaframeworktest.MediaNames; 37 import com.android.mediaframeworktest.MediaProfileReader; 38 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.io.FileOutputStream; 44 import java.io.IOException; 45 46 @RunWith(AndroidJUnit4.class) 47 public class MediaMetadataRetrieverTest { 48 49 private static final String TAG = "MediaMetadataRetrieverTest"; 50 51 @Rule 52 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 53 54 // Test album art extraction. 55 @MediumTest 56 @Test testGetEmbeddedPicture()57 public void testGetEmbeddedPicture() throws Exception { 58 Log.v(TAG, "testGetEmbeddedPicture starts."); 59 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 60 boolean supportWMA = MediaProfileReader.getWMAEnable(); 61 boolean hasFailed = false; 62 boolean supportWMV = MediaProfileReader.getWMVEnable(); 63 for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) { 64 try { 65 Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]); 66 if ((MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wma") && !supportWMA) 67 || (MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wmv") && !supportWMV)) { 68 Log.v( 69 TAG, 70 "windows media is not supported and thus we will skip the test for this" 71 + " file"); 72 continue; 73 } 74 retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]); 75 byte[] albumArt = retriever.getEmbeddedPicture(); 76 77 // TODO: 78 // A better test would be to compare the retrieved album art with the 79 // known result. 80 if (albumArt == null) { // Do we have expect in JUnit? 81 Log.e( 82 TAG, 83 "Fails to get embedded picture for " 84 + MediaNames.ALBUMART_TEST_FILES[i]); 85 hasFailed = true; 86 } 87 } catch (Exception e) { 88 Log.e(TAG, "Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i]); 89 hasFailed = true; 90 } 91 Thread.yield(); // Don't be evil 92 } 93 retriever.release(); 94 Log.v(TAG, "testGetEmbeddedPicture completes."); 95 assertTrue(!hasFailed); 96 } 97 98 // Test frame capture 99 @LargeTest 100 @Test testThumbnailCapture()101 public void testThumbnailCapture() throws Exception { 102 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 103 boolean supportWMA = MediaProfileReader.getWMAEnable(); 104 boolean supportWMV = MediaProfileReader.getWMVEnable(); 105 boolean hasFailed = false; 106 Log.v(TAG, "Thumbnail processing starts"); 107 long startedAt = System.currentTimeMillis(); 108 for (int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) { 109 try { 110 Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 111 if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) 112 || (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") 113 && !supportWMV)) { 114 Log.v( 115 TAG, 116 "windows media is not supported and thus we will skip the test for this" 117 + " file"); 118 continue; 119 } 120 retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 121 Bitmap bitmap = retriever.getFrameAtTime(-1); 122 assertTrue(bitmap != null); 123 try { 124 java.io.OutputStream stream = 125 new FileOutputStream( 126 MediaNames.THUMBNAIL_METADATA_TEST_FILES[i] + ".jpg"); 127 bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream); 128 stream.close(); 129 } catch (Exception e) { 130 Log.e( 131 TAG, 132 "Fails to convert the bitmap to a JPEG file for " 133 + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 134 hasFailed = true; 135 Log.e(TAG, e.toString()); 136 } 137 } catch (Exception e) { 138 Log.e( 139 TAG, 140 "Fails to setDataSource for file " 141 + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 142 hasFailed = true; 143 } 144 Thread.yield(); // Don't be evil 145 } 146 long endedAt = System.currentTimeMillis(); 147 retriever.release(); 148 assertTrue(!hasFailed); 149 Log.v( 150 TAG, 151 "Average processing time per thumbnail: " 152 + (endedAt - startedAt) / MediaNames.THUMBNAIL_METADATA_TEST_FILES.length 153 + " ms"); 154 } 155 156 @LargeTest 157 @Test testMetadataRetrieval()158 public void testMetadataRetrieval() throws Exception { 159 boolean supportWMA = MediaProfileReader.getWMAEnable(); 160 boolean supportWMV = MediaProfileReader.getWMVEnable(); 161 boolean hasFailed = false; 162 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 163 for (int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) { 164 try { 165 Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 166 if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) 167 || (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") 168 && !supportWMV)) { 169 Log.v( 170 TAG, 171 "windows media is not supported and thus we will skip the test for this" 172 + " file"); 173 continue; 174 } 175 retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 176 extractAllSupportedMetadataValues(retriever); 177 } catch (Exception e) { 178 Log.e( 179 TAG, 180 "Fails to setDataSource for file " 181 + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]); 182 hasFailed = true; 183 } 184 Thread.yield(); // Don't be evil 185 } 186 retriever.release(); 187 assertTrue(!hasFailed); 188 } 189 190 // If the specified call order and valid media file is used, no exception 191 // should be thrown. 192 @MediumTest 193 @Test testBasicNormalMethodCallSequence()194 public void testBasicNormalMethodCallSequence() throws Exception { 195 boolean hasFailed = false; 196 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 197 try { 198 retriever.setDataSource(MediaNames.TEST_PATH_1); 199 Bitmap bitmap = retriever.getFrameAtTime(-1); 200 assertTrue(bitmap != null); 201 try { 202 java.io.OutputStream stream = new FileOutputStream("/sdcard/thumbnailout.jpg"); 203 bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream); 204 stream.close(); 205 } catch (Exception e) { 206 throw new Exception( 207 "Fails to convert the bitmap to a JPEG file for " + MediaNames.TEST_PATH_1, 208 e); 209 } 210 extractAllSupportedMetadataValues(retriever); 211 } catch (Exception e) { 212 Log.e(TAG, "Fails to setDataSource for " + MediaNames.TEST_PATH_1, e); 213 hasFailed = true; 214 } 215 retriever.release(); 216 assertTrue(!hasFailed); 217 } 218 219 // If setDataSource() has not been called, both getFrameAtTime() and extractMetadata() must 220 // return null. 221 @MediumTest 222 @Test testBasicAbnormalMethodCallSequence()223 public void testBasicAbnormalMethodCallSequence() { 224 boolean hasFailed = false; 225 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 226 if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) { 227 Log.e(TAG, "No album metadata expected, but is available"); 228 hasFailed = true; 229 } 230 if (retriever.getFrameAtTime(-1) != null) { 231 Log.e(TAG, "No frame expected, but is available"); 232 hasFailed = true; 233 } 234 assertTrue(!hasFailed); 235 } 236 237 // Test setDataSource() 238 @MediumTest 239 @Test testSetDataSource()240 public void testSetDataSource() throws IOException { 241 MediaMetadataRetriever retriever = new MediaMetadataRetriever(); 242 boolean hasFailed = false; 243 244 // Null pointer argument 245 try { 246 String path = null; 247 retriever.setDataSource(path); 248 Log.e(TAG, "IllegalArgumentException failed to be thrown."); 249 hasFailed = true; 250 } catch (Exception e) { 251 if (!(e instanceof IllegalArgumentException)) { 252 Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception"); 253 hasFailed = true; 254 } 255 } 256 257 // Use mem:// path 258 try { 259 retriever.setDataSource(MediaNames.TEST_PATH_5); 260 Log.e(TAG, "IllegalArgumentException failed to be thrown."); 261 hasFailed = true; 262 } catch (Exception e) { 263 if (!(e instanceof IllegalArgumentException)) { 264 Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception"); 265 hasFailed = true; 266 } 267 } 268 269 // The pathname does not correspond to any existing file 270 try { 271 retriever.setDataSource(MediaNames.TEST_PATH_4); 272 Log.e(TAG, "RuntimeException failed to be thrown."); 273 hasFailed = true; 274 } catch (Exception e) { 275 if (!(e instanceof RuntimeException)) { 276 Log.e(TAG, "Expected a RuntimeException, but got a different exception"); 277 hasFailed = true; 278 } 279 } 280 281 // The pathname does correspond to a file, but this file 282 // is not a valid media file 283 try { 284 retriever.setDataSource(MediaNames.TEST_PATH_3); 285 Log.e(TAG, "RuntimeException failed to be thrown."); 286 hasFailed = true; 287 } catch (Exception e) { 288 if (!(e instanceof RuntimeException)) { 289 Log.e(TAG, "Expected a RuntimeException, but got a different exception"); 290 hasFailed = true; 291 } 292 } 293 294 retriever.release(); 295 assertTrue(!hasFailed); 296 } 297 298 /** Test the thumbnail is generated when the default is set to RGBA8888 */ 299 @MediumTest 300 // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.enableFlags 301 @RequiresFlagsEnabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888) 302 @Test testGetFrameAtTimeWithRGBA8888Flag_Set()303 public void testGetFrameAtTimeWithRGBA8888Flag_Set() throws IOException { 304 try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { 305 retriever.setDataSource(MediaNames.TEST_PATH_1); 306 Bitmap bitmap = retriever.getFrameAtTime(-1); 307 assertNotNull(bitmap); 308 assertEquals(Bitmap.Config.ARGB_8888, bitmap.getConfig()); 309 } 310 } 311 312 /** Test the thumbnail is generated when the default is not set to RGBA8888 */ 313 @MediumTest 314 // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.disableFlags 315 @RequiresFlagsDisabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888) 316 @Test testGetFrameAtTimeWithRGBA8888Flag_Unset()317 public void testGetFrameAtTimeWithRGBA8888Flag_Unset() throws IOException { 318 try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) { 319 retriever.setDataSource(MediaNames.TEST_PATH_1); 320 Bitmap bitmap = retriever.getFrameAtTime(-1); 321 assertNotNull(bitmap); 322 assertEquals(Bitmap.Config.RGB_565, bitmap.getConfig()); 323 } 324 } 325 326 // TODO: 327 // Encode and test for the correct mix of metadata elements on a per-file basis? 328 // We should be able to compare the actual returned metadata with the expected metadata 329 // with each given sample test file. extractAllSupportedMetadataValues(MediaMetadataRetriever retriever)330 private static void extractAllSupportedMetadataValues(MediaMetadataRetriever retriever) { 331 int[] metadataRetrieverKeys = 332 new int[] { 333 MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, 334 MediaMetadataRetriever.METADATA_KEY_DURATION, 335 MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS, 336 MediaMetadataRetriever.METADATA_KEY_ALBUM, 337 MediaMetadataRetriever.METADATA_KEY_ARTIST, 338 MediaMetadataRetriever.METADATA_KEY_AUTHOR, 339 MediaMetadataRetriever.METADATA_KEY_COMPOSER, 340 MediaMetadataRetriever.METADATA_KEY_DATE, 341 MediaMetadataRetriever.METADATA_KEY_GENRE, 342 MediaMetadataRetriever.METADATA_KEY_TITLE, 343 MediaMetadataRetriever.METADATA_KEY_YEAR 344 }; 345 for (int metadataRetrieverKey : metadataRetrieverKeys) { 346 String value = retriever.extractMetadata(metadataRetrieverKey); 347 Log.v(TAG, value == null ? "not found" : value); 348 } 349 } 350 } 351