VideoSurfaceViewWithMp1.java
/*
* 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 androidx.media.widget;
import static androidx.media.widget.VideoView2.VIEW_TYPE_SURFACEVIEW;
import android.content.Context;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
@RequiresApi(21)
class VideoSurfaceViewWithMp1 extends SurfaceView
implements VideoViewInterfaceWithMp1, SurfaceHolder.Callback {
private static final String TAG = "VideoSurfaceViewWithMp1";
private static final boolean DEBUG = 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 VideoViewInterfaceWithMp1 mOldView;
VideoSurfaceViewWithMp1(Context context) {
super(context, null);
getHolder().addCallback(this);
}
////////////////////////////////////////////////////
// implements VideoViewInterfaceWithMp1
////////////////////////////////////////////////////
@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 VideoViewInterfaceWithMp1 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);
}
}
@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());
}
}
}