提交 969aafaf authored 作者: dokieyang's avatar dokieyang

Update version:1.0.2

1、SuperPlayer用Flutter代码重构 2、新增播放器License设置功能 3、优化点播和直播播放器SDK接口
上级 3e5997e8
.idea/
.dart_tool/
.packages
\ No newline at end of file
差异被折叠。
group 'com.example.super_player'
version '1.0'
group 'com.tencent.vod.flutter'
apply from:'config.gradle'
version '1.0.2'
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
......@@ -15,27 +16,44 @@ buildscript {
rootProject.allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
apply plugin: 'com.android.library'
android {
//获取local.properties配置文件
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
//获取flutter的sdk路径
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
}
// lines skipped
dependencies {
provided rootProject.findProject(":superplayerkit")
compileOnly 'androidx.annotation:annotation:1.2.0'
//此处仅处理因插件项目内报红显示的处理方式
compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':superplayerkit')
implementation rootProject.ext.liteavSdk
}
\ No newline at end of file
rootProject.ext {
compileSdkVersion = 28
buildToolsVersion = "28.0.3"
supportSdkVersion = "26.0.1"
minSdkVersion = 19
targetSdkVersion = 28
/*
在此处可以更换需要的SDK版本,替换为专业版为 com.tencent.liteav:LiteAVSDK_Professional:latest.release
其中 latest.release 可指定为自己需要的版本号,例如 "com.tencent.liteav:LiteAVSDK_Player:9.5.29035" ,写成 latest.release 则默认使用最新版本
*/
// liteavSdk="com.tencent.liteav:LiteAVSDK_Player:latest.release"
liteavSdk="com.tencent.liteav:LiteAVSDK_Professional:latest.release"
imSdk = 'com.tencent.imsdk:imsdk:4.9.1'
versionCode = 1
versionName = "v1.0"
ndkAbi = 'armeabi'//,'armeabi-v7a', 'arm64-v8a'
aekit_version = '1.0.10-cloud'
}
\ No newline at end of file
rootProject.name = 'super_player'
rootProject.name = 'flutter_super_player'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.super_player">
package="com.tencent.vod.flutterr">
</manifest>
package com.example.super_player;
import android.app.Activity;
import android.content.Context;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
public class SuperPlatformViewFactory extends PlatformViewFactory {
/**
* @param createArgsCodec the codec used to decode the args parameter of {@link #create}.
*/
private FlutterPlugin.FlutterPluginBinding mFlutterPluginBinding;
private Activity mActivity;
public SuperPlatformViewFactory(FlutterPlugin.FlutterPluginBinding flutterPluginBinding, Activity activity) {
super(StandardMessageCodec.INSTANCE);
mFlutterPluginBinding = flutterPluginBinding;
mActivity = activity;
}
@Override
public PlatformView create(Context context, int viewId, Object args) {
if (mActivity == null) {
return null;
}
if (args instanceof Map) {
SuperPlatformPlayerView playerView = new SuperPlatformPlayerView(mActivity, ((Map) args), viewId, mFlutterPluginBinding);
return playerView;
}
return null;
}
}
package com.example.super_player;
import android.app.Activity;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import com.tencent.rtmp.TXLiveBase;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.platform.PlatformViewRegistry;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
/** SuperPlayerPlugin */
public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
/// 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
private MethodChannel channel;
private FlutterPluginBinding mFlutterPluginBinding;
private ActivityPluginBinding mActivityPluginBinding;
private SparseArray<FTXBasePlayer> mPlayers;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
mFlutterPluginBinding = flutterPluginBinding;
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "super_player");
channel.setMethodCallHandler(this);
mPlayers = new SparseArray();
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if(call.method.equals("createVodPlayer")) {
FTXVodPlayer player = new FTXVodPlayer(mFlutterPluginBinding);
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if(call.method.equals("createLivePlayer")) {
FTXLivePlayer player = new FTXLivePlayer(mFlutterPluginBinding,mActivityPluginBinding.getActivity());
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if(call.method.equals("releasePlayer")) {
Integer playerId = call.argument("playerId");
FTXBasePlayer player = mPlayers.get(playerId);
if (player!=null){
player.destory();
mPlayers.remove(playerId);
}
result.success(null);
} else if(call.method.equals("setConsoleEnabled")) {
boolean bnabled = call.argument("enabled");
TXLiveBase.setConsoleEnabled(bnabled);
result.success(null);
} else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
mFlutterPluginBinding = null;
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
mActivityPluginBinding = binding;
mFlutterPluginBinding.getPlatformViewRegistry().registerViewFactory("super_player_view", new SuperPlatformViewFactory(mFlutterPluginBinding, binding.getActivity()));
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
}
@Override
public void onDetachedFromActivity() {
}
}
package com.example.super_player;
package com.tencent.vod.flutter;
import java.util.concurrent.atomic.AtomicInteger;
/**
* player base
*/
public class FTXBasePlayer {
private static final AtomicInteger mAtomicId = new AtomicInteger(0);
private final int mPlayerId;
......
package com.example.super_player;
package com.tencent.vod.flutter;
import android.app.Activity;
import android.graphics.SurfaceTexture;
......@@ -10,13 +10,10 @@ import androidx.annotation.NonNull;
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.TXVodPlayer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -26,6 +23,9 @@ import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.view.TextureRegistry;
/**
* live player processor
*/
public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.MethodCallHandler, ITXLivePlayListener {
private static final String TAG = "FTXLivePlayer";
......@@ -156,13 +156,9 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
setMute(mute);
result.success(null);
}else if (call.method.equals("seek")) {
double progress = call.argument("progress");
seek((float) progress);
result.success(null);
result.notImplemented();
}else if (call.method.equals("setRate")) {
double rate = call.argument("rate");
setRate((float) rate);
result.success(null);
result.notImplemented();
}else if(call.method.equals("setVolume")) {
Integer volume = call.argument("volume");
setVolume(volume);
......@@ -184,11 +180,11 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
setAppID(appId);
result.success(null);
}else if(call.method.equals("prepareLiveSeek")) {
String domain = call.argument("domain");
int bizId = call.argument("bizId");
int r = prepareLiveSeek(domain, bizId);
result.notImplemented();
}else if(call.method.equals("resumeLive")) {
int r = resumeLive();
result.success(r);
} else {
}else {
result.notImplemented();
}
}
......@@ -334,6 +330,20 @@ public class FTXLivePlayer extends FTXBasePlayer implements MethodChannel.Method
return Uninitialized;
}
private int resumeLive() {
if (mLivePlayer != null) {
return mLivePlayer.resumeLive();
}
return Uninitialized;
}
private void setRenderMode(int renderMode) {
if (mLivePlayer != null) {
mLivePlayer.setRenderMode(renderMode);
}
}
private Map<String, Object> getParams(int event, Bundle bundle) {
Map<String, Object> param = new HashMap();
if (event != 0) {
......
package com.example.super_player;
package com.tencent.vod.flutter;
import java.util.LinkedList;
import java.util.Queue;
import io.flutter.plugin.common.EventChannel;
/**
* handle flutter event
*/
public class FTXPlayerEventSink implements EventChannel.EventSink {
private EventChannel.EventSink eventSink;
......
package com.tencent.vod.flutter;
import android.text.TextUtils;
import com.tencent.rtmp.TXPlayerGlobalSetting;
import com.tencent.rtmp.TXVodPlayConfig;
import java.util.HashMap;
import java.util.Map;
/**
* 对象转化
*/
public class FTXTransformation {
@SuppressWarnings("unchecked")
public static TXVodPlayConfig transformToConfig(Map<Object, Object> config) {
TXVodPlayConfig playConfig = new TXVodPlayConfig();
Integer connectRetryCount = (Integer) config.get("connectRetryCount");
if (intIsNotEmpty(connectRetryCount)) {
playConfig.setConnectRetryCount(connectRetryCount);
}
Integer connectRetryInterval = (Integer) config.get("connectRetryInterval");
if (intIsNotEmpty(connectRetryInterval)) {
playConfig.setConnectRetryInterval(connectRetryInterval);
}
Integer timeout = (Integer) config.get("timeout");
if (intIsNotEmpty(timeout)) {
playConfig.setTimeout(timeout);
}
Integer playerType = (Integer) config.get("playerType");
if(null != playerType) {
playConfig.setPlayerType(playerType);
}
Map<String, String> headers = (Map<String, String>) config.get("headers");
if (null == headers) {
headers = new HashMap<>();
}
playConfig.setHeaders(headers);
Boolean enableAccurateSeek = (Boolean) config.get("enableAccurateSeek");
if(null != enableAccurateSeek) {
playConfig.setEnableAccurateSeek(enableAccurateSeek);
}
Boolean autoRotate = (Boolean) config.get("autoRotate");
if(null != autoRotate) {
playConfig.setAutoRotate(autoRotate);
}
Boolean smoothSwitchBitrate = (Boolean) config.get("smoothSwitchBitrate");
if(null != smoothSwitchBitrate) {
playConfig.setSmoothSwitchBitrate(smoothSwitchBitrate);
}
String cacheMp4ExtName = (String) config.get("cacheMp4ExtName");
if (!TextUtils.isEmpty(cacheMp4ExtName)) {
playConfig.setCacheMp4ExtName(cacheMp4ExtName);
}
Integer progressInterval = (Integer) config.get("progressInterval");
if (intIsNotEmpty(progressInterval)) {
playConfig.setProgressInterval(progressInterval);
}
Integer maxBufferSize = (Integer) config.get("maxBufferSize");
if (intIsNotEmpty(maxBufferSize)) {
playConfig.setMaxBufferSize(maxBufferSize);
}
Integer maxPreloadSize = (Integer) config.get("maxPreloadSize");
if (intIsNotEmpty(maxPreloadSize)) {
playConfig.setMaxPreloadSize(maxPreloadSize);
}
Integer firstStartPlayBufferTime = (Integer) config.get("firstStartPlayBufferTime");
if(null != firstStartPlayBufferTime) {
playConfig.setFirstStartPlayBufferTime(firstStartPlayBufferTime);
}
Integer nextStartPlayBufferTime = (Integer) config.get("nextStartPlayBufferTime");
if(null != nextStartPlayBufferTime) {
playConfig.setNextStartPlayBufferTime(nextStartPlayBufferTime);
}
String overlayKey = (String) config.get("overlayKey");
if (!TextUtils.isEmpty(overlayKey)) {
playConfig.setOverlayKey(overlayKey);
}
String overlayIv = (String) config.get("overlayIv");
if (!TextUtils.isEmpty(overlayIv)) {
playConfig.setOverlayIv(overlayIv);
}
Map<String, Object> extInfoMap = (Map<String, Object>) config.get("extInfoMap");
if (null == extInfoMap) {
extInfoMap = new HashMap<>();
}
playConfig.setExtInfo(extInfoMap);
Boolean enableRenderProcess = (Boolean) config.get("enableRenderProcess");
if(null != enableRenderProcess) {
playConfig.setEnableRenderProcess(enableRenderProcess);
}
String preferredResolutionStr = (String) config.get("preferredResolution");
if (null != preferredResolutionStr) {
long preferredResolution = Long.parseLong(preferredResolutionStr);
playConfig.setPreferredResolution(preferredResolution);
}
return playConfig;
}
private static boolean intIsNotEmpty(Integer value) {
return null != value && value > 0;
}
}
package com.tencent.vod.flutter;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import com.tencent.rtmp.TXLiveBase;
import com.tencent.rtmp.TXPlayerGlobalSetting;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
/**
* SuperPlayerPlugin
* <p>
* 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
*/
public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
static final String TAG = "SuperPlayerPlugin";
private static final int SUPPORT_MAJOR_VERSION = 8;
private static final int SUPPORT_MINOR_VERSION = 5;
private MethodChannel channel;
private FlutterPluginBinding mFlutterPluginBinding;
private ActivityPluginBinding mActivityPluginBinding;
private SparseArray<FTXBasePlayer> mPlayers;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
mFlutterPluginBinding = flutterPluginBinding;
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_super_player");
channel.setMethodCallHandler(this);
mPlayers = new SparseArray();
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("createVodPlayer")) {
FTXVodPlayer player = new FTXVodPlayer(mFlutterPluginBinding);
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if (call.method.equals("createLivePlayer")) {
FTXLivePlayer player = new FTXLivePlayer(mFlutterPluginBinding, mActivityPluginBinding.getActivity());
int playerId = player.getPlayerId();
mPlayers.append(playerId, player);
result.success(playerId);
} else if (call.method.equals("releasePlayer")) {
Integer playerId = call.argument("playerId");
FTXBasePlayer player = mPlayers.get(playerId);
if (player != null) {
player.destory();
mPlayers.remove(playerId);
}
result.success(null);
} else if (call.method.equals("setConsoleEnabled")) {
boolean bnabled = call.argument("enabled");
TXLiveBase.setConsoleEnabled(bnabled);
result.success(null);
} else if (call.method.equals("setGlobalMaxCacheSize")) {
Integer size = call.argument("size");
if (null != size && size > 0) {
TXPlayerGlobalSetting.setMaxCacheSize(size);
}
} else if (call.method.equals("setGlobalCacheFolderPath")) {
String path = call.argument("path");
if (!TextUtils.isEmpty(path)) {
TXPlayerGlobalSetting.setCacheFolderPath(path);
}
} else if (call.method.equals("setGlobalLicense")) {
String licenceUrl = call.argument("licenceUrl");
String licenceKey = call.argument("licenceKey");
TXLiveBase.getInstance().setLicence(mFlutterPluginBinding.getApplicationContext(), licenceUrl, licenceKey);
} else {
result.notImplemented();
}
}
private boolean isVersionSupportAppendUrl() {
String strVersion = TXLiveBase.getSDKVersionStr();
String[] strVers = strVersion.split("\\.");
if (strVers.length <= 1) {
return false;
}
int majorVer = 0;
int minorVer = 0;
try {
majorVer = Integer.parseInt(strVers[0]);
minorVer = Integer.parseInt(strVers[1]);
} catch (NumberFormatException e) {
Log.e(TAG, "parse version failed.", e);
majorVer = 0;
minorVer = 0;
}
Log.i(TAG, strVersion + " , " + majorVer + " , " + minorVer);
return majorVer > SUPPORT_MAJOR_VERSION || (majorVer == SUPPORT_MAJOR_VERSION && minorVer >= SUPPORT_MINOR_VERSION);
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
mFlutterPluginBinding = null;
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
mActivityPluginBinding = binding;
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
}
@Override
public void onDetachedFromActivity() {
}
}
差异被折叠。
......@@ -122,7 +122,7 @@ _controller.onPlayerEventBroadcast.listen((event) {//订阅事件分发
});
```
### step 8: 清晰度无缝切换
### step 7: 清晰度无缝切换
日常使用中,网络情况在不断发生变化。在网络较差的情况下,最好适度降低画质,以减少卡顿;反之,网速比较好,可以观看更高画质。
传统切流方式一般是重新播放,会导致切换前后画面衔接不上、黑屏、卡顿等问题。使用无缝切换方案,在不中断直播的情况下,能直接切到另条流上。
......@@ -136,7 +136,7 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692
>清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 [提交工单](https://console.cloud.tencent.com/workorder) 申请使用。
### step 9: 直播回看
### step 8: 直播回看
时移功能是腾讯云推出的特色能力,可以在直播过程中,随时观看回退到任意直播历史时间点,并能在此时间点一直观看直播。非常适合游戏、球赛等互动性不高,但观看连续性较强的场景。
```dart
......@@ -207,6 +207,193 @@ _controller.setLiveMode(TXPlayerLiveMode.Smooth);
- **该功能按播放时长收费**
本功能按照播放时长收费,费用跟拉流的路数有关系,跟音视频流的码率无关,具体价格请参考 [价格总览](https://cloud.tencent.com/document/product/454/8008)
## SDK 接口列表[](id:sdkList)
#### 初始化播放器
**说明**
初始化controller,请求分配共享纹理
**接口**
```dart
await _controller.initialize();
```
#### url播放
**说明**
通过播视频url进行播放
**接口**
```dart
_controller.startPlay(url);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| url | String | 要播放的视频url |
| playType | int | 支持的直播类型,默认RTMP直播 可选|
#### 暂停播放
**说明**
暂停当前正在播放的视频
**接口**
```dart
_controller.pause();
```
#### 恢复播放
**说明**
将当前处于暂停状态的视频恢复播放
**接口**
```dart
_controller.resume();
```
#### 停止播放
**说明**
停止当前正在播放的视频
**接口**
```dart
_controller.stop();
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| isNeedClear | bool | 是否清除最后一帧画面 |
#### 设置是否自动播放
**说明**
设置即将播放的视频,在startPlay加载视频地址之后,是否直接自动播放
**接口**
```dart
_controller.setIsAutoPlay(true);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| isAutoPlay | bool | 是否自动播放 |
#### 播放器是否在播放中
**说明**
当前播放器是否正在播放
**接口**
```dart
_controller.isPlaying();
```
#### 设置静音
**说明**
设置当前播放是否静音
**接口**
```dart
_controller.setMute(true);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mute | bool | 是否静音 |
#### 设置视频声音大小
**说明**
设置视频的声音大小
**接口**
```dart
_controller.setVolume(volume);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| volume | int | 视频声音大小,范围0~100 |
#### 设置直播模式
**说明**
设置直播模式
**接口**
```dart
_controller.setLiveMode(mode);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mode | int | 直播模式,自动模式、极速模式、流畅模式 |
#### 设置 appID
**说明**
设置 appID,云控使用
**接口**
```dart
_controller.setAppID(appId);
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| appId | int | appId |
#### 返回直播
**说明**
停止时移播放,返回直播
**接口**
```dart
_controller.resumeLive();
```
## SDK 事件监听
SDK 的内部状态信息均会通过 onPlayerEventBroadcast(事件通知)和 onPlayerNetStatusBroadcast(状态反馈)通知给您。
......@@ -260,7 +447,7 @@ SDK 的内部状态信息均会通过 onPlayerEventBroadcast(事件通知)
站在 SDK 的角度,如果只是拿到一个 URL 字符串,它是回答不出这个问题的。要知道视频画面的宽和高各是多少个 pixel,SDK 需要先访问云端服务器,直到加载到能够分析出视频画面大小的信息才行,所以对于视频信息而言,SDK 也只能以通知的方式告知您的应用程序。
**onNetStatus** 通知每秒都会被触发一次,目的是实时反馈当前的推流器状态,它就像汽车的仪表盘,可以告知您目前 SDK 内部的一些具体情况,以便您能对当前网络状况和视频信息等有所了解。
| 评估参数 | 含义说明 |
| :------------------------ | :------------------------ |
| NET_STATUS_CPU_USAGE | 当前瞬时 CPU 使用率 |
......
差异被折叠。
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
......@@ -12,10 +12,16 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
/**
* 在此处可以更换需要的SDK版本,替换为专业版为 com.tencent.liteav:LiteAVSDK_Professional:latest.release
* 其中 latest.release 可指定为自己需要的版本号,例如 "com.tencent.liteav:LiteAVSDK_Player:9.5.29035" ,版本号写成 latest.release 则默认使用最新版本。
* 如果赋值为空字符串或者null,则sdk中默认依赖com.tencent.liteav:LiteAVSDK_Player的最新版本
*/
rootProject.ext.liteavSdkCustom=""
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
......@@ -27,17 +33,3 @@ subprojects {
task clean(type: Delete) {
delete rootProject.buildDir
}
ext {
compileSdkVersion = 28
buildToolsVersion = "28.0.3"
supportSdkVersion = "26.0.1"
minSdkVersion = 19
targetSdkVersion = 28
liteavSdk="com.tencent.liteav:LiteAVSDK_Professional:latest.release"
imSdk = 'com.tencent.imsdk:imsdk:4.9.1'
versionCode = 1
versionName = "v1.0"
ndkAbi = 'armeabi'//,'armeabi-v7a', 'arm64-v8a'
aekit_version = '1.0.10-cloud'
}
include ':superplayerkit'
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
......
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
}
profile {
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// compile project(':liteav_sdk')
compile rootProject.ext.liteavSdk
compile 'com.github.ctiao:DanmakuFlameMaster:0.5.3'
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
-keep class com.tencent.** { *; }
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.liteav.demo.superplayer" />
package com.tencent.liteav.demo.superplayer;
public class SuperPlayerCode {
public static final int OK = 0;
public static final int NET_ERROR = 10001;
public static final int PLAY_URL_EMPTY = 20001;
public static final int LIVE_PLAY_END = 30001;
public static final int LIVE_SHIFT_FAIL = 30002;
public static final int VOD_PLAY_FAIL = 40001;
public static final int VOD_REQUEST_FILE_ID_FAIL = 40002;
}
package com.tencent.liteav.demo.superplayer;
public class SuperPlayerDef {
public enum PlayerMode {
WINDOW, // 窗口模式
FULLSCREEN, // 全屏模式
FLOAT // 悬浮窗模式
}
public enum PlayerState {
PLAYING, // 播放中
PAUSE, // 暂停中
LOADING, // 缓冲中
END // 结束播放
}
public enum PlayerType {
VOD, // 点播
LIVE, // 直播
LIVE_SHIFT // 直播会看
}
public enum Orientation {
LANDSCAPE, // 横屏
PORTRAIT // 竖屏
}
}
package com.tencent.liteav.demo.superplayer;
import com.tencent.rtmp.TXLiveConstants;
/**
* Created by yuejiaoli on 2018/7/4.
*
* 超级播放器全局配置类
*/
public class SuperPlayerGlobalConfig {
private static class Singleton {
private static SuperPlayerGlobalConfig sInstance = new SuperPlayerGlobalConfig();
}
public static SuperPlayerGlobalConfig getInstance() {
return Singleton.sInstance;
}
/**
* 默认播放填充模式 ( 默认播放模式为 自适应模式 )
*/
public int renderMode = TXLiveConstants.RENDER_MODE_ADJUST_RESOLUTION;
/**
* 播放器最大缓存个数 ( 默认缓存 5 )
*/
public int maxCacheItem = 5;
/**
* 是否启用悬浮窗 ( 默认开启 true )
*/
public boolean enableFloatWindow = true;
/**
* 是否开启硬件加速 ( 默认开启硬件加速 )
*/
public boolean enableHWAcceleration = true;
/**
* 时移域名 (修改为自己app的时移域名)
*/
public String playShiftDomain = "liteavapp.timeshift.qcloud.com";
/**
* 悬浮窗位置 ( 默认在左上角,初始化一个宽为 810,高为 540的悬浮窗口 )
*/
public TXRect floatViewRect = new TXRect(0, 0, 810, 540);
public final static class TXRect {
public int x;
public int y;
public int width;
public int height;
TXRect(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public TXRect() {
}
}
}
package com.tencent.liteav.demo.superplayer;
import com.tencent.liteav.demo.superplayer.model.entity.SuperPlayerVideoIdV2;
import java.util.List;
/**
* 超级播放器支持三种方式播放视频:
* 1. 视频 URL
* 填写视频 URL, 如需使用直播时移功能,还需填写appId
* 2. 腾讯云点播 File ID 播放
* 填写 appId 及 videoId (如果使用旧版本V2, 请填写videoIdV2)
* 3. 多码率视频播放
* 是URL播放方式扩展,可同时传入多条URL,用于进行码率切换
*/
public class SuperPlayerModel {
public int appId; // AppId 用于腾讯云点播 File ID 播放及腾讯云直播时移功能
/**
* ------------------------------------------------------------------
* 直接使用URL播放
* <p>
* 支持 RTMP、FLV、MP4、HLS 封装格式
* 使用腾讯云直播时移功能则需要填写appId
* ------------------------------------------------------------------
*/
public String url = ""; // 视频URL
/**
* ------------------------------------------------------------------
* 多码率视频 URL
* <p>
* 用于拥有多个播放地址的多清晰度视频播放
* ------------------------------------------------------------------
*/
public List<SuperPlayerURL> multiURLs;
public int playDefaultIndex; // 指定多码率情况下,默认播放的连接Index
/**
* ------------------------------------------------------------------
* 腾讯云点播 File ID 播放参数
* ------------------------------------------------------------------
*/
public SuperPlayerVideoId videoId;
/*
* 用于兼容旧版本(V2)腾讯云点播 File ID 播放参数(即将废弃,不推荐使用)
*/
@Deprecated
public SuperPlayerVideoIdV2 videoIdV2;
public String title = ""; // 视频文件名 (用于显示在UI层);使用file id播放,若未指定title,则使用FileId返回的Title;使用url播放需要指定title,否则title显示为空
public static class SuperPlayerURL {
public SuperPlayerURL(String url, String qualityName) {
this.qualityName = qualityName;
this.url = url;
}
public SuperPlayerURL() {
}
public String qualityName = "原画"; // 清晰度名称(用于显示在UI层)
public String url = ""; // 该清晰度对应的地址
}
}
package com.tencent.liteav.demo.superplayer;
/**
* Created by hans on 2019/3/25.
* 使用腾讯云fileId播放
*/
public class SuperPlayerVideoId {
public String fileId; // 腾讯云视频fileId
public String pSign; // v4 开启防盗链必填
@Override
public String toString() {
return "SuperPlayerVideoId{" +
", fileId='" + fileId + '\'' +
", pSign='" + pSign + '\'' +
'}';
}
}
package com.tencent.liteav.demo.superplayer.model;
import com.tencent.liteav.demo.superplayer.SuperPlayerDef;
import com.tencent.liteav.demo.superplayer.SuperPlayerModel;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.rtmp.ui.TXCloudVideoView;
import java.util.List;
public interface SuperPlayer {
/**
* 开始播放
*
* @param url 视频地址
*/
void play(String url);
/**
* 开始播放
*
* @param appId 腾讯云视频appId
* @param url 直播播放地址
*/
void play(int appId, String url);
/**
* 开始播放
*
* @param appId 腾讯云视频appId
* @param fileId 腾讯云视频fileId
* @param psign 防盗链签名,开启防盗链的视频必填,非防盗链视频可不填
*/
void play(int appId, String fileId, String psign);
/**
* 多分辨率播放
* @param appId 腾讯云视频appId
* @param superPlayerURLS 不同分辨率数据
* @param defaultIndex 默认播放Index
*/
void play(int appId, List<SuperPlayerModel.SuperPlayerURL> superPlayerURLS, int defaultIndex);
/**
* 重播
*/
void reStart();
/**
* 暂停播放
*/
void pause();
/**
* 暂停点播视频
*/
void pauseVod();
/**
* 恢复播放
*/
void resume();
/**
* 恢复直播播放,从直播时移播放中,恢复到直播播放。
*/
void resumeLive();
/**
* 停止播放
*/
void stop();
/**
* 销毁播放器
*/
void destroy();
/**
* 切换播放器模式
*
* @param playerMode {@link SuperPlayerDef.PlayerMode#WINDOW } 窗口模式
* {@link SuperPlayerDef.PlayerMode#FULLSCREEN } 全屏模式
* {@link SuperPlayerDef.PlayerMode#FLOAT } 悬浮窗模式
*/
void switchPlayMode(SuperPlayerDef.PlayerMode playerMode);
void enableHardwareDecode(boolean enable);
void setPlayerView(TXCloudVideoView videoView);
void seek(int position);
void snapshot(TXLivePlayer.ITXSnapshotListener listener);
void setRate(float speedLevel);
void setMirror(boolean isMirror);
void switchStream(VideoQuality quality);
String getPlayURL();
/**
* 获取当前播放器模式
*
* @return {@link SuperPlayerDef.PlayerMode#WINDOW } 窗口模式
* {@link SuperPlayerDef.PlayerMode#FULLSCREEN } 全屏模式
* {@link SuperPlayerDef.PlayerMode#FLOAT } 悬浮窗模式
*/
SuperPlayerDef.PlayerMode getPlayerMode();
/**
* 获取当前播放器状态
*
* @return {@link SuperPlayerDef.PlayerState#PLAYING } 播放中
* {@link SuperPlayerDef.PlayerState#PAUSE } 暂停中
* {@link SuperPlayerDef.PlayerState#LOADING } 缓冲中
* {@link SuperPlayerDef.PlayerState#END } 结束播放
*/
SuperPlayerDef.PlayerState getPlayerState();
/**
* 获取当前播放器类型
*
* @return {@link SuperPlayerDef.PlayerType#LIVE } 直播
* {@link SuperPlayerDef.PlayerType#LIVE_SHIFT } 直播时移
* {@link SuperPlayerDef.PlayerType#VOD } 点播
*/
SuperPlayerDef.PlayerType getPlayerType();
/**
* 设置播放器状态回调
*
* @param observer {@link SuperPlayerObserver}
*/
void setObserver(SuperPlayerObserver observer);
/**
* 设置是否循环
* @param isLoop true循环,false不循环
*/
void setLoop(boolean isLoop);
/**
* 设置开始时间
* @param startPos 开始时间
*/
void setStartTime(float startPos);
/**
* 设置是否自动播放
* @param isAutoPlay true自动播放,false不自动播放
*/
void setAutoPlay(boolean isAutoPlay);
}
package com.tencent.liteav.demo.superplayer.model;
import com.tencent.liteav.demo.superplayer.SuperPlayerDef;
import com.tencent.liteav.demo.superplayer.model.entity.PlayImageSpriteInfo;
import com.tencent.liteav.demo.superplayer.model.entity.PlayKeyFrameDescInfo;
import com.tencent.liteav.demo.superplayer.model.entity.VideoQuality;
import com.tencent.rtmp.TXLivePlayer;
import java.util.List;
public abstract class SuperPlayerObserver {
/**
* 开始播放
* @param name 当前视频名称
*/
public void onPlayBegin(String name) {}
/**
* 播放暂停
*/
public void onPlayPause() {}
/**
* 播放器停止
*/
public void onPlayStop() {}
/**
* 播放器进入Loading状态
*/
public void onPlayLoading() {}
/**
* 播放进度回调
*
* @param current
* @param duration
*/
public void onPlayProgress(long current, long duration) {}
public void onSeek(int position) {}
public void onSwitchStreamStart(boolean success, SuperPlayerDef.PlayerType playerType, VideoQuality quality){}
public void onSwitchStreamEnd(boolean success, SuperPlayerDef.PlayerType playerType, VideoQuality quality){}
public void onError(int code, String message) {}
public void onPlayerTypeChange(SuperPlayerDef.PlayerType playType) {}
public void onPlayTimeShiftLive(TXLivePlayer player, String url) {}
public void onVideoQualityListChange(List<VideoQuality> videoQualities, VideoQuality defaultVideoQuality) {}
public void onVideoImageSpriteAndKeyFrameChanged(PlayImageSpriteInfo info, List<PlayKeyFrameDescInfo> list) {}
}
package com.tencent.liteav.demo.superplayer.model.entity;
/**
* Created by hans on 2019/3/25.
* <p>
* 自适应码流信息
*/
public class EncryptedStreamingInfo {
public String drmType;
public String url;
@Override
public String toString() {
return "TCEncryptedStreamingInfo{" +
", drmType='" + drmType + '\'' +
", url='" + url + '\'' +
'}';
}
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论