diff options
Diffstat (limited to 'com/android/widget/VideoSurfaceView.java')
-rw-r--r-- | com/android/widget/VideoSurfaceView.java | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/com/android/widget/VideoSurfaceView.java b/com/android/widget/VideoSurfaceView.java new file mode 100644 index 00000000..85771234 --- /dev/null +++ b/com/android/widget/VideoSurfaceView.java @@ -0,0 +1,198 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.widget; + +import android.content.Context; +import android.graphics.Rect; +import android.media.MediaPlayer; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; + +import static android.widget.VideoView2.VIEW_TYPE_SURFACEVIEW; + +class VideoSurfaceView extends SurfaceView implements VideoViewInterface, SurfaceHolder.Callback { + private static final String TAG = "VideoSurfaceView"; + private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG); + private SurfaceHolder mSurfaceHolder = null; + private SurfaceListener mSurfaceListener = null; + private MediaPlayer mMediaPlayer; + // A flag to indicate taking over other view should be proceed. + private boolean mIsTakingOverOldView; + private VideoViewInterface mOldView; + + + public VideoSurfaceView(Context context) { + this(context, null); + } + + public VideoSurfaceView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + getHolder().addCallback(this); + } + + //////////////////////////////////////////////////// + // implements VideoViewInterface + //////////////////////////////////////////////////// + + @Override + public boolean assignSurfaceToMediaPlayer(MediaPlayer mp) { + Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurfaceHolder: " + mSurfaceHolder); + if (mp == null || !hasAvailableSurface()) { + return false; + } + mp.setDisplay(mSurfaceHolder); + return true; + } + + @Override + public void setSurfaceListener(SurfaceListener l) { + mSurfaceListener = l; + } + + @Override + public int getViewType() { + return VIEW_TYPE_SURFACEVIEW; + } + + @Override + public void setMediaPlayer(MediaPlayer mp) { + mMediaPlayer = mp; + if (mIsTakingOverOldView) { + takeOver(mOldView); + } + } + + @Override + public void takeOver(@NonNull VideoViewInterface oldView) { + if (assignSurfaceToMediaPlayer(mMediaPlayer)) { + ((View) oldView).setVisibility(GONE); + mIsTakingOverOldView = false; + mOldView = null; + if (mSurfaceListener != null) { + mSurfaceListener.onSurfaceTakeOverDone(this); + } + } else { + mIsTakingOverOldView = true; + mOldView = oldView; + } + } + + @Override + public boolean hasAvailableSurface() { + return (mSurfaceHolder != null && mSurfaceHolder.getSurface() != null); + } + + //////////////////////////////////////////////////// + // implements SurfaceHolder.Callback + //////////////////////////////////////////////////// + + @Override + public void surfaceCreated(SurfaceHolder holder) { + Log.d(TAG, "surfaceCreated: mSurfaceHolder: " + mSurfaceHolder + ", new holder: " + holder); + mSurfaceHolder = holder; + if (mIsTakingOverOldView) { + takeOver(mOldView); + } else { + assignSurfaceToMediaPlayer(mMediaPlayer); + } + + if (mSurfaceListener != null) { + Rect rect = mSurfaceHolder.getSurfaceFrame(); + mSurfaceListener.onSurfaceCreated(this, rect.width(), rect.height()); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (mSurfaceListener != null) { + mSurfaceListener.onSurfaceChanged(this, width, height); + } + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + // After we return from this we can't use the surface any more + mSurfaceHolder = null; + if (mSurfaceListener != null) { + mSurfaceListener.onSurfaceDestroyed(this); + } + } + + // TODO: Investigate the way to move onMeasure() code into FrameLayout. + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int videoWidth = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoWidth(); + int videoHeight = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoHeight(); + if (DEBUG) { + Log.d(TAG, "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", " + + MeasureSpec.toString(heightMeasureSpec) + ")"); + Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight()); + Log.i(TAG, " viewSize: " + getWidth() + "/" + getHeight()); + Log.i(TAG, " mVideoWidth/height: " + videoWidth + ", " + videoHeight); + } + + int width = getDefaultSize(videoWidth, widthMeasureSpec); + int height = getDefaultSize(videoHeight, heightMeasureSpec); + + if (videoWidth > 0 && videoHeight > 0) { + int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); + + width = widthSpecSize; + height = heightSpecSize; + + // for compatibility, we adjust size based on aspect ratio + if (videoWidth * height < width * videoHeight) { + width = height * videoWidth / videoHeight; + if (DEBUG) { + Log.d(TAG, "image too wide, correcting. width: " + width); + } + } else if (videoWidth * height > width * videoHeight) { + height = width * videoHeight / videoWidth; + if (DEBUG) { + Log.d(TAG, "image too tall, correcting. height: " + height); + } + } + } else { + // no size yet, just adopt the given spec sizes + } + setMeasuredDimension(width, height); + if (DEBUG) { + Log.i(TAG, "end of onMeasure()"); + Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight()); + } + } + + @Override + public String toString() { + return "ViewType: SurfaceView / Visibility: " + getVisibility() + + " / surfaceHolder: " + mSurfaceHolder; + } +} |