提交 330b46b8 authored 作者: kongdywang's avatar kongdywang

add orientation independent api

上级 082fc31c
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
- [点播播放](https://github.com/LiteAVSDK/Player_Flutter/blob/main/Flutter/docs/%E7%82%B9%E6%92%AD%E6%92%AD%E6%94%BE.md)`TXVodPlayerController`对Android和iOS两个平台的点播播放器SDK进行接口封装, 你可以通过集成`TXVodPlayerController`进行点播播放业务开发。详细使用例子可以参考`DemoTXVodPlayer` - [点播播放](https://github.com/LiteAVSDK/Player_Flutter/blob/main/Flutter/docs/%E7%82%B9%E6%92%AD%E6%92%AD%E6%94%BE.md)`TXVodPlayerController`对Android和iOS两个平台的点播播放器SDK进行接口封装, 你可以通过集成`TXVodPlayerController`进行点播播放业务开发。详细使用例子可以参考`DemoTXVodPlayer`
- [直播播放](https://github.com/LiteAVSDK/Player_Flutter/blob/main/Flutter/docs/%E7%9B%B4%E6%92%AD%E6%92%AD%E6%94%BE.md)`TXLivePlayerController`对Android和iOS两个平台的直播播放器SDK进行接口封装, 你可以通过集成`TXLivePlayerController`进行直播播放业务开发。详细使用例子可以参考`DemoTXLivePlayer` - [直播播放](https://github.com/LiteAVSDK/Player_Flutter/blob/main/Flutter/docs/%E7%9B%B4%E6%92%AD%E6%92%AD%E6%94%BE.md)`TXLivePlayerController`对Android和iOS两个平台的直播播放器SDK进行接口封装, 你可以通过集成`TXLivePlayerController`进行直播播放业务开发。详细使用例子可以参考`DemoTXLivePlayer`
- [播放器API文档](./docs/API 文档.md):包含播放器配置、点播播放和直播播放等API使用说明。 - [播放器API文档](./docs/API文档.md):包含播放器配置、点播播放和直播播放等API使用说明。
为了减少接入成本, 在example里提供了播放器组件(带UI的播放器),基于播放器组件简单的几行代码就可以搭建视频播放业务。您可以根据自己项目的需求, 把播放组件的相关代码应用到项目中去,根据需求进行调整UI和交互细节。 为了减少接入成本, 在example里提供了播放器组件(带UI的播放器),基于播放器组件简单的几行代码就可以搭建视频播放业务。您可以根据自己项目的需求, 把播放组件的相关代码应用到项目中去,根据需求进行调整UI和交互细节。
......
...@@ -9,6 +9,7 @@ import android.media.AudioManager; ...@@ -9,6 +9,7 @@ import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.OrientationEventListener; import android.view.OrientationEventListener;
import android.view.Window; import android.view.Window;
...@@ -95,32 +96,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti ...@@ -95,32 +96,7 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
mEventSink.setEventSinkProxy(null); mEventSink.setEventSinkProxy(null);
} }
}); });
mFTXDownloadManager = new FTXDownloadManager(mFlutterPluginBinding); mFTXDownloadManager = new FTXDownloadManager(flutterPluginBinding);
mOrientationManager = new OrientationEventListener(flutterPluginBinding.getApplicationContext()) {
@Override
public void onOrientationChanged(int orientation) {
if (isAutoRotateOn()) {
int orientationEvent = mCurrentOrientation;
// 每个方向判断当前方向正负30度,共计60度的区间
if (((orientation >= 0) && (orientation < 30)) || (orientation > 330)) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_UP;
} else if (orientation > 240 && orientation < 300) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_RIGHT;
} else if (orientation > 150 && orientation < 210) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_DOWN;
} else if (orientation > 60 && orientation < 110) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_LEFT;
}
if (orientationEvent != mCurrentOrientation) {
mCurrentOrientation = orientationEvent;
Bundle bundle = new Bundle();
bundle.putInt(FTXEvent.EXTRA_NAME_ORIENTATION, orientationEvent);
mEventSink.success(getParams(FTXEvent.EVENT_ORIENTATION_CHANGED, bundle));
}
}
}
};
mOrientationManager.enable();
} }
@Override @Override
...@@ -214,11 +190,53 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti ...@@ -214,11 +190,53 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
String envConfig = call.argument("envConfig"); String envConfig = call.argument("envConfig");
int setResult = TXLiveBase.setGlobalEnv(envConfig); int setResult = TXLiveBase.setGlobalEnv(envConfig);
result.success(setResult); result.success(setResult);
} else if(call.method.equals("startVideoOrientationService")) {
boolean setResult = startVideoOrientationService();
result.success(setResult);
} else { } else {
result.notImplemented(); result.notImplemented();
} }
} }
private boolean startVideoOrientationService() {
if(null == mFlutterPluginBinding) {
return false;
}
if(null == mOrientationManager) {
try{
mOrientationManager = new OrientationEventListener(mFlutterPluginBinding.getApplicationContext()) {
@Override
public void onOrientationChanged(int orientation) {
if (isAutoRotateOn()) {
int orientationEvent = mCurrentOrientation;
// 每个方向判断当前方向正负30度,共计60度的区间
if (((orientation >= 0) && (orientation < 30)) || (orientation > 330)) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_UP;
} else if (orientation > 240 && orientation < 300) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_RIGHT;
} else if (orientation > 150 && orientation < 210) {
orientationEvent = FTXEvent.ORIENTATION_PORTRAIT_DOWN;
} else if (orientation > 60 && orientation < 110) {
orientationEvent = FTXEvent.ORIENTATION_LANDSCAPE_LEFT;
}
if (orientationEvent != mCurrentOrientation) {
mCurrentOrientation = orientationEvent;
Bundle bundle = new Bundle();
bundle.putInt(FTXEvent.EXTRA_NAME_ORIENTATION, orientationEvent);
mEventSink.success(getParams(FTXEvent.EVENT_ORIENTATION_CHANGED, bundle));
}
}
}
};
mOrientationManager.enable();
} catch (Exception e) {
Log.getStackTraceString(e);
return false;
}
}
return true;
}
private void initAudioManagerIfNeed() { private void initAudioManagerIfNeed() {
if (null == mTxAudioManager) { if (null == mTxAudioManager) {
mTxAudioManager = new FTXAudioManager(mFlutterPluginBinding.getApplicationContext()); mTxAudioManager = new FTXAudioManager(mFlutterPluginBinding.getApplicationContext());
...@@ -238,6 +256,9 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti ...@@ -238,6 +256,9 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
channel.setMethodCallHandler(null); channel.setMethodCallHandler(null);
mFTXDownloadManager.destroy(); mFTXDownloadManager.destroy();
mFlutterPluginBinding = null; mFlutterPluginBinding = null;
if (null != mOrientationManager) {
mOrientationManager.disable();
}
} }
@Override @Override
...@@ -261,9 +282,6 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti ...@@ -261,9 +282,6 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
if (null != mTxPipManager) { if (null != mTxPipManager) {
mTxPipManager.releaseReceiver(); mTxPipManager.releaseReceiver();
} }
if (null != mOrientationManager) {
mOrientationManager.disable();
}
unregisterReceiver(); unregisterReceiver();
} }
...@@ -282,9 +300,14 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti ...@@ -282,9 +300,14 @@ public class SuperPlayerPlugin implements FlutterPlugin, MethodCallHandler, Acti
*/ */
protected boolean isAutoRotateOn() { protected boolean isAutoRotateOn() {
//获取系统是否允许自动旋转屏幕 //获取系统是否允许自动旋转屏幕
return (android.provider.Settings.System.getInt( try{
mFlutterPluginBinding.getApplicationContext().getContentResolver(), return (android.provider.Settings.System.getInt(
Settings.System.ACCELEROMETER_ROTATION, 0) == 1); mFlutterPluginBinding.getApplicationContext().getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0) == 1);
} catch (Exception e) {
Log.getStackTraceString(e);
return false;
}
} }
/** /**
......
...@@ -415,6 +415,32 @@ static Future<int> setGlobalEnv(String envConfig) async; ...@@ -415,6 +415,32 @@ static Future<int> setGlobalEnv(String envConfig) async;
| ------ | ------ | ------------------ | | ------ | ------ | ------------------ |
| result | int | 1 设置成功, 2 设置失败 | | result | int | 1 设置成功, 2 设置失败 |
### startVideoOrientationService
**说明**
开始监听设备旋转方向,开启之后,如果设备自动旋转打开,播放器会自动根据当前设备方向来旋转视频方向。
该接口目前只适用安卓端,IOS端会自动开启该能力。
**注意**
在调用该接口前,请务必向用户告知隐私风险。
**接口**
```dart
static Future<bool> startVideoOrientationService() async
```
**参数说明**
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| result | bool | true 开启成功,false 开启失败,如开启过早,还未等到上下文初始化、获取sensor失败等原因 |
## TXVodPlayerController类 ## TXVodPlayerController类
......
...@@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; ...@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:super_player/super_player.dart'; import 'package:super_player/super_player.dart';
import 'package:super_player_example/ui/demo_inputdialog.dart'; import 'package:super_player_example/ui/demo_inputdialog.dart';
import 'superplayer/demo_superplayer_lib.dart'; import 'superplayer/demo_superplayer_lib.dart';
/// flutter superplayer demo /// flutter superplayer demo
...@@ -29,22 +30,11 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> { ...@@ -29,22 +30,11 @@ class _DemoSuperplayerState extends State<DemoSuperplayer> {
fontSize: 16, color: Colors.grey fontSize: 16, color: Colors.grey
); );
void aa() async {
// List<TXVodDownloadMedialnfo> downloadInfoList = await TXVodDownloadController.instance.getDownloadList();
// bool result = await TXVodDownloadController.instance.deleteDownloadMediaInfo(medialnfo);
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// 监听设备旋转
TXVodDownloadMedialnfo medialnfo = TXVodDownloadMedialnfo(); SuperPlayerPlugin.startVideoOrientationService();
medialnfo.url = "http://1500005830.vod2.myqcloud.com/43843ec0vodtranscq1500005830/00eb06a88602268011437356984/video_10_0.m3u8";
TXVodDownloadController.instance.startDonwload(medialnfo);
_controller = SuperPlayerController(context); _controller = SuperPlayerController(context);
FTXVodPlayConfig config = FTXVodPlayConfig(); FTXVodPlayConfig config = FTXVodPlayConfig();
// 如果不配置preferredResolution,则在播放多码率视频的时候优先播放720 * 1280分辨率的码率 // 如果不配置preferredResolution,则在播放多码率视频的时候优先播放720 * 1280分辨率的码率
......
...@@ -26,7 +26,7 @@ static const int uninitialized = -1; ...@@ -26,7 +26,7 @@ static const int uninitialized = -1;
// 旧的一帧 // 旧的一帧
CVPixelBufferRef _lastBuffer; CVPixelBufferRef _lastBuffer;
int64_t _textureId; int64_t _textureId;
id<FlutterPluginRegistrar> _registrar; id<FlutterPluginRegistrar> _registrar;
id<FlutterTextureRegistry> _textureRegistry; id<FlutterTextureRegistry> _textureRegistry;
} }
...@@ -40,20 +40,20 @@ static const int uninitialized = -1; ...@@ -40,20 +40,20 @@ static const int uninitialized = -1;
_textureId = -1; _textureId = -1;
_eventSink = [FTXPlayerEventSinkQueue new]; _eventSink = [FTXPlayerEventSinkQueue new];
_netStatusSink = [FTXPlayerEventSinkQueue new]; _netStatusSink = [FTXPlayerEventSinkQueue new];
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
_methodChannel = [FlutterMethodChannel methodChannelWithName:[@"cloud.tencent.com/txliveplayer/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]]; _methodChannel = [FlutterMethodChannel methodChannelWithName:[@"cloud.tencent.com/txliveplayer/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]];
[_methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) { [_methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
[weakSelf handleMethodCall:call result:result]; [weakSelf handleMethodCall:call result:result];
}]; }];
_eventChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txliveplayer/event/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]]; _eventChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txliveplayer/event/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]];
[_eventChannel setStreamHandler:self]; [_eventChannel setStreamHandler:self];
_netStatusChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txliveplayer/net/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]]; _netStatusChannel = [FlutterEventChannel eventChannelWithName:[@"cloud.tencent.com/txliveplayer/net/" stringByAppendingString:[self.playerId stringValue]] binaryMessenger:[registrar messenger]];
[_netStatusChannel setStreamHandler:self]; [_netStatusChannel setStreamHandler:self];
} }
return self; return self;
} }
...@@ -62,7 +62,7 @@ static const int uninitialized = -1; ...@@ -62,7 +62,7 @@ static const int uninitialized = -1;
[self stopPlay]; [self stopPlay];
[_txLivePlayer removeVideoWidget]; [_txLivePlayer removeVideoWidget];
_txLivePlayer = nil; _txLivePlayer = nil;
if (_textureId >= 0) { if (_textureId >= 0) {
[_textureRegistry unregisterTexture:_textureId]; [_textureRegistry unregisterTexture:_textureId];
_textureId = -1; _textureId = -1;
...@@ -82,7 +82,7 @@ static const int uninitialized = -1; ...@@ -82,7 +82,7 @@ static const int uninitialized = -1;
CVPixelBufferRelease(_lastBuffer); CVPixelBufferRelease(_lastBuffer);
_lastBuffer = nil; _lastBuffer = nil;
} }
[_methodChannel setMethodCallHandler:nil]; [_methodChannel setMethodCallHandler:nil];
_methodChannel = nil; _methodChannel = nil;
...@@ -102,7 +102,7 @@ static const int uninitialized = -1; ...@@ -102,7 +102,7 @@ static const int uninitialized = -1;
int64_t tId = [_textureRegistry registerTexture:self]; int64_t tId = [_textureRegistry registerTexture:self];
_textureId = tId; _textureId = tId;
} }
if (_txLivePlayer != nil) { if (_txLivePlayer != nil) {
TXLivePlayConfig *config = [TXLivePlayConfig new]; TXLivePlayConfig *config = [TXLivePlayConfig new];
[config setPlayerPixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]; [config setPlayerPixelFormatType:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
...@@ -209,7 +209,7 @@ static const int uninitialized = -1; ...@@ -209,7 +209,7 @@ static const int uninitialized = -1;
- (void)setLiveMode:(int)type - (void)setLiveMode:(int)type
{ {
TXLivePlayConfig *config = _txLivePlayer.config; TXLivePlayConfig *config = _txLivePlayer.config;
if (type == 0) { if (type == 0) {
//自动模式 //自动模式
config.bAutoAdjustCacheTime = YES; config.bAutoAdjustCacheTime = YES;
...@@ -240,7 +240,7 @@ static const int uninitialized = -1; ...@@ -240,7 +240,7 @@ static const int uninitialized = -1;
if (_txLivePlayer != nil) { if (_txLivePlayer != nil) {
return [_txLivePlayer prepareLiveSeek:domain bizId:bizId]; return [_txLivePlayer prepareLiveSeek:domain bizId:bizId];
} }
return uninitialized; return uninitialized;
} }
...@@ -248,7 +248,7 @@ static const int uninitialized = -1; ...@@ -248,7 +248,7 @@ static const int uninitialized = -1;
if (_txLivePlayer != nil) { if (_txLivePlayer != nil) {
return [_txLivePlayer resumeLive]; return [_txLivePlayer resumeLive];
} }
return uninitialized; return uninitialized;
} }
...@@ -283,7 +283,7 @@ static const int uninitialized = -1; ...@@ -283,7 +283,7 @@ static const int uninitialized = -1;
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
{ {
NSDictionary *args = call.arguments; NSDictionary *args = call.arguments;
if([@"init" isEqualToString:call.method]){ if([@"init" isEqualToString:call.method]){
BOOL onlyAudio = [args[@"onlyAudio"] boolValue]; BOOL onlyAudio = [args[@"onlyAudio"] boolValue];
NSNumber* textureId = [self createPlayer:onlyAudio]; NSNumber* textureId = [self createPlayer:onlyAudio];
......
...@@ -192,6 +192,9 @@ SuperPlayerPlugin* instance; ...@@ -192,6 +192,9 @@ SuperPlayerPlugin* instance;
NSString *envConfig = call.arguments[@"envConfig"]; NSString *envConfig = call.arguments[@"envConfig"];
int setResult = [TXLiveBase setGlobalEnv:[envConfig UTF8String]]; int setResult = [TXLiveBase setGlobalEnv:[envConfig UTF8String]];
result(@(setResult)); result(@(setResult));
} else if([@"startVideoOrientationService" isEqualToString:call.method]) {
// only for android
result(nil);
} else { } else {
result(FlutterMethodNotImplemented); result(FlutterMethodNotImplemented);
} }
......
...@@ -166,4 +166,16 @@ class SuperPlayerPlugin { ...@@ -166,4 +166,16 @@ class SuperPlayerPlugin {
static Future<int> setGlobalEnv(String envConfig) async { static Future<int> setGlobalEnv(String envConfig) async {
return await _channel.invokeMethod("setGlobalEnv", {"envConfig": envConfig}); return await _channel.invokeMethod("setGlobalEnv", {"envConfig": envConfig});
} }
///
/// 开始监听设备旋转方向,开启之后,如果设备自动旋转打开,播放器会自动根据当前设备方向来旋转视频方向。
/// <h1>该接口目前只适用安卓端,IOS端会自动开启该能力</h1>
/// 在调用该接口前,请务必向用户告知隐私风险。
/// 如有需要,请确认是否有获取旋转sensor的权限。
/// @return true : 开启成功
/// false : 开启失败,如开启过早,还未等到上下文初始化、获取sensor失败等原因
static Future<bool> startVideoOrientationService() async {
return await _channel.invokeMethod("startVideoOrientationService");
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论