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

1. android pip optimize

2. superPlayerWidget pos changed 3. unified plugin log output 4. fix known issues
上级 fa52f557
#!/usr/bin/env bash
buildLog() {
echo `date +"%Y-%m-%d %H:%M:%S"`" build process: $1"
}
inputVersion=$1
export VERSION_NAME="11.8.1"
if [ -n "$inputVersion" ]; then
VERSION_NAME=$inputVersion
fi
buildLog "start config Version=${VERSION_NAME}"
buildLog "currentPathIs:$(pwd)"
buildLog "start config flutter lib pubspec version"
sed -i "" "s/version:.*$/version: $VERSION_NAME/" ../pubspec.yaml
buildLog "config success on flutter lib pubspec version"
buildLog "start config flutter lib code version"
sed -i "" "s/PLAYER_VERSION = \"[0-9.]*\"/PLAYER_VERSION = \"$VERSION_NAME\"/" ../lib/Core/common/common_config.dart
buildLog "config success on flutter lib code version"
buildLog "start config flutter superplayer_widget pubspec version"
sed -i "" "s/version:.*$/version: $VERSION_NAME/" ../superplayer_widget/pubspec.yaml
buildLog "config success on superplayer_widget pubspec version"
buildLog "start config plugin android version"
sed -i "" "s/playerVersion = \"[0-9.]*\"/playerVersion = \"$VERSION_NAME\"/" ../android/config.gradle
buildLog "config success on plugin android version"
buildLog "start config plugin ios version"
sed -i "" "s/s.version = '[0-9.]*'/s.version = '$VERSION_NAME'/" ../ios/super_player.podspec
buildLog "config success on plugin ios version"
buildLog "config Version=${VERSION_NAME} done"
\ No newline at end of file
......@@ -23,6 +23,7 @@ rootProject.allprojects {
android {
compileSdkVersion rootProject.ext.compileSdkVersion
namespace="com.tencent.vod.flutter"
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
......
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.tencent.vod.flutter">
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.REORDER_TASKS" />
<application>
......
......@@ -9,7 +9,8 @@ import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.tencent.liteav.base.util.LiteavLog;
import java.util.ArrayList;
import java.util.List;
......@@ -147,7 +148,7 @@ public class FTXAudioManager {
result = mAudioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
}
Log.e(TAG, "requestAudioFocus result:" + result);
LiteavLog.e(TAG, "requestAudioFocus result:" + result);
}
public void addAudioFocusChangedListener(AudioFocusChangeListener listener) {
......
......@@ -94,6 +94,12 @@ public class FTXEvent {
// PIP error, current interface has been destroyed.
// pip 错误,当前界面已销毁
public static final int ERROR_PIP_ACTIVITY_DESTROYED = -103;
// PIP error, miss player
// pip 错误,丢失播放器
public static final int ERROR_PIP_MISS_PLAYER = -104;
// PIP error, pip is busy
// pip 错误,已经存在画中画窗口
public static final int ERROR_PIP_IN_BUSY = -105;
// Event from PIP container,eventBus key value
// 来自画中画容器的事件,eventBus键值
public static final String EVENT_PIP_ACTION = "com.tencent.flutter.pipevent";
......@@ -134,9 +140,6 @@ public class FTXEvent {
// PIP parameters.
// 画中画参数
public static final String EXTRA_NAME_PARAMS = "pipParams";
// Video source.
// 视频源
public static final String EXTRA_NAME_VIDEO = "videoModel";
// End parameters of PIP.
// 画中画结束参数
public static final String EXTRA_NAME_RESULT = "pipResult";
......
......@@ -4,16 +4,17 @@ package com.tencent.vod.flutter;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.NonNull;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.rtmp.ITXLivePlayListener;
import com.tencent.rtmp.TXLiveBase;
import com.tencent.rtmp.TXLiveConstants;
import com.tencent.rtmp.TXLivePlayConfig;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.rtmp.TXVodConstants;
import com.tencent.rtmp.TXVodPlayer;
import com.tencent.vod.flutter.messages.FtxMessages.BoolMsg;
import com.tencent.vod.flutter.messages.FtxMessages.BoolPlayerMsg;
import com.tencent.vod.flutter.messages.FtxMessages.FTXLivePlayConfigPlayerMsg;
......@@ -25,8 +26,9 @@ import com.tencent.vod.flutter.messages.FtxMessages.StringIntPlayerMsg;
import com.tencent.vod.flutter.messages.FtxMessages.StringPlayerMsg;
import com.tencent.vod.flutter.messages.FtxMessages.TXFlutterLivePlayerApi;
import com.tencent.vod.flutter.model.TXPipResult;
import com.tencent.vod.flutter.model.TXVideoModel;
import com.tencent.vod.flutter.model.TXPlayerHolder;
import com.tencent.vod.flutter.tools.TXCommonUtil;
import com.tencent.vod.flutter.tools.TXFlutterEngineHolder;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.EventChannel;
......@@ -59,16 +61,23 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
private int mSurfaceHeight = 0;
private final FTXPIPManager mPipManager;
private FTXPIPManager.PipParams mPipParams;
private TXVideoModel mVideoModel;
private boolean mNeedPipResume = false;
private final FTXPIPManager.PipCallback pipCallback = new FTXPIPManager.PipCallback() {
@Override
public void onPipResult(TXPipResult result) {
// When starting PIP, if the current player is paused and PIP is still playing when exiting,
// the current player will also be set to playing state upon exiting PIP.
if (mLivePlayer != null) {
mLivePlayer.setSurface(mSurface);
mLivePlayer.setPlayListener(FTXLivePlayer.this);
}
// When starting PIP, the current player has been paused. After PIP exits,
// if PIP is still in playing state, the current player will also be set to playing state.
boolean isPipPlaying = result.isPlaying();
if (isPipPlaying) {
if (TXFlutterEngineHolder.getInstance().isInForeground()) {
resumePlayer();
} else {
mNeedPipResume = true;
}
}
}
......@@ -78,6 +87,21 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
}
};
private final TXFlutterEngineHolder.TXAppStatusListener mAppLifeListener
= new TXFlutterEngineHolder.TXAppStatusListener() {
@Override
public void onResume() {
if (mNeedPipResume) {
mNeedPipResume = false;
resumePlayer();
}
}
@Override
public void onEnterBack() {
}
};
/**
* Live streaming player.
*
......@@ -87,8 +111,7 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
super();
mFlutterPluginBinding = flutterPluginBinding;
mPipManager = pipManager;
mVideoModel = new TXVideoModel();
mVideoModel.setPlayerType(FTXEvent.PLAYER_LIVE);
TXFlutterEngineHolder.getInstance().addAppLifeListener(mAppLifeListener);
mSurfaceTextureEntry = mFlutterPluginBinding.getTextureRegistry().createSurfaceTexture();
mSurfaceTexture = mSurfaceTextureEntry.surfaceTexture();
......@@ -145,6 +168,7 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
mSurface = null;
}
TXFlutterEngineHolder.getInstance().removeAppLifeListener(mAppLifeListener);
mEventChannel.setStreamHandler(null);
mNetChannel.setStreamHandler(null);
}
......@@ -161,7 +185,7 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
mHardwareDecodeFail = true;
}
if (event != TXVodConstants.VOD_PLAY_EVT_PLAY_PROGRESS) {
Log.e(TAG, "onLivePlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
LiteavLog.e(TAG, "onLivePlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
}
mEventSink.success(TXCommonUtil.getParams(event, bundle));
}
......@@ -192,17 +216,15 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
mLivePlayer = new TXLivePlayer(mFlutterPluginBinding.getApplicationContext());
mLivePlayer.setPlayListener(this);
}
Log.d("AndroidLog", "textureId :" + mSurfaceTextureEntry.id());
LiteavLog.d("AndroidLog", "textureId :" + mSurfaceTextureEntry.id());
return mSurfaceTextureEntry == null ? -1 : mSurfaceTextureEntry.id();
}
int startPlayerLivePlay(String url, Integer type) {
Log.d(TAG, "startLivePlay:");
LiteavLog.d(TAG, "startLivePlay:");
if (null == type) {
type = TXLivePlayer.PLAY_TYPE_LIVE_FLV;
}
mVideoModel.setVideoUrl(url);
mVideoModel.setLiveType(type);
if (mLivePlayer != null) {
mLivePlayer.setSurface(mSurface);
mLivePlayer.setPlayListener(this);
......@@ -215,7 +237,7 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
int width = texture.width;
int height = texture.height;
if (width != mSurfaceWidth || height != mSurfaceHeight) {
Log.d(TAG, "onRenderVideoFrame: width=" + texture.width + ",height=" + texture.height);
LiteavLog.d(TAG, "onRenderVideoFrame: width=" + texture.width + ",height=" + texture.height);
mLivePlayer.setSurfaceSize(width, height);
mSurfaceTexture.setDefaultBufferSize(width, height);
mSurfaceWidth = width;
......@@ -429,14 +451,14 @@ public class FTXLivePlayer extends FTXBasePlayer implements ITXLivePlayListener,
@Override
public IntMsg enterPictureInPictureMode(@NonNull PipParamsPlayerMsg pipParamsMsg) {
mPipManager.addCallback(getPlayerId(), pipCallback);
mPipParams = new FTXPIPManager.PipParams(
FTXPIPManager.PipParams pipParams = new FTXPIPManager.PipParams(
mPipManager.toAndroidPath(pipParamsMsg.getBackIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getPlayIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getPauseIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getForwardIconForAndroid()),
getPlayerId(), false, false, true);
mPipParams.setIsPlaying(isPlayerPlaying());
int pipResult = mPipManager.enterPip(mPipParams, mVideoModel);
pipParams.setIsPlaying(isPlayerPlaying());
int pipResult = mPipManager.enterPip(pipParams, new TXPlayerHolder(mLivePlayer));
// After the startup is successful, pause the video on the current interface.
if (pipResult == FTXEvent.NO_ERROR) {
pausePlayer();
......
......@@ -20,14 +20,14 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.util.Rational;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.vod.flutter.model.TXPipResult;
import com.tencent.vod.flutter.model.TXVideoModel;
import com.tencent.vod.flutter.model.TXPlayerHolder;
import com.tencent.vod.flutter.tools.TXCommonUtil;
import com.tencent.vod.flutter.tools.TXSimpleEventBus;
import com.tencent.vod.flutter.ui.FlutterPipImplActivity;
......@@ -127,15 +127,13 @@ public class FTXPIPManager implements TXSimpleEventBus.EventSubscriber {
*
* @return {@link FTXEvent} ERROR_PIP
*/
public int enterPip(PipParams params, TXVideoModel videoModel) {
public int enterPip(PipParams params, TXPlayerHolder playerHolder) {
int pipResult = isSupportDevice();
if (pipResult == FTXEvent.NO_ERROR) {
pipResult = FlutterPipImplActivity.startPip(mActivityBinding.getActivity(), params, playerHolder);
if (pipResult == FTXEvent.NO_ERROR) {
mPipEventSink.success(TXCommonUtil.getParams(FTXEvent.EVENT_PIP_MODE_REQUEST_START, null));
Intent intent = new Intent(mActivityBinding.getActivity(), FlutterPipImplActivity.class);
intent.setAction(FTXEvent.PIP_ACTION_START);
intent.putExtra(FTXEvent.EXTRA_NAME_PARAMS, params);
intent.putExtra(FTXEvent.EXTRA_NAME_VIDEO, videoModel);
mActivityBinding.getActivity().startActivity(intent);
}
mIsInPipMode = true;
}
return pipResult;
......@@ -170,19 +168,20 @@ public class FTXPIPManager implements TXSimpleEventBus.EventSubscriber {
activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
if (!isSuccess) {
pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION;
Log.e(TAG, "enterPip failed,because PIP feature is disabled");
LiteavLog.e(TAG, "enterPip failed,because PIP feature is disabled");
} else if (!hasPipPermission(activity)) {
pipResult = FTXEvent.ERROR_PIP_DENIED_PERMISSION;
Log.e(TAG, "enterPip failed,because PIP has no permission");
LiteavLog.e(TAG, "enterPip failed,because PIP has no permission");
}
} 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);
LiteavLog.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;
Log.e(TAG, "enterPip failed,because activity is destroyed");
LiteavLog.e(TAG, "enterPip failed,because activity is destroyed");
}
return pipResult;
}
......@@ -229,7 +228,7 @@ public class FTXPIPManager implements TXSimpleEventBus.EventSubscriber {
TXSimpleEventBus.getInstance().unregister(FTXEvent.EVENT_PIP_PLAYER_EVENT_ACTION, this);
}
} catch (Exception e) {
Log.getStackTraceString(e);
LiteavLog.e(TAG, "releaseActivityListener error", e);
}
}
......@@ -262,9 +261,10 @@ public class FTXPIPManager implements TXSimpleEventBus.EventSubscriber {
|| pipEventId == FTXEvent.EVENT_PIP_MODE_RESTORE_UI)) {
TXPipResult pipResult = params.getParcelable(FTXEvent.EXTRA_NAME_RESULT);
if (null != pipResult) {
callbackData.putDouble(FTXEvent.EVENT_PIP_PLAY_TIME, pipResult.getPlayTime());
callbackData.putFloat(FTXEvent.EVENT_PIP_PLAY_TIME, pipResult.getPlayTime());
handlePipResult(pipResult);
}
mIsInPipMode = false;
}
mPipEventSink.success(TXCommonUtil.getParams(pipEventId, callbackData));
} else if (TextUtils.equals(eventType, FTXEvent.EVENT_PIP_PLAYER_EVENT_ACTION)) {
......@@ -474,7 +474,7 @@ public class FTXPIPManager implements TXSimpleEventBus.EventSubscriber {
return Icon.createWithBitmap(iconBitmap);
}
} catch (IOException e) {
Log.getStackTraceString(e);
LiteavLog.e(TAG, "getIcon error", e);
}
return Icon.createWithResource(activity, defaultResId);
}
......
......@@ -6,9 +6,11 @@ import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.NonNull;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.rtmp.ITXVodPlayListener;
import com.tencent.rtmp.TXBitrateItem;
import com.tencent.rtmp.TXImageSprite;
......@@ -36,8 +38,9 @@ import com.tencent.vod.flutter.messages.FtxMessages.StringPlayerMsg;
import com.tencent.vod.flutter.messages.FtxMessages.TXPlayInfoParamsPlayerMsg;
import com.tencent.vod.flutter.messages.FtxMessages.UInt8ListMsg;
import com.tencent.vod.flutter.model.TXPipResult;
import com.tencent.vod.flutter.model.TXVideoModel;
import com.tencent.vod.flutter.model.TXPlayerHolder;
import com.tencent.vod.flutter.tools.TXCommonUtil;
import com.tencent.vod.flutter.tools.TXFlutterEngineHolder;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
......@@ -49,7 +52,6 @@ import java.util.Map;
import java.util.Objects;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.view.TextureRegistry;
......@@ -73,29 +75,30 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
private TXVodPlayer mVodPlayer;
private TXImageSprite mTxImageSprite;
private TXVideoModel mVideoModel;
private static final int Uninitialized = -101;
private TextureRegistry.SurfaceTextureEntry mSurfaceTextureEntry;
private boolean mEnableHardwareDecode = true;
private boolean mHardwareDecodeFail = false;
private final FTXPIPManager mPipManager;
private FTXPIPManager.PipParams mPipParams;
private final FTXPIPManager.PipCallback pipCallback = new FTXPIPManager.PipCallback() {
private boolean mNeedPipResume = false;
private final FTXPIPManager.PipCallback mPipCallback = new FTXPIPManager.PipCallback() {
@Override
public void onPipResult(TXPipResult result) {
float playTime = result.getPlayTime();
float duration = mVodPlayer.getDuration();
if (playTime > duration) {
playTime = duration;
if (mVodPlayer != null) {
mSurface = new Surface(mSurfaceTexture);
mVodPlayer.setSurface(mSurface);
mVodPlayer.setVodListener(FTXVodPlayer.this);
}
seekPlayer(playTime);
// When starting PIP, the current player has been paused. After PIP exits,
// if PIP is still in playing state, the current player will also be set to playing state.
boolean isPipPlaying = result.isPlaying();
if (isPipPlaying) {
if (TXFlutterEngineHolder.getInstance().isInForeground()) {
playerResume();
} else {
mNeedPipResume = true;
}
}
}
......@@ -105,6 +108,21 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
}
};
private final TXFlutterEngineHolder.TXAppStatusListener mAppLifeListener
= new TXFlutterEngineHolder.TXAppStatusListener() {
@Override
public void onResume() {
if (mNeedPipResume) {
mNeedPipResume = false;
playerResume();
}
}
@Override
public void onEnterBack() {
}
};
/**
* VOD player.
*
......@@ -114,8 +132,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
super();
mPipManager = pipManager;
mFlutterPluginBinding = flutterPluginBinding;
mVideoModel = new TXVideoModel();
mVideoModel.setPlayerType(FTXEvent.PLAYER_VOD);
TXFlutterEngineHolder.getInstance().addAppLifeListener(mAppLifeListener);
mEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "cloud.tencent"
+ ".com/txvodplayer/event/" + super.getPlayerId());
......@@ -171,6 +188,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
mEventChannel.setStreamHandler(null);
mNetChannel.setStreamHandler(null);
TXFlutterEngineHolder.getInstance().removeAppLifeListener(mAppLifeListener);
releaseTXImageSprite();
if (null != mPipManager) {
mPipManager.releaseCallback(getPlayerId());
......@@ -212,7 +230,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
mHardwareDecodeFail = true;
}
if (event != TXVodConstants.VOD_PLAY_EVT_PLAY_PROGRESS) {
Log.e(TAG, "onPlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
LiteavLog.e(TAG, "onPlayEvent:" + event + "," + bundle.getString(TXLiveConstants.EVT_DESCRIPTION));
}
mEventSink.success(TXCommonUtil.getParams(event, bundle));
}
......@@ -243,7 +261,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
return stream.toByteArray();
}
} else {
Log.e(TAG, "getImageSprite failed, time is null or initImageSprite not invoke");
LiteavLog.e(TAG, "getImageSprite failed, time is null or initImageSprite not invoke");
}
return null;
}
......@@ -291,10 +309,6 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
int startPlayerVodPlay(String url) {
if (mVodPlayer != null) {
mVideoModel.setVideoUrl(url);
mVideoModel.setAppId(0);
mVideoModel.setFileId("");
mVideoModel.setPSign("");
return mVodPlayer.startVodPlay(url);
}
return Uninitialized;
......@@ -302,10 +316,6 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
void startPlayerVodPlayWithParams(int appId, String fileId, String psign) {
if (mVodPlayer != null) {
mVideoModel.setVideoUrl("");
mVideoModel.setAppId(appId);
mVideoModel.setFileId(fileId);
mVideoModel.setPSign(psign);
TXPlayInfoParams playInfoParams = new TXPlayInfoParams(appId, fileId, psign);
mVodPlayer.startVodPlay(playInfoParams);
}
......@@ -315,6 +325,7 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
if (mVodPlayer != null) {
return mVodPlayer.stopPlay(isNeedClearLastImg);
}
mPipManager.exitPip();
releaseTXImageSprite();
mHardwareDecodeFail = false;
return Uninitialized;
......@@ -464,10 +475,8 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
if (mVodPlayer != null) {
if (TextUtils.isEmpty(token)) {
mVodPlayer.setToken(null);
mVideoModel.setToken(null);
} else {
mVodPlayer.setToken(token);
mVideoModel.setToken(token);
}
}
}
......@@ -712,23 +721,24 @@ public class FTXVodPlayer extends FTXBasePlayer implements ITXVodPlayListener, F
@NonNull
@Override
public IntMsg enterPictureInPictureMode(@NonNull PipParamsPlayerMsg pipParamsMsg) {
mPipManager.addCallback(getPlayerId(), pipCallback);
mPipParams = new FTXPIPManager.PipParams(
mPipManager.addCallback(getPlayerId(), mPipCallback);
FTXPIPManager.PipParams pipParams = new FTXPIPManager.PipParams(
mPipManager.toAndroidPath(pipParamsMsg.getBackIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getPlayIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getPauseIconForAndroid()),
mPipManager.toAndroidPath(pipParamsMsg.getForwardIconForAndroid()),
getPlayerId());
mPipParams.setIsPlaying(isPlayerPlaying());
mPipParams.setCurrentPlayTime(getPlayerCurrentPlaybackTime());
pipParams.setIsPlaying(isPlayerPlaying());
pipParams.setCurrentPlayTime(getPlayerCurrentPlaybackTime());
int pipResult = FTXEvent.ERROR_PIP_MISS_PLAYER;
if (null != mVodPlayer) {
mPipParams.setRadio(mVodPlayer.getWidth(), mVodPlayer.getHeight());
}
int pipResult = mPipManager.enterPip(mPipParams, mVideoModel);
pipParams.setRadio(mVodPlayer.getWidth(), mVodPlayer.getHeight());
pipResult = mPipManager.enterPip(pipParams, new TXPlayerHolder(mVodPlayer));
// After successful startup, pause the current interface video.
if (pipResult == FTXEvent.NO_ERROR) {
playerPause();
}
}
return TXCommonUtil.intMsgWith((long) pipResult);
}
......
......@@ -17,7 +17,6 @@ import android.os.Looper;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.OrientationEventListener;
import android.view.Window;
......@@ -26,6 +25,7 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.rtmp.TXLiveBase;
import com.tencent.rtmp.TXLiveBaseListener;
import com.tencent.rtmp.TXPlayerGlobalSetting;
......@@ -76,12 +76,12 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
private EventChannel mEventChannel;
private EventChannel mPipEventChannel;
private FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private VolumeBroadcastReceiver mVolumeBroadcastReceiver;
private FlutterPluginBinding mFlutterPluginBinding;
private ActivityPluginBinding mActivityPluginBinding;
private SparseArray<FTXBasePlayer> mPlayers;
private final SparseArray<FTXBasePlayer> mPlayers = new SparseArray<>();
private FTXDownloadManager mFTXDownloadManager;
private FTXAudioManager mTxAudioManager;
......@@ -89,9 +89,8 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
private OrientationEventListener mOrientationManager;
private int mCurrentOrientation = FTXEvent.ORIENTATION_PORTRAIT_UP;
private final TXFlutterEngineHolder mEngineHolder = new TXFlutterEngineHolder();
private boolean mIsBrightnessObserverRegistered = false;
private Handler mMainHandler = new Handler(Looper.getMainLooper());
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private final FTXAudioManager.AudioFocusChangeListener audioFocusChangeListener =
new FTXAudioManager.AudioFocusChangeListener() {
......@@ -116,15 +115,15 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
private final TXLiveBaseListener mSDKEvent = new TXLiveBaseListener() {
@Override
public void onLog(int level, String module, String log) {
super.onLog(level, module, log);
public void onLog(int level, String module, String liteavLog) {
super.onLog(level, module, liteavLog);
// mMainHandler.post(new Runnable() {
// @Override
// public void run() {
// Bundle params = new Bundle();
// params.putInt(FTXEvent.EVENT_LOG_LEVEL, level);
// params.putString(FTXEvent.EVENT_LOG_MODULE, module);
// params.putString(FTXEvent.EVENT_LOG_MSG, log);
// params.putString(FTXEvent.EVENT_LOG_MSG, LiteavLog);
// mEventSink.success(getParams(FTXEvent.EVENT_ON_LOG, params));
// }
// });
......@@ -180,7 +179,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
Log.i(TAG, "onAttachedToEngine");
LiteavLog.i(TAG, "onAttachedToEngine");
TXFlutterSuperPlayerPluginAPI.setup(flutterPluginBinding.getBinaryMessenger(), this);
TXFlutterNativeAPI.setup(flutterPluginBinding.getBinaryMessenger(), this);
TXFlutterVodPlayerApi.setup(flutterPluginBinding.getBinaryMessenger(), new FTXVodPlayerDispatcher(
......@@ -188,7 +187,6 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
TXFlutterLivePlayerApi.setup(flutterPluginBinding.getBinaryMessenger(), new FTXLivePlayerDispatcher(
() -> mPlayers));
mFlutterPluginBinding = flutterPluginBinding;
mPlayers = new SparseArray<>();
initAudioManagerIfNeed();
mPipEventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),
FTXEvent.PIP_CHANNEL_NAME);
......@@ -357,7 +355,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
};
mOrientationManager.enable();
} catch (Exception e) {
Log.getStackTraceString(e);
LiteavLog.e(TAG, "innerStartVideoOrientationService error", e);
return false;
}
}
......@@ -444,7 +442,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
Log.i(TAG, "onDetachedFromEngine");
LiteavLog.i(TAG, "onDetachedFromEngine");
mFTXDownloadManager.destroy();
mFlutterPluginBinding = null;
if (null != mOrientationManager) {
......@@ -455,13 +453,13 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
if (null != mActivityPluginBinding && mActivityPluginBinding != binding) {
mEngineHolder.destroy(binding);
TXFlutterEngineHolder.getInstance().destroy(binding);
}
mActivityPluginBinding = binding;
initAudioManagerIfNeed();
initPipManagerIfNeed();
registerReceiver();
mEngineHolder.attachBindLife(binding);
TXFlutterEngineHolder.getInstance().attachBindLife(binding);
TXLiveBase.enableCustomHttpDNS(true);
TXLiveBase.setListener(mSDKEvent);
}
......@@ -485,7 +483,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
Intent serviceIntent = new Intent(mActivityPluginBinding.getActivity(), TXAndroid12BridgeService.class);
mActivityPluginBinding.getActivity().stopService(serviceIntent);
unregisterReceiver();
mEngineHolder.destroy(mActivityPluginBinding);
TXFlutterEngineHolder.getInstance().destroy(mActivityPluginBinding);
TXLiveBase.setListener(null);
}
......@@ -509,7 +507,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, ActivityAware,
mFlutterPluginBinding.getApplicationContext().getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
} catch (Exception e) {
Log.getStackTraceString(e);
LiteavLog.e(TAG, "isDeviceAutoRotateOn error", e);
return false;
}
}
......
package com.tencent.vod.flutter.model;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.rtmp.TXVodPlayer;
import com.tencent.vod.flutter.FTXEvent;
public class TXPlayerHolder {
private TXVodPlayer mVodPlayer;
private TXLivePlayer mLivePlayer;
private int mPlayerType;
private boolean mInitPlayingStatus;
public TXPlayerHolder(TXVodPlayer vodPlayer) {
mVodPlayer = vodPlayer;
mInitPlayingStatus = vodPlayer.isPlaying();
mPlayerType = FTXEvent.PLAYER_VOD;
}
public TXPlayerHolder(TXLivePlayer livePlayer) {
mLivePlayer = livePlayer;
mInitPlayingStatus = livePlayer.isPlaying();
mPlayerType = FTXEvent.PLAYER_LIVE;
}
public TXVodPlayer getVodPlayer() {
return mVodPlayer;
}
public TXLivePlayer getLivePlayer() {
return mLivePlayer;
}
public boolean isPlayingWhenCreate() {
return mInitPlayingStatus;
}
public void tmpPause() {
if (null != mVodPlayer) {
mVodPlayer.pause();
} else if (null != mLivePlayer) {
mLivePlayer.pause();
}
}
public int getPlayerType() {
return mPlayerType;
}
}
// Copyright (c) 2022 Tencent. All rights reserved.
package com.tencent.vod.flutter.model;
import android.os.Parcel;
import android.os.Parcelable;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.vod.flutter.FTXEvent;
/**
* Video model.
*
* 视频model
*/
public class TXVideoModel implements Parcelable {
private String videoUrl;
private int appId;
private String fileId;
private String pSign;
private int mPlayerType = FTXEvent.PLAYER_VOD;
private int mLiveType = TXLivePlayer.PLAY_TYPE_LIVE_FLV;
private String mToken;
public TXVideoModel() {}
protected TXVideoModel(Parcel in) {
videoUrl = in.readString();
appId = in.readInt();
fileId = in.readString();
pSign = in.readString();
mPlayerType = in.readInt();
mLiveType = in.readInt();
mToken = in.readString();
}
public static final Creator<TXVideoModel> CREATOR = new Creator<TXVideoModel>() {
@Override
public TXVideoModel createFromParcel(Parcel in) {
return new TXVideoModel(in);
}
@Override
public TXVideoModel[] newArray(int size) {
return new TXVideoModel[size];
}
};
public String getVideoUrl() {
return videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
public String getToken() {
return mToken;
}
public void setToken(String token) {
this.mToken = token;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public String getPSign() {
return pSign;
}
public void setPSign(String pSign) {
this.pSign = pSign;
}
public int getPlayerType() {
return mPlayerType;
}
public void setPlayerType(int mPlayerType) {
this.mPlayerType = mPlayerType;
}
public int getLiveType() {
return mLiveType;
}
public void setLiveType(int mLiveType) {
this.mLiveType = mLiveType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(videoUrl);
dest.writeInt(appId);
dest.writeString(fileId);
dest.writeString(pSign);
dest.writeInt(mPlayerType);
dest.writeInt(mLiveType);
dest.writeString(mToken);
}
}
......@@ -6,8 +6,8 @@ import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import com.tencent.liteav.base.util.LiteavLog;
import com.tencent.rtmp.downloader.TXVodDownloadMediaInfo;
import com.tencent.vod.flutter.FTXEvent;
import com.tencent.vod.flutter.messages.FtxMessages.BoolMsg;
......@@ -68,7 +68,7 @@ public class TXCommonUtil {
maxBrightness = system.getInteger(resId);
}
} catch (Exception e) {
Log.getStackTraceString(e);
LiteavLog.e(TAG, "getBrightnessMax error", e);
}
if (TXCommonUtil.isMIUI() && Build.VERSION.SDK_INT >= 33) {
maxBrightness = 128F;
......
......@@ -7,19 +7,35 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.Log;
import com.tencent.liteav.base.util.LiteavLog;
import java.util.ArrayList;
import java.util.List;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
public class TXFlutterEngineHolder {
private static final String TAG = "TXFlutterEngineHolder";
private static final class SingletonInstance {
private static TXFlutterEngineHolder instance = new TXFlutterEngineHolder();
}
private int mFrontContextCount = 0;
private Application.ActivityLifecycleCallbacks mLifeCallback;
private final List<TXAppStatusListener> mListeners = new ArrayList<>();
private boolean mIsEnterBack = false;
private final List<Activity> mActivityList = new ArrayList<>();
public static TXFlutterEngineHolder getInstance() {
return SingletonInstance.instance;
}
public void attachBindLife(ActivityPluginBinding binding) {
if (mLifeCallback != null) {
Log.w(TAG, "TXFlutterEngineHolder is already attach");
LiteavLog.w(TAG, "TXFlutterEngineHolder is already attach");
return;
}
if (null == binding) {
......@@ -32,6 +48,7 @@ public class TXFlutterEngineHolder {
return;
}
mLifeCallback = new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
......@@ -40,11 +57,23 @@ public class TXFlutterEngineHolder {
@Override
public void onActivityStarted(@NonNull Activity activity) {
mFrontContextCount++;
if (mIsEnterBack && mFrontContextCount > 0) {
mIsEnterBack = false;
notifyResume();
}
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
synchronized (mActivityList) {
if (mActivityList.contains(activity)) {
// refresh index
mActivityList.remove(activity);
mActivityList.add(activity);
} else {
mActivityList.add(activity);
}
}
}
@Override
......@@ -55,6 +84,10 @@ public class TXFlutterEngineHolder {
@Override
public void onActivityStopped(@NonNull Activity activity) {
mFrontContextCount--;
if (!mIsEnterBack && mFrontContextCount <= 0) {
mIsEnterBack = true;
notifyEnterBack();
}
}
@Override
......@@ -64,14 +97,33 @@ public class TXFlutterEngineHolder {
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
synchronized (mActivityList) {
mActivityList.remove(activity);
}
}
};
binding.getActivity().getApplication().registerActivityLifecycleCallbacks(mLifeCallback);
}
public boolean isInForeground() {
return mFrontContextCount > 0;
return !mIsEnterBack;
}
public Activity getActivityByIndex(int index) {
synchronized (mActivityList) {
if (index >= mActivityList.size() || index < 0) {
return null;
}
return mActivityList.get(index);
}
}
public Activity getPreActivity() {
synchronized (mActivityList) {
final int size = mActivityList.size();
final int preIndex = size - 2;
return getActivityByIndex(preIndex);
}
}
public void destroy(ActivityPluginBinding binding) {
......@@ -89,4 +141,46 @@ public class TXFlutterEngineHolder {
}
binding.getActivity().getApplication().unregisterActivityLifecycleCallbacks(mLifeCallback);
}
public void addAppLifeListener(TXAppStatusListener listener) {
synchronized (mListeners) {
if (!mListeners.contains(listener)) {
mListeners.add(listener);
}
}
}
public void removeAppLifeListener(TXAppStatusListener listener) {
synchronized (mListeners) {
mListeners.remove(listener);
}
}
public void clearListener() {
synchronized (mListeners) {
mListeners.clear();
}
}
private void notifyResume() {
synchronized (mListeners) {
for (TXAppStatusListener listener : mListeners) {
listener.onResume();
}
}
}
private void notifyEnterBack() {
synchronized (mListeners) {
for (TXAppStatusListener listener : mListeners) {
listener.onEnterBack();
}
}
}
public abstract static class TXAppStatusListener {
public abstract void onResume();
public abstract void onEnterBack();
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
tools:context="com.tencent.vod.flutter.ui.FlutterPipImplActivity">
<SurfaceView
android:id="@+id/sv_video_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:visibility="gone"/>
android:visibility="gone" />
<ProgressBar
android:id="@+id/pb_video_progress"
style="@android:style/Widget.Holo.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_alignParentBottom="true"
android:max="100"
android:visibility="gone"
style="@android:style/Widget.Holo.ProgressBar.Horizontal"/>
android:visibility="gone" />
</RelativeLayout>
\ No newline at end of file
......@@ -27,11 +27,12 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 33
namespace="com.example.flutter.player"
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.tencent.liteav.demo"
minSdkVersion 19
targetSdkVersion 31
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
......@@ -44,7 +45,7 @@ android {
}
debug {
minifyEnabled true // 关闭混淆
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
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.player">
>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.player">
>
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
......
......@@ -20,6 +20,8 @@ class _DemoShortVideoPlayerState extends State<DemoShortVideoPlayer> with Widget
@override
void initState() {
super.initState();
// stop pip window if exists
TXPipController.instance.exitAndReleaseCurrentPip();
ShortVideoDataLoader loader = ShortVideoDataLoader();
loader.getPageListDataOneByOneFunction((dataModels) {
setState(() {
......
......@@ -118,7 +118,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
),
),
),
onWillPop: onWillPop);
onWillPop: onWillPop,);
}
Future<bool> onWillPop() async {
......@@ -217,7 +217,9 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
onTap: () => playCurrentModel(playModel, 0),
horizontalTitleGap: 10,
),
Divider()
Divider(
color: Colors.transparent,
)
],
);
}
......
......@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:super_player/super_player.dart';
import 'package:super_player_example/res/app_localizations.dart';
import 'package:superplayer_widget/demo_superplayer_lib.dart';
import 'ui/demo_inputdialog.dart';
import 'ui/demo_volume_slider.dart';
......@@ -94,6 +95,8 @@ class _DemoTXLivelayerState extends State<DemoTXLivePlayer> with WidgetsBindingO
@override
void initState() {
super.initState();
// stop pip window if exists
TXPipController.instance.exitAndReleaseCurrentPip();
init();
WidgetsBinding.instance.addObserver(this);
EasyLoading.show(status: 'loading...');
......
......@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'dart:async';
import 'package:super_player/super_player.dart';
import 'package:super_player_example/res/app_localizations.dart';
import 'package:superplayer_widget/demo_superplayer_lib.dart';
import 'ui/demo_inputdialog.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'ui/demo_volume_slider.dart';
......@@ -102,6 +103,8 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb
@override
void initState() {
super.initState();
// stop pip window if exists
TXPipController.instance.exitAndReleaseCurrentPip();
_controller = TXVodPlayerController();
init();
WidgetsBinding.instance.addObserver(this);
......
......@@ -5,7 +5,7 @@ import 'package:super_player/super_player.dart';
/// progress slider widget
class VideoSliderView extends StatefulWidget {
final ChangeNotifier _controller;
final TXPlayerController _controller;
VideoSliderView(this._controller,Key key):super(key: key);
......
......@@ -27,7 +27,7 @@ dependencies:
path: ../
superplayer_widget:
# 该路径根据superplayer_widget存放路径改变
path: ../superplayer_widget
path: ../../FlutterWidget/superplayer_widget
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
......
......@@ -9,6 +9,7 @@
#import <libkern/OSAtomic.h>
#import "FtxMessages.h"
#import "TXCommonUtil.h"
#import "FTXLog.h"
static const int uninitialized = -1;
......@@ -301,7 +302,7 @@ static const int uninitialized = -1;
- (void)onPlayEvent:(int)EvtID withParam:(NSDictionary *)param
{
[_eventSink success:[FTXLivePlayer getParamsWithEvent:EvtID withParams:param]];
NSLog(@"onLivePlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]);
FTXLOGI(@"onLivePlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION])
}
/**
......
......@@ -11,6 +11,7 @@
#import "FTXEvent.h"
#import "FtxMessages.h"
#import "TXCommonUtil.h"
#import "FTXLog.h"
static const int uninitialized = -1;
static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
......@@ -375,7 +376,7 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
return data;
}
} else {
NSLog(@"getImageSprite failed, time is null or initImageSprite not invoke");
FTXLOGE(@"getImageSprite failed, time is null or initImageSprite not invoke");
}
return nil;
}
......@@ -462,7 +463,7 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
});
}
if (EvtID != PLAY_EVT_PLAY_PROGRESS) {
NSLog(@"onPlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]);
FTXLOGI(@"onPlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]);
}
[_eventSink success:[FTXVodPlayer getParamsWithEvent:EvtID withParams:param]];
}
......@@ -786,7 +787,7 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
break;
}
self.hasEnteredPipMode = NO;
NSLog(@"[onPlayer], pictureInPictureErrorDidOccur errorType= %ld", type);
FTXLOGE(@"[onPlayer], pictureInPictureErrorDidOccur errorType= %ld", type);
if (self.delegate && [self.delegate respondsToSelector:@selector(onPlayerPipStateError:)]) {
[self.delegate onPlayerPipStateError:type];
}
......
......@@ -12,6 +12,7 @@
#import "FtxMessages.h"
#import "FTXVodPlayerDispatcher.h"
#import "FTXLivePlayerDispatcher.h"
#import "FTXLog.h"
@interface SuperPlayerPlugin ()<FlutterStreamHandler,FTXVodPlayerDelegate,TXFlutterSuperPlayerPluginAPI,TXFlutterNativeAPI, ITXPlayersBridge, FlutterPlugin, TXLiveBaseDelegate>
......@@ -303,6 +304,7 @@ SuperPlayerPlugin* instance;
- (void)setLogLevelLogLevel:(nonnull IntMsg *)logLevel error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
[TXLiveBase setLogLevel:logLevel.value.intValue];
[FTXLog setLogLevel:logLevel.value.intValue];
}
- (nullable BoolMsg *)startVideoOrientationServiceWithError:(FlutterError * _Nullable __autoreleasing * _Nonnull)error {
......
// Copyright (c) 2022 Tencent. All rights reserved.
#ifndef SUPERPLAYER_FLUTTER_IOS_CLASSES_TOOLS_FTXLOG_H_
#define SUPERPLAYER_FLUTTER_IOS_CLASSES_TOOLS_FTXLOG_H_
#import <Foundation/Foundation.h>
#import "FTXLiteAVSDKHeader.h"
NS_ASSUME_NONNULL_BEGIN
#define FTXLOGV(fmt, ...) \
[FTXLog logLevel:LOGLEVEL_VERBOSE \
file:__FILE__ \
line:__LINE__ \
function:__FUNCTION__ \
info:[NSString stringWithFormat:fmt, ##__VA_ARGS__]];
#define FTXLOGD(fmt, ...) \
[FTXLog logLevel:LOGLEVEL_DEBUG \
file:__FILE__ \
line:__LINE__ \
function:__FUNCTION__ \
info:[NSString stringWithFormat:fmt, ##__VA_ARGS__]];
#define FTXLOGI(fmt, ...) \
[FTXLog logLevel:LOGLEVEL_INFO \
file:__FILE__ \
line:__LINE__ \
function:__FUNCTION__ \
info:[NSString stringWithFormat:fmt, ##__VA_ARGS__]];
#define FTXLOGW(fmt, ...) \
[FTXLog logLevel:LOGLEVEL_WARN \
file:__FILE__ \
line:__LINE__ \
function:__FUNCTION__ \
info:[NSString stringWithFormat:fmt, ##__VA_ARGS__]];
#define FTXLOGE(fmt, ...) \
[FTXLog logLevel:LOGLEVEL_ERROR \
file:__FILE__ \
line:__LINE__ \
function:__FUNCTION__ \
info:[NSString stringWithFormat:fmt, ##__VA_ARGS__]];
@interface FTXLog : NSObject
/**
* 日志打印
* @param level 方法
* @param file 文件名
* @param line 行
* @param function 方法
* @param info 信息
*/
+ (void)logLevel:(TX_Enum_Type_LogLevel)level
file:(const char *)file
line:(int)line
function:(const char *)function
info:(NSString *)info;
+ (void)setLogLevel:(TX_Enum_Type_LogLevel)level;
@end
NS_ASSUME_NONNULL_END
#endif // SUPERPLAYER_FLUTTER_IOS_CLASSES_TOOLS_FTXLOG_H_
// Copyright (c) 2022 Tencent. All rights reserved.
#import "FTXLog.h"
extern void tpl_log(int level, const char *file, int line, const char *func, const char *format, ...);
static TX_Enum_Type_LogLevel currentLogLevel = LOGLEVEL_VERBOSE;
@implementation FTXLog
+ (void)setLogLevel:(TX_Enum_Type_LogLevel)level {
currentLogLevel = level;
}
+ (void)logLevel:(TX_Enum_Type_LogLevel)level file:(const char *)file line:(int)line function:(const char *)function info:(NSString *)info {
if (level >= currentLogLevel) {
NSString *finalInfoString = [NSString stringWithFormat:@"[FTXPlayerLog] %@", info];
const char *finalInfo = [finalInfoString UTF8String];
[self logL:level
file:file
line:line
function:function
info:finalInfo];
}
}
#pragma mark - private methods
//LOGLEVEL_VERBOSE = 0, // VERBOSE
//LOGLEVEL_DEBUG = 1, // DEBUG
//LOGLEVEL_INFO = 2, // INFO
//LOGLEVEL_WARN = 3, // WARNING
//LOGLEVEL_ERROR = 4, // ERROR
//LOGLEVEL_FATAL = 5, // FATAL
//LOGLEVEL_NULL = 6, // NONE
+ (void)logL:(TX_Enum_Type_LogLevel)level
file:(const char *)file
line:(int)line
function:(const char *)function
info:(const char *)info {
switch (level) {
case LOGLEVEL_VERBOSE:
{
tpl_log(0, file, line, function, info);
}
break;
case LOGLEVEL_DEBUG:
{
tpl_log(1, file, line, function, info);
}
break;
case LOGLEVEL_INFO:
{
tpl_log(2, file, line, function, info);
}
break;
case LOGLEVEL_WARN:
{
tpl_log(3, file, line, function, info);
}
break;
case LOGLEVEL_ERROR:
{
tpl_log(4, file, line, function, info);
}
break;
case LOGLEVEL_FATAL:
{
tpl_log(5, file, line, function, info);
}
break;
case LOGLEVEL_NULL:
{
tpl_log(6, file, line, function, info);
}
break;
default:
break;
}
}
@end
......@@ -173,6 +173,8 @@ abstract class TXVodPlayEvent {
// Video SEI frame information, Player Premium version 11.6 starts to support
// 视频 SEI 帧信息, 播放器高级版 11.6 版本开始支持
static const VOD_PLAY_EVT_VIDEO_SEI = 2030;
// video loop once complete
static const VOD_PLAY_EVT_LOOP_ONCE_COMPLETE = 6001;
// UTC time
// UTC时间
......
......@@ -180,6 +180,10 @@ class SuperPlayerController {
break;
case TXVodPlayEvent.PLAY_EVT_PLAY_END:
_updatePlayerState(SuperPlayerState.END);
// reset start time when end
if (startPos > 0) {
await setStartTime(0);
}
break;
case TXVodPlayEvent.PLAY_EVT_PLAY_PROGRESS:
dynamic progress = event[TXVodPlayEvent.EVT_PLAY_PROGRESS];
......@@ -207,11 +211,17 @@ class SuperPlayerController {
currentSubtitleData = new TXVodSubtitleData(subtitleDataStr, startPositionMs, durationMs, trackIndex);
_observer?.onSubtitleData(currentSubtitleData);
break;
case TXVodPlayEvent.VOD_PLAY_EVT_SELECT_TRACK_COMPLETE: {
case TXVodPlayEvent.VOD_PLAY_EVT_SELECT_TRACK_COMPLETE:
int trackIndex = event[TXVodPlayEvent.EVT_KEY_SELECT_TRACK_INDEX];
int errorCode = event[TXVodPlayEvent.EVT_KEY_SELECT_TRACK_ERROR_CODE];
LogUtils.d(TAG, "SELECT_TRACK_COMPLETE trackIndex: ${trackIndex}, errorCode: ${errorCode}");
break;
case TXVodPlayEvent.VOD_PLAY_EVT_LOOP_ONCE_COMPLETE:
// reset start time when once complete
if (startPos > 0) {
await setStartTime(0);
}
break;
}
});
_vodNetEventListener = _vodPlayerController.onPlayerNetStatusBroadcast.listen((event) {
......
......@@ -54,6 +54,10 @@ class TXPipController {
} else if ((Platform.isIOS && eventCode == TXVodPlayEvent.EVENT_IOS_PIP_MODE_WILL_EXIT) ||
(Platform.isAndroid && eventCode == TXVodPlayEvent.EVENT_PIP_MODE_ALREADY_EXIT)) {
_playerData?.isEnterPip = false;
/**
* if you do not intend to continue reusing this vod player.
* exitAndReleaseCurrentPip must be called, otherwise there may be a obj leak
*/
await exitAndReleaseCurrentPip();
} else if (eventCode == TXVodPlayEvent.EVENT_IOS_PIP_MODE_RESTORE_UI) {
_extParams[ARGUMENT_PIP_START_TIME] = event["playTime"];
......
......@@ -132,7 +132,8 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
_pipSubscription =
SuperPlayerPlugin.instance.onExtraEventBroadcast.listen((event) {
int eventCode = event["event"];
if (eventCode == TXVodPlayEvent.EVENT_PIP_MODE_ALREADY_EXIT) {
if (eventCode == TXVodPlayEvent.EVENT_PIP_MODE_ALREADY_EXIT
|| eventCode == TXVodPlayEvent.EVENT_IOS_PIP_MODE_RESTORE_UI) {
_isFloatingMode = false;
_playController._updatePlayerUIStatus(_pipPreUiStatus);
} else if (eventCode == TXVodPlayEvent.EVENT_PIP_MODE_REQUEST_START) {
......@@ -634,7 +635,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
} else if (result == TXVodPlayEvent.ERROR_PIP_ACTIVITY_DESTROYED) {
failedStr = "enterPip failed,because activity is destroyed";
} else {
failedStr = "enterPip failed,unkonw error";
failedStr = "enterPip failed,unkonw error:$result";
}
LogUtils.e(TAG, failedStr);
}
......
......@@ -20,7 +20,7 @@ dependencies:
# See https://dart.dev/tools/pub/dependencies#version-constraints
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
path: ../../Flutter
dev_dependencies:
flutter_test:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论