13bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/* 23bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Copyright (C) 2017 The Android Open Source Project 33bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 43bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Licensed under the Apache License, Version 2.0 (the "License"); 53bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * you may not use this file except in compliance with the License. 63bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * You may obtain a copy of the License at 73bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 83bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * http://www.apache.org/licenses/LICENSE-2.0 93bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Unless required by applicable law or agreed to in writing, software 113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * distributed under the License is distributed on an "AS IS" BASIS, 123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * See the License for the specific language governing permissions and 143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * limitations under the License. 153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.leanback.media; 183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 193bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.content.Context; 203bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.media.AudioManager; 213bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.media.MediaPlayer; 223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.net.Uri; 233bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.os.Handler; 243bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.SurfaceHolder; 253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 268619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikasimport androidx.leanback.R; 278619e0ef7062b6a714f22af993e4b440fae7ef08Aurimas Liutikas 283bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport java.io.IOException; 293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/** 313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * This implementation extends the {@link PlayerAdapter} with a {@link MediaPlayer}. 323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class MediaPlayerAdapter extends PlayerAdapter { 343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Context mContext; 363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer mPlayer = new MediaPlayer(); 373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu SurfaceHolderGlueHost mSurfaceHolderGlueHost; 383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final Runnable mRunnable = new Runnable() { 393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void run() { 413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onCurrentPositionChanged(MediaPlayerAdapter.this); 423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mHandler.postDelayed(this, getUpdatePeriod()); 433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu };; 453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final Handler mHandler = new Handler(); 463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean mInitialized = false; // true when the MediaPlayer is prepared/initialized 473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu Uri mMediaSourceUri = null; 483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean mHasDisplay; 493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu long mBufferedProgress; 503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu MediaPlayer.OnPreparedListener mOnPreparedListener = new MediaPlayer.OnPreparedListener() { 523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onPrepared(MediaPlayer mp) { 543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mInitialized = true; 553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu notifyBufferingStartEnd(); 563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mSurfaceHolderGlueHost == null || mHasDisplay) { 573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPreparedStateChanged(MediaPlayerAdapter.this); 583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnCompletionListener mOnCompletionListener = 633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new MediaPlayer.OnCompletionListener() { 643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onCompletion(MediaPlayer mediaPlayer) { 663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPlayStateChanged(MediaPlayerAdapter.this); 673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPlayCompleted(MediaPlayerAdapter.this); 683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener = 723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new MediaPlayer.OnBufferingUpdateListener() { 733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onBufferingUpdate(MediaPlayer mp, int percent) { 753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBufferedProgress = getDuration() * percent / 100; 763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onBufferedPositionChanged(MediaPlayerAdapter.this); 773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener = 813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new MediaPlayer.OnVideoSizeChangedListener() { 823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) { 843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onVideoSizeChanged(MediaPlayerAdapter.this, width, height); 853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnErrorListener mOnErrorListener = 893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new MediaPlayer.OnErrorListener() { 903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onError(MediaPlayer mp, int what, int extra) { 923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onError(MediaPlayerAdapter.this, what, 933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mContext.getString(R.string.lb_media_player_error, what, extra)); 943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return MediaPlayerAdapter.this.onError(what, extra); 953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = 993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu new MediaPlayer.OnSeekCompleteListener() { 1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onSeekComplete(MediaPlayer mp) { 1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu MediaPlayerAdapter.this.onSeekComplete(); 1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu final MediaPlayer.OnInfoListener mOnInfoListener = new MediaPlayer.OnInfoListener() { 1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean onInfo(MediaPlayer mp, int what, int extra) { 1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean handled = false; 1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu switch (what) { 1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case MediaPlayer.MEDIA_INFO_BUFFERING_START: 1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBufferingStart = true; 1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu notifyBufferingStartEnd(); 1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu handled = true; 1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu break; 1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu case MediaPlayer.MEDIA_INFO_BUFFERING_END: 1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBufferingStart = false; 1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu notifyBufferingStartEnd(); 1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu handled = true; 1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu break; 1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean thisHandled = MediaPlayerAdapter.this.onInfo(what, extra); 1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return handled || thisHandled; 1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu }; 1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean mBufferingStart; 1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void notifyBufferingStartEnd() { 1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onBufferingStateChanged(MediaPlayerAdapter.this, 1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mBufferingStart || !mInitialized); 1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Constructor. 1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 1373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public MediaPlayerAdapter(Context context) { 1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mContext = context; 1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onAttachedToHost(PlaybackGlueHost host) { 1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (host instanceof SurfaceHolderGlueHost) { 1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSurfaceHolderGlueHost = ((SurfaceHolderGlueHost) host); 1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSurfaceHolderGlueHost.setSurfaceHolderCallback(new VideoPlayerSurfaceHolderCallback()); 1463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 1503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Will reset the {@link MediaPlayer} and the glue such that a new file can be played. You are 1513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * not required to call this method before playing the first file. However you have to call it 1523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * before playing a second one. 1533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 1543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void reset() { 1553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changeToUnitialized(); 1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.reset(); 1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void changeToUnitialized() { 1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mInitialized) { 1613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mInitialized = false; 1623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu notifyBufferingStartEnd(); 1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mHasDisplay) { 1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPreparedStateChanged(MediaPlayerAdapter.this); 1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 1703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Release internal MediaPlayer. Should not use the object after call release(). 1713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void release() { 1733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu changeToUnitialized(); 1743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mHasDisplay = false; 1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.release(); 1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void onDetachedFromHost() { 1803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mSurfaceHolderGlueHost != null) { 1813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSurfaceHolderGlueHost.setSurfaceHolderCallback(null); 1823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mSurfaceHolderGlueHost = null; 1833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu reset(); 1853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu release(); 1863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 1873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 1883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 1893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Called to indicate an error. 1903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 1913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param what the type of error that has occurred: 1923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <ul> 1933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_UNKNOWN} 1943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_SERVER_DIED} 1953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * </ul> 1963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param extra an extra code, specific to the error. Typically 1973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * implementation dependent. 1983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <ul> 1993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_IO} 2003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_MALFORMED} 2013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_UNSUPPORTED} 2023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_ERROR_TIMED_OUT} 2033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li><code>MEDIA_ERROR_SYSTEM (-2147483648)</code> - low-level system error. 2043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * </ul> 2053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return True if the method handled the error, false if it didn't. 2063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returning false, will cause the {@link PlayerAdapter.Callback#onPlayCompleted(PlayerAdapter)} 2073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * being called. 2083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected boolean onError(int what, int extra) { 2103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 2113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Called to indicate the completion of a seek operation. 2153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected void onSeekComplete() { 2173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Called to indicate an info or a warning. 2213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 2223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param what the type of info or warning. 2233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <ul> 2243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_UNKNOWN} 2253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_VIDEO_TRACK_LAGGING} 2263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START} 2273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_BUFFERING_START} 2283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_BUFFERING_END} 2293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li><code>MEDIA_INFO_NETWORK_BANDWIDTH (703)</code> - 2303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * bandwidth information is available (as <code>extra</code> kbps) 2313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_BAD_INTERLEAVING} 2323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_NOT_SEEKABLE} 2333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_METADATA_UPDATE} 2343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_UNSUPPORTED_SUBTITLE} 2353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * <li>{@link MediaPlayer#MEDIA_INFO_SUBTITLE_TIMED_OUT} 2363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * </ul> 2373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @param extra an extra code, specific to the info. Typically 2383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * implementation dependent. 2393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return True if the method handled the info, false if it didn't. 2403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Returning false, will cause the info to be discarded. 2413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu protected boolean onInfo(int what, int extra) { 2433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 2443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 2473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @see MediaPlayer#setDisplay(SurfaceHolder) 2483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu void setDisplay(SurfaceHolder surfaceHolder) { 2503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu boolean hadDisplay = mHasDisplay; 2513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mHasDisplay = surfaceHolder != null; 2523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (hadDisplay == mHasDisplay) { 2533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 2543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setDisplay(surfaceHolder); 2563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mHasDisplay) { 2573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mInitialized) { 2583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPreparedStateChanged(MediaPlayerAdapter.this); 2593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 2613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mInitialized) { 2623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPreparedStateChanged(MediaPlayerAdapter.this); 2633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void setProgressUpdatingEnabled(final boolean enabled) { 2703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mHandler.removeCallbacks(mRunnable); 2713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!enabled) { 2723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 2733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mHandler.postDelayed(mRunnable, getUpdatePeriod()); 2753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu int getUpdatePeriod() { 2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return 16; 2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean isPlaying() { 2833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mInitialized && mPlayer.isPlaying(); 2843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public long getDuration() { 2883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mInitialized ? mPlayer.getDuration() : -1; 2893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public long getCurrentPosition() { 2933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mInitialized ? mPlayer.getCurrentPosition() : -1; 2943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 2953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 2963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 2973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void play() { 2983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInitialized || mPlayer.isPlaying()) { 2993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 3003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.start(); 3023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPlayStateChanged(MediaPlayerAdapter.this); 3033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onCurrentPositionChanged(MediaPlayerAdapter.this); 3043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void pause() { 3083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (isPlaying()) { 3093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.pause(); 3103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPlayStateChanged(MediaPlayerAdapter.this); 3113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void seekTo(long newPosition) { 3163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (!mInitialized) { 3173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 3183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.seekTo((int) newPosition); 3203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public long getBufferedPosition() { 3243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mBufferedProgress; 3253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 3283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Sets the media source of the player witha given URI. 3293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * 3303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return Returns <code>true</code> if uri represents a new media; <code>false</code> 3313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * otherwise. 3323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @see MediaPlayer#setDataSource(String) 3333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 3343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean setDataSource(Uri uri) { 3353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mMediaSourceUri != null ? mMediaSourceUri.equals(uri) : uri == null) { 3363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return false; 3373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mMediaSourceUri = uri; 3393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu prepareMediaForPlaying(); 3403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return true; 3413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu private void prepareMediaForPlaying() { 3443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu reset(); 3453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu try { 3463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu if (mMediaSourceUri != null) { 3473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setDataSource(mContext, mMediaSourceUri); 3483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } else { 3493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return; 3503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } catch (IOException e) { 3523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu e.printStackTrace(); 3533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu throw new RuntimeException(e); 3543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 3563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnPreparedListener(mOnPreparedListener); 3573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener); 3583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnErrorListener(mOnErrorListener); 3593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnSeekCompleteListener(mOnSeekCompleteListener); 3603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnCompletionListener(mOnCompletionListener); 3613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnInfoListener(mOnInfoListener); 3623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener); 3633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu notifyBufferingStartEnd(); 3643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu mPlayer.prepareAsync(); 3653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu getCallback().onPlayStateChanged(MediaPlayerAdapter.this); 3663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 3693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * @return True if MediaPlayer OnPreparedListener is invoked and got a SurfaceHolder if 3703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link PlaybackGlueHost} provides SurfaceHolder. 3713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 3723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public boolean isPrepared() { 3743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu return mInitialized && (mSurfaceHolderGlueHost == null || mHasDisplay); 3753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu /** 3783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Implements {@link SurfaceHolder.Callback} that can then be set on the 3793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * {@link PlaybackGlueHost}. 3803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */ 3813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu class VideoPlayerSurfaceHolderCallback implements SurfaceHolder.Callback { 3823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void surfaceCreated(SurfaceHolder surfaceHolder) { 3843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setDisplay(surfaceHolder); 3853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { 3893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu 3913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu @Override 3923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 3933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu setDisplay(null); 3943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu } 3963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu} 397