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
28public class MediaMetadataRetrieverTest extends AndroidTestCase {
29
30    private static final String TAG         = "MediaMetadataRetrieverTest";
31
32    // Test album art extraction.
33    @MediumTest
34    public static void testGetEmbeddedPicture() throws Exception {
35        Log.v(TAG, "testGetEmbeddedPicture starts.");
36        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
37        boolean supportWMA = MediaProfileReader.getWMAEnable();
38        boolean hasFailed = false;
39        boolean supportWMV = MediaProfileReader.getWMVEnable();
40        for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
41            try {
42                Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]);
43                if ((MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
44                    (MediaNames.ALBUMART_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
45                   ) {
46                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
47                    continue;
48                }
49                retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]);
50                byte[] albumArt = retriever.getEmbeddedPicture();
51
52                // TODO:
53                // A better test would be to compare the retrieved album art with the
54                // known result.
55                if (albumArt == null) {  // Do we have expect in JUnit?
56                    Log.e(TAG, "Fails to get embedded picture for " + MediaNames.ALBUMART_TEST_FILES[i]);
57                    hasFailed = true;
58                }
59            } catch(Exception e) {
60                Log.e(TAG, "Fails to setDataSource for " + MediaNames.ALBUMART_TEST_FILES[i]);
61                hasFailed = true;
62            }
63            Thread.yield();  // Don't be evil
64        }
65        retriever.release();
66        Log.v(TAG, "testGetEmbeddedPicture completes.");
67        assertTrue(!hasFailed);
68    }
69
70    // Test frame capture
71    @LargeTest
72    public static void testThumbnailCapture() throws Exception {
73        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
74        boolean supportWMA = MediaProfileReader.getWMAEnable();
75        boolean supportWMV = MediaProfileReader.getWMVEnable();
76        boolean hasFailed = false;
77        Log.v(TAG, "Thumbnail processing starts");
78        long startedAt = System.currentTimeMillis();
79        for(int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) {
80            try {
81                Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
82                if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
83                    (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
84                   ) {
85                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
86                    continue;
87                }
88                retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
89                Bitmap bitmap = retriever.getFrameAtTime(-1);
90                assertTrue(bitmap != null);
91                try {
92                    java.io.OutputStream stream = new FileOutputStream(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i] + ".jpg");
93                    bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
94                    stream.close();
95                } catch (Exception e) {
96                    Log.e(TAG, "Fails to convert the bitmap to a JPEG file for " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
97                    hasFailed = true;
98                    Log.e(TAG, e.toString());
99                }
100            } catch(Exception e) {
101                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
102                hasFailed = true;
103            }
104            Thread.yield();  // Don't be evil
105        }
106        long endedAt = System.currentTimeMillis();
107        retriever.release();
108        assertTrue(!hasFailed);
109        Log.v(TAG, "Average processing time per thumbnail: " + (endedAt - startedAt)/MediaNames.THUMBNAIL_METADATA_TEST_FILES.length + " ms");
110    }
111
112    @LargeTest
113    public static void testMetadataRetrieval() throws Exception {
114        boolean supportWMA = MediaProfileReader.getWMAEnable();
115        boolean supportWMV = MediaProfileReader.getWMVEnable();
116        boolean hasFailed = false;
117        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
118        for(int i = 0, n = MediaNames.THUMBNAIL_METADATA_TEST_FILES.length; i < n; ++i) {
119            try {
120                Log.v(TAG, "File " + i + ": " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
121                if ((MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wma") && !supportWMA) ||
122                    (MediaNames.THUMBNAIL_METADATA_TEST_FILES[i].endsWith(".wmv") && !supportWMV)
123                   ) {
124                    Log.v(TAG, "windows media is not supported and thus we will skip the test for this file");
125                    continue;
126                }
127                retriever.setDataSource(MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
128                extractAllSupportedMetadataValues(retriever);
129            } catch(Exception e) {
130                Log.e(TAG, "Fails to setDataSource for file " + MediaNames.THUMBNAIL_METADATA_TEST_FILES[i]);
131                hasFailed = true;
132            }
133            Thread.yield();  // Don't be evil
134        }
135        retriever.release();
136        assertTrue(!hasFailed);
137    }
138
139    // If the specified call order and valid media file is used, no exception
140    // should be thrown.
141    @MediumTest
142    public static void testBasicNormalMethodCallSequence() throws Exception {
143        boolean hasFailed = false;
144        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
145        try {
146            retriever.setDataSource(MediaNames.TEST_PATH_1);
147            Bitmap bitmap = retriever.getFrameAtTime(-1);
148            assertTrue(bitmap != null);
149            try {
150                java.io.OutputStream stream = new FileOutputStream("/sdcard/thumbnailout.jpg");
151                bitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
152                stream.close();
153            } catch (Exception e) {
154                throw new Exception("Fails to convert the bitmap to a JPEG file for " + MediaNames.TEST_PATH_1, e);
155            }
156            extractAllSupportedMetadataValues(retriever);
157        } catch(Exception e) {
158            Log.e(TAG, "Fails to setDataSource for " + MediaNames.TEST_PATH_1, e);
159            hasFailed = true;
160        }
161        retriever.release();
162        assertTrue(!hasFailed);
163    }
164
165    // If setDataSource() has not been called, both getFrameAtTime() and extractMetadata() must
166    // return null.
167    @MediumTest
168    public static void testBasicAbnormalMethodCallSequence() {
169        boolean hasFailed = false;
170        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
171        if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) {
172            Log.e(TAG, "No album metadata expected, but is available");
173            hasFailed = true;
174        }
175        if (retriever.getFrameAtTime(-1) != null) {
176            Log.e(TAG, "No frame expected, but is available");
177            hasFailed = true;
178        }
179        assertTrue(!hasFailed);
180    }
181
182    // Test setDataSource()
183    @MediumTest
184    public static void testSetDataSource() {
185        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
186        boolean hasFailed = false;
187
188        // Null pointer argument
189        try {
190            String path = null;
191            retriever.setDataSource(path);
192            Log.e(TAG, "IllegalArgumentException failed to be thrown.");
193            hasFailed = true;
194        } catch(Exception e) {
195            if (!(e instanceof IllegalArgumentException)) {
196                Log.e(TAG, "Expected a IllegalArgumentException, but got a different exception");
197                hasFailed = true;
198            }
199        }
200
201        // Use mem:// path
202        try {
203            retriever.setDataSource(MediaNames.TEST_PATH_5);
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        // The pathname does not correspond to any existing file
214        try {
215            retriever.setDataSource(MediaNames.TEST_PATH_4);
216            Log.e(TAG, "RuntimeException failed to be thrown.");
217            hasFailed = true;
218        } catch(Exception e) {
219            if (!(e instanceof RuntimeException)) {
220                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
221                hasFailed = true;
222            }
223        }
224
225        // The pathname does correspond to a file, but this file
226        // is not a valid media file
227        try {
228            retriever.setDataSource(MediaNames.TEST_PATH_3);
229            Log.e(TAG, "RuntimeException failed to be thrown.");
230            hasFailed = true;
231        } catch(Exception e) {
232            if (!(e instanceof RuntimeException)) {
233                Log.e(TAG, "Expected a RuntimeException, but got a different exception");
234                hasFailed = true;
235            }
236        }
237
238        retriever.release();
239        assertTrue(!hasFailed);
240    }
241
242    // TODO:
243    // Encode and test for the correct mix of metadata elements on a per-file basis?
244    // We should be able to compare the actual returned metadata with the expected metadata
245    // with each given sample test file.
246    private static void extractAllSupportedMetadataValues(MediaMetadataRetriever retriever) {
247        String value = null;
248        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER)) == null? "not found": value);
249        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)) == null? "not found": value);
250        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS)) == null? "not found": value);
251        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)) == null? "not found": value);
252        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)) == null? "not found": value);
253        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR)) == null? "not found": value);
254        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER)) == null? "not found": value);
255        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)) == null? "not found": value);
256        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)) == null? "not found": value);
257        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)) == null? "not found": value);
258        Log.v(TAG, (value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR)) == null? "not found": value);
259    }
260}
261