123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*
- * Copyright (C) 2015 Bilibili
- * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
- *
- * 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.edufound.mobile.ijkplayer.media;
- import android.annotation.TargetApi;
- import android.content.Context;
- import android.graphics.SurfaceTexture;
- import android.os.Build;
- import android.support.annotation.NonNull;
- import android.support.annotation.Nullable;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.Surface;
- import android.view.SurfaceHolder;
- import android.view.TextureView;
- import android.view.View;
- import android.view.accessibility.AccessibilityEvent;
- import android.view.accessibility.AccessibilityNodeInfo;
- import java.lang.ref.WeakReference;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import tv.danmaku.ijk.media.player.IMediaPlayer;
- import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
- import tv.danmaku.ijk.media.player.ISurfaceTextureHost;
- @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
- public class TextureRenderView extends TextureView implements IRenderView {
- private static final String TAG = "TextureRenderView";
- private MeasureHelper mMeasureHelper;
- public TextureRenderView(Context context) {
- super(context);
- initView(context);
- }
- public TextureRenderView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initView(context);
- }
- public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initView(context);
- }
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- initView(context);
- }
- private void initView(Context context) {
- mMeasureHelper = new MeasureHelper(this);
- mSurfaceCallback = new SurfaceCallback(this);
- setSurfaceTextureListener(mSurfaceCallback);
- }
- @Override
- public View getView() {
- return this;
- }
- @Override
- public boolean shouldWaitForResize() {
- return false;
- }
- @Override
- protected void onDetachedFromWindow() {
- mSurfaceCallback.willDetachFromWindow();
- super.onDetachedFromWindow();
- mSurfaceCallback.didDetachFromWindow();
- }
- //--------------------
- // Layout & Measure
- //--------------------
- @Override
- public void setVideoSize(int videoWidth, int videoHeight) {
- if (videoWidth > 0 && videoHeight > 0) {
- mMeasureHelper.setVideoSize(videoWidth, videoHeight);
- requestLayout();
- }
- }
- @Override
- public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
- if (videoSarNum > 0 && videoSarDen > 0) {
- mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
- requestLayout();
- }
- }
- @Override
- public void setVideoRotation(int degree) {
- mMeasureHelper.setVideoRotation(degree);
- setRotation(degree);
- }
- @Override
- public void setAspectRatio(int aspectRatio) {
- mMeasureHelper.setAspectRatio(aspectRatio);
- requestLayout();
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
- setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
- }
- //--------------------
- // TextureViewHolder
- //--------------------
- public ISurfaceHolder getSurfaceHolder() {
- return new InternalSurfaceHolder(this, mSurfaceCallback.mSurfaceTexture, mSurfaceCallback);
- }
- private static final class InternalSurfaceHolder implements ISurfaceHolder {
- private TextureRenderView mTextureView;
- private SurfaceTexture mSurfaceTexture;
- private ISurfaceTextureHost mSurfaceTextureHost;
- public InternalSurfaceHolder(@NonNull TextureRenderView textureView,
- @Nullable SurfaceTexture surfaceTexture,
- @NonNull ISurfaceTextureHost surfaceTextureHost) {
- mTextureView = textureView;
- mSurfaceTexture = surfaceTexture;
- mSurfaceTextureHost = surfaceTextureHost;
- }
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- public void bindToMediaPlayer(IMediaPlayer mp) {
- if (mp == null)
- return;
- if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) &&
- (mp instanceof ISurfaceTextureHolder)) {
- ISurfaceTextureHolder textureHolder = (ISurfaceTextureHolder) mp;
- mTextureView.mSurfaceCallback.setOwnSurfaceTexture(false);
- SurfaceTexture surfaceTexture = textureHolder.getSurfaceTexture();
- if (surfaceTexture != null) {
- mTextureView.setSurfaceTexture(surfaceTexture);
- } else {
- textureHolder.setSurfaceTexture(mSurfaceTexture);
- textureHolder.setSurfaceTextureHost(mTextureView.mSurfaceCallback);
- }
- } else {
- mp.setSurface(openSurface());
- }
- }
- @NonNull
- @Override
- public IRenderView getRenderView() {
- return mTextureView;
- }
- @Nullable
- @Override
- public SurfaceHolder getSurfaceHolder() {
- return null;
- }
- @Nullable
- @Override
- public SurfaceTexture getSurfaceTexture() {
- return mSurfaceTexture;
- }
- @Nullable
- @Override
- public Surface openSurface() {
- if (mSurfaceTexture == null)
- return null;
- return new Surface(mSurfaceTexture);
- }
- }
- //-------------------------
- // SurfaceHolder.Callback
- //-------------------------
- @Override
- public void addRenderCallback(IRenderCallback callback) {
- mSurfaceCallback.addRenderCallback(callback);
- }
- @Override
- public void removeRenderCallback(IRenderCallback callback) {
- mSurfaceCallback.removeRenderCallback(callback);
- }
- private SurfaceCallback mSurfaceCallback;
- private static final class SurfaceCallback implements SurfaceTextureListener, ISurfaceTextureHost {
- private SurfaceTexture mSurfaceTexture;
- private boolean mIsFormatChanged;
- private int mWidth;
- private int mHeight;
- private boolean mOwnSurfaceTexture = true;
- private boolean mWillDetachFromWindow = false;
- private boolean mDidDetachFromWindow = false;
- private WeakReference<TextureRenderView> mWeakRenderView;
- private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<IRenderCallback, Object>();
- public SurfaceCallback(@NonNull TextureRenderView renderView) {
- mWeakRenderView = new WeakReference<TextureRenderView>(renderView);
- }
- public void setOwnSurfaceTexture(boolean ownSurfaceTexture) {
- mOwnSurfaceTexture = ownSurfaceTexture;
- }
- public void addRenderCallback(@NonNull IRenderCallback callback) {
- mRenderCallbackMap.put(callback, callback);
- ISurfaceHolder surfaceHolder = null;
- if (mSurfaceTexture != null) {
- if (surfaceHolder == null)
- surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
- callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
- }
- if (mIsFormatChanged) {
- if (surfaceHolder == null)
- surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), mSurfaceTexture, this);
- callback.onSurfaceChanged(surfaceHolder, 0, mWidth, mHeight);
- }
- }
- public void removeRenderCallback(@NonNull IRenderCallback callback) {
- mRenderCallbackMap.remove(callback);
- }
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- mSurfaceTexture = surface;
- mIsFormatChanged = false;
- mWidth = 0;
- mHeight = 0;
- ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
- for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
- renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
- }
- }
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- mSurfaceTexture = surface;
- mIsFormatChanged = true;
- mWidth = width;
- mHeight = height;
- ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
- for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
- renderCallback.onSurfaceChanged(surfaceHolder, 0, width, height);
- }
- }
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- mSurfaceTexture = surface;
- mIsFormatChanged = false;
- mWidth = 0;
- mHeight = 0;
- ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakRenderView.get(), surface, this);
- for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
- renderCallback.onSurfaceDestroyed(surfaceHolder);
- }
- Log.d(TAG, "onSurfaceTextureDestroyed: destroy: " + mOwnSurfaceTexture);
- return mOwnSurfaceTexture;
- }
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- }
- //-------------------------
- // ISurfaceTextureHost
- //-------------------------
- @Override
- public void releaseSurfaceTexture(SurfaceTexture surfaceTexture) {
- if (surfaceTexture == null) {
- Log.d(TAG, "releaseSurfaceTexture: null");
- } else if (mDidDetachFromWindow) {
- if (surfaceTexture != mSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release different SurfaceTexture");
- surfaceTexture.release();
- } else if (!mOwnSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): release detached SurfaceTexture");
- surfaceTexture.release();
- } else {
- Log.d(TAG, "releaseSurfaceTexture: didDetachFromWindow(): already released by TextureView");
- }
- } else if (mWillDetachFromWindow) {
- if (surfaceTexture != mSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): release different SurfaceTexture");
- surfaceTexture.release();
- } else if (!mOwnSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): re-attach SurfaceTexture to TextureView");
- setOwnSurfaceTexture(true);
- } else {
- Log.d(TAG, "releaseSurfaceTexture: willDetachFromWindow(): will released by TextureView");
- }
- } else {
- if (surfaceTexture != mSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: alive: release different SurfaceTexture");
- surfaceTexture.release();
- } else if (!mOwnSurfaceTexture) {
- Log.d(TAG, "releaseSurfaceTexture: alive: re-attach SurfaceTexture to TextureView");
- setOwnSurfaceTexture(true);
- } else {
- Log.d(TAG, "releaseSurfaceTexture: alive: will released by TextureView");
- }
- }
- }
- public void willDetachFromWindow() {
- Log.d(TAG, "willDetachFromWindow()");
- mWillDetachFromWindow = true;
- }
- public void didDetachFromWindow() {
- Log.d(TAG, "didDetachFromWindow()");
- mDidDetachFromWindow = true;
- }
- }
- //--------------------
- // Accessibility
- //--------------------
- @Override
- public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- super.onInitializeAccessibilityEvent(event);
- event.setClassName(TextureRenderView.class.getName());
- }
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- info.setClassName(TextureRenderView.class.getName());
- }
- }
|