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