提交 525c9243 authored 作者: kongdywang's avatar kongdywang

pipController add exit callback & fix bug

上级 86800444
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.os.Bundle;
......@@ -40,6 +41,9 @@ public class CommonUtil {
return param;
}
/**
* 通过宽高获得对应的缓存视频清晰度
*/
public static int getCacheVideoQuality(Integer width, Integer height) {
if (width == null || height == null) {
return TXVodDownloadDataSource.QUALITY_FLU;
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.content.Context;
......@@ -18,7 +19,7 @@ import java.util.List;
*/
public class FTXAudioManager {
private final static String TAG = "FTXAudioManager";
private static final String TAG = "FTXAudioManager";
private AudioManager mAudioManager;
private AudioFocusRequest mFocusRequest;
......@@ -116,6 +117,9 @@ public class FTXAudioManager {
}
}
/**
* 请求获取音频焦点
*/
public void requestAudioFocus() {
int result;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
......@@ -141,7 +145,7 @@ public class FTXAudioManager {
}
public void addAudioFocusChangedListener(AudioFocusChangeListener listener) {
if(!mAudioFocusListeners.contains(listener)) {
if (!mAudioFocusListeners.contains(listener)) {
mAudioFocusListeners.add(listener);
}
}
......@@ -151,19 +155,20 @@ public class FTXAudioManager {
}
void onAudioFocusPause() {
for(AudioFocusChangeListener listener : mAudioFocusListeners) {
for (AudioFocusChangeListener listener : mAudioFocusListeners) {
listener.onAudioFocusPause();
}
}
void onAudioFocusPlay() {
for(AudioFocusChangeListener listener : mAudioFocusListeners) {
for (AudioFocusChangeListener listener : mAudioFocusListeners) {
listener.onAudioFocusPlay();
}
}
interface AudioFocusChangeListener {
void onAudioFocusPause();
void onAudioFocusPlay();
}
}
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import java.util.concurrent.atomic.AtomicInteger;
/**
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.os.Bundle;
......@@ -29,18 +30,23 @@ import io.flutter.plugin.common.MethodChannel;
*/
public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXVodDownloadListener {
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
final private MethodChannel mMethodChannel;
private final MethodChannel mMethodChannel;
private final EventChannel mEventChannel;
final private FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private Handler mMainHandler;
/**
* 视频下载管理
*/
public FTXDownloadManager(FlutterPlugin.FlutterPluginBinding flutterPluginBinding) {
mFlutterPluginBinding = flutterPluginBinding;
mMainHandler = new Handler(mFlutterPluginBinding.getApplicationContext().getMainLooper());
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/txvodplayer/download/api");
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/txvodplayer/download/api");
mMethodChannel.setMethodCallHandler(this);
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/txvodplayer/download/event");
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/txvodplayer/download/event");
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -92,8 +98,8 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
if (!TextUtils.isEmpty(videoUrl)) {
TXVodDownloadManager.getInstance().startDownloadUrl(videoUrl, userName);
} else if (null != appId && null != fileId) {
TXVodDownloadDataSource dataSource = new TXVodDownloadDataSource(appId, fileId, optQuality(quality), pSign,
userName);
TXVodDownloadDataSource dataSource =
new TXVodDownloadDataSource(appId, fileId, optQuality(quality), pSign, userName);
TXVodDownloadManager.getInstance().startDownload(dataSource);
}
result.success(null);
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
/**
......@@ -41,7 +42,7 @@ public class FTXEvent {
*/
public static final String PIP_CHANNEL_NAME = "cloud.tencent.com/playerPlugin/componentEvent";
// pip广播action
public final static String ACTION_PIP_PLAY_CONTROL = "vodPlayControl";
public static final String ACTION_PIP_PLAY_CONTROL = "vodPlayControl";
// pip 操作
public static final String EXTRA_NAME_PLAY_OP = "vodPlayOp";
// pip需要操作的播放器
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.app.Activity;
......@@ -29,15 +30,15 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
private static final String TAG = "FTXLivePlayer";
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
final private MethodChannel mMethodChannel;
private final MethodChannel mMethodChannel;
private final EventChannel mEventChannel;
private final EventChannel mNetChannel;
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
final private FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
final private FTXPlayerEventSink mNetStatusSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mNetStatusSink = new FTXPlayerEventSink();
private TXLivePlayer mLivePlayer;
private static final int Uninitialized = -101;
......@@ -46,6 +47,9 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
private TextureRegistry.SurfaceTextureEntry mSurfaceTextureEntry;
private Activity mActivity;
private int mSurfaceWidth = 0;
private int mSurfaceHeight = 0;
private final FTXPIPManager mPipManager;
private FTXPIPManager.PipParams mPipParams;
private VideoModel mVideoModel;
......@@ -54,12 +58,15 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
public void onPipResult(PipResult result) {
// 启动pip的时候,当前player已经暂停,pip退出之后,如果退出的时候pip还处于播放状态,那么当前player也置为播放状态
boolean isPipPlaying = result.isPlaying();
if(isPipPlaying) {
if (isPipPlaying) {
resume();
}
}
};
/**
* 直播播放器
*/
public FTXLivePlayer(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, Activity activity,
FTXPIPManager pipManager) {
super();
......@@ -73,10 +80,12 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
mSurfaceTexture = mSurfaceTextureEntry.surfaceTexture();
mSurface = new Surface(mSurfaceTexture);
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/txliveplayer/" + super.getPlayerId());
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/txliveplayer/" + super.getPlayerId());
mMethodChannel.setMethodCallHandler(this);
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/txliveplayer/event/" + super.getPlayerId());
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/txliveplayer/event/" + super.getPlayerId());
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -89,7 +98,8 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
}
});
mNetChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/txliveplayer/net/" + super.getPlayerId());
mNetChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/txliveplayer/net/" + super.getPlayerId());
mNetChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -242,11 +252,11 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
mPipParams.setIsPlaying(isPlaying());
int pipResult = mPipManager.enterPip(mPipParams, mVideoModel);
// 启动成功之后,暂停当前界面视频
if(pipResult == FTXEvent.NO_ERROR) {
if (pipResult == FTXEvent.NO_ERROR) {
pause();
}
result.success(pipResult);
} else if(call.method.equals("exitPictureInPictureMode")) {
} else if (call.method.equals("exitPictureInPictureMode")) {
mPipManager.exitPip();
result.success(null);
} else if (call.method.equals("setConfig")) {
......@@ -267,8 +277,6 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
return mSurfaceTextureEntry == null ? -1 : mSurfaceTextureEntry.id();
}
private int mSurfaceWidth, mSurfaceHeight = 0;
int startLivePlay(String url, int type) {
Log.d(TAG, "startLivePlay:");
mVideoModel.setVideoUrl(url);
......
......@@ -77,6 +77,7 @@ public class FTXPIPManager {
};
/**
* 画中画管理
* @param mTxAudioManager 音频管理,用于画中画模式下请求音频焦点
* @param activityBinding activityBinding
* @param flutterAssets flutter资源管理
......@@ -159,6 +160,9 @@ public class FTXPIPManager {
}
}
/**
* 设备是否支持画中画
*/
public int isSupportDevice() {
int pipResult = FTXEvent.NO_ERROR;
Activity activity = mActivityBinding.getActivity();
......@@ -176,8 +180,8 @@ public class FTXPIPManager {
}
} else {
pipResult = FTXEvent.ERROR_PIP_LOWER_VERSION;
Log.e(TAG, "enterPip failed,because android version is too low,Minimum supported version is android " +
"24,but current is " + Build.VERSION.SDK_INT);
Log.e(TAG, "enterPip failed,because android version is too low,Minimum supported version is android "
+ "24,but current is " + Build.VERSION.SDK_INT);
}
} else {
pipResult = FTXEvent.ERROR_PIP_ACTIVITY_DESTROYED;
......@@ -259,6 +263,7 @@ public class FTXPIPManager {
private float mCurrentPlayTime = 0;
/**
* 画中画参数
* @param mPlayBackAssetPath 回退按钮图片资源路径,传空则使用系统默认图标, 地址必须经过toAndroidPath转换
* @param mPlayResumeAssetPath 播放按钮图片资源路径,传空则使用系统默认图标, 地址必须经过toAndroidPath转换
* @param mPlayPauseAssetPath 暂停按钮图片资源路径,传空则使用系统默认图标, 地址必须经过toAndroidPath转换
......@@ -329,9 +334,11 @@ public class FTXPIPManager {
this.mCurrentPlayTime = mCurrentPlayTime;
}
/**
* 构造画中画参数
*/
@RequiresApi(api = VERSION_CODES.O)
public PictureInPictureParams buildParams(Activity activity) {
PictureInPictureParams.Builder mPipParams = new Builder();
List<RemoteAction> actions = new ArrayList<>();
// play back
if (mIsNeedPlayBack) {
......@@ -373,6 +380,7 @@ public class FTXPIPManager {
actions.add(nextAction);
}
PictureInPictureParams.Builder mPipParams = new Builder();
mPipParams.setActions(actions);
return mPipParams.build();
}
......@@ -404,7 +412,8 @@ public class FTXPIPManager {
Bitmap iconBitmap = BitmapFactory.decodeStream(activity.getAssets().open(path));
return Icon.createWithBitmap(iconBitmap);
}
} catch (IOException ignored) {
} catch (IOException e) {
Log.getStackTraceString(e);
}
return Icon.createWithResource(activity, defaultResId);
}
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import java.util.LinkedList;
......@@ -21,13 +22,17 @@ public class FTXPlayerEventSink implements EventChannel.EventSink {
}
private void enqueue(Object event) {
if (isEnd) return;
if (isEnd) {
return;
}
eventQueue.offer(event);
}
private void consume() {
if (eventSink == null) return;
while (!eventQueue.isEmpty()){
if (eventSink == null) {
return;
}
while (!eventQueue.isEmpty()) {
Object event = eventQueue.poll();
if (event instanceof EndEvent) {
eventSink.endOfStream();
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.text.TextUtils;
......@@ -14,6 +15,9 @@ import java.util.Map;
*/
public class FTXTransformation {
/**
* 将map转换为config
*/
@SuppressWarnings("unchecked")
public static TXVodPlayConfig transformToVodConfig(Map<Object, Object> config) {
TXVodPlayConfig playConfig = new TXVodPlayConfig();
......@@ -30,7 +34,7 @@ public class FTXTransformation {
playConfig.setTimeout(timeout);
}
Integer playerType = (Integer) config.get("playerType");
if(null != playerType) {
if (null != playerType) {
playConfig.setPlayerType(playerType);
}
Map<String, String> headers = (Map<String, String>) config.get("headers");
......@@ -39,15 +43,15 @@ public class FTXTransformation {
}
playConfig.setHeaders(headers);
Boolean enableAccurateSeek = (Boolean) config.get("enableAccurateSeek");
if(null != enableAccurateSeek) {
if (null != enableAccurateSeek) {
playConfig.setEnableAccurateSeek(enableAccurateSeek);
}
Boolean autoRotate = (Boolean) config.get("autoRotate");
if(null != autoRotate) {
if (null != autoRotate) {
playConfig.setAutoRotate(autoRotate);
}
Boolean smoothSwitchBitrate = (Boolean) config.get("smoothSwitchBitrate");
if(null != smoothSwitchBitrate) {
if (null != smoothSwitchBitrate) {
playConfig.setSmoothSwitchBitrate(smoothSwitchBitrate);
}
String cacheMp4ExtName = (String) config.get("cacheMp4ExtName");
......@@ -67,11 +71,11 @@ public class FTXTransformation {
playConfig.setMaxPreloadSize(maxPreloadSize);
}
Integer firstStartPlayBufferTime = (Integer) config.get("firstStartPlayBufferTime");
if(null != firstStartPlayBufferTime) {
if (null != firstStartPlayBufferTime) {
playConfig.setFirstStartPlayBufferTime(firstStartPlayBufferTime);
}
Integer nextStartPlayBufferTime = (Integer) config.get("nextStartPlayBufferTime");
if(null != nextStartPlayBufferTime) {
if (null != nextStartPlayBufferTime) {
playConfig.setNextStartPlayBufferTime(nextStartPlayBufferTime);
}
......@@ -89,7 +93,7 @@ public class FTXTransformation {
}
playConfig.setExtInfo(extInfoMap);
Boolean enableRenderProcess = (Boolean) config.get("enableRenderProcess");
if(null != enableRenderProcess) {
if (null != enableRenderProcess) {
playConfig.setEnableRenderProcess(enableRenderProcess);
}
String preferredResolutionStr = (String) config.get("preferredResolution");
......@@ -101,50 +105,53 @@ public class FTXTransformation {
return playConfig;
}
/**
* map转config
*/
public static TXLivePlayConfig transformToLiveConfig(Map<Object, Object> config) {
TXLivePlayConfig livePlayConfig = new TXLivePlayConfig();
Double cacheTime = (Double) config.get("cacheTime");
if(doubleIsNotEmpty(cacheTime)) {
if (doubleIsNotEmpty(cacheTime)) {
livePlayConfig.setCacheTime(cacheTime.floatValue());
}
Double maxAutoAdjustCacheTime = (Double) config.get("maxAutoAdjustCacheTime");
if(doubleIsNotEmpty(maxAutoAdjustCacheTime)) {
if (doubleIsNotEmpty(maxAutoAdjustCacheTime)) {
livePlayConfig.setMaxAutoAdjustCacheTime(maxAutoAdjustCacheTime.floatValue());
}
Double minAutoAdjustCacheTime = (Double) config.get("minAutoAdjustCacheTime");
if(doubleIsNotEmpty(minAutoAdjustCacheTime)) {
if (doubleIsNotEmpty(minAutoAdjustCacheTime)) {
livePlayConfig.setMinAutoAdjustCacheTime(minAutoAdjustCacheTime.floatValue());
}
Integer videoBlockThreshold = (Integer) config.get("videoBlockThreshold");
if(intIsNotEmpty(videoBlockThreshold)) {
if (intIsNotEmpty(videoBlockThreshold)) {
livePlayConfig.setVideoBlockThreshold(videoBlockThreshold);
}
Integer connectRetryCount = (Integer) config.get("connectRetryCount");
if(intIsNotEmpty(connectRetryCount)) {
if (intIsNotEmpty(connectRetryCount)) {
livePlayConfig.setConnectRetryCount(connectRetryCount);
}
Integer connectRetryInterval = (Integer) config.get("connectRetryInterval");
if(intIsNotEmpty(connectRetryInterval)) {
if (intIsNotEmpty(connectRetryInterval)) {
livePlayConfig.setConnectRetryInterval(connectRetryInterval);
}
Boolean autoAdjustCacheTime = (Boolean) config.get("autoAdjustCacheTime");
if(null != autoAdjustCacheTime) {
if (null != autoAdjustCacheTime) {
livePlayConfig.setAutoAdjustCacheTime(autoAdjustCacheTime);
}
Boolean enableAec= (Boolean) config.get("enableAec");
if(null != enableAec) {
Boolean enableAec = (Boolean) config.get("enableAec");
if (null != enableAec) {
livePlayConfig.setEnableAEC(enableAec);
}
Boolean enableMessage = (Boolean) config.get("enableMessage");
if(null != enableMessage) {
if (null != enableMessage) {
livePlayConfig.setEnableMessage(enableMessage);
}
Boolean enableMetaData = (Boolean) config.get("enableMetaData");
if(null != enableMetaData) {
if (null != enableMetaData) {
livePlayConfig.setEnableMetaData(enableMetaData);
}
String flvSessionKey = (String) config.get("flvSessionKey");
if(!TextUtils.isEmpty(flvSessionKey)) {
if (!TextUtils.isEmpty(flvSessionKey)) {
livePlayConfig.setFlvSessionKey(flvSessionKey);
}
return livePlayConfig;
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.graphics.Bitmap;
......@@ -35,15 +36,15 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
final private MethodChannel mMethodChannel;
private final MethodChannel mMethodChannel;
private final EventChannel mEventChannel;
private final EventChannel mNetChannel;
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
final private FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
final private FTXPlayerEventSink mNetStatusSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mNetStatusSink = new FTXPlayerEventSink();
private TXVodPlayer mVodPlayer;
private TXImageSprite mTxImageSprite;
......@@ -67,12 +68,15 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
seek(playTime);
// 启动pip的时候,当前player已经暂停,pip退出之后,如果退出的时候pip还处于播放状态,那么当前player也置为播放状态
boolean isPipPlaying = result.isPlaying();
if(isPipPlaying) {
if (isPipPlaying) {
resume();
}
}
};
/**
* 点播播放器
*/
public FTXVodPlayer(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, FTXPIPManager pipManager) {
super();
mPipManager = pipManager;
......@@ -80,12 +84,12 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
mVideoModel = new VideoModel();
mVideoModel.setPlayerType(FTXEvent.PLAYER_VOD);
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent" +
".com/txvodplayer/" + super.getPlayerId());
mMethodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent"
+ ".com/txvodplayer/" + super.getPlayerId());
mMethodChannel.setMethodCallHandler(this);
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent" +
".com/txvodplayer/event/" + super.getPlayerId());
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent"
+ ".com/txvodplayer/event/" + super.getPlayerId());
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -98,8 +102,8 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
}
});
mNetChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent" +
".com/txvodplayer/net/" + super.getPlayerId());
mNetChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent"
+ ".com/txvodplayer/net/" + super.getPlayerId());
mNetChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -147,9 +151,9 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
@Override
public void onPlayEvent(TXVodPlayer txVodPlayer, int event, Bundle bundle) {
if (event == TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION) {
String EVT_PARAM3 = bundle.getString("EVT_PARAM3");
if (!TextUtils.isEmpty(EVT_PARAM3)) {
String[] array = EVT_PARAM3.split(",");
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;
......@@ -182,7 +186,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
// surface 的大小默认是宽高为1,当硬解失败时或使用软解时,软解会依赖surface的窗口渲染,不更新会导致只有1px的内容
private void setDefaultBufferSizeForSoftDecode(int width, int height) {
if (mSurfaceTextureEntry!= null && mSurfaceTextureEntry.surfaceTexture() != null) {
if (mSurfaceTextureEntry != null && mSurfaceTextureEntry.surfaceTexture() != null) {
SurfaceTexture surfaceTexture = mSurfaceTextureEntry.surfaceTexture();
surfaceTexture.setDefaultBufferSize(width, height);
if (mSurface != null) {
......@@ -341,26 +345,26 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
mPipParams.setCurrentPlayTime(getCurrentPlaybackTime());
int pipResult = mPipManager.enterPip(mPipParams, mVideoModel);
// 启动成功之后,暂停当前界面视频
if(pipResult == FTXEvent.NO_ERROR) {
if (pipResult == FTXEvent.NO_ERROR) {
pause();
}
result.success(pipResult);
} else if(call.method.equals("exitPictureInPictureMode")) {
} else if (call.method.equals("exitPictureInPictureMode")) {
mPipManager.exitPip();
result.success(null);
} else if(call.method.equals("initImageSprite")) {
} else if (call.method.equals("initImageSprite")) {
String vvtUrl = call.argument("vvtUrl");
List<String> imageUrls = call.argument("imageUrls");
mTxImageSprite.setVTTUrlAndImageUrls(vvtUrl,imageUrls);
result.success(null);
} else if(call.method.equals("getImageSprite")) {
} else if (call.method.equals("getImageSprite")) {
final Double time = call.argument("time");
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = mTxImageSprite.getThumbnail(time.floatValue());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
if(null != bitmap) {
if (null != bitmap) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
result.success(byteArray);
......@@ -398,11 +402,11 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
}
int startVodPlay(String url) {
if (mVodPlayer != null) {
mVideoModel.setVideoUrl(url);
mVideoModel.setAppId(0);
mVideoModel.setFileId("");
mVideoModel.setPSign("");
if (mVodPlayer != null) {
return mVodPlayer.startVodPlay(url);
}
return Uninitialized;
......@@ -573,8 +577,10 @@ public class FTXVodPlayer extends FTXBasePlayer implements MethodChannel.MethodC
if (mVodPlayer != null) {
if (TextUtils.isEmpty(token)) {
mVodPlayer.setToken(null);
mVideoModel.setToken(null);
} else {
mVodPlayer.setToken(token);
mVideoModel.setToken(token);
}
}
}
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter;
import android.content.BroadcastReceiver;
......@@ -40,6 +41,7 @@ import io.flutter.plugin.common.MethodChannel.Result;
* The MethodChannel that will the communication between Flutter and native Android
* This local reference serves to register the plugin with the Flutter Engine and unregister it
* when the Flutter Engine is detached from the Activity
* </p>
*/
public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
......@@ -84,7 +86,8 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
channel.setMethodCallHandler(this);
mPlayers = new SparseArray();
initAudioManagerIfNeed();
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent.com/playerPlugin/event");
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),
"cloud.tencent.com/playerPlugin/event");
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
......@@ -109,7 +112,8 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
mPlayers.append(playerId, player);
result.success(playerId);
} else if (call.method.equals("createLivePlayer")) {
FTXLivePlayer player = new FTXLivePlayer(mFlutterPluginBinding, mActivityPluginBinding.getActivity(), mTxPipManager);
FTXLivePlayer player = new FTXLivePlayer(mFlutterPluginBinding, mActivityPluginBinding.getActivity(),
mTxPipManager);
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
......@@ -186,11 +190,11 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
result.success(mTxPipManager.isSupportDevice());
} else if (call.method.equals("getLiteAVSDKVersion")) {
result.success(TXLiveBase.getSDKVersionStr());
} else if(call.method.equals("setGlobalEnv")) {
} else if (call.method.equals("setGlobalEnv")) {
String envConfig = call.argument("envConfig");
int setResult = TXLiveBase.setGlobalEnv(envConfig);
result.success(setResult);
} else if(call.method.equals("startVideoOrientationService")) {
} else if (call.method.equals("startVideoOrientationService")) {
boolean setResult = startVideoOrientationService();
result.success(setResult);
} else {
......@@ -199,11 +203,11 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
}
private boolean startVideoOrientationService() {
if(null == mFlutterPluginBinding) {
if (null == mFlutterPluginBinding) {
return false;
}
if(null == mOrientationManager) {
try{
if (null == mOrientationManager) {
try {
mOrientationManager = new OrientationEventListener(mFlutterPluginBinding.getApplicationContext()) {
@Override
public void onOrientationChanged(int orientation) {
......@@ -300,7 +304,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
*/
protected boolean isAutoRotateOn() {
//获取系统是否允许自动旋转屏幕
try{
try {
return (android.provider.Settings.System.getInt(
mFlutterPluginBinding.getApplicationContext().getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
......
......@@ -18,6 +18,7 @@ public class VideoModel implements Parcelable {
private String pSign;
private int mPlayerType = FTXEvent.PLAYER_VOD;
private int mLiveType = TXLivePlayer.PLAY_TYPE_LIVE_FLV;
private String mToken;
public VideoModel() {}
......@@ -28,6 +29,7 @@ public class VideoModel implements Parcelable {
pSign = in.readString();
mPlayerType = in.readInt();
mLiveType = in.readInt();
mToken = in.readString();
}
public static final Creator<VideoModel> CREATOR = new Creator<VideoModel>() {
......@@ -50,6 +52,14 @@ public class VideoModel implements Parcelable {
this.videoUrl = videoUrl;
}
public String getToken() {
return mToken;
}
public void setToken(String token) {
this.mToken = token;
}
public int getAppId() {
return appId;
}
......@@ -103,5 +113,6 @@ public class VideoModel implements Parcelable {
dest.writeString(pSign);
dest.writeInt(mPlayerType);
dest.writeInt(mLiveType);
dest.writeString(mToken);
}
}
......@@ -79,6 +79,9 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
case FTXEvent.EXTRA_PIP_PLAY_FORWARD:
handlePlayForward();
break;
default:
Log.e(TAG, "unknown control code");
break;
}
}
}
......@@ -88,7 +91,6 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerPipBroadcast();
Intent intent = getIntent();
PipParams params = intent.getParcelableExtra(FTXEvent.EXTRA_NAME_PARAMS);
if (null == params) {
......@@ -102,6 +104,7 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
configPipMode(null);
}
}
registerPipBroadcast();
handleIntent(intent);
setContentView(R.layout.activity_flutter_pip_impl);
mVodPlayer = new TXVodPlayer(this);
......@@ -161,6 +164,11 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
@Override
public void onPictureInPictureUiStateChanged(@NonNull PictureInPictureUiState pipState) {
super.onPictureInPictureUiStateChanged(pipState);
......@@ -274,6 +282,7 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
if (mVideoModel.getPlayerType() == FTXEvent.PLAYER_VOD) {
mVodPlayer.setStartTime(playTime);
mVodPlayer.setAutoPlay(isPlaying);
mVodPlayer.setToken(mVideoModel.getToken());
if (!TextUtils.isEmpty(mVideoModel.getVideoUrl())) {
mVodPlayer.startVodPlay(mVideoModel.getVideoUrl());
} else if (!TextUtils.isEmpty(mVideoModel.getFileId())) {
......@@ -293,11 +302,6 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
}
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsSurfaceCreated = true;
......@@ -319,7 +323,6 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
@Override
protected void onStop() {
super.onStop();
unRegisterPipBroadcast();
mVodPlayer.stopPlay(true);
mLivePlayer.stopPlay(true);
mIsNeedToStop = true;
......@@ -333,6 +336,7 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
@Override
protected void onDestroy() {
unRegisterPipBroadcast();
super.onDestroy();
}
......@@ -413,22 +417,22 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
@Override
public void onPlayEvent(TXVodPlayer txVodPlayer, int event, Bundle bundle) {
if (VERSION.SDK_INT >= VERSION_CODES.N && isInPictureInPictureMode()) {
if(null != mCurrentParams) {
if (null != mCurrentParams) {
if (event == TXLiveConstants.PLAY_EVT_PLAY_END) {
// 播放完毕的时候,自动将播放按钮置为播放
mCurrentParams.setIsPlaying(false);
} else if(event == TXLiveConstants.PLAY_EVT_PLAY_BEGIN) {
} else if (event == TXLiveConstants.PLAY_EVT_PLAY_BEGIN) {
// 播放开始的时候,自动将播放按钮置为暂停
mCurrentParams.setIsPlaying(true);
}
updatePip(mCurrentParams);
}
if(event == TXLiveConstants.PLAY_EVT_PLAY_PROGRESS) {
if (event == TXLiveConstants.PLAY_EVT_PLAY_PROGRESS) {
int progress = bundle.getInt(TXLiveConstants.EVT_PLAY_PROGRESS_MS);
int duration = bundle.getInt(TXLiveConstants.EVT_PLAY_DURATION_MS);
float percentage = (progress / 1000F) / (duration / 1000F);
final int progressToShow = Math.round(percentage * mVideoProgress.getMax());
if(null != mVideoProgress) {
if (null != mVideoProgress) {
mVideoProgress.post(new Runnable() {
@Override
public void run() {
......@@ -441,11 +445,11 @@ public class FlutterPipImplActivity extends FlutterActivity implements Callback,
}
@Override
public void onNetStatus(TXVodPlayer txVodPlayer, Bundle bundle) {
public void onPlayEvent(int event, Bundle bundle) {
}
@Override
public void onPlayEvent(int event, Bundle bundle) {
public void onNetStatus(TXVodPlayer txVodPlayer, Bundle bundle) {
}
@Override
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player_example">
package="com.example.player">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.super_player_example">
package="com.example.player">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
......@@ -11,7 +11,7 @@
android:requestLegacyExternalStorage="true"
tools:replace="android:label">
<activity
android:name=".MainActivity"
android:name="com.example.player.MainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true"
android:launchMode="singleTask"
......
// Copyright (c) 2022 Tencent. All rights reserved.
package com.example.super_player_example;
package com.example.player;
import io.flutter.embedding.android.FlutterActivity;
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player_example">
package="com.example.player">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
......
// Copyright (c) 2022 Tencent. All rights reserved.
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
......
// Copyright (c) 2022 Tencent. All rights reserved.
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
......
......@@ -26,6 +26,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
List<SuperPlayerModel> videoModels = [];
bool _isFullScreen = false;
late SuperPlayerController _controller;
SuperVodDataLoader loader = SuperVodDataLoader();
StreamSubscription? simpleEventSubscription;
int tabSelectPos = 0;
SuperPlayerModel? currentVideoModel;
......@@ -212,7 +213,12 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
return;
}
playCurrentModel(model, 0);
loader.getVideoData(model, (resultModel) {
setState(() {
videoModels.add(resultModel);
});
playCurrentModel(resultModel, 0);
});
},
needPisgn: !isLive,
showFileEdited: !isLive,
......@@ -327,7 +333,6 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
models.add(model);
List<Future<void>> requestList = [];
SuperVodDataLoader loader = SuperVodDataLoader();
for (SuperPlayerModel tempModel in models) {
requestList.add(loader.getVideoData(tempModel, (_) {}));
}
......
......@@ -23,6 +23,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
String _url =
"http://liteavapp.qcloud.com/live/liteavdemoplayerstreamid_demo1080p.flv";
bool _isStop = true;
bool _isPlaying = false;
double _maxLiveProgressTime = 0;
StreamSubscription? playEventSubscription;
StreamSubscription? playNetEventSubscription;
......@@ -45,6 +46,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {
//首帧出现
_isStop = false;
_isPlaying = true;
EasyLoading.dismiss();
} else if (event["event"] == TXVodPlayEvent.PLAY_EVT_STREAM_SWITCH_SUCC) {
//切换流成功
......@@ -102,7 +104,9 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
case AppLifecycleState.inactive:
break;
case AppLifecycleState.resumed:
if(_isPlaying) {
_controller.resume();
}
break;
case AppLifecycleState.paused:
_controller.pause();
......@@ -181,6 +185,7 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
EasyLoading.showError('已经停止播放, 请重新播放');
return;
}
_isPlaying = false;
_controller.pause();
},
child: Container(
......
......@@ -30,6 +30,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer>
double _rate = 1.0;
bool enableHardware = true;
int volume = 80;
bool _isPlaying = false;
StreamSubscription? playEventSubscription;
StreamSubscription? playNetEventSubscription;
......@@ -52,6 +53,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer>
event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {
EasyLoading.dismiss();
_supportedBitrates = (await _controller.getSupportedBitrates())!;
_isPlaying = true;
} else if (event["event"] == TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS) {
_currentProgress = event[TXVodPlayEvent.EVT_PLAY_PROGRESS].toDouble();
double videoDuration = event[TXVodPlayEvent.EVT_PLAY_DURATION].toDouble(); // 总播放时长,转换后的单位 秒
......@@ -103,7 +105,9 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer>
case AppLifecycleState.inactive:
break;
case AppLifecycleState.resumed:
if(_isPlaying) {
_controller.resume();
}
break;
case AppLifecycleState.paused:
_controller.pause();
......@@ -187,7 +191,9 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer>
),
),
new GestureDetector(
onTap: () => {_controller.pause()},
onTap: () {
_isPlaying = false;
_controller.pause();},
child: Container(
alignment: Alignment.center,
child: Text(
......
......@@ -125,7 +125,7 @@ class _DemoInputDialogState extends State<DemoInputDialog> {
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green.withOpacity(0.4), width: 3.0)),
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10.0)), borderSide: BorderSide(color: Colors.green, width: 4.0)),
labelText:"请输入fileId", labelStyle: TextStyle(color: Colors.grey),
labelText:"请输入fileid", labelStyle: TextStyle(color: Colors.grey),
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: () {
......
......@@ -6,8 +6,8 @@
@interface CommonUtil : NSObject
+(int)getCacheVideoQuality:(int)width height:(int)pHeight;
+(NSNumber*)getCacheVideoQuality:(int)width height:(int)pHeight;
+(int)getDownloadEventByState:(int)downloadState;
+(NSNumber*)getDownloadEventByState:(int)downloadState;
@end
......@@ -4,7 +4,7 @@
@implementation CommonUtil
+ (int)getCacheVideoQuality:(int)width height:(int)pHeight{
+ (NSNumber*)getCacheVideoQuality:(int)width height:(int)pHeight{
int minValue = MIN(width, pHeight);
int cacheQualityIndex;
if (minValue == 240 || minValue == 180) {
......@@ -24,10 +24,10 @@
} else {
cacheQualityIndex = TXVodQualityFLU;
}
return cacheQualityIndex;
return [NSNumber numberWithInt:cacheQualityIndex];
}
+ (int)getDownloadEventByState:(int)downloadState{
+ (NSNumber*)getDownloadEventByState:(int)downloadState{
int result;
switch (downloadState) {
case TXVodDownloadMediaInfoStateInit:
......@@ -49,7 +49,7 @@
result = EVENT_DOWNLOAD_ERROR;
break;
}
return result;
return [NSNumber numberWithInt:result];;
}
......
......@@ -6,9 +6,9 @@
@interface FTXAudioManager : NSObject
- (float)getVolume;
- (CGFloat)getVolume;
- (void)setVolume:(float)value;
- (void)setVolume:(CGFloat)value;
- (void)setVolumeUIVisible:(BOOL)volumeUIVisible;
......
......@@ -34,13 +34,13 @@ NSString *const NOTIFCATION_NAME = @"SystemVolumeDidChange";
return self;
};
- (float)getVolume
- (CGFloat)getVolume
{
return _volumeSlider.value > 0 ? _volumeSlider.value : [[AVAudioSession sharedInstance]outputVolume];
}
- (void)setVolume:(float)value
- (void)setVolume:(CGFloat)value
{
// 需要设置 showsVolumeSlider 为 YES
volumeView.showsVolumeSlider = YES;
......
......@@ -211,7 +211,7 @@
if(nil != info && [NSNull null] != (NSNull *)info) {
[dict setValue:info.playPath forKey:@"playPath"];
[dict setValue:@(info.progress) forKey:@"progress"];
[dict setValue:@([CommonUtil getDownloadEventByState:(int)info.downloadState]) forKey:@"downloadState"];
[dict setValue:[CommonUtil getDownloadEventByState:(int)info.downloadState] forKey:@"downloadState"];
[dict setValue:info.userName forKey:@"userName"];
[dict setValue:@(info.duration) forKey:@"duration"];
[dict setValue:@(info.playableDuration) forKey:@"playableDuration"];
......
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef FTXEvent_h
#define FTXEvent_h
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXEVENT_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXEVENT_H_
// 音频变化事件code
#define EVENT_VOLUME_CHANGED 1
......@@ -59,4 +59,4 @@
// 横屏,底部在左
#define ORIENTATION_LANDSCAPE_LEFT 414
#endif /* FTXEvent_h */
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXEVENT_H_
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXLIVEPLAYER_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXLIVEPLAYER_H_
#import <Foundation/Foundation.h>
#import "FTXBasePlayer.h"
......@@ -14,3 +16,5 @@ NS_ASSUME_NONNULL_BEGIN
@end
NS_ASSUME_NONNULL_END
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXLIVEPLAYER_H_
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXPLAYEREVENTSINKQUEUE_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXPLAYEREVENTSINKQUEUE_H_
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
......@@ -7,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface FTXPlayerEventSinkQueue : NSObject
- (void)success:(NSObject *)event;
- (void)success:(id)event;
- (void)setDelegate:(_Nullable FlutterEventSink)sink;
- (void)error:(NSString *)code
......@@ -17,3 +19,4 @@ NS_ASSUME_NONNULL_BEGIN
@end
NS_ASSUME_NONNULL_END
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXPLAYEREVENTSINKQUEUE_H_
......@@ -14,7 +14,7 @@
#pragma mark - public
- (void)success:(NSObject *)event
- (void)success:(id)event
{
[self enqueue:event];
[self flushIfNeed];
......
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXTRANSFORMATION_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXTRANSFORMATION_H_
#import <Foundation/Foundation.h>
#import <TXLiteAVSDK_Player/TXLiteAVSDK.h>
......@@ -11,3 +14,5 @@ static int maxCacheItems = -1;
+ (TXLivePlayConfig *)transformToLiveConfig:(NSDictionary*)map;
@end
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXTRANSFORMATION_H_
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXVODPLAYER_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXVODPLAYER_H_
#import <Foundation/Foundation.h>
#import "FTXBasePlayer.h"
......@@ -25,10 +27,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface FTXVodPlayer : FTXBasePlayer
@property (nonatomic, weak) id<FTXVodPlayerDelegate> delegate;
@property(nonatomic, weak) id<FTXVodPlayerDelegate> delegate;
- (instancetype)initWithRegistrar:(id<FlutterPluginRegistrar>)registrar;
@end
NS_ASSUME_NONNULL_END
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_FTXVODPLAYER_H_
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_SUPERPLAYERPLUGIN_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_SUPERPLAYERPLUGIN_H_
#import <Flutter/Flutter.h>
@interface SuperPlayerPlugin : NSObject<FlutterPlugin>
@end
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_SUPERPLAYERPLUGIN_H_
......@@ -3,6 +3,7 @@ part of SuperPlayer;
class TXLivePlayerController extends ChangeNotifier implements ValueListenable<TXPlayerValue?>, TXPlayerController {
int? _playerId = -1;
static String kTag = "TXLivePlayerController";
final Completer<int> _initPlayer;
final Completer<int> _createTexture;
......@@ -127,11 +128,17 @@ class TXLivePlayerController extends ChangeNotifier implements ValueListenable<T
_stateStreamController.add(_state);
}
void printVersionInfo() async {
LogUtils.d(kTag, "dart SDK version:${Platform.version}");
LogUtils.d(kTag, "liteAV SDK version:${await SuperPlayerPlugin.platformVersion}");
}
///
/// 当设置[LivePlayer] 类型播放器时,需要参数[playType]
/// 参考: [PlayType.LIVE_RTMP] ...
@deprecated
Future<bool> play(String url, {int? playType}) async {
printVersionInfo();
return await startLivePlay(url, playType: playType);
}
......@@ -146,7 +153,7 @@ class TXLivePlayerController extends ChangeNotifier implements ValueListenable<T
await _initPlayer.future;
await _createTexture.future;
_changeState(TXPlayerState.buffering);
printVersionInfo();
final result = await _channel.invokeMethod("startLivePlay", {"url": url, "playType": playType});
return result == 0;
}
......
......@@ -3,6 +3,7 @@ part of SuperPlayer;
class TXVodPlayerController extends ChangeNotifier implements ValueListenable<TXPlayerValue?>, TXPlayerController {
int? _playerId = -1;
static String kTag = "TXVodPlayerController";
final Completer<int> _initPlayer;
final Completer<int> _createTexture;
......@@ -137,6 +138,11 @@ class TXVodPlayerController extends ChangeNotifier implements ValueListenable<TX
_stateStreamController.add(_state);
}
void printVersionInfo() async {
LogUtils.d(kTag, "dart SDK version:${Platform.version}");
LogUtils.d(kTag, "liteAV SDK version:${await SuperPlayerPlugin.platformVersion}");
}
/// 通过url开始播放视频
/// 10.7版本开始,startPlay变更为startVodPlay,需要通过 {@link SuperPlayerPlugin#setGlobalLicense} 设置 Licence 后方可成功播放,
/// 否则将播放失败(黑屏),全局仅设置一次即可。直播 Licence、短视频 Licence 和视频播放 Licence 均可使用,若您暂未获取上述 Licence ,
......@@ -148,7 +154,7 @@ class TXVodPlayerController extends ChangeNotifier implements ValueListenable<TX
await _initPlayer.future;
await _createTexture.future;
_changeState(TXPlayerState.buffering);
printVersionInfo();
final result = await _channel.invokeMethod("startVodPlay", {"url": url});
return result == 0;
}
......@@ -164,7 +170,7 @@ class TXVodPlayerController extends ChangeNotifier implements ValueListenable<TX
await _initPlayer.future;
await _createTexture.future;
_changeState(TXPlayerState.buffering);
printVersionInfo();
await _channel.invokeMethod("startVodPlayWithParams", params.toJson());
}
......
......@@ -2,7 +2,7 @@
part of demo_super_player_lib;
typedef OnJumpToPipPlayer = void Function(Map params);
typedef OnPopCurrent = void Function();
typedef OnPipClose = void Function();
///
/// 画中画控制器,单例,只能存在一个画中画
......@@ -19,6 +19,7 @@ class TXPipController {
final Map<String, dynamic> _extParams = {};
TXPipPlayerRestorePage? _onPipEnterListener;
OnJumpToPipPlayer? _onJumpToPipPlayer;
OnPipClose? _onPipClose;
StreamSubscription? _pipEventSubscription;
/// TXPipController
......@@ -44,7 +45,11 @@ class TXPipController {
(Platform.isAndroid && eventCode == TXVodPlayEvent.EVENT_PIP_MODE_REQUEST_START)) {
_onPipEnterListener?.onNeedSavePipPageState(_extParams);
_playerData?.isEnterPip = true;
if(_onPipClose != null) {
_onPipClose!.call();
} else {
Navigator.of(context).pop();
}
} else if ((Platform.isIOS && eventCode == TXVodPlayEvent.EVENT_IOS_PIP_MODE_WILL_EXIT) ||
(Platform.isAndroid && eventCode == TXVodPlayEvent.EVENT_PIP_MODE_ALREADY_EXIT)) {
_playerData?.isEnterPip = false;
......@@ -100,8 +105,9 @@ class TXPipController {
_onPipEnterListener = listener;
}
void setNavigatorHandle(OnJumpToPipPlayer onJumpToPipPlayer) {
void setNavigatorHandle(OnJumpToPipPlayer onJumpToPipPlayer,{OnPipClose? onPipClose}) {
_onJumpToPipPlayer = onJumpToPipPlayer;
_onPipClose = onPipClose;
}
}
......
......@@ -78,6 +78,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
_coverViewController = CoverViewController(_onDoubleTapVideo, _onSingleTapVideo);
_qualitListViewController = QualityListViewController((quality) {
_playController.switchStream(quality);
hideControlView();
});
_moreViewController = MoreViewController(
() => _playController._isOpenHWAcceleration,
......@@ -181,6 +182,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
}, (code, msg) {
// onError
_togglePlayUIState(false);
EasyLoading.showToast("play video error,code:$code,error:$msg");
}, (playerType) {
// onPlayerTypeChange
_videoBottomKey.currentState?.updatePlayerType(playerType);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论