提交 47762343 authored 作者: kongdywang's avatar kongdywang

update to 12.6

上级 14de057c
#### Version: 12.5.1 2025.05.29
#### Version: 12.6.0 2025.06.20
##### Features:
- set Android TXLiteAVSDK_Player to 12.6.0.17772,tag:release_player_v12.6.0
- set iOS TXLiteAVSDK_Player to 12.6.18866, tag:release_player_v12.6.0
#### Version: 12.5.1 2025.06.18
##### Features:
......
......@@ -5,7 +5,7 @@ buildLog() {
}
inputVersion=$1
export VERSION_NAME="12.5.1"
export VERSION_NAME="12.6.0"
if [ -n "$inputVersion" ]; then
VERSION_NAME=$inputVersion
fi
......
......@@ -13,6 +13,9 @@ rootProject.allprojects {
}
android {
buildFeatures {
buildConfig = true
}
compileSdkVersion rootProject.ext.compileSdkVersion
namespace="com.tencent.vod.flutter"
......
......@@ -4,7 +4,7 @@ rootProject.ext {
supportSdkVersion = "26.0.1"
minSdkVersion = 19
targetSdkVersion = 28
playerVersion = "12.5.1"
playerVersion = "12.6.0"
compat = "androidx.appcompat:appcompat:1.6.1"
/**
......@@ -14,5 +14,5 @@ rootProject.ext {
Professional SDK: liteavSdk="com.tencent.liteav:LiteAVSDK_Professional:latest.release"
If you want to specify the SDK version(eg 11.7.0.13946), use: liteavSdk="com.tencent.liteav:LiteAVSDK_Player:11.7.0.13946"
*/
liteavSdk="com.tencent.liteav:LiteAVSDK_Player:12.5.0.17576"
liteavSdk="com.tencent.liteav:LiteAVSDK_Player:12.6.0.17772"
}
\ No newline at end of file
......@@ -4912,6 +4912,8 @@ public class FtxMessages {
void setRenderMode(@NonNull Long renderMode);
void reDraw();
/** The codec used by TXFlutterVodPlayerApi. */
static @NonNull MessageCodec<Object> getCodec() {
return PigeonCodec.INSTANCE;
......@@ -5902,6 +5904,27 @@ public class FtxMessages {
api.setRenderMode(renderModeArg);
wrapped.add(0, null);
}
catch (Throwable exception) {
wrapped = wrapError(exception);
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.super_player.TXFlutterVodPlayerApi.reDraw" + messageChannelSuffix, getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
try {
api.reDraw();
wrapped.add(0, null);
}
catch (Throwable exception) {
wrapped = wrapError(exception);
}
......
......@@ -162,37 +162,51 @@ public class FTXVodPlayer extends FTXVodPlayerRenderHost implements ITXVodPlayLi
@Override
public void onPlayEvent(TXVodPlayer txVodPlayer, int event, Bundle bundle) {
if (event == TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION) {
String evtParam3 = bundle.getString("EVT_PARAM3");
if (!TextUtils.isEmpty(evtParam3)) {
String[] array = evtParam3.split(",");
if (array.length == 6) {
int videoWidth = Integer.parseInt(array[4]) - Integer.parseInt(array[2]) + 1;
int videoHeight = Integer.parseInt(array[5]) - Integer.parseInt(array[3]) + 1;
int videoLeft = -Integer.parseInt(array[2]);
int videoTop = -Integer.parseInt(array[3]);
int videoRight = Integer.parseInt(array[4]) + 1 - Integer.parseInt(array[0]);
int videoBottom = Integer.parseInt(array[5]) + 1 - Integer.parseInt(array[1]);
bundle.putInt("videoWidth", videoWidth);
bundle.putInt("videoHeight", videoHeight);
bundle.putInt("videoLeft", videoLeft);
bundle.putInt("videoTop", videoTop);
bundle.putInt("videoRight", videoRight);
bundle.putInt("videoBottom", videoBottom);
mVodFlutterApi.onPlayerEvent(TXCommonUtil.getParams(event, bundle), this);
return;
switch (event) {
case TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION:
String evtParam3 = bundle.getString("EVT_PARAM3");
if (!TextUtils.isEmpty(evtParam3)) {
String[] array = evtParam3.split(",");
if (array.length == 6) {
int videoWidth = Integer.parseInt(array[4]) - Integer.parseInt(array[2]) + 1;
int videoHeight = Integer.parseInt(array[5]) - Integer.parseInt(array[3]) + 1;
int videoLeft = -Integer.parseInt(array[2]);
int videoTop = -Integer.parseInt(array[3]);
int videoRight = Integer.parseInt(array[4]) + 1 - Integer.parseInt(array[0]);
int videoBottom = Integer.parseInt(array[5]) + 1 - Integer.parseInt(array[1]);
bundle.putInt("videoWidth", videoWidth);
bundle.putInt("videoHeight", videoHeight);
bundle.putInt("videoLeft", videoLeft);
bundle.putInt("videoTop", videoTop);
bundle.putInt("videoRight", videoRight);
bundle.putInt("videoBottom", videoBottom);
mUIHandler.post(new Runnable() {
@Override
public void run() {
mVodFlutterApi.onPlayerEvent(TXCommonUtil.getParams(event, bundle),
FTXVodPlayer.this);
}
});
return;
}
}
}
} else if (event == TXLiveConstants.PLAY_WARNING_HW_ACCELERATION_FAIL) {
mHardwareDecodeFail = true;
}
if (event == TXVodConstants.VOD_PLAY_EVT_CHANGE_RESOLUTION) {
int resolutionWidth = bundle.getInt(TXLiveConstants.EVT_PARAM1);
int resolutionHeight = bundle.getInt(TXLiveConstants.EVT_PARAM2);
notifyTextureResolution(resolutionWidth, resolutionHeight);
break;
case TXLiveConstants.PLAY_WARNING_HW_ACCELERATION_FAIL:
mHardwareDecodeFail = true;
break;
case TXLiveConstants.PLAY_EVT_VOD_PLAY_PREPARED:
int resolutionWidth = txVodPlayer.getWidth();
int resolutionHeight = txVodPlayer.getHeight();
notifyTextureResolution(resolutionWidth, resolutionHeight);
break;
case TXVodConstants.VOD_PLAY_EVT_SEEK_COMPLETE:
reDraw();
break;
default:
break;
}
if (event != TXVodConstants.VOD_PLAY_EVT_PLAY_PROGRESS) {
LiteavLog.e(TAG, "onPlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
LiteavLog.i(TAG, "onPlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
}
if (event == TXLiveConstants.PLAY_EVT_RCV_FIRST_I_FRAME) {
// delay fir
......@@ -201,7 +215,7 @@ public class FTXVodPlayer extends FTXVodPlayerRenderHost implements ITXVodPlayLi
public void run() {
mVodFlutterApi.onPlayerEvent(TXCommonUtil.getParams(event, bundle), FTXVodPlayer.this);
}
}, 50);
}, 200);
} else {
mUIHandler.post(new Runnable() {
@Override
......@@ -243,6 +257,13 @@ public class FTXVodPlayer extends FTXVodPlayerRenderHost implements ITXVodPlayLi
}
}
@Override
public void reDraw() {
if (mCurRenderView != null) {
mCurRenderView.getRenderView().reDrawVod();
}
}
protected long init(boolean onlyAudio) {
if (mVodPlayer == null) {
mVodPlayer = new TXVodPlayer(mFlutterPluginBinding.getApplicationContext());
......
......@@ -2,22 +2,22 @@
package com.tencent.vod.flutter.player.render;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.TextureView;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.live2.V2TXLivePlayer;
import com.tencent.vod.flutter.player.FTXBasePlayer;
import com.tencent.vod.flutter.ui.render.CarrierViewObserver;
import com.tencent.vod.flutter.ui.render.FTXCarrierSurfaceListener;
import com.tencent.vod.flutter.ui.render.FTXRenderCarrier;
import com.tencent.vod.flutter.ui.render.FTXRenderView;
public abstract class FTXLivePlayerRenderHost extends FTXBasePlayer implements FTXPlayerRenderHost,
CarrierViewObserver {
FTXCarrierSurfaceListener {
private static final String TAG = "FTXLivePlayerRenderHost";
protected FTXRenderView mCurRenderView;
private boolean isTargetDetached = false;
@Override
public void setUpPlayerView(FTXRenderView renderView) {
......@@ -27,22 +27,25 @@ public abstract class FTXLivePlayerRenderHost extends FTXBasePlayer implements F
renderView.setPlayer(this);
} else {
LiteavLog.w(TAG, "start setUpPlayerView met null view, reset player, player:" + hashCode());
mCurRenderView = null;
setRenderView(null);
if (null != mCurRenderView && null != mCurRenderView.getRenderView()) {
mCurRenderView.getRenderView().removeSurfaceTextureListener(this);
}
mCurRenderView = null;
}
}
@Override
public void setRenderView(FTXRenderCarrier textureView) {
final V2TXLivePlayer livePlayer = getLivePlayer();
isTargetDetached = false;
if (null != textureView) {
LiteavLog.i(TAG, "start bind Player:" + textureView + ", player:" + hashCode());
if (textureView instanceof TextureView) {
livePlayer.setRenderView((TextureView) textureView);
textureView.addViewObserver(this);
textureView.addSurfaceTextureListener(this);
} else if (textureView instanceof SurfaceView) {
livePlayer.setRenderView((SurfaceView) textureView);
textureView.addSurfaceTextureListener(this);
} else {
LiteavLog.e(TAG, "setRenderView met a unImpl renderView, view obj:" + textureView);
}
......@@ -50,22 +53,19 @@ public abstract class FTXLivePlayerRenderHost extends FTXBasePlayer implements F
LiteavLog.i(TAG, "setRenderView met a null textureView, player:" + hashCode());
livePlayer.setRenderView((TextureView) null);
livePlayer.setRenderView((SurfaceView) null);
if (null != mCurRenderView && mCurRenderView.getRenderView() != null) {
mCurRenderView.getRenderView().removeViewObserver(this);
}
}
}
@Override
public void onDetachWindow(FTXRenderCarrier carrier) {
isTargetDetached = true;
public void onSurfaceTextureAvailable(Surface surface) {
if (null != mCurRenderView) {
setRenderView(mCurRenderView.getRenderView());
}
}
@Override
public void onAttachWindow(FTXRenderCarrier carrier) {
if (isTargetDetached && null != mCurRenderView) {
setUpPlayerView(mCurRenderView);
}
public boolean onSurfaceTextureDestroyed(Surface surface) {
return false;
}
protected abstract V2TXLivePlayer getLivePlayer();
......
......@@ -13,7 +13,6 @@ import android.view.Surface;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.vod.flutter.common.FTXPlayerConstants;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
......@@ -24,6 +23,8 @@ public class FTXEGLRender implements SurfaceTexture.OnFrameAvailableListener {
private static final long FRAME_WAIT_TIME = 5000;
private static final int FPS_DEFAULT = 30;
// min refresh count for obtain new img
private static final int RE_DRAW_COUNT = 50;
private SurfaceTexture mSurfaceTexture;
private FTXTextureRender mTextureRender;
......@@ -53,6 +54,7 @@ public class FTXEGLRender implements SurfaceTexture.OnFrameAvailableListener {
private int mFps;
private float frameInterval = 0;
private HandlerThread mDrawHandlerThread = new HandlerThread(TAG);
private Handler mDrawHandler = null;
private boolean isReleased = false;
public FTXEGLRender(int width, int height) {
......@@ -75,11 +77,16 @@ public class FTXEGLRender implements SurfaceTexture.OnFrameAvailableListener {
。或者暂停状态下 seek,seek 之后画面改变,纹理上的画面仍然是 seek 之前或者上一次 seek 的画面。
所以这里使用独立线程主动拉取画面进行渲染,但是一直拉取画面,会导致发热情况严重,所以默认有 60帧率的限制。所以这块播放器默认帧率为 60帧。
*/
// mLock.lock();
// if (mStart) {
// mCondition.signalAll();
// }
// mLock.unlock();
if (mStart) {
mDrawHandler.post(new Runnable() {
@Override
public void run() {
mLock.lock();
startDrawSurface();
mLock.unlock();
}
});
}
}
private synchronized void startDrawSurface() {
......@@ -95,16 +102,9 @@ public class FTXEGLRender implements SurfaceTexture.OnFrameAvailableListener {
}
mCurrentTime = System.currentTimeMillis();
final long time = mCurrentTime - mPreTime;
boolean isNotFirstFrame = mPreTime > 0;
if (time >= frameInterval) {
drawImage();
swapBuffers();
mPreTime = mCurrentTime;
} else if (isNotFirstFrame) {
final long waitTime = (long) (frameInterval - time);
mCondition.await(waitTime, TimeUnit.MILLISECONDS);
}
drawImage();
swapBuffers();
mPreTime = mCurrentTime;
mSurfaceTexture.updateTexImage();
} catch (Exception e) {
LiteavLog.e(TAG, "startDrawSurface error: " + e);
......@@ -347,28 +347,29 @@ public class FTXEGLRender implements SurfaceTexture.OnFrameAvailableListener {
public void startRender() {
LiteavLog.i(TAG, "called start render");
mStart = true;
if (mDrawHandlerThread.isAlive()) {
LiteavLog.e(TAG, "old draw thread is alive, stop first");
mDrawHandlerThread.quitSafely();
}
mDrawHandlerThread = new HandlerThread(TAG);
mDrawHandlerThread.start();
Handler handler = new Handler(mDrawHandlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
while (mStart) {
mDrawHandler = new Handler(mDrawHandlerThread.getLooper());
mStart = true;
}
public void refreshRender() {
if (null != mDrawHandler) {
mDrawHandler.post(new Runnable() {
@Override
public void run() {
mLock.lock();
try {
for (int i = 0; i < RE_DRAW_COUNT; i++) {
startDrawSurface();
} finally {
mLock.unlock();
}
mLock.unlock();
}
LiteavLog.e(TAG, "startDrawSurface thread is finished");
}
});
});
}
}
public synchronized void resumeRender() {
......
......@@ -190,7 +190,6 @@ public class FlutterPipImplActivity extends Activity implements ITXVodPlayListen
}
}
}
handleIntent(intent);
}
......@@ -237,7 +236,7 @@ public class FlutterPipImplActivity extends Activity implements ITXVodPlayListen
} else {
if (isInPictureInPictureMode) {
sendPipEvent(FTXEvent.EVENT_PIP_MODE_ALREADY_ENTER, null);
showComponent();
setUpPipVideo();
} else {
handlePipExitEvent();
}
......@@ -464,7 +463,6 @@ public class FlutterPipImplActivity extends Activity implements ITXVodPlayListen
}
private void startPipVideo() {
attachRenderView(mVideoRenderView);
startPlay();
}
......@@ -503,6 +501,7 @@ public class FlutterPipImplActivity extends Activity implements ITXVodPlayListen
mPlayerHolder = null;
pipPlayerHolder = null;
isInPip = false;
attachRenderView(null);
super.onDestroy();
}
......@@ -589,10 +588,12 @@ public class FlutterPipImplActivity extends Activity implements ITXVodPlayListen
* 显示组件
* 为了防止画中画启动一瞬间的黑屏,组件一开始为隐藏状态,只有进入画中画之后才会显示组件
*/
private void showComponent() {
private void setUpPipVideo() {
mVideoRenderView.setVisibility(View.VISIBLE);
mVideoProgress.setVisibility(View.VISIBLE);
mPipContainer.setBackgroundColor(Color.parseColor("#33000000"));
attachRenderView(mVideoRenderView);
startPipVideo();
}
private void controlPipPlayStatus(boolean isPlaying) {
......
package com.tencent.vod.flutter.ui.render;
public interface CarrierViewObserver {
void onAttachWindow(FTXRenderCarrier carrier);
void onDetachWindow(FTXRenderCarrier carrier);
}
package com.tencent.vod.flutter.ui.render;
import android.view.Surface;
public interface FTXCarrierSurfaceListener {
void onSurfaceTextureAvailable(Surface surface);
boolean onSurfaceTextureDestroyed(Surface surface);
}
......@@ -2,9 +2,6 @@ package com.tencent.vod.flutter.ui.render;
import com.tencent.vod.flutter.player.render.FTXPlayerRenderSurfaceHost;
import java.lang.ref.WeakReference;
import java.util.List;
public interface FTXRenderCarrier {
void bindPlayer(FTXPlayerRenderSurfaceHost surfaceHost);
......@@ -21,11 +18,11 @@ public interface FTXRenderCarrier {
void destroyRender();
void addViewObserver(CarrierViewObserver observer);
void reDrawVod();
void removeViewObserver(CarrierViewObserver observer);
void addSurfaceTextureListener(FTXCarrierSurfaceListener listener);
void removeAllViewObserver();
void removeSurfaceTextureListener(FTXCarrierSurfaceListener listener);
List<WeakReference<CarrierViewObserver>> getViewObservers();
void removeAllSurfaceListener();
}
......@@ -72,7 +72,7 @@ public class FTXRenderView implements PlatformView {
+ ",new:" + player + ", view:" + hashCode());
if (null != mBasePlayer) {
mBasePlayer.setRenderView(null);
mTextureView.removeAllViewObserver();
mTextureView.removeAllSurfaceListener();
clearTexture();
}
mBasePlayer = player;
......
......@@ -14,12 +14,10 @@ import com.tencent.vod.flutter.player.render.FTXPlayerRenderSurfaceHost;
import com.tencent.vod.flutter.player.render.gl.FTXEGLRender;
import com.tencent.vod.flutter.player.render.gl.GLSurfaceTools;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callback, FTXRenderCarrier {
public class FTXSurfaceView extends SurfaceView implements FTXRenderCarrier {
private static final String TAG = "FTXSurfaceView";
......@@ -34,7 +32,7 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
private int mViewHeight = 0;
private final Object mLayoutLock = new Object();
private FTXEGLRender mRender;
private final List<WeakReference<CarrierViewObserver>> mViewObservers = new ArrayList<>();
private final SurfaceViewInnerListener mSurfaceListenerDelegate = new SurfaceViewInnerListener(this);
public FTXSurfaceView(Context context) {
super(context);
......@@ -42,10 +40,8 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
}
private void init() {
getHolder().addCallback(this);
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mRender = new FTXEGLRender(1, 1);
getHolder().addCallback(mSurfaceListenerDelegate);
mRender = new FTXEGLRender(1080, 720);
}
@Override
......@@ -66,7 +62,7 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
if (videoHeight >= 0) {
mVideoHeight = videoHeight;
}
mRender.updateSizeAndRenderMode(videoWidth, videoHeight, mRenderMode);
updateVideoRenderMode();
LiteavLog.i(TAG, "notifyVideoResolutionChanged updateSize, mVideoWidth:"
+ mVideoWidth + ",mVideoHeight:" + mVideoHeight);
}
......@@ -78,29 +74,19 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
super.onDetachedFromWindow();
LiteavLog.i(TAG, "target onDetachedFromWindow,view:" + hashCode());
mRender.stopRender();
for (WeakReference<CarrierViewObserver> observer : mViewObservers) {
if (observer.get() != null) {
observer.get().onDetachWindow(this);
}
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
LiteavLog.i(TAG, "target onAttachedToWindow,view:" + hashCode());
for (WeakReference<CarrierViewObserver> observer : mViewObservers) {
if (observer.get() != null) {
observer.get().onAttachWindow(this);
}
}
}
@Override
public void updateRenderMode(long renderMode) {
if (mRenderMode != renderMode) {
mRenderMode = renderMode;
layoutTextureRenderMode();
updateVideoRenderMode();
}
}
......@@ -109,7 +95,7 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
updateRenderSizeIfNeed(viewWidth, viewHeight);
}
public void layoutTextureRenderMode() {
public void updateVideoRenderMode() {
if (mRender != null) {
mRender.updateSizeAndRenderMode(mVideoWidth, mVideoHeight, mRenderMode);
}
......@@ -132,12 +118,10 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
connectPlayer(surfaceHost);
}
if (null != surfaceHost) {
final int videoWidth = surfaceHost.getVideoWidth();
final int videoHeight = surfaceHost.getVideoHeight();
mRenderMode = surfaceHost.getPlayerRenderMode();
mVideoWidth = surfaceHost.getVideoWidth();
mVideoHeight = surfaceHost.getVideoHeight();
mRender.updateSizeAndRenderMode(videoWidth, videoHeight, mRenderMode);
updateVideoRenderMode();
LiteavLog.i(TAG, "updateSize, mVideoWidth:" + mVideoWidth + ",mVideoHeight:"
+ mVideoHeight + ",renderMode:" + mRenderMode);
}
......@@ -180,7 +164,7 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
mRender.initOpengl(surface);
mPlayer.setSurface(mRender.getInputSurface());
mRender.startRender();
mPlayer.setSurface(mRender.getInputSurface());
LiteavLog.i(TAG, "updateHostSurface:" + surface);
}
}
......@@ -201,60 +185,67 @@ public class FTXSurfaceView extends SurfaceView implements SurfaceHolder.Callbac
@Override
public void destroyRender() {
mRender.stopRender();
removeAllViewObserver();
}
@Override
public void addViewObserver(CarrierViewObserver observer) {
if (null != observer) {
mViewObservers.add(new WeakReference<>(observer));
public void reDrawVod() {
// surfaceView will detach view, so reDraw will invalid
if (null != mRender) {
mRender.refreshRender();
}
}
@Override
public void removeViewObserver(CarrierViewObserver observer) {
int removeIndex = -1;
for (int i = 0; i < mViewObservers.size(); i++) {
WeakReference<CarrierViewObserver> observerWeakReference = mViewObservers.get(i);
if (observerWeakReference.get() == observer) {
removeIndex = i;
break;
}
}
if (removeIndex >= 0) {
mViewObservers.remove(removeIndex);
public void addSurfaceTextureListener(FTXCarrierSurfaceListener listener) {
if (null != listener && !mSurfaceListenerDelegate.mExternalSurfaceListeners.contains(listener)) {
mSurfaceListenerDelegate.mExternalSurfaceListeners.add(listener);
}
}
@Override
public void removeAllViewObserver() {
mViewObservers.clear();
public void removeSurfaceTextureListener(FTXCarrierSurfaceListener listener) {
if (null != listener) {
mSurfaceListenerDelegate.mExternalSurfaceListeners.remove(listener);
}
}
@Override
public List<WeakReference<CarrierViewObserver>> getViewObservers() {
return mViewObservers;
public void removeAllSurfaceListener() {
mSurfaceListenerDelegate.mExternalSurfaceListeners.clear();
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
LiteavLog.v(TAG, "surfaceCreated");
applySurfaceConfig(holder.getSurface(), 0, 0);
updateRenderSizeIfCan();
}
private static class SurfaceViewInnerListener implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
LiteavLog.v(TAG, "surfaceChanged");
applySurfaceConfig(holder.getSurface(), width, height);
}
private final List<FTXCarrierSurfaceListener> mExternalSurfaceListeners = new CopyOnWriteArrayList<>();
private final FTXSurfaceView mContainer;
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
LiteavLog.v(TAG, "onSurfaceTextureDestroyed");
if (null != mSurface) {
mSurface.release();
private SurfaceViewInnerListener(FTXSurfaceView container) {
this.mContainer = container;
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
LiteavLog.v(TAG, "onSurfaceTextureAvailable");
mContainer.applySurfaceConfig(holder.getSurface(), 0, 0);
mContainer.updateRenderSizeIfCan();
for (FTXCarrierSurfaceListener listener : mExternalSurfaceListeners) {
listener.onSurfaceTextureAvailable(mContainer.mSurface);
}
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
LiteavLog.v(TAG, "surfaceChanged");
mContainer.applySurfaceConfig(holder.getSurface(), width, height);
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
LiteavLog.v(TAG, "onSurfaceTextureDestroyed:" + mContainer.mSurface);
for (FTXCarrierSurfaceListener listener : mExternalSurfaceListeners) {
listener.onSurfaceTextureDestroyed(mContainer.mSurface);
}
mContainer.mSurface = null;
}
mSurface = null;
}
}
......@@ -8,10 +8,6 @@ import androidx.annotation.NonNull;
import com.tencent.liteav.base.util.LiteavLog;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class FTXTextureContainer extends FrameLayout {
private static final String TAG = "FTXTextureContainer";
......@@ -29,16 +25,8 @@ public class FTXTextureContainer extends FrameLayout {
LiteavLog.i(TAG, "start remove old carrier:" + mTextureHolder + ",view:" + hashCode());
removeView((View) mTextureHolder);
mTextureHolder.destroyRender();
mTextureHolder.removeAllSurfaceListener();
} else {
List<WeakReference<CarrierViewObserver>> mOldObservers = new ArrayList<>();
if (null != mTextureHolder) {
removeView((View) mTextureHolder);
mOldObservers.addAll(mTextureHolder.getViewObservers());
mTextureHolder.destroyRender();
}
for (WeakReference<CarrierViewObserver> ref : mOldObservers) {
carrier.addViewObserver(ref.get());
}
LiteavLog.i(TAG, "start add new carrier:" + carrier + ",view:" + hashCode());
addView((View) carrier);
}
......
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:label="super_player_example"
<application
android:icon="@mipmap/ic_launcher"
android:label="super_player_example"
android:requestLegacyExternalStorage="true"
tools:replace="android:label">
<activity
android:name="com.example.player.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:exported="true"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:screenOrientation="portrait"
android:supportsPictureInPicture="true"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="stateHidden"
tools:ignore="UnusedAttribute">
<!-- Specifies an Android theme to apply to this Activity as soon as
<!--
Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
to determine the Window background behind the Flutter UI.
-->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<!--
Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
Flutter's first frame.
-->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<!--
Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java
-->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
</manifest>
\ No newline at end of file
// Copyright (c) 2022 Tencent. All rights reserved.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:super_player/super_player.dart';
import 'package:super_player_example/res/app_localizations.dart';
import 'package:superplayer_widget/demo_superplayer_lib.dart';
import 'common/demo_config.dart';
import 'ui/demo_bitrate_checkbox.dart';
import 'ui/demo_inputdialog.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'ui/demo_volume_slider.dart';
import 'ui/demo_speed_slider.dart';
import 'ui/demo_bitrate_checkbox.dart';
import 'ui/demo_video_slider_view.dart';
import 'common/demo_config.dart';
import 'ui/demo_volume_slider.dart';
class DemoTXVodPlayer extends StatefulWidget {
@override
......@@ -75,7 +77,6 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb
await _controller.setLoop(true);
await _controller.enableHardwareDecode(enableHardware);
await _controller.setConfig(FTXVodPlayConfig());
await _controller.setStartTime(0);
await _controller.setRenderMode(_renderMode);
if (!isLicenseSuc.isCompleted) {
SuperPlayerPlugin.setGlobalLicense(LICENSE_URL, LICENSE_KEY);
......@@ -109,6 +110,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb
if (_isPlaying) {
_controller.resume();
}
_controller.reDraw();
break;
default:
break;
......
......@@ -736,6 +736,7 @@ extern void SetUpTXFlutterNativeAPIWithSuffix(id<FlutterBinaryMessenger> binaryM
- (void)setStringOptionPlayerMsg:(StringOptionPlayerMsg *)playerMsg error:(FlutterError *_Nullable *_Nonnull)error;
- (void)setPlayerViewRenderViewId:(NSInteger)renderViewId error:(FlutterError *_Nullable *_Nonnull)error;
- (void)setRenderModeRenderMode:(NSInteger)renderMode error:(FlutterError *_Nullable *_Nonnull)error;
- (void)reDrawWithError:(FlutterError *_Nullable *_Nonnull)error;
@end
extern void SetUpTXFlutterVodPlayerApi(id<FlutterBinaryMessenger> binaryMessenger, NSObject<TXFlutterVodPlayerApi> *_Nullable api);
......
......@@ -2817,6 +2817,23 @@ void SetUpTXFlutterVodPlayerApiWithSuffix(id<FlutterBinaryMessenger> binaryMesse
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc]
initWithName:[NSString stringWithFormat:@"%@%@", @"dev.flutter.pigeon.super_player.TXFlutterVodPlayerApi.reDraw", messageChannelSuffix]
binaryMessenger:binaryMessenger
codec:nullGetFtxMessagesCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(reDrawWithError:)], @"TXFlutterVodPlayerApi api (%@) doesn't respond to @selector(reDrawWithError:)", api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
FlutterError *error;
[api reDrawWithError:&error];
callback(wrapResult(nil, error));
}];
} else {
[channel setMessageHandler:nil];
}
}
}
void SetUpTXFlutterLivePlayerApi(id<FlutterBinaryMessenger> binaryMessenger, NSObject<TXFlutterLivePlayerApi> *api) {
SetUpTXFlutterLivePlayerApiWithSuffix(binaryMessenger, api, @"");
......
......@@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'super_player'
s.version = '12.5.1'
s.version = '12.6.0'
s.summary = 'The super_player Flutter plugin is one of the sub-product SDKs of the audio/video terminal SDK (Tencent Cloud Video on Demand).'
s.description = <<-DESC
player plugin.
......@@ -26,7 +26,7 @@ player plugin.
# Player_Premium SDK: s.dependency 'TXLiteAVSDK_Player_Premium'
# Professional SDK: s.dependency 'TXLiteAVSDK_Professional'
# If you want to specify the SDK version(eg 11.6.15041), use: s.dependency 'TXLiteAVSDK_Player','11.6.15041'
s.dependency 'TXLiteAVSDK_Player','12.5.18393'
s.dependency 'TXLiteAVSDK_Player','12.6.18866'
# s.dependency 'FTXPiPKit'
s.vendored_frameworks = [
'localdep/FTXPiPKit.xcframework'
......
......@@ -2,5 +2,5 @@
part of SuperPlayer;
abstract class FPlayerPckInfo {
static const String PLAYER_VERSION = "12.5.1";
static const String PLAYER_VERSION = "12.6.0";
}
\ No newline at end of file
......@@ -670,6 +670,8 @@ abstract class TXFlutterVodPlayerApi {
void setPlayerView(int renderViewId);
void setRenderMode(int renderMode);
void reDraw();
}
@HostApi()
......
......@@ -3154,6 +3154,28 @@ class TXFlutterVodPlayerApi {
return;
}
}
Future<void> reDraw() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.super_player.TXFlutterVodPlayerApi.reDraw$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_channel.send(null) as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
class TXFlutterLivePlayerApi {
......
......@@ -46,6 +46,7 @@ class TXPlayerVideoState extends State<TXPlayerVideo> {
int _viewId = -1;
Completer<int> _viewIdCompleter = Completer();
// for force rebuild
Key _platformViewKey = UniqueKey();
@override
......@@ -69,22 +70,21 @@ class TXPlayerVideoState extends State<TXPlayerVideo> {
if (defaultTargetPlatform == TargetPlatform.android) {
return IgnorePointer(
ignoring: true,
child: PlatformViewLink(
key: _platformViewKey,
surfaceFactory: (context, controller) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: _onCreatePlatformAndroidView,
viewType: _kFTXPlayerRenderViewType),
child: AndroidView(
key: _platformViewKey,
onPlatformViewCreated: _onCreateAndroidView,
viewType: _kFTXPlayerRenderViewType,
layoutDirection: TextDirection.ltr,
creationParams: {_kFTXAndroidRenderTypeKey : widget.renderViewType.index},
creationParamsCodec: const StandardMessageCodec(),
)
);
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
return IgnorePointer(
ignoring: true,
child: UiKitView(
key: _platformViewKey,
viewType: _kFTXPlayerRenderViewType,
layoutDirection: TextDirection.ltr,
creationParams: const {},
......@@ -97,40 +97,13 @@ class TXPlayerVideoState extends State<TXPlayerVideo> {
}
}
PlatformViewController _onCreatePlatformAndroidView(PlatformViewCreationParams params) {
void _onCreateAndroidView(int id) {
if (_viewIdCompleter.isCompleted) {
_viewIdCompleter = Completer();
}
_viewId = params.id;
_viewIdCompleter.complete(params.id);
widget.onRenderViewCreatedListener?.call(params.id);
if (widget.renderViewType == FTXAndroidRenderViewType.DRM_SURFACE_VIEW) {
return PlatformViewsService.initSurfaceAndroidView(
id: params.id,
viewType: _kFTXPlayerRenderViewType,
layoutDirection: TextDirection.ltr,
creationParams: {_kFTXAndroidRenderTypeKey : widget.renderViewType.index},
creationParamsCodec: const StandardMessageCodec(),
onFocus: () {
params.onFocusChanged(true);
},
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
} else {
return PlatformViewsService.initAndroidView(
id: params.id,
viewType: _kFTXPlayerRenderViewType,
layoutDirection: TextDirection.ltr,
creationParams: {_kFTXAndroidRenderTypeKey : widget.renderViewType.index},
creationParamsCodec: const StandardMessageCodec(),
onFocus: () {
params.onFocusChanged(true);
},
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
}
_viewId = id;
_viewIdCompleter.complete(id);
widget.onRenderViewCreatedListener?.call(id);
}
void _onCreateIOSView(int id) {
......
......@@ -643,6 +643,15 @@ class TXVodPlayerController extends ChangeNotifier implements ValueListenable<TX
await _vodPlayerApi.setRenderMode(renderMode.index);
}
///
/// only valid on Android
///
Future<void> reDraw() async {
if (_isNeedDisposed) return;
await _initPlayer.future;
await _vodPlayerApi.reDraw();
}
/// release controller
///
/// 释放controller
......
name: super_player
description: The super_player Flutter plugin is one of the sub-product SDKs of the audio/video terminal SDK (Tencent Cloud Video on Demand).
version: 12.5.1
version: 12.6.0
homepage: https://github.com/LiteAVSDK/Player_Flutter
environment:
......@@ -14,7 +14,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
pigeon: ^22.6.0
# pigeon: ^22.6.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
......
......@@ -3,5 +3,5 @@ part of demo_super_player_lib;
class PlayerConstants {
static const PKG_NAME = "superplayer_widget";
static const String PLAYER_WIDGET_VERSION = "12.5.1";
static const String PLAYER_WIDGET_VERSION = "12.6.0";
}
......@@ -60,4 +60,8 @@ enum SuperPlayerRenderMode {
ADJUST_RESOLUTION
}
abstract class SPConstants {
static const VALID_SUBTITLE_INDEX = -1;
}
......@@ -427,6 +427,11 @@ class SuperPlayerController {
_vodPlayerController.deselectTrack(tempInfo.trackIndex);
}
}
// clear deselect subtitle
if (trackInfo.trackIndex == SPConstants.VALID_SUBTITLE_INDEX) {
currentSubtitleData = null;
_observer?.onSubtitleData(currentSubtitleData);
}
}
}
......@@ -924,7 +929,7 @@ class FullScreenController {
Future<void> forceSwitchOrientation(int orientationDirection) async {
currentOrientation = orientationDirection;
if (orientationDirection == TXVodPlayEvent.ORIENTATION_PORTRAIT_UP) {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, overlays: SystemUiOverlay.values);
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
exitFullScreen();
} else if (orientationDirection == TXVodPlayEvent.ORIENTATION_LANDSCAPE_RIGHT) {
......
......@@ -32,7 +32,7 @@ class _SubtitleListState extends State<SubtitleListView> {
List<TXTrackInfo>? _trackInfoList;
TXTrackInfo? _currentTXTrackInfo;
final TXTrackInfo closeItem = TXTrackInfo(FSPLocal.current.txSubtitleTitleClose, -1, 0);
final TXTrackInfo closeItem = TXTrackInfo(FSPLocal.current.txSubtitleTitleClose, SPConstants.VALID_SUBTITLE_INDEX, 0);
List<DropdownMenuItem<int>> _colorSettingList = [
DropdownMenuItem(
......
......@@ -300,11 +300,11 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
_playController._updatePlayerUIStatus(SuperPlayerUIStatus.WINDOW_MODE);
_videoBottomKey.currentState?.updateUIStatus(SuperPlayerUIStatus.WINDOW_MODE);
_videoTitleKey.currentState?.updateUIStatus(SuperPlayerUIStatus.WINDOW_MODE);
hideControlView();
// exit full screen
setState(() {
_currentUIStatus = SuperPlayerUIStatus.WINDOW_MODE;
});
hideControlView();
if (_playController.playerType != SuperPlayerType.VOD) {
Future.delayed(Duration(milliseconds: 180), () async {
// reset render mode for live
......@@ -392,10 +392,15 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (_isPlaying && _currentUIStatus != SuperPlayerUIStatus.PIP_MODE) {
if (_currentUIStatus != SuperPlayerUIStatus.PIP_MODE) {
if (state == AppLifecycleState.resumed) {
// The page does not update the status when it returns from the background, and directly resumes.
_playController.getCurrentController().resume();
if (_isPlaying) {
_playController.getCurrentController().resume();
}
if (_playController.playerType == SuperPlayerType.VOD) {
_playController._vodPlayerController.reDraw();
}
checkBrightness();
// If the screen orientation is changed from landscape to portrait after returning from the background,
// switch to landscape mode based on the judgment made here.
......@@ -433,16 +438,11 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
Widget _getNoPaddingBody(BuildContext context) {
bool isFullMode = _currentUIStatus == SuperPlayerUIStatus.FULLSCREEN_MODE;
final Size screenSize = MediaQuery.of(context).size;
return OverflowBox(
alignment: Alignment.topCenter,
maxWidth: isFullMode ? double.infinity : null,
maxHeight: isFullMode ? double.infinity : null,
child: Center(
child: Container(
width: isFullMode ? screenSize.width : null,
height: isFullMode ? screenSize.height : null,
child: _getWidgetBody(),
),
return Center(
child: Container(
width: isFullMode ? screenSize.width : null,
height: isFullMode ? screenSize.height : null,
child: _getWidgetBody(),
),
);
}
......
name: superplayer_widget
description: superplayer,base on vodplayer
version: 12.5.1
version: 12.6.0
environment:
sdk: '>=2.17.0 <4.0.0'
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论