MediaMetadataRetrieverTest.java revision 454f69c84c294b8e0875788653a9c7d4fd80b233
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
17package com.android.mediaframeworktest.unit;
18
19import android.util.Log;
20import android.media.MediaMetadataRetriever;
21import android.graphics.Bitmap;
22import java.io.FileOutputStream;
23import android.test.AndroidTestCase;
24import com.android.mediaframeworktest.MediaNames;
25import com.android.mediaframeworktest.MediaProfileReader;
26import android.test.suitebuilder.annotation.*;
27
28/**
29 * WARNING:
30 * Currently, captureFrame() does not work, due to hardware access permission problem.
31 * We are currently only testing the metadata/album art retrieval features.
32 */
33public class MediaMetadataRetrieverTest extends AndroidTestCase {
34
35    private static final String TAG         = "MediaMetadataRetrieverTest";
36
37    // Test album art extraction.
38    @MediumTest
39    public static void testAlbumArt() throws Exception {
40        Log.v(TAG, "testAlbumArt starts.");
41        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
42        boolean supportWMA = MediaProfileReader.getWMAEnable();
43        boolean hasFailed = false;
44        boolean supportWMV = MediaProfileReader.getWMVEnable();
45        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
46        for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
47            try {
48                Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]);
49                if ((MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
50                    (MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
51                   ) {
52                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
53                    continue;
54                }
55                retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]);
56                byte[] albumArt = retriever.extractAlbumArt();
57
58                // TODO:
59                // A better test would be to compare the retrieved album art with the
60                // known result.
61                if (albumArt == null) {  // Do we have expect in JUnit?
62                    Log.e(TAG, "Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]);
63                    hasFailed = true;
64                }
65            } catch(Exception e) {
66                Log.e(TAG, "Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i]);
67                hasFailed = true;
68            }
69            Thread.yield();  // Don't be evil
70        }
71        retriever.release();
72        Log.v(TAG, "testAlbumArt completes.");
73        assertTrue(!hasFailed);
74    }
75
76    // Test frame capture
77    @LargeTest
78    public static void testThumbnailCapture() throws Exception {
79        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
80        boolean supportWMA = MediaProfileReader.getWMAEnable();
81        boolean supportWMV = MediaProfileReader.getWMVEnable();
82        boolean hasFailed = false;
83        Log.v(TAG, "Thumbnail processing starts");
84        long startedAt = System.currentTimeMillis();
85        for(int i = 0, n = MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length; i < n; ++i) {
86            try {
87                Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
88                if ((MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
89                    (MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
90                   ) {
91                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
92                    continue;
93                }
94                retriever.setDataSource(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
95                Bitmap bitmap = retriever.captureFrame();
96                assertTrue(bitmap != null);
97                try {
98                    java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i] + ".jpg");
99                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
100                    stream.close();
101                } catch (Exception e) {
102                    Log.e(TAG, "Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
103                    hasFailed = true;
104                }
105            } catch(Exception e) {
106                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_CAPTURE_TEST_FILES[i]);
107                hasFailed = true;
108            }
109            Thread.yield();  // Don't be evil
110        }
111        long endedAt = System.currentTimeMillis();
112        retriever.release();
113        assertTrue(!hasFailed);
114        Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_CAPTURE_TEST_FILES.length + " ms");
115    }
116
117    @LargeTest
118    public static void testMetadataRetrieval() throws Exception {
119        boolean supportWMA = MediaProfileReader.getWMAEnable();
120        boolean supportWMV = MediaProfileReader.getWMVEnable();
121        boolean hasFailed = false;
122        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
123        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
124        for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
125            try {
126                Log.v(TAG, "File " + i + ": " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
127                if ((MediaNames.METADATA_RETRIEVAL_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
128                    (MediaNames.METADATA_RETRIEVAL_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
129                   ) {
130                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
131                    continue;
132                }
133                retriever.setDataSource(MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
134                extractAllSupportedMetadataValues(retriever);
135            } catch(Exception e) {
136                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
137                hasFailed = true;
138            }
139            Thread.yield();  // Don't be evil
140        }
141        retriever.release();
142        assertTrue(!hasFailed);
143    }
144
145    // If the specified call order and valid media file is used, no exception
146    // should be thrown.
147    @MediumTest
148    public static void testBasicNormalMethodCallSequence() throws Exception {
149        boolean hasFailed = false;
150        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
151        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
152        try {
153            retriever.setDataSource(MediaNames.TEST_PATH_1);
154            /*
155             * captureFrame() fails due to lack of permission to access hardware decoder devices
156            Bitmap bitmap = retriever.captureFrame();
157            assertTrue(bitmap != null);
158            try {
159                java.io.OutputStream stream = new FileOutputStream("/sdcard/thumbnailout.jpg");
160                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
161                stream.close();
162            } catch (Exception e) {
163                throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.TEST_PATH_1, e);
164            }
165            */
166            extractAllSupportedMetadataValues(retriever);
167        } catch(Exception e) {
168            Log.e(TAG, "Fails to setDataSource for " + MediaNames.TEST_PATH_1, e);
169            hasFailed = true;
170        }
171        retriever.release();
172        assertTrue(!hasFailed);
173    }
174
175    // If setDataSource() has not been called, both captureFrame() and extractMetadata() must
176    // return null.
177    @MediumTest
178    public static void testBasicAbnormalMethodCallSequence() {
179        boolean hasFailed = false;
180        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
181        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
182        if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) {
183            Log.e(TAG, "No album metadata expected, but is available");
184            hasFailed = true;
185        }
186        if (retriever.captureFrame() != null) {
187            Log.e(TAG, "No frame expected, but is available");
188            hasFailed = true;
189        }
190        assertTrue(!hasFailed);
191    }
192
193    // Test setDataSource()
194    @MediumTest
195    public static void testSetDataSource() {
196        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
197        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
198        boolean hasFailed = false;
199
200        // Null pointer argument
201        try {
202            String path = null;
203            retriever.setDataSource(path);
204            Log.e(TAG, "IllegalArgumentException failed to be thrown.");
205            hasFailed = true;
206        } catch(Exception e) {
207            if (!(e instanceof IllegalArgumentException)) {
208                Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception");
209                hasFailed = true;
210            }
211        }
212
213        // Use mem:// path
214        try {
215            retriever.setDataSource(MediaNames.TEST_PATH_5);
216            Log.e(TAG, "IllegalArgumentException failed to be thrown.");
217            hasFailed = true;
218        } catch(Exception e) {
219            if (!(e instanceof IllegalArgumentException)) {
220                Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception");
221                hasFailed = true;
222            }
223        }
224
225        // The pathname does not correspond to any existing file
226        try {
227            retriever.setDataSource(MediaNames.TEST_PATH_4);
228            Log.e(TAG, "RuntimeException failed to be thrown.");
229            hasFailed = true;
230        } catch(Exception e) {
231            if (!(e instanceof RuntimeException)) {
232                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
233                hasFailed = true;
234            }
235        }
236
237        // The pathname does correspond to a file, but this file
238        // is not a valid media file
239        try {
240            retriever.setDataSource(MediaNames.TEST_PATH_3);
241            Log.e(TAG, "RuntimeException failed to be thrown.");
242            hasFailed = true;
243        } catch(Exception e) {
244            if (!(e instanceof RuntimeException)) {
245                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
246                hasFailed = true;
247            }
248        }
249
250        retriever.release();
251        assertTrue(!hasFailed);
252    }
253
254    // Due to the lack of permission to access hardware decoder, any calls
255    // attempting to capture a frame will fail. These are commented out for now
256    // until we find a solution to this access permission problem.
257    @MediumTest
258    public static void testIntendedUsage() {
259        // By default, capture frame and retrieve metadata
260        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
261        boolean hasFailed = false;
262        // retriever.setDataSource(MediaNames.TEST_PATH_1);
263        // assertTrue(retriever.captureFrame() != null);
264        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
265
266        // Do not capture frame or retrieve metadata
267        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY & MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
268        retriever.setDataSource(MediaNames.TEST_PATH_1);
269        if (retriever.captureFrame() != null) {
270            Log.e(TAG, "No frame expected, but is available");
271            hasFailed = true;
272        }
273        if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null) {
274            Log.e(TAG, "No num track metadata expected, but is available");
275            hasFailed = true;
276        }
277
278        // Capture frame only
279        // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
280        // retriever.setDataSource(MediaNames.TEST_PATH_1);
281        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null);
282
283        // Retriever metadata only
284        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
285        retriever.setDataSource(MediaNames.TEST_PATH_1);
286        if (retriever.captureFrame() != null) {
287            Log.e(TAG, "No frame expected, but is available");
288            hasFailed = true;
289        }
290
291        // Capture frame and retrieve metadata
292        // retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY | MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
293        // retriever.setDataSource(MediaNames.TEST_PATH_1);
294        // assertTrue(retriever.captureFrame() != null);
295        // assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
296        retriever.release();
297        assertTrue(!hasFailed);
298    }
299
300    // TODO:
301    // Encode and test for the correct mix of metadata elements on a per-file basis?
302    // We should be able to compare the actual returned metadata with the expected metadata
303    // with each given sample test file.
304    private static void extractAllSupportedMetadataValues(MediaMetadataRetriever retriever) {
305        String value = null;
306        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER)) == null? "not found": value);
307        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) == null? "not found": value);
308        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS)) == null? "not found": value);
309        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)) == null? "not found": value);
310        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)) == null? "not found": value);
311        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR)) == null? "not found": value);
312        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER)) == null? "not found": value);
313        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)) == null? "not found": value);
314        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)) == null? "not found": value);
315        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)) == null? "not found": value);
316        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR)) == null? "not found": value);
317    }
318}
319