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.functional;
18 
19 
20 
21 //import android.content.Resources;
22 import com.android.mediaframeworktest.MediaFrameworkTest;
23 import com.android.mediaframeworktest.MediaNames;
24 
25 import android.content.res.AssetFileDescriptor;
26 import android.graphics.Bitmap;
27 import android.graphics.BitmapFactory;
28 import android.media.MediaCodecInfo;
29 import android.media.MediaCodecList;
30 import android.media.MediaExtractor;
31 import android.media.MediaFormat;
32 import android.media.MediaMetadataRetriever;
33 import android.media.MediaPlayer;
34 import android.media.MediaRecorder;
35 import android.os.Looper;
36 import android.os.SystemClock;
37 import android.util.Log;
38 
39 import java.io.File;
40 import java.io.FileWriter;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.OutputStream;
44 import java.io.Writer;
45 import java.io.FileOutputStream;
46 import java.util.HashSet;
47 import java.util.Random;
48 import java.util.Set;
49 /**
50  * Junit / Instrumentation test case for the media player api
51 
52  */
53 public class CodecTest {
54     private static String TAG = "CodecTest";
55     private static MediaPlayer mMediaPlayer;
56     private MediaPlayer.OnPreparedListener mOnPreparedListener;
57 
58     private static int WAIT_FOR_COMMAND_TO_COMPLETE = 60000;  //1 min max.
59     private static boolean mInitialized = false;
60     private static boolean mPrepareReset = false;
61     private static Looper mLooper = null;
62     private static final Object lock = new Object();
63     private static final Object prepareDone = new Object();
64     private static final Object videoSizeChanged = new Object();
65     private static final Object onCompletion = new Object();
66     private static boolean onPrepareSuccess = false;
67     public static boolean onCompleteSuccess = false;
68     public static boolean mPlaybackError = false;
69     public static boolean mFailedToCompleteWithNoError = true;
70     public static int mMediaInfoUnknownCount = 0;
71     public static int mMediaInfoVideoTrackLaggingCount = 0;
72     public static int mMediaInfoBadInterleavingCount = 0;
73     public static int mMediaInfoNotSeekableCount = 0;
74     public static int mMediaInfoMetdataUpdateCount = 0;
75     private static Set<String> mSupportedTypes = new HashSet<>();
76 
printCpuInfo()77     public static String printCpuInfo(){
78         String cm = "dumpsys cpuinfo";
79         String cpuinfo =null;
80         int ch;
81         try{
82             Process  p = Runtime.getRuntime().exec(cm);
83             InputStream in = p.getInputStream();
84             StringBuffer sb = new StringBuffer(512);
85             while ( ( ch = in.read() ) != -1 ){
86                 sb.append((char) ch);
87             }
88             cpuinfo = sb.toString();
89         }catch (IOException e){
90             Log.v(TAG, e.toString());
91         }
92         return cpuinfo;
93     }
94 
95 
getDuration(String filePath)96     public static int getDuration(String filePath) {
97         Log.v(TAG, "getDuration - " + filePath);
98         MediaPlayer mp = new MediaPlayer();
99         try{
100             mp.setDataSource(filePath);
101             mp.prepare();
102         }catch (Exception e){
103             Log.v(TAG, e.toString());
104         }
105         int duration = mp.getDuration();
106         Log.v(TAG, "Duration " + duration);
107         mp.release();
108         Log.v(TAG, "release");
109         return duration;
110     }
111 
getCurrentPosition(String filePath)112     public static boolean getCurrentPosition(String filePath){
113         Log.v(TAG, "GetCurrentPosition - " + filePath);
114         int currentPosition = 0;
115         long t1=0;
116         long t2 =0;
117         MediaPlayer mp = new MediaPlayer();
118         try{
119             mp.setDataSource(filePath);
120             Log.v(TAG, "start playback");
121             mp.prepare();
122             mp.start();
123             t1=SystemClock.uptimeMillis();
124             Thread.sleep(10000);
125             mp.pause();
126             Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
127             t2=SystemClock.uptimeMillis();
128         }catch (Exception e){
129             Log.v(TAG, e.toString());
130         }
131         currentPosition = mp.getCurrentPosition();
132         mp.stop();
133         mp.release();
134         Log.v(TAG, "mp currentPositon = " + currentPosition + " play duration = " + (t2-t1));
135         //The currentposition should be within 10% of the sleep time
136         //For the very short mp3, it should return the length instead of 10 seconds
137         if (filePath.equals(MediaNames.SHORTMP3)){
138             if (currentPosition < 1000 )
139                 return true;
140         }
141         if ((currentPosition < ((t2-t1) *1.2)) && (currentPosition > 0))
142             return true;
143         else
144             return false;
145     }
146 
seekTo(String filePath)147     public static boolean seekTo(String filePath){
148         Log.v(TAG, "seekTo " + filePath);
149         int currentPosition = 0;
150         MediaPlayer mp = new MediaPlayer();
151         try{
152             mp.setDataSource(filePath);
153             mp.prepare();
154             mp.start();
155             mp.seekTo(MediaNames.SEEK_TIME);
156             Thread.sleep(MediaNames.WAIT_TIME);
157             currentPosition = mp.getCurrentPosition();
158         }catch (Exception e){
159             Log.v(TAG, e.getMessage());
160         }
161         mp.stop();
162         mp.release();
163         Log.v(TAG, "CurrentPosition = " + currentPosition);
164         //The currentposition should be at least greater than the 80% of seek time
165         if ((currentPosition > MediaNames.SEEK_TIME *0.8))
166             return true;
167         else
168             return false;
169     }
170 
setLooping(String filePath)171     public static boolean setLooping(String filePath){
172         int currentPosition = 0;
173         int duration = 0;
174         long t1 =0;
175         long t2 =0;
176         Log.v (TAG, "SetLooping - " + filePath);
177         MediaPlayer mp = new MediaPlayer();
178         try{
179             mp.setDataSource(filePath);
180             mp.prepare();
181             duration = mp.getDuration();
182             Log.v(TAG, "setLooping duration " + duration);
183             mp.setLooping(true);
184             mp.start();
185             Thread.sleep(5000);
186             mp.seekTo(duration - 5000);
187             t1=SystemClock.uptimeMillis();
188             Thread.sleep(20000);
189             t2=SystemClock.uptimeMillis();
190             Log.v(TAG, "pause");
191             //Bug# 1106852 - IllegalStateException will be thrown if pause is called
192             //in here
193             //mp.pause();
194             currentPosition = mp.getCurrentPosition();
195             Log.v(TAG, "looping position " + currentPosition + "duration = " + (t2-t1));
196         }catch (Exception e){
197             Log.v(TAG, "Exception : " + e.toString());
198         }
199         mp.stop();
200         mp.release();
201         //The current position should be within 20% of the sleep time
202         //and should be greater than zero.
203         if ((currentPosition < ((t2-t1-5000)*1.2)) && currentPosition > 0)
204             return true;
205         else
206             return false;
207     }
208 
pause(String filePath)209     public static boolean pause(String filePath) throws Exception {
210         Log.v(TAG, "pause - " + filePath);
211         boolean misPlaying = true;
212         boolean pauseResult = false;
213         long t1=0;
214         long t2=0;
215         MediaPlayer mp = new MediaPlayer();
216         mp.setDataSource(filePath);
217         mp.prepare();
218         int duration = mp.getDuration();
219         mp.start();
220         t1=SystemClock.uptimeMillis();
221         Thread.sleep(5000);
222         mp.pause();
223         Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
224         t2=SystemClock.uptimeMillis();
225         misPlaying = mp.isPlaying();
226         int curPosition = mp.getCurrentPosition();
227         Log.v(TAG, filePath + " pause currentPositon " + curPosition);
228         Log.v(TAG, "isPlaying "+ misPlaying + " wait time " + (t2 - t1) );
229         String cpuinfo = printCpuInfo();
230         Log.v(TAG, cpuinfo);
231         if ((curPosition>0) && (curPosition < ((t2-t1) * 1.3)) && (misPlaying == false))
232             pauseResult = true;
233         mp.stop();
234         mp.release();
235         return pauseResult;
236     }
237 
prepareStopRelease(String filePath)238     public static void prepareStopRelease(String filePath) throws Exception {
239         Log.v(TAG, "prepareStopRelease" + filePath);
240         MediaPlayer mp = new MediaPlayer();
241         mp.setDataSource(filePath);
242         mp.prepare();
243         mp.stop();
244         mp.release();
245     }
246 
preparePauseRelease(String filePath)247     public static void preparePauseRelease(String filePath) throws Exception {
248         Log.v(TAG, "preparePauseRelease" + filePath);
249         MediaPlayer mp = new MediaPlayer();
250         mp.setDataSource(filePath);
251         mp.prepare();
252         mp.pause();
253         mp.release();
254     }
255 
256     static MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener =
257         new MediaPlayer.OnVideoSizeChangedListener() {
258             public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
259                 synchronized (videoSizeChanged) {
260                     Log.v(TAG, "sizechanged notification received ...");
261                     videoSizeChanged.notify();
262                 }
263             }
264     };
265 
266     //Register the videoSizeChanged listener
videoHeight(String filePath)267     public static int videoHeight(String filePath) throws Exception {
268         Log.v(TAG, "videoHeight - " + filePath);
269         int videoHeight = 0;
270         synchronized (lock) {
271             initializeMessageLooper();
272             try {
273                 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
274             } catch(Exception e) {
275                 Log.v(TAG, "looper was interrupted.");
276                 return 0;
277             }
278         }
279         try {
280             mMediaPlayer.setDataSource(filePath);
281             mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
282             mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
283             synchronized (videoSizeChanged) {
284                 try {
285                     mMediaPlayer.prepare();
286                     mMediaPlayer.start();
287                     videoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
288                 } catch (Exception e) {
289                     Log.v(TAG, "wait was interrupted");
290                 }
291             }
292             videoHeight = mMediaPlayer.getVideoHeight();
293             terminateMessageLooper();
294         } catch (Exception e) {
295             Log.e(TAG, e.getMessage());
296         }
297 
298         return videoHeight;
299     }
300 
301     //Register the videoSizeChanged listener
videoWidth(String filePath)302     public static int videoWidth(String filePath) throws Exception {
303         Log.v(TAG, "videoWidth - " + filePath);
304         int videoWidth = 0;
305 
306         synchronized (lock) {
307             initializeMessageLooper();
308             try {
309                 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
310             } catch(Exception e) {
311                 Log.v(TAG, "looper was interrupted.");
312                 return 0;
313             }
314         }
315         try {
316             mMediaPlayer.setDataSource(filePath);
317             mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
318             mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
319             synchronized (videoSizeChanged) {
320                 try {
321                     mMediaPlayer.prepare();
322                     mMediaPlayer.start();
323                     videoSizeChanged.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
324                 } catch (Exception e) {
325                     Log.v(TAG, "wait was interrupted");
326                 }
327             }
328             videoWidth = mMediaPlayer.getVideoWidth();
329             terminateMessageLooper();
330         } catch (Exception e) {
331             Log.e(TAG, e.getMessage());
332         }
333         return videoWidth;
334     }
335 
336     //This also test the streaming video which may take a long
337     //time to start the playback.
videoSeekTo(String filePath)338     public static boolean videoSeekTo(String filePath) throws Exception {
339         Log.v(TAG, "videoSeekTo - " + filePath);
340         int currentPosition = 0;
341         int duration = 0;
342         boolean videoResult = false;
343         MediaPlayer mp = new MediaPlayer();
344         mp.setDataSource(filePath);
345         mp.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
346         mp.prepare();
347         mp.start();
348         if (filePath.equals(MediaNames.VIDEO_SHORT_3GP)){
349             mp.pause();
350             Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
351             mp.seekTo(0);
352             mp.start();
353             Thread.sleep(1000);
354             currentPosition = mp.getCurrentPosition();
355             Log.v(TAG,"short position " + currentPosition);
356             if (currentPosition > 100 )
357                 return true;
358             else
359                 return false;
360         }
361         Thread.sleep(5000);
362         duration = mp.getDuration();
363         Log.v(TAG, "video duration " + duration);
364         mp.pause();
365         Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
366         mp.seekTo(duration - 20000 );
367         mp.start();
368         Thread.sleep(1000);
369         mp.pause();
370         Thread.sleep(MediaNames.PAUSE_WAIT_TIME);
371         mp.seekTo(duration/2);
372         mp.start();
373         Thread.sleep(10000);
374         currentPosition = mp.getCurrentPosition();
375         Log.v(TAG, "video currentPosition " + currentPosition);
376         mp.release();
377         if (currentPosition > (duration /2 )*0.9)
378             return true;
379         else
380             return false;
381 
382     }
383 
seekToEnd(String filePath)384     public static boolean seekToEnd(String filePath){
385         Log.v(TAG, "seekToEnd - " + filePath);
386         int duration = 0;
387         int currentPosition = 0;
388         boolean isPlaying = false;
389         MediaPlayer mp = new MediaPlayer();
390         try{
391             mp.setDataSource(filePath);
392             Log.v(TAG, "start playback");
393             mp.prepare();
394             duration = mp.getDuration();
395             mp.seekTo(duration - 3000);
396             mp.start();
397             Thread.sleep(6000);
398         }catch (Exception e){}
399         isPlaying = mp.isPlaying();
400         currentPosition = mp.getCurrentPosition();
401         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
402         mp.stop();
403         mp.release();
404         Log.v(TAG, "duration = " + duration);
405         if (currentPosition < 0.9 * duration || isPlaying)
406             return false;
407         else
408             return true;
409     }
410 
shortMediaStop(String filePath)411     public static boolean shortMediaStop(String filePath){
412         Log.v(TAG, "shortMediaStop - " + filePath);
413         //This test is only for the short media file
414         int duration = 0;
415         int currentPosition = 0;
416         boolean isPlaying = false;
417         MediaPlayer mp = new MediaPlayer();
418         try{
419             mp.setDataSource(filePath);
420             Log.v(TAG, "start playback");
421             mp.prepare();
422             duration = mp.getDuration();
423             mp.start();
424             Thread.sleep(10000);
425         }catch (Exception e){}
426         isPlaying = mp.isPlaying();
427         currentPosition = mp.getCurrentPosition();
428         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
429         mp.stop();
430         mp.release();
431         Log.v(TAG, "duration = " + duration);
432         if (currentPosition > duration || isPlaying)
433             return false;
434         else
435             return true;
436     }
437 
playToEnd(String filePath)438     public static boolean playToEnd(String filePath){
439         Log.v(TAG, "shortMediaStop - " + filePath);
440         //This test is only for the short media file
441         int duration = 200000;
442         int updateDuration = 0;
443         int currentPosition = 0;
444         boolean isPlaying = false;
445         MediaPlayer mp = new MediaPlayer();
446         try{
447             Thread.sleep(5000);
448             mp.setDataSource(filePath);
449             Log.v(TAG, "start playback");
450             mp.prepare();
451             //duration = mp.getDuration();
452             mp.start();
453             Thread.sleep(50000);
454         }catch (Exception e){}
455         isPlaying = mp.isPlaying();
456         currentPosition = mp.getCurrentPosition();
457         //updateDuration = mp.getDuration();
458         Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
459         mp.stop();
460         mp.release();
461         //Log.v(TAG, "duration = " + duration);
462         //Log.v(TAG, "Update duration = " + updateDuration);
463         if (currentPosition > duration || isPlaying)
464             return false;
465         else
466             return true;
467     }
468 
seektoBeforeStart(String filePath)469     public static boolean seektoBeforeStart(String filePath){
470         Log.v(TAG, "seektoBeforeStart - " + filePath);
471         //This test is only for the short media file
472         int duration = 0;
473         int currentPosition = 0;
474 
475         MediaPlayer mp = new MediaPlayer();
476         try{
477             mp.setDataSource(filePath);
478             mp.prepare();
479             duration = mp.getDuration();
480             mp.seekTo(duration - 10000);
481             mp.start();
482             currentPosition=mp.getCurrentPosition();
483             mp.stop();
484             mp.release();
485         }catch (Exception e){}
486         if (currentPosition < duration/2)
487             return false;
488         else
489             return true;
490     }
491 
mediaRecorderRecord(String filePath)492     public static boolean mediaRecorderRecord(String filePath){
493         Log.v(TAG, "SoundRecording - " + filePath);
494         //This test is only for the short media file
495         int duration = 0;
496         try{
497             MediaRecorder mRecorder = new MediaRecorder();
498             mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
499             mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
500             mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
501             mRecorder.setOutputFile(filePath);
502             mRecorder.prepare();
503             mRecorder.start();
504             Thread.sleep(500);
505             mRecorder.stop();
506             Log.v(TAG, "sound recorded");
507             mRecorder.release();
508         }catch (Exception e){
509             Log.v(TAG, e.toString());
510         }
511 
512         //Verify the recorded file
513         MediaPlayer mp = new MediaPlayer();
514         try{
515             mp.setDataSource(filePath);
516             mp.prepare();
517             duration = mp.getDuration();
518             Log.v(TAG,"Duration " + duration);
519             mp.release();
520         }catch (Exception e){}
521         //Check the record media file length is greate than zero
522         if (duration > 0)
523             return true;
524         else
525             return false;
526 
527     }
528 
529     //Test for mediaMeta Data Thumbnail
getThumbnail(String filePath, String goldenPath)530     public static boolean getThumbnail(String filePath, String goldenPath){
531         Log.v(TAG, "getThumbnail - " + filePath);
532 
533         int goldenHeight = 0;
534         int goldenWidth = 0;
535         int outputWidth = 0;
536         int outputHeight = 0;
537 
538         //This test is only for the short media file
539         try{
540             BitmapFactory mBitmapFactory = new BitmapFactory();
541 
542             MediaMetadataRetriever mMediaMetadataRetriever = new MediaMetadataRetriever();
543             try {
544                 mMediaMetadataRetriever.setDataSource(filePath);
545             } catch(Exception e) {
546                 e.printStackTrace();
547                 return false;
548             }
549             Bitmap outThumbnail = mMediaMetadataRetriever.getFrameAtTime(-1);
550 
551             //Verify the thumbnail
552             Bitmap goldenBitmap = mBitmapFactory.decodeFile(goldenPath);
553             outputWidth = outThumbnail.getWidth();
554             outputHeight = outThumbnail.getHeight();
555             goldenHeight = goldenBitmap.getHeight();
556             goldenWidth = goldenBitmap.getWidth();
557 
558             //check the image dimension
559             if ((outputWidth != goldenWidth) || (outputHeight != goldenHeight))
560                 return false;
561 
562             // Check half line of pixel
563             int x = goldenHeight / 2;
564             for (int j = 1; j < goldenWidth / 2; j++) {
565                 if (goldenBitmap.getPixel(x, j) != outThumbnail.getPixel(x, j)) {
566                     Log.v(TAG, "pixel = " + goldenBitmap.getPixel(x, j));
567                     return false;
568                 }
569            }
570         }catch (Exception e){
571             Log.v(TAG, e.toString());
572             return false;
573         }
574         return true;
575     }
576 
577     //Load midi file from resources
resourcesPlayback(AssetFileDescriptor afd, int expectedDuration)578     public static boolean resourcesPlayback(AssetFileDescriptor afd, int expectedDuration){
579         int duration = 0;
580         try{
581             MediaPlayer mp = new MediaPlayer();
582             mp.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
583             mp.prepare();
584             mp.start();
585             duration = mp.getDuration();
586             Thread.sleep(5000);
587             mp.release();
588         }catch (Exception e){
589             Log.v(TAG,e.getMessage());
590         }
591         if (duration > expectedDuration)
592             return true;
593         else
594             return false;
595     }
596 
prepareAsyncReset(String filePath)597     public static boolean prepareAsyncReset(String filePath){
598         //preparesAsync
599         try{
600             MediaPlayer mp = new MediaPlayer();
601             mp.setDataSource(filePath);
602             mp.prepareAsync();
603             mp.reset();
604             mp.release();
605         }catch (Exception e){
606             Log.v(TAG,e.getMessage());
607             return false;
608         }
609         return true;
610     }
611 
612 
isLooping(String filePath)613     public static boolean isLooping(String filePath) {
614         MediaPlayer mp = null;
615 
616         try {
617             mp = new MediaPlayer();
618             if (mp.isLooping()) {
619                 Log.v(TAG, "MediaPlayer.isLooping() returned true after ctor");
620                 return false;
621             }
622             mp.setDataSource(filePath);
623             mp.prepare();
624 
625             mp.setLooping(true);
626             if (!mp.isLooping()) {
627                 Log.v(TAG, "MediaPlayer.isLooping() returned false after setLooping(true)");
628                 return false;
629             }
630 
631             mp.setLooping(false);
632             if (mp.isLooping()) {
633                 Log.v(TAG, "MediaPlayer.isLooping() returned true after setLooping(false)");
634                 return false;
635             }
636         }catch (Exception e){
637             Log.v(TAG, "Exception : " + e.toString());
638             return false;
639         } finally {
640             if (mp != null)
641                 mp.release();
642         }
643 
644         return true;
645     }
646 
isLoopingAfterReset(String filePath)647     public static boolean isLoopingAfterReset(String filePath) {
648         MediaPlayer mp = null;
649         try {
650             mp = new MediaPlayer();
651             mp.setDataSource(filePath);
652             mp.prepare();
653 
654             mp.setLooping(true);
655             mp.reset();
656             if (mp.isLooping()) {
657                 Log.v(TAG, "MediaPlayer.isLooping() returned true after reset()");
658                 return false;
659             }
660         }catch (Exception e){
661             Log.v(TAG, "Exception : " + e.toString());
662             return false;
663         } finally {
664             if (mp != null)
665                 mp.release();
666         }
667 
668         return true;
669     }
670 
671     /*
672      * Initializes the message looper so that the mediaPlayer object can
673      * receive the callback messages.
674      */
initializeMessageLooper()675     private static void initializeMessageLooper() {
676         Log.v(TAG, "start looper");
677         new Thread() {
678             @Override
679             public void run() {
680                 // Set up a looper to be used by camera.
681                 Looper.prepare();
682                 Log.v(TAG, "start loopRun");
683                 // Save the looper so that we can terminate this thread
684                 // after we are done with it.
685                 mLooper = Looper.myLooper();
686                 mMediaPlayer = new MediaPlayer();
687                 synchronized (lock) {
688                     mInitialized = true;
689                     lock.notify();
690                 }
691                 Looper.loop();  // Blocks forever until Looper.quit() is called.
692                 Log.v(TAG, "initializeMessageLooper: quit.");
693             }
694         }.start();
695     }
696 
697     /*
698      * Terminates the message looper thread.
699      */
terminateMessageLooper()700     private static void terminateMessageLooper() {
701         mLooper.quit();
702         mMediaPlayer.release();
703     }
704 
705     static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
706         public void onPrepared(MediaPlayer mp) {
707             synchronized (prepareDone) {
708                 if(mPrepareReset){
709                     Log.v(TAG, "call Reset");
710                     mMediaPlayer.reset();
711                 }
712                 Log.v(TAG, "notify the prepare callback");
713                 prepareDone.notify();
714                 onPrepareSuccess = true;
715             }
716         }
717     };
718 
prepareAsyncCallback(String filePath, boolean reset)719     public static boolean prepareAsyncCallback(String filePath, boolean reset) throws Exception {
720         //Added the PrepareReset flag which allow us to switch to different
721         //test case.
722         if (reset){
723             mPrepareReset = true;
724         }
725 
726         synchronized (lock) {
727             initializeMessageLooper();
728             try {
729                 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
730             } catch(Exception e) {
731                 Log.v(TAG, "looper was interrupted.");
732                 return false;
733             }
734         }
735         try{
736             mMediaPlayer.setOnPreparedListener(mPreparedListener);
737             mMediaPlayer.setDataSource(filePath);
738             mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
739             mMediaPlayer.prepareAsync();
740             synchronized (prepareDone) {
741                 try {
742                     prepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
743                 } catch (Exception e) {
744                     Log.v(TAG, "wait was interrupted.");
745                 }
746             }
747             terminateMessageLooper();
748         }catch (Exception e){
749             Log.v(TAG,e.getMessage());
750         }
751        return onPrepareSuccess;
752     }
753 
754     static MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
755         public void onCompletion(MediaPlayer mp) {
756             synchronized (onCompletion) {
757                 Log.v(TAG, "notify the completion callback");
758                 onCompletion.notify();
759                 onCompleteSuccess = true;
760             }
761         }
762     };
763 
764     static MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
765         public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
766             mPlaybackError = true;
767             mp.reset();
768             return true;
769         }
770     };
771 
772     static MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
773         public boolean onInfo(MediaPlayer mp, int what, int extra) {
774             switch (what){
775                 case MediaPlayer.MEDIA_INFO_UNKNOWN:
776                     mMediaInfoUnknownCount++;
777                     break;
778                 case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
779                     mMediaInfoVideoTrackLaggingCount++;
780                     break;
781                 case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
782                     mMediaInfoBadInterleavingCount++;
783                     break;
784                 case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
785                     mMediaInfoNotSeekableCount++;
786                     break;
787                 case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
788                     mMediaInfoMetdataUpdateCount++;
789                     break;
790             }
791             return true;
792         }
793     };
794 
playMediaSamples(String filePath)795     public static boolean playMediaSamples(String filePath) throws Exception {
796         return playMediaSamples(filePath, 2000, false /* streamingTest */);
797     }
798 
799     // For each media file, just play to the end
playMediaSamples(String filePath, int buffertime, boolean streamingTest)800     public static boolean playMediaSamples(String filePath, int buffertime, boolean streamingTest)
801             throws Exception {
802         int duration = 0;
803         int curPosition = 0;
804         int nextPosition = 0;
805         int waittime = 0;
806         onCompleteSuccess = false;
807         mMediaInfoUnknownCount = 0;
808         mMediaInfoVideoTrackLaggingCount = 0;
809         mMediaInfoBadInterleavingCount = 0;
810         mMediaInfoNotSeekableCount = 0;
811         mMediaInfoMetdataUpdateCount = 0;
812         mPlaybackError = false;
813         mFailedToCompleteWithNoError = true;
814         String testResult;
815 
816         boolean hasSupportedVideo = false;
817 
818         if (!streamingTest) {
819             if (mSupportedTypes.isEmpty()) {
820                 final MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
821                 for (MediaCodecInfo info : list.getCodecInfos()) {
822                     for (String type : info.getSupportedTypes()) {
823                         mSupportedTypes.add(type);
824                     }
825                 }
826             }
827             final MediaExtractor extractor = new MediaExtractor();
828 
829             try {
830                 extractor.setDataSource(filePath);
831 
832                 for (int index = 0; index < extractor.getTrackCount(); ++index) {
833                     MediaFormat format = extractor.getTrackFormat(index);
834                     String type = format.getString(MediaFormat.KEY_MIME);
835                     if (!type.startsWith("video/")) {
836                         continue;
837                     }
838 
839                     if (mSupportedTypes.contains(type)) {
840                         hasSupportedVideo = true;
841                         break;
842                     }
843                 }
844             } finally {
845                 extractor.release();
846             }
847         } else { // streamingTest
848             hasSupportedVideo = true;
849         }
850 
851         initializeMessageLooper();
852         synchronized (lock) {
853             try {
854                 lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
855             } catch(Exception e) {
856                 Log.v(TAG, "looper was interrupted.");
857                 return false;
858             }
859         }
860         try {
861             mMediaPlayer.setOnCompletionListener(mCompletionListener);
862             mMediaPlayer.setOnErrorListener(mOnErrorListener);
863             mMediaPlayer.setOnInfoListener(mInfoListener);
864             Log.v(TAG, "playMediaSamples: sample file name " + filePath);
865             mMediaPlayer.setDataSource(filePath);
866             if (hasSupportedVideo) {
867                 mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
868             } else {
869                 Log.i(TAG, "Set no display due to no (supported) video track.");
870                 mMediaPlayer.setDisplay(null);
871             }
872             mMediaPlayer.prepare();
873             duration = mMediaPlayer.getDuration();
874             // start to play
875             mMediaPlayer.start();
876             if (duration < 0) {
877                 Log.w(TAG, filePath + " has unknown duration, waiting until playback completes");
878                 while (mMediaPlayer.isPlaying()) {
879                     SystemClock.sleep(1000);
880                 }
881             } else {
882                 waittime = duration - mMediaPlayer.getCurrentPosition();
883                 synchronized(onCompletion){
884                     try {
885                         onCompletion.wait(waittime + buffertime);
886                     } catch (Exception e) {
887                         Log.v(TAG, "playMediaSamples are interrupted");
888                         return false;
889                     }
890                 }
891             }
892             terminateMessageLooper();
893         } catch (Exception e) {
894             Log.v(TAG, "playMediaSamples:" + e.getMessage());
895         }
896         // Check if playback state is unknown (neither completed nor erroneous) unless
897         // it's not interrupted in the middle. If true, that is an exceptional case to investigate.
898         mFailedToCompleteWithNoError = !(onCompleteSuccess || mPlaybackError);
899         return onCompleteSuccess;
900     }
901 }
902