11ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang/* 21ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * Copyright 2018 The Android Open Source Project 31ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * 41ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * Licensed under the Apache License, Version 2.0 (the "License"); 51ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * you may not use this file except in compliance with the License. 61ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * You may obtain a copy of the License at 71ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * 81ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * http://www.apache.org/licenses/LICENSE-2.0 91ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * 101ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * Unless required by applicable law or agreed to in writing, software 111ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * distributed under the License is distributed on an "AS IS" BASIS, 121ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * See the License for the specific language governing permissions and 141ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang * limitations under the License. 151ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang */ 161ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 171ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangpackage androidx.media.widget; 181ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 191ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport static androidx.media.widget.VideoView2.VIEW_TYPE_SURFACEVIEW; 201ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 211ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.content.Context; 221ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.graphics.Rect; 231ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.util.Log; 241ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.view.Surface; 251ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.view.SurfaceHolder; 261ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.view.SurfaceView; 271ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport android.view.View; 281ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 291ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport androidx.annotation.NonNull; 301ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport androidx.annotation.RequiresApi; 311ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangimport androidx.media.MediaPlayer2; 321ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 331ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang@RequiresApi(21) 341ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kangclass VideoSurfaceView extends SurfaceView 351ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang implements VideoViewInterface, SurfaceHolder.Callback { 361ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private static final String TAG = "VideoSurfaceView"; 371ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 381ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private Surface mSurface = null; 391ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private SurfaceListener mSurfaceListener = null; 401ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private MediaPlayer2 mMediaPlayer; 411ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // A flag to indicate taking over other view should be proceed. 421ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private boolean mIsTakingOverOldView; 431ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang private VideoViewInterface mOldView; 441ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 451ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang VideoSurfaceView(Context context) { 461ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang super(context, null); 471ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang getHolder().addCallback(this); 481ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 491ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 501ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang //////////////////////////////////////////////////// 511ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // implements VideoViewInterfaceWithMp1 521ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang //////////////////////////////////////////////////// 531ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 541ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 551ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public boolean assignSurfaceToMediaPlayer(MediaPlayer2 mp) { 561ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.d(TAG, "assignSurfaceToMediaPlayer(): mSurface: " + mSurface); 571ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mp == null || !hasAvailableSurface()) { 581ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang return false; 591ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 601ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mp.setSurface(mSurface); 611ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang return true; 621ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 631ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 641ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 651ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void setSurfaceListener(SurfaceListener l) { 661ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurfaceListener = l; 671ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 681ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 691ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 701ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public int getViewType() { 711ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang return VIEW_TYPE_SURFACEVIEW; 721ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 731ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 741ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 751ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void setMediaPlayer(MediaPlayer2 mp) { 761ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mMediaPlayer = mp; 771ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mIsTakingOverOldView) { 781ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang takeOver(mOldView); 791ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 801ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 811ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 821ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 831ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void takeOver(@NonNull VideoViewInterface oldView) { 841ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (assignSurfaceToMediaPlayer(mMediaPlayer)) { 851ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang ((View) oldView).setVisibility(GONE); 861ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mIsTakingOverOldView = false; 871ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mOldView = null; 881ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mSurfaceListener != null) { 891ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurfaceListener.onSurfaceTakeOverDone(this); 901ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 911ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } else { 921ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mIsTakingOverOldView = true; 931ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mOldView = oldView; 941ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 951ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 961ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 971ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 981ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public boolean hasAvailableSurface() { 991ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang return mSurface != null && mSurface.isValid(); 1001ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1011ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1021ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang //////////////////////////////////////////////////// 1031ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // implements SurfaceHolder.Callback 1041ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang //////////////////////////////////////////////////// 1051ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1061ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 1071ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void surfaceCreated(SurfaceHolder holder) { 1081ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.d(TAG, "surfaceCreated: mSurface: " + mSurface + ", new : " + holder.getSurface()); 1091ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurface = holder.getSurface(); 1101ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mIsTakingOverOldView) { 1111ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang takeOver(mOldView); 1121ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } else { 1131ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang assignSurfaceToMediaPlayer(mMediaPlayer); 1141ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1151ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1161ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mSurfaceListener != null) { 1171ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Rect rect = holder.getSurfaceFrame(); 1181ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurfaceListener.onSurfaceCreated(this, rect.width(), rect.height()); 1191ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1201ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1211ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1221ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 1231ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 1241ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mSurfaceListener != null) { 1251ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurfaceListener.onSurfaceChanged(this, width, height); 1261ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1271ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1281ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1291ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 1301ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang public void surfaceDestroyed(SurfaceHolder holder) { 1311ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // After we return from this we can't use the surface any more 1321ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurface = null; 1331ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (mSurfaceListener != null) { 1341ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang mSurfaceListener.onSurfaceDestroyed(this); 1351ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1361ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1371ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1381ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang @Override 1391ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1401ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int videoWidth = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoWidth(); 1411ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int videoHeight = (mMediaPlayer == null) ? 0 : mMediaPlayer.getVideoHeight(); 1421ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (DEBUG) { 1431ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.d(TAG, "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", " 1441ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang + MeasureSpec.toString(heightMeasureSpec) + ")"); 1451ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight()); 1461ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.i(TAG, " viewSize: " + getWidth() + "/" + getHeight()); 1471ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.i(TAG, " mVideoWidth/height: " + videoWidth + ", " + videoHeight); 1481ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1491ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1501ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int width = getDefaultSize(videoWidth, widthMeasureSpec); 1511ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int height = getDefaultSize(videoHeight, heightMeasureSpec); 1521ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1531ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (videoWidth > 0 && videoHeight > 0) { 1541ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 1551ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 1561ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1571ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang width = widthSpecSize; 1581ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang height = heightSpecSize; 1591ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang 1601ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // for compatibility, we adjust size based on aspect ratio 1611ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (videoWidth * height < width * videoHeight) { 1621ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang width = height * videoWidth / videoHeight; 1631ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (DEBUG) { 1641ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.d(TAG, "image too wide, correcting. width: " + width); 1651ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1661ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } else if (videoWidth * height > width * videoHeight) { 1671ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang height = width * videoHeight / videoWidth; 1681ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (DEBUG) { 1691ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.d(TAG, "image too tall, correcting. height: " + height); 1701ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1711ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1721ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } else { 1731ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang // no size yet, just adopt the given spec sizes 1741ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1751ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang setMeasuredDimension(width, height); 1761ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang if (DEBUG) { 1771ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.i(TAG, "end of onMeasure()"); 1781ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang Log.i(TAG, " measuredSize: " + getMeasuredWidth() + "/" + getMeasuredHeight()); 1791ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1801ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang } 1811ed376b73eeaea2ba6211cde50575bf9734ff705Insun Kang} 182