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.functional;
18
19
20
21//import android.content.Resources;
22import com.android.mediaframeworktest.MediaFrameworkTest;
23import com.android.mediaframeworktest.MediaNames;
24
25import android.content.res.AssetFileDescriptor;
26import android.graphics.Bitmap;
27import android.graphics.BitmapFactory;
28import android.media.MediaCodecInfo;
29import android.media.MediaCodecList;
30import android.media.MediaExtractor;
31import android.media.MediaFormat;
32import android.media.MediaMetadataRetriever;
33import android.media.MediaPlayer;
34import android.media.MediaRecorder;
35import android.os.Looper;
36import android.os.SystemClock;
37import android.util.Log;
38
39import java.io.File;
40import java.io.FileWriter;
41import java.io.IOException;
42import java.io.InputStream;
43import java.io.OutputStream;
44import java.io.Writer;
45import java.io.FileOutputStream;
46import java.util.HashSet;
47import java.util.Random;
48import java.util.Set;
49/**
50 * Junit / Instrumentation test case for the media player api
51
52 */
53public 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
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
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
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
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
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     */
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     */
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
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
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
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