Loading packages/MediaComponents/src/com/android/widget/VideoSurfaceView.java +4 −4 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.widget; import android.content.Context; import android.graphics.Rect; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.util.Log; Loading @@ -33,7 +33,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG); private SurfaceHolder mSurfaceHolder = null; private SurfaceListener mSurfaceListener = null; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; // A flag to indicate taking over other view should be proceed. private boolean mIsTakingOverOldView; private VideoViewInterface mOldView; Loading Loading @@ -62,7 +62,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac //////////////////////////////////////////////////// @Override public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) { public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) { Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurfaceHolder: " + mSurfaceHolder); if (mp == null || !hasAvailableSurface()) { return false; Loading @@ -82,7 +82,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac } @Override public void setMediaPlayer(MediaPlayer mp) { public void setMediaPlayer(MediaPlayer2 mp) { mMediaPlayer = mp; if (mIsTakingOverOldView) { takeOver(mOldView); Loading packages/MediaComponents/src/com/android/widget/VideoTextureView.java +4 −4 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.widget; import android.content.Context; import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.util.AttributeSet; Loading @@ -38,7 +38,7 @@ class VideoTextureView extends TextureView private SurfaceTexture mSurfaceTexture; private Surface mSurface; private SurfaceListener mSurfaceListener; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; // A flag to indicate taking over other view should be proceed. private boolean mIsTakingOverOldView; private VideoViewInterface mOldView; Loading Loading @@ -66,7 +66,7 @@ class VideoTextureView extends TextureView //////////////////////////////////////////////////// @Override public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) { public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) { Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurfaceTexture: " + mSurfaceTexture); if (mp == null || !hasAvailableSurface()) { // Surface is not ready. Loading @@ -87,7 +87,7 @@ class VideoTextureView extends TextureView } @Override public void setMediaPlayer(MediaPlayer mp) { public void setMediaPlayer(MediaPlayer2 mp) { mMediaPlayer = mp; if (mIsTakingOverOldView) { takeOver(mOldView); Loading packages/MediaComponents/src/com/android/widget/VideoView2Impl.java +152 −165 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ import android.media.AudioFocusRequest; import android.media.AudioManager; import android.media.DataSourceDesc; import android.media.MediaMetadata; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.media.MediaPlayer2.MediaPlayer2EventCallback; import android.media.MediaPlayer2Impl; import android.media.MediaPlayerBase; import android.media.Cea708CaptionRenderer; import android.media.ClosedCaptionRenderer; Loading Loading @@ -103,7 +105,7 @@ public class VideoView2Impl extends BaseLayout private VideoTextureView mTextureView; private VideoSurfaceView mSurfaceView; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; private MediaControlView2 mMediaControlView; private MediaSession mMediaSession; private MediaController mMediaController; Loading Loading @@ -196,7 +198,6 @@ public class VideoView2Impl extends BaseLayout mSubtitleView.setBackgroundColor(0); mInstance.addView(mSubtitleView); // TODO: Need a common namespace for attributes those are defined in updatable library. boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue( "http://schemas.android.com/apk/res/android", "enableControlView", true); Loading Loading @@ -363,8 +364,9 @@ public class VideoView2Impl extends BaseLayout @Override public void setVideoUri_impl(Uri uri, Map<String, String> headers) { mSeekWhenPrepared = 0; openVideo(uri, headers); DataSourceDesc.Builder builder = new DataSourceDesc.Builder(); builder.setDataSource(mInstance.getContext(), uri, headers, null); mInstance.setDataSource(builder.build()); } @Override Loading @@ -374,7 +376,8 @@ public class VideoView2Impl extends BaseLayout @Override public void setDataSource_impl(DataSourceDesc dsd) { // TODO: implement this mSeekWhenPrepared = 0; openVideo(dsd); } @Override Loading Loading @@ -557,8 +560,10 @@ public class VideoView2Impl extends BaseLayout && mTargetState == STATE_PLAYING); } // Creates a MediaPlayer instance and prepare playback. private void openVideo(Uri uri, Map<String, String> headers) { // Creates a MediaPlayer2 instance and prepare playback. private void openVideo(DataSourceDesc dsd) { Uri uri = dsd.getUri(); Map<String, String> headers = dsd.getUriHeaders(); resetPlayer(); if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) { // TODO this should have a focus listener Loading @@ -570,13 +575,13 @@ public class VideoView2Impl extends BaseLayout } try { Log.d(TAG, "openVideo(): creating new MediaPlayer instance."); mMediaPlayer = new MediaPlayer(); Log.d(TAG, "openVideo(): creating new MediaPlayer2 instance."); mMediaPlayer = new MediaPlayer2Impl(); mSurfaceView.setMediaPlayer(mMediaPlayer); mTextureView.setMediaPlayer(mMediaPlayer); mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer); // TODO: create SubtitleController in MediaPlayer, but we need // TODO: create SubtitleController in MediaPlayer2, but we need // a context for the subtitle renderers final Context context = mInstance.getContext(); final SubtitleController controller = new SubtitleController( Loading @@ -588,23 +593,21 @@ public class VideoView2Impl extends BaseLayout controller.registerRenderer(new SRTRenderer(context)); mMediaPlayer.setSubtitleAnchor( controller, (SubtitleController.Anchor) mSubtitleView); // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. mMediaPlayer.setOnTimedTextListener(mTimedTextListener); mMediaPlayer.setOnPreparedListener(mPreparedListener); mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); mMediaPlayer.setOnCompletionListener(mCompletionListener); mMediaPlayer.setOnErrorListener(mErrorListener); mMediaPlayer.setOnInfoListener(mInfoListener); mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); Executor executor = new Executor() { @Override public void execute(Runnable runnable) { runnable.run(); } }; mMediaPlayer.setMediaPlayer2EventCallback(executor, mMediaPlayer2Callback); mCurrentBufferPercentage = 0; mMediaPlayer.setDataSource(mInstance.getContext(), uri, headers); mMediaPlayer.setDataSource(dsd); mMediaPlayer.setAudioAttributes(mAudioAttributes); // we don't set the target state here either, but preserve the // target state that was there before. mCurrentState = STATE_PREPARING; mMediaPlayer.prepareAsync(); mMediaPlayer.prepare(); // Save file name as title since the file may not have a title Metadata. mTitle = uri.getPath(); Loading @@ -617,24 +620,12 @@ public class VideoView2Impl extends BaseLayout Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState + ", mTargetState=" + mTargetState); } /* for (Pair<InputStream, MediaFormat> pending: mPendingSubtitleTracks) { try { mMediaPlayer.addSubtitleSource(pending.first, pending.second); } catch (IllegalStateException e) { mInfoListener.onInfo( mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0); } } */ } catch (IOException | IllegalArgumentException ex) { } catch (IllegalArgumentException ex) { Log.w(TAG, "Unable to open content: " + uri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, MediaPlayer.MEDIA_ERROR_IO); } finally { //mPendingSubtitleTracks.clear(); mMediaPlayer2Callback.onError(mMediaPlayer, dsd, MediaPlayer2.MEDIA_ERROR_UNKNOWN, MediaPlayer2.MEDIA_ERROR_IO); } } Loading @@ -644,7 +635,7 @@ public class VideoView2Impl extends BaseLayout private void resetPlayer() { if (mMediaPlayer != null) { mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer.close(); mMediaPlayer = null; //mPendingSubtitleTracks.clear(); mCurrentState = STATE_IDLE; Loading @@ -660,8 +651,8 @@ public class VideoView2Impl extends BaseLayout private void updatePlaybackState() { if (mStateBuilder == null) { // Get the capabilities of the player for this stream mMetadata = mMediaPlayer.getMetadata(MediaPlayer.METADATA_ALL, MediaPlayer.BYPASS_METADATA_FILTER); mMetadata = mMediaPlayer.getMetadata(MediaPlayer2.METADATA_ALL, MediaPlayer2.BYPASS_METADATA_FILTER); // Add Play action as default long playbackActions = PlaybackState.ACTION_PLAY; Loading Loading @@ -701,6 +692,8 @@ public class VideoView2Impl extends BaseLayout if (mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING) { // TODO: this should be replaced with MediaPlayer2.getBufferedPosition() once it is // implemented. mStateBuilder.setBufferedPosition( (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration()); } Loading Loading @@ -817,18 +810,18 @@ public class VideoView2Impl extends BaseLayout } private void extractTracks() { MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo(); List<MediaPlayer2.TrackInfo> trackInfos = mMediaPlayer.getTrackInfo(); mVideoTrackIndices = new ArrayList<>(); mAudioTrackIndices = new ArrayList<>(); mSubtitleTrackIndices = new ArrayList<>(); for (int i = 0; i < trackInfos.length; ++i) { int trackType = trackInfos[i].getTrackType(); if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) { for (int i = 0; i < trackInfos.size(); ++i) { int trackType = trackInfos.get(i).getTrackType(); if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) { mVideoTrackIndices.add(i); } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) { } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) { mAudioTrackIndices.add(i); } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { mSubtitleTrackIndices.add(i); } } Loading @@ -842,27 +835,63 @@ public class VideoView2Impl extends BaseLayout mMediaSession.sendSessionEvent(MediaControlView2Impl.EVENT_UPDATE_TRACK_STATUS, data); } MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() { public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { MediaPlayer2EventCallback mMediaPlayer2Callback = new MediaPlayer2EventCallback() { @Override public void onVideoSizeChanged( MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) { if (DEBUG) { Log.d(TAG, "OnVideoSizeChanged(): size: " + width + "/" + height); Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height); } mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); if (DEBUG) { Log.d(TAG, "OnVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/" Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/" + mVideoHeight); } if (mVideoWidth != 0 && mVideoHeight != 0) { mInstance.requestLayout(); } } }; MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. @Override public void onTimedText( MediaPlayer2 mp, DataSourceDesc dsd, TimedText text) { Log.d(TAG, "TimedText: " + text.getText()); } @Override public void onInfo( MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) { extractTracks(); } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { this.onPrepared(mp, dsd); } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { this.onCompletion(mp, dsd); } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) { this.onBufferingUpdate(mp, dsd, extra); } } @Override public void onError( MediaPlayer2 mp, DataSourceDesc dsd, int frameworkErr, int implErr) { if (DEBUG) { Log.d(TAG, "Error: " + frameworkErr + "," + implErr); } mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; updatePlaybackState(); if (mMediaControlView != null) { mMediaControlView.setVisibility(View.GONE); } } private void onPrepared(MediaPlayer2 mp, DataSourceDesc dsd) { if (DEBUG) { Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState + ", mTargetState=" + mTargetState); Loading Loading @@ -899,7 +928,6 @@ public class VideoView2Impl extends BaseLayout Log.i(TAG, " viewSize: " + mInstance.getWidth() + "/" + mInstance.getHeight()); } mVideoWidth = videoWidth; mVideoHeight = videoHeight; mInstance.requestLayout(); Loading @@ -915,85 +943,44 @@ public class VideoView2Impl extends BaseLayout mMediaController.getTransportControls().play(); } } // Get and set duration and title values as MediaMetadata for MediaControlView2 MediaMetadata.Builder builder = new MediaMetadata.Builder(); if (mMetadata != null && mMetadata.has(Metadata.TITLE)) { mTitle = mMetadata.getString(Metadata.TITLE); } builder.putString(MediaMetadata.METADATA_KEY_TITLE, mTitle); builder.putLong(MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration()); builder.putLong( MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration()); if (mMediaSession != null) { mMediaSession.setMetadata(builder.build()); // TODO: merge this code with the above code when integrating with MediaSession2. // TODO: merge this code with the above code when integrating with // MediaSession2. if (mNeedUpdateMediaType) { mMediaSession.sendSessionEvent( MediaControlView2Impl.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData); MediaControlView2Impl.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData); mNeedUpdateMediaType = false; } } } }; private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { private void onCompletion(MediaPlayer2 mp, DataSourceDesc dsd) { mCurrentState = STATE_PLAYBACK_COMPLETED; mTargetState = STATE_PLAYBACK_COMPLETED; updatePlaybackState(); if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) { mAudioManager.abandonAudioFocus(null); } } }; private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() { public boolean onInfo(MediaPlayer mp, int what, int extra) { if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) { extractTracks(); } return true; } }; private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp, int frameworkErr, int implErr) { if (DEBUG) { Log.d(TAG, "Error: " + frameworkErr + "," + implErr); } mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; updatePlaybackState(); if (mMediaControlView != null) { mMediaControlView.setVisibility(View.GONE); } return true; } }; private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { public void onBufferingUpdate(MediaPlayer mp, int percent) { private void onBufferingUpdate(MediaPlayer2 mp, DataSourceDesc dsd, int percent) { mCurrentBufferPercentage = percent; updatePlaybackState(); } }; // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. private MediaPlayer.OnTimedTextListener mTimedTextListener = new MediaPlayer.OnTimedTextListener() { public void onTimedText(MediaPlayer mp, TimedText text) { Log.d(TAG, "TimedText: " + text.getText()); } }; private class MediaSessionCallback extends MediaSession.Callback { @Override public void onCommand(String command, Bundle args, ResultReceiver receiver) { Loading Loading @@ -1033,7 +1020,7 @@ public class VideoView2Impl extends BaseLayout } else { if (isInPlaybackState() && mCurrentView.hasAvailableSurface()) { applySpeed(); mMediaPlayer.start(); mMediaPlayer.play(); mCurrentState = STATE_PLAYING; updatePlaybackState(); } Loading Loading @@ -1073,7 +1060,7 @@ public class VideoView2Impl extends BaseLayout mRouteSessionCallback.onSeekTo(pos); } else { if (isInPlaybackState()) { mMediaPlayer.seekTo(pos, MediaPlayer.SEEK_PREVIOUS_SYNC); mMediaPlayer.seekTo(pos, MediaPlayer2.SEEK_PREVIOUS_SYNC); mSeekWhenPrepared = 0; updatePlaybackState(); } else { Loading packages/MediaComponents/src/com/android/widget/VideoViewInterface.java +10 −10 Original line number Diff line number Diff line Loading @@ -17,31 +17,31 @@ package com.android.widget; import android.annotation.NonNull; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.view.View; interface VideoViewInterface { /** * Assigns the view's surface to the given MediaPlayer instance. * Assigns the view's surface to the given MediaPlayer2 instance. * * @param mp MediaPlayer * @param mp MediaPlayer2 * @return true if the surface is successfully assigned, false if not. It will fail to assign * if any of MediaPlayer or surface is unavailable. * if any of MediaPlayer2 or surface is unavailable. */ boolean assignSurfaceToMediaPlayer(MediaPlayer mp); boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp); void setSurfaceListener(SurfaceListener l); int getViewType(); void setMediaPlayer(MediaPlayer mp); void setMediaPlayer(MediaPlayer2 mp); /** * Takes over oldView. It means that the MediaPlayer will start rendering on this view. * Takes over oldView. It means that the MediaPlayer2 will start rendering on this view. * The visibility of oldView will be set as {@link View.GONE}. If the view doesn't have a * MediaPlayer instance or its surface is not available, the actual execution is deferred until * a MediaPlayer instance is set by {@link #setMediaPlayer} or its surface becomes available. * MediaPlayer2 instance or its surface is not available, the actual execution is deferred until * a MediaPlayer2 instance is set by {@link #setMediaPlayer} or its surface becomes available. * {@link SurfaceListener.onSurfaceTakeOverDone} will be called when the actual execution is * done. * * @param oldView The view that MediaPlayer is currently rendering on. * @param oldView The view that MediaPlayer2 is currently rendering on. */ void takeOver(@NonNull VideoViewInterface oldView); Loading Loading
packages/MediaComponents/src/com/android/widget/VideoSurfaceView.java +4 −4 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.widget; import android.content.Context; import android.graphics.Rect; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.util.Log; Loading @@ -33,7 +33,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG); private SurfaceHolder mSurfaceHolder = null; private SurfaceListener mSurfaceListener = null; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; // A flag to indicate taking over other view should be proceed. private boolean mIsTakingOverOldView; private VideoViewInterface mOldView; Loading Loading @@ -62,7 +62,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac //////////////////////////////////////////////////// @Override public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) { public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) { Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurfaceHolder: " + mSurfaceHolder); if (mp == null || !hasAvailableSurface()) { return false; Loading @@ -82,7 +82,7 @@ class VideoSurfaceView extends SurfaceView implements VideoViewInterface, Surfac } @Override public void setMediaPlayer(MediaPlayer mp) { public void setMediaPlayer(MediaPlayer2 mp) { mMediaPlayer = mp; if (mIsTakingOverOldView) { takeOver(mOldView); Loading
packages/MediaComponents/src/com/android/widget/VideoTextureView.java +4 −4 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.widget; import android.content.Context; import android.graphics.SurfaceTexture; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.util.AttributeSet; Loading @@ -38,7 +38,7 @@ class VideoTextureView extends TextureView private SurfaceTexture mSurfaceTexture; private Surface mSurface; private SurfaceListener mSurfaceListener; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; // A flag to indicate taking over other view should be proceed. private boolean mIsTakingOverOldView; private VideoViewInterface mOldView; Loading Loading @@ -66,7 +66,7 @@ class VideoTextureView extends TextureView //////////////////////////////////////////////////// @Override public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) { public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) { Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurfaceTexture: " + mSurfaceTexture); if (mp == null || !hasAvailableSurface()) { // Surface is not ready. Loading @@ -87,7 +87,7 @@ class VideoTextureView extends TextureView } @Override public void setMediaPlayer(MediaPlayer mp) { public void setMediaPlayer(MediaPlayer2 mp) { mMediaPlayer = mp; if (mIsTakingOverOldView) { takeOver(mOldView); Loading
packages/MediaComponents/src/com/android/widget/VideoView2Impl.java +152 −165 Original line number Diff line number Diff line Loading @@ -24,7 +24,9 @@ import android.media.AudioFocusRequest; import android.media.AudioManager; import android.media.DataSourceDesc; import android.media.MediaMetadata; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.media.MediaPlayer2.MediaPlayer2EventCallback; import android.media.MediaPlayer2Impl; import android.media.MediaPlayerBase; import android.media.Cea708CaptionRenderer; import android.media.ClosedCaptionRenderer; Loading Loading @@ -103,7 +105,7 @@ public class VideoView2Impl extends BaseLayout private VideoTextureView mTextureView; private VideoSurfaceView mSurfaceView; private MediaPlayer mMediaPlayer; private MediaPlayer2 mMediaPlayer; private MediaControlView2 mMediaControlView; private MediaSession mMediaSession; private MediaController mMediaController; Loading Loading @@ -196,7 +198,6 @@ public class VideoView2Impl extends BaseLayout mSubtitleView.setBackgroundColor(0); mInstance.addView(mSubtitleView); // TODO: Need a common namespace for attributes those are defined in updatable library. boolean enableControlView = (attrs == null) || attrs.getAttributeBooleanValue( "http://schemas.android.com/apk/res/android", "enableControlView", true); Loading Loading @@ -363,8 +364,9 @@ public class VideoView2Impl extends BaseLayout @Override public void setVideoUri_impl(Uri uri, Map<String, String> headers) { mSeekWhenPrepared = 0; openVideo(uri, headers); DataSourceDesc.Builder builder = new DataSourceDesc.Builder(); builder.setDataSource(mInstance.getContext(), uri, headers, null); mInstance.setDataSource(builder.build()); } @Override Loading @@ -374,7 +376,8 @@ public class VideoView2Impl extends BaseLayout @Override public void setDataSource_impl(DataSourceDesc dsd) { // TODO: implement this mSeekWhenPrepared = 0; openVideo(dsd); } @Override Loading Loading @@ -557,8 +560,10 @@ public class VideoView2Impl extends BaseLayout && mTargetState == STATE_PLAYING); } // Creates a MediaPlayer instance and prepare playback. private void openVideo(Uri uri, Map<String, String> headers) { // Creates a MediaPlayer2 instance and prepare playback. private void openVideo(DataSourceDesc dsd) { Uri uri = dsd.getUri(); Map<String, String> headers = dsd.getUriHeaders(); resetPlayer(); if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) { // TODO this should have a focus listener Loading @@ -570,13 +575,13 @@ public class VideoView2Impl extends BaseLayout } try { Log.d(TAG, "openVideo(): creating new MediaPlayer instance."); mMediaPlayer = new MediaPlayer(); Log.d(TAG, "openVideo(): creating new MediaPlayer2 instance."); mMediaPlayer = new MediaPlayer2Impl(); mSurfaceView.setMediaPlayer(mMediaPlayer); mTextureView.setMediaPlayer(mMediaPlayer); mCurrentView.assignSurfaceToMediaPlayer(mMediaPlayer); // TODO: create SubtitleController in MediaPlayer, but we need // TODO: create SubtitleController in MediaPlayer2, but we need // a context for the subtitle renderers final Context context = mInstance.getContext(); final SubtitleController controller = new SubtitleController( Loading @@ -588,23 +593,21 @@ public class VideoView2Impl extends BaseLayout controller.registerRenderer(new SRTRenderer(context)); mMediaPlayer.setSubtitleAnchor( controller, (SubtitleController.Anchor) mSubtitleView); // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. mMediaPlayer.setOnTimedTextListener(mTimedTextListener); mMediaPlayer.setOnPreparedListener(mPreparedListener); mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); mMediaPlayer.setOnCompletionListener(mCompletionListener); mMediaPlayer.setOnErrorListener(mErrorListener); mMediaPlayer.setOnInfoListener(mInfoListener); mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); Executor executor = new Executor() { @Override public void execute(Runnable runnable) { runnable.run(); } }; mMediaPlayer.setMediaPlayer2EventCallback(executor, mMediaPlayer2Callback); mCurrentBufferPercentage = 0; mMediaPlayer.setDataSource(mInstance.getContext(), uri, headers); mMediaPlayer.setDataSource(dsd); mMediaPlayer.setAudioAttributes(mAudioAttributes); // we don't set the target state here either, but preserve the // target state that was there before. mCurrentState = STATE_PREPARING; mMediaPlayer.prepareAsync(); mMediaPlayer.prepare(); // Save file name as title since the file may not have a title Metadata. mTitle = uri.getPath(); Loading @@ -617,24 +620,12 @@ public class VideoView2Impl extends BaseLayout Log.d(TAG, "openVideo(). mCurrentState=" + mCurrentState + ", mTargetState=" + mTargetState); } /* for (Pair<InputStream, MediaFormat> pending: mPendingSubtitleTracks) { try { mMediaPlayer.addSubtitleSource(pending.first, pending.second); } catch (IllegalStateException e) { mInfoListener.onInfo( mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0); } } */ } catch (IOException | IllegalArgumentException ex) { } catch (IllegalArgumentException ex) { Log.w(TAG, "Unable to open content: " + uri, ex); mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, MediaPlayer.MEDIA_ERROR_IO); } finally { //mPendingSubtitleTracks.clear(); mMediaPlayer2Callback.onError(mMediaPlayer, dsd, MediaPlayer2.MEDIA_ERROR_UNKNOWN, MediaPlayer2.MEDIA_ERROR_IO); } } Loading @@ -644,7 +635,7 @@ public class VideoView2Impl extends BaseLayout private void resetPlayer() { if (mMediaPlayer != null) { mMediaPlayer.reset(); mMediaPlayer.release(); mMediaPlayer.close(); mMediaPlayer = null; //mPendingSubtitleTracks.clear(); mCurrentState = STATE_IDLE; Loading @@ -660,8 +651,8 @@ public class VideoView2Impl extends BaseLayout private void updatePlaybackState() { if (mStateBuilder == null) { // Get the capabilities of the player for this stream mMetadata = mMediaPlayer.getMetadata(MediaPlayer.METADATA_ALL, MediaPlayer.BYPASS_METADATA_FILTER); mMetadata = mMediaPlayer.getMetadata(MediaPlayer2.METADATA_ALL, MediaPlayer2.BYPASS_METADATA_FILTER); // Add Play action as default long playbackActions = PlaybackState.ACTION_PLAY; Loading Loading @@ -701,6 +692,8 @@ public class VideoView2Impl extends BaseLayout if (mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING) { // TODO: this should be replaced with MediaPlayer2.getBufferedPosition() once it is // implemented. mStateBuilder.setBufferedPosition( (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration()); } Loading Loading @@ -817,18 +810,18 @@ public class VideoView2Impl extends BaseLayout } private void extractTracks() { MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo(); List<MediaPlayer2.TrackInfo> trackInfos = mMediaPlayer.getTrackInfo(); mVideoTrackIndices = new ArrayList<>(); mAudioTrackIndices = new ArrayList<>(); mSubtitleTrackIndices = new ArrayList<>(); for (int i = 0; i < trackInfos.length; ++i) { int trackType = trackInfos[i].getTrackType(); if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) { for (int i = 0; i < trackInfos.size(); ++i) { int trackType = trackInfos.get(i).getTrackType(); if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_VIDEO) { mVideoTrackIndices.add(i); } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) { } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_AUDIO) { mAudioTrackIndices.add(i); } else if (trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { } else if (trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE || trackType == MediaPlayer2.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) { mSubtitleTrackIndices.add(i); } } Loading @@ -842,27 +835,63 @@ public class VideoView2Impl extends BaseLayout mMediaSession.sendSessionEvent(MediaControlView2Impl.EVENT_UPDATE_TRACK_STATUS, data); } MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() { public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { MediaPlayer2EventCallback mMediaPlayer2Callback = new MediaPlayer2EventCallback() { @Override public void onVideoSizeChanged( MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) { if (DEBUG) { Log.d(TAG, "OnVideoSizeChanged(): size: " + width + "/" + height); Log.d(TAG, "onVideoSizeChanged(): size: " + width + "/" + height); } mVideoWidth = mp.getVideoWidth(); mVideoHeight = mp.getVideoHeight(); if (DEBUG) { Log.d(TAG, "OnVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/" Log.d(TAG, "onVideoSizeChanged(): mVideoSize:" + mVideoWidth + "/" + mVideoHeight); } if (mVideoWidth != 0 && mVideoHeight != 0) { mInstance.requestLayout(); } } }; MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { public void onPrepared(MediaPlayer mp) { // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. @Override public void onTimedText( MediaPlayer2 mp, DataSourceDesc dsd, TimedText text) { Log.d(TAG, "TimedText: " + text.getText()); } @Override public void onInfo( MediaPlayer2 mp, DataSourceDesc dsd, int what, int extra) { if (what == MediaPlayer2.MEDIA_INFO_METADATA_UPDATE) { extractTracks(); } else if (what == MediaPlayer2.MEDIA_INFO_PREPARED) { this.onPrepared(mp, dsd); } else if (what == MediaPlayer2.MEDIA_INFO_PLAYBACK_COMPLETE) { this.onCompletion(mp, dsd); } else if (what == MediaPlayer2.MEDIA_INFO_BUFFERING_UPDATE) { this.onBufferingUpdate(mp, dsd, extra); } } @Override public void onError( MediaPlayer2 mp, DataSourceDesc dsd, int frameworkErr, int implErr) { if (DEBUG) { Log.d(TAG, "Error: " + frameworkErr + "," + implErr); } mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; updatePlaybackState(); if (mMediaControlView != null) { mMediaControlView.setVisibility(View.GONE); } } private void onPrepared(MediaPlayer2 mp, DataSourceDesc dsd) { if (DEBUG) { Log.d(TAG, "OnPreparedListener(). mCurrentState=" + mCurrentState + ", mTargetState=" + mTargetState); Loading Loading @@ -899,7 +928,6 @@ public class VideoView2Impl extends BaseLayout Log.i(TAG, " viewSize: " + mInstance.getWidth() + "/" + mInstance.getHeight()); } mVideoWidth = videoWidth; mVideoHeight = videoHeight; mInstance.requestLayout(); Loading @@ -915,85 +943,44 @@ public class VideoView2Impl extends BaseLayout mMediaController.getTransportControls().play(); } } // Get and set duration and title values as MediaMetadata for MediaControlView2 MediaMetadata.Builder builder = new MediaMetadata.Builder(); if (mMetadata != null && mMetadata.has(Metadata.TITLE)) { mTitle = mMetadata.getString(Metadata.TITLE); } builder.putString(MediaMetadata.METADATA_KEY_TITLE, mTitle); builder.putLong(MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration()); builder.putLong( MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration()); if (mMediaSession != null) { mMediaSession.setMetadata(builder.build()); // TODO: merge this code with the above code when integrating with MediaSession2. // TODO: merge this code with the above code when integrating with // MediaSession2. if (mNeedUpdateMediaType) { mMediaSession.sendSessionEvent( MediaControlView2Impl.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData); MediaControlView2Impl.EVENT_UPDATE_MEDIA_TYPE_STATUS, mMediaTypeData); mNeedUpdateMediaType = false; } } } }; private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { private void onCompletion(MediaPlayer2 mp, DataSourceDesc dsd) { mCurrentState = STATE_PLAYBACK_COMPLETED; mTargetState = STATE_PLAYBACK_COMPLETED; updatePlaybackState(); if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) { mAudioManager.abandonAudioFocus(null); } } }; private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() { public boolean onInfo(MediaPlayer mp, int what, int extra) { if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) { extractTracks(); } return true; } }; private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp, int frameworkErr, int implErr) { if (DEBUG) { Log.d(TAG, "Error: " + frameworkErr + "," + implErr); } mCurrentState = STATE_ERROR; mTargetState = STATE_ERROR; updatePlaybackState(); if (mMediaControlView != null) { mMediaControlView.setVisibility(View.GONE); } return true; } }; private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { public void onBufferingUpdate(MediaPlayer mp, int percent) { private void onBufferingUpdate(MediaPlayer2 mp, DataSourceDesc dsd, int percent) { mCurrentBufferPercentage = percent; updatePlaybackState(); } }; // TODO: Remove timed text related code later once relevant Renderer is defined. // This is just for debugging purpose. private MediaPlayer.OnTimedTextListener mTimedTextListener = new MediaPlayer.OnTimedTextListener() { public void onTimedText(MediaPlayer mp, TimedText text) { Log.d(TAG, "TimedText: " + text.getText()); } }; private class MediaSessionCallback extends MediaSession.Callback { @Override public void onCommand(String command, Bundle args, ResultReceiver receiver) { Loading Loading @@ -1033,7 +1020,7 @@ public class VideoView2Impl extends BaseLayout } else { if (isInPlaybackState() && mCurrentView.hasAvailableSurface()) { applySpeed(); mMediaPlayer.start(); mMediaPlayer.play(); mCurrentState = STATE_PLAYING; updatePlaybackState(); } Loading Loading @@ -1073,7 +1060,7 @@ public class VideoView2Impl extends BaseLayout mRouteSessionCallback.onSeekTo(pos); } else { if (isInPlaybackState()) { mMediaPlayer.seekTo(pos, MediaPlayer.SEEK_PREVIOUS_SYNC); mMediaPlayer.seekTo(pos, MediaPlayer2.SEEK_PREVIOUS_SYNC); mSeekWhenPrepared = 0; updatePlaybackState(); } else { Loading
packages/MediaComponents/src/com/android/widget/VideoViewInterface.java +10 −10 Original line number Diff line number Diff line Loading @@ -17,31 +17,31 @@ package com.android.widget; import android.annotation.NonNull; import android.media.MediaPlayer; import android.media.MediaPlayer2; import android.view.View; interface VideoViewInterface { /** * Assigns the view's surface to the given MediaPlayer instance. * Assigns the view's surface to the given MediaPlayer2 instance. * * @param mp MediaPlayer * @param mp MediaPlayer2 * @return true if the surface is successfully assigned, false if not. It will fail to assign * if any of MediaPlayer or surface is unavailable. * if any of MediaPlayer2 or surface is unavailable. */ boolean assignSurfaceToMediaPlayer(MediaPlayer mp); boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp); void setSurfaceListener(SurfaceListener l); int getViewType(); void setMediaPlayer(MediaPlayer mp); void setMediaPlayer(MediaPlayer2 mp); /** * Takes over oldView. It means that the MediaPlayer will start rendering on this view. * Takes over oldView. It means that the MediaPlayer2 will start rendering on this view. * The visibility of oldView will be set as {@link View.GONE}. If the view doesn't have a * MediaPlayer instance or its surface is not available, the actual execution is deferred until * a MediaPlayer instance is set by {@link #setMediaPlayer} or its surface becomes available. * MediaPlayer2 instance or its surface is not available, the actual execution is deferred until * a MediaPlayer2 instance is set by {@link #setMediaPlayer} or its surface becomes available. * {@link SurfaceListener.onSurfaceTakeOverDone} will be called when the actual execution is * done. * * @param oldView The view that MediaPlayer is currently rendering on. * @param oldView The view that MediaPlayer2 is currently rendering on. */ void takeOver(@NonNull VideoViewInterface oldView); Loading