hyzp_ybqx-Commit177:已经实现违章视频的循环播放
This commit is contained in:
@@ -0,0 +1,739 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/screen_util.dart';
|
||||
import 'package:flutter_superplayer/flutter_superplayer.dart';
|
||||
import 'package:flutterptcontrol/flutterptcontrol.dart';
|
||||
import 'package:hyzp_ybqx/components/commonFun.dart';
|
||||
import 'package:hyzp_ybqx/components/dioFun.dart';
|
||||
import 'package:hyzp_ybqx/provider/player_ratio.dart';
|
||||
import 'package:hyzp_ybqx/provider/player_region.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../components/commonFun.dart';
|
||||
import '../services/Storage.dart';
|
||||
|
||||
const _kControlViewTypes = [kControlViewTypeDefault, kControlViewTypeWithout];
|
||||
|
||||
class SuperPlayerPage extends StatefulWidget {
|
||||
SuperPlayerPage(
|
||||
{@required this.url,
|
||||
this.id = -2, // 播放点位视频的点位编号,-2 表示播放违章视频
|
||||
this.dwip = '', // 点位IP,用于点位视频控制球机方向
|
||||
this.loop = 1,
|
||||
this.title = 'Tencent Player',
|
||||
Key key})
|
||||
: super(key: key);
|
||||
String dwip;
|
||||
String url;
|
||||
String title;
|
||||
int loop; //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
||||
int id;
|
||||
|
||||
@override
|
||||
_SuperPlayerPageState createState() => _SuperPlayerPageState();
|
||||
}
|
||||
|
||||
class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListener {
|
||||
SuperPlayerController _playerController = SuperPlayerController();
|
||||
|
||||
String _sdkVersion = 'Unknown';
|
||||
List<String> _logs = [];
|
||||
bool bFullScreen = false;
|
||||
|
||||
String _controlViewType = _kControlViewTypes.first;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
Playing = false;
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
setSphericalCameraDio(id: widget.id, dwip: widget.dwip, cmdCode: 1);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
//initPlatformState();
|
||||
// Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
// _playerController.playWithModel(SuperPlayerModel(url: widget.url));
|
||||
// setState(() {
|
||||
// });
|
||||
// });
|
||||
init();
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
await _playerController.addListener(this);
|
||||
await initPlatformState();
|
||||
if (!mounted) return;
|
||||
print('mounted = ${mounted}');
|
||||
// 开启调试日志
|
||||
//await FTXPlayerController.setConsoleEnabled(true);
|
||||
// 初始化播放器
|
||||
//await _controller.initialize(onlyAudio: true);
|
||||
|
||||
await _playerController.uiHideDanmu(); // 隐藏弹幕
|
||||
//设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
||||
if (0 == widget.loop) {
|
||||
await _playerController.setLoop(true);
|
||||
}
|
||||
|
||||
await _playerController.playWithModel(testSuperPlayerModel);
|
||||
//_controller.play("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
|
||||
// _controller
|
||||
// .play('rtmp://125.64.218.67:9901/rtp/gb_play_34020000001320003016_34020000001320003016');
|
||||
// 设置循环播放
|
||||
//await _controller.setLoop(true);
|
||||
// 开始播放
|
||||
//await _controller.play("http://125.64.218.67:9908/video/2_6063_20210409_140608_川Q31715.mp4");
|
||||
}
|
||||
|
||||
SuperPlayerModel get testSuperPlayerModel {
|
||||
// int appId = 1252463788;
|
||||
// String fileId = "5285890781763144364";
|
||||
|
||||
SuperPlayerModel superPlayerModel = SuperPlayerModel(
|
||||
url: widget.url,
|
||||
// appId: appId,
|
||||
// videoId: SuperPlayerVideoId(fileId: fileId),
|
||||
);
|
||||
return superPlayerModel;
|
||||
}
|
||||
|
||||
// Platform messages are asynchronous, so we initialize in an async method.
|
||||
Future<void> initPlatformState() async {
|
||||
String sdkVersion;
|
||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||
try {
|
||||
sdkVersion = await FlutterSuperPlayer.sdkVersion;
|
||||
} on PlatformException {
|
||||
sdkVersion = 'Failed to get platform version.';
|
||||
}
|
||||
print('sdkVersion = ${sdkVersion}');
|
||||
print('mounted = ${mounted}');
|
||||
|
||||
// If the widget was removed from the tree while the asynchronous platform
|
||||
// message was in flight, we want to discard the reply rather than calling
|
||||
// setState to update our non-existent appearance.
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_sdkVersion = sdkVersion;
|
||||
});
|
||||
}
|
||||
|
||||
void _addLog(String method, dynamic data) {
|
||||
_logs.add('>>>$method');
|
||||
if (data != null) {
|
||||
_logs.add(data is Map ? json.encode(data) : data);
|
||||
}
|
||||
_logs.add(' ');
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
PlayerRatioProvide playerRatioProvide;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
playerRegionProvide = Provider.of<PlayerRegionProvide>(context);
|
||||
playerRatioProvide = Provider.of<PlayerRatioProvide>(context);
|
||||
// List<Widget> listData = getDataListControl2();
|
||||
double btnHeight1 = 70; //第一按钮行高度
|
||||
double btnHeight2 = 160; //第二按钮行高度
|
||||
int btnCount = 4; //每行按钮个数
|
||||
// int btnCount3 = listData.length; //每行按钮个数
|
||||
var mediaSize = MediaQuery.of(context).size;
|
||||
|
||||
// widget.id:播放点位视频的点位编号,-2 表示播放违章视频
|
||||
double btn_left = -2 == widget.id ? 347 : 70; //第一按钮行高度
|
||||
double btn_gap = -2 == widget.id ? 104 : 70; //第一按钮行高度
|
||||
|
||||
//远程控制球机方向按钮外半径和内半径
|
||||
double _outerRadius = 270;
|
||||
double _innerRadius = _outerRadius / 2;
|
||||
|
||||
//double barHeight = bFullScreen ? 0 : MediaQueryData.fromWindow(window).padding.top;
|
||||
return Scaffold(
|
||||
appBar: bFullScreen
|
||||
? null
|
||||
: PreferredSize(
|
||||
preferredSize: Size.fromHeight(ScreenUtil().setHeight(173)), // 设置appBar高度
|
||||
// 设置appBar高度
|
||||
child: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: true,
|
||||
titleSpacing: 0.0,
|
||||
//设置title的左边距
|
||||
flexibleSpace: Container(
|
||||
//SizedBox(height: ScreenUtil().statusBarHeight), //显示顶部状态栏
|
||||
// SizedBox(height: ScreenUtil().setHeight(10)), //显示顶部状态栏
|
||||
padding: EdgeInsets.only(top: ScreenUtil().statusBarHeight), //留出顶部状态栏高度
|
||||
child: Container(
|
||||
//height: ScreenUtil().setHeight(173),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight,
|
||||
colors: [
|
||||
Color.fromRGBO(12, 186, 156, 1),
|
||||
Color.fromRGBO(39, 127, 235, 1),
|
||||
],
|
||||
),
|
||||
),
|
||||
// decoration: BoxDecoration(
|
||||
// gradient: LinearGradient(colors: [
|
||||
// Color(0xFF0018EB),
|
||||
// Color(0xFF01C1D9),
|
||||
// ], begin: Alignment.bottomCenter, end: Alignment.topCenter),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
title: Padding(
|
||||
padding: EdgeInsets.only(left: 0, right: 0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
getIconAndTextButton(
|
||||
iconColor: Colors.white,
|
||||
iconData: Icons.chevron_left_outlined,
|
||||
onPress: () {
|
||||
getingDwVideo = false;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Text(widget.title,
|
||||
style: TextStyle(color: Colors.white, fontSize: 18),
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
SizedBox(width: 50),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: WillPopScope(
|
||||
child: Container(
|
||||
// height: ScreenUtil().screenHeight -
|
||||
// ScreenUtil().statusBarHeight -
|
||||
// ScreenUtil().bottomBarHeight,
|
||||
color: Color.fromRGBO(224, 224, 224, 1),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
//第2行组件,视频播放区
|
||||
Center(
|
||||
child: Container(
|
||||
//padding: EdgeInsets.only(top: barHeight),
|
||||
alignment: Alignment(0, -1),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.width * (9 / 16),
|
||||
color: Colors.black,
|
||||
child: Stack(
|
||||
children: [
|
||||
_playState <= 2 ? getMoreWidget(strokeWidth: 3.0) : SizedBox.shrink(),
|
||||
SuperPlayerView(
|
||||
controller: _playerController,
|
||||
controlViewType: _kControlViewTypes[0],
|
||||
),
|
||||
//_playState < 3 ? SizedBox.shrink() : getMoreWidget(strokeWidth: 3.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
//第3.1行组件,控制按钮区
|
||||
bFullScreen ? SizedBox.shrink() : SizedBox(height: ScreenUtil().setHeight(69)),
|
||||
bFullScreen
|
||||
? SizedBox.shrink()
|
||||
: Row(
|
||||
children: [
|
||||
SizedBox(width: ScreenUtil().setWidth(btn_left)),
|
||||
getRoundButton(
|
||||
//(bPlaying) ? '暂停' : '播放',
|
||||
text: playerRegionProvide.playerText,
|
||||
icon: playerRegionProvide.playerIcon,
|
||||
diameter: 130,
|
||||
onPress: playOrPause,
|
||||
),
|
||||
SizedBox(width: ScreenUtil().setWidth(btn_gap)),
|
||||
getRoundButton(
|
||||
text: '刷新',
|
||||
icon: Icons.autorenew,
|
||||
diameter: 130,
|
||||
onPress: () {
|
||||
restartPlay(urlnew);
|
||||
},
|
||||
),
|
||||
// widget.id:播放点位视频的点位编号,-2 表示播放违章视频
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: SizedBox(width: ScreenUtil().setWidth(btn_gap)),
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: getRoundButton_image(
|
||||
text: '雨刷',
|
||||
image_path: 'assets/images/wiper.png',
|
||||
diameter: 130,
|
||||
onPress: () {
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 3);
|
||||
},
|
||||
),
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: SizedBox(width: ScreenUtil().setWidth(btn_gap)),
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: getRoundButton_image(
|
||||
text: '放大',
|
||||
image_path: 'assets/images/zoom_in.png',
|
||||
imageSize: 72,
|
||||
diameter: 130,
|
||||
onPress: () {
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 11);
|
||||
},
|
||||
),
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: SizedBox(width: ScreenUtil().setWidth(btn_gap)),
|
||||
-2 == widget.id
|
||||
? SizedBox.shrink()
|
||||
: getRoundButton_image(
|
||||
text: '缩小',
|
||||
image_path: 'assets/images/zoom_out.png',
|
||||
imageSize: 72,
|
||||
diameter: 130,
|
||||
onPress: () {
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 12);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
bFullScreen ? SizedBox.shrink() : SizedBox(height: ScreenUtil().setHeight(79)),
|
||||
bFullScreen
|
||||
? SizedBox.shrink()
|
||||
: Container(
|
||||
height: ScreenUtil().setHeight(2 * _outerRadius),
|
||||
width: ScreenUtil().setWidth(2 * _outerRadius),
|
||||
child: PtControlWidget(
|
||||
// innerRadius: _innerRadius,
|
||||
// outerRadius: _outerRadius,
|
||||
// 进行像素单位转换,解决按钮响应错乱问题
|
||||
innerRadius: _innerRadius / ScreenUtil().pixelRatio,
|
||||
outerRadius: _outerRadius / ScreenUtil().pixelRatio,
|
||||
callback: -2 == widget.id // 播放点位视频的点位编号,-2 表示播放违章视频
|
||||
? null
|
||||
: (status) {
|
||||
///点击回调
|
||||
print('status = $status');
|
||||
switch (status) {
|
||||
|
||||
/// status == -1 超出范围
|
||||
/// status == 0 右
|
||||
case 0:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 24);
|
||||
break;
|
||||
|
||||
/// status == 1 右上
|
||||
case 1:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 26);
|
||||
break;
|
||||
|
||||
///三、球机位移接口方向代码说明:
|
||||
// 上:8 下:4 左:2 右:1 左上:10 左下:6 右上:9 右下:5
|
||||
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
// 21:上移
|
||||
// 22:下移
|
||||
// 23:左移
|
||||
// 24:右移
|
||||
// 25:左上移动
|
||||
// 26:右上移动
|
||||
// 27:左下移动
|
||||
// 28:右下移动
|
||||
/// status == 2 上
|
||||
case 2:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 21);
|
||||
break;
|
||||
|
||||
/// status == 3 左上
|
||||
case 3:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 25);
|
||||
break;
|
||||
|
||||
/// status == 4 左
|
||||
case 4:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 23);
|
||||
break;
|
||||
|
||||
/// status == 5 左下
|
||||
case 5:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 27);
|
||||
break;
|
||||
|
||||
/// status == 6 下
|
||||
case 6:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 22);
|
||||
break;
|
||||
|
||||
/// status == 7 右下
|
||||
case 7:
|
||||
setSphericalCameraDio(
|
||||
id: widget.id, dwip: widget.dwip, cmdCode: 28);
|
||||
break;
|
||||
|
||||
/// status == 8 还原
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
),
|
||||
// child: GridView.custom(
|
||||
// // padding: EdgeInsets.only(
|
||||
// // left: ScreenUtil().setWidth(35), right: ScreenUtil().setWidth(35)),
|
||||
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
// crossAxisCount: btnCount3,
|
||||
// mainAxisSpacing: 0,
|
||||
// crossAxisSpacing: 1,
|
||||
// childAspectRatio: ratio3,
|
||||
// ),
|
||||
// childrenDelegate: SliverChildBuilderDelegate((context, position) {
|
||||
// return getItemContainer(listData[position]);
|
||||
// }, childCount: btnCount3)),
|
||||
),
|
||||
//SizedBox(height: ScreenUtil().setHeight(49)),
|
||||
//Divider(color: Colors.blue),
|
||||
//第4行组件,分隔栏
|
||||
// Container(
|
||||
// //height: 11,
|
||||
// height: ScreenUtil().setHeight(28),
|
||||
// color: Color.fromRGBO(224, 224, 224, 1),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
onWillPop: () {
|
||||
Playing = false;
|
||||
getingDwVideo = false;
|
||||
// 云台控制代码:1:停止动作、3:启动雨刷、11:焦距变大、12:焦距变小
|
||||
setSphericalCameraDio(id: widget.id, dwip: widget.dwip, cmdCode: 1);
|
||||
Navigator.pop(context); //关闭弹框,播放输入视频地址
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClickFloatCloseBtn() {
|
||||
_addLog('onClickFloatCloseBtn', {});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClickSmallReturnBtn() {
|
||||
_addLog('onClickSmallReturnBtn', {});
|
||||
Navigator.maybePop(context);
|
||||
}
|
||||
|
||||
@override
|
||||
void onFullScreenChange(bool isFullScreen) {
|
||||
_addLog('onFullScreenChange', {'isFullScreen': isFullScreen});
|
||||
bFullScreen = !bFullScreen;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void onPlayProgressChange(int current, int duration) {
|
||||
_addLog('onPlayProgressChange', {'current': current, 'duration': duration});
|
||||
}
|
||||
|
||||
int _playState = 4;
|
||||
int i = 0;
|
||||
|
||||
@override
|
||||
void onPlayStateChange(int playState) {
|
||||
_playState = playState;
|
||||
i++;
|
||||
print('$i、playState = $playState');
|
||||
_addLog('onPlayStateChange', {'playState': playState});
|
||||
setPlayOrPauseIcon(playState);
|
||||
}
|
||||
|
||||
void setPlayOrPauseIcon(int state) {
|
||||
//state : 1 播放状态,2 暂停状态
|
||||
print('state = $state');
|
||||
if (1 == state) {
|
||||
bPlaying = true;
|
||||
} else {
|
||||
bPlaying = false;
|
||||
}
|
||||
playerRegionProvide.changePlayerState(bPlaying);
|
||||
Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void onStartFloatWindowPlay() {
|
||||
_addLog('onStartFloatWindowPlay', {});
|
||||
}
|
||||
|
||||
//生成圆形按钮部件,基于图标
|
||||
Widget getRoundButton(
|
||||
{double diameter = 144,
|
||||
double marginVer = 10,
|
||||
String text,
|
||||
IconData icon,
|
||||
double fontSize = 16,
|
||||
double iconSize = 90,
|
||||
Color color = const Color.fromRGBO(52, 157, 237, 1),
|
||||
var onPress}) {
|
||||
return InkWell(
|
||||
onTap: onPress,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: ScreenUtil().setWidth(diameter),
|
||||
height: ScreenUtil().setHeight(diameter),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(
|
||||
icon,
|
||||
size: ScreenUtil().setWidth(iconSize),
|
||||
color: Color.fromRGBO(52, 157, 237, 1),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(200)),
|
||||
border: Border.all(width: 0, style: BorderStyle.none),
|
||||
),
|
||||
),
|
||||
SizedBox(height: ScreenUtil().setHeight(marginVer)),
|
||||
Text(text, style: TextStyle(fontSize: fontSize, color: Color.fromRGBO(139, 139, 139, 1))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//生成圆形按钮部件,基于图片
|
||||
Widget getRoundButton_image(
|
||||
{double diameter = 144,
|
||||
double marginVer = 10,
|
||||
String text,
|
||||
String image_path,
|
||||
double fontSize = 16,
|
||||
double imageSize = 90,
|
||||
Color color = const Color.fromRGBO(52, 157, 237, 1),
|
||||
Color color_bkg = Colors.white,
|
||||
var onPress}) {
|
||||
return InkWell(
|
||||
onTap: onPress,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: ScreenUtil().setWidth(diameter),
|
||||
height: ScreenUtil().setHeight(diameter),
|
||||
alignment: Alignment.center,
|
||||
child: Image.asset(image_path,
|
||||
fit: BoxFit.fitWidth,
|
||||
width: ScreenUtil().setWidth(imageSize),
|
||||
//height: ScreenUtil().setWidth(iconSize),
|
||||
color: Color.fromRGBO(52, 157, 237, 1)),
|
||||
// child: Icon(
|
||||
// icon,
|
||||
// size: ScreenUtil().setWidth(iconSize),
|
||||
// color: Color.fromRGBO(52, 157, 237, 1),
|
||||
// ),
|
||||
decoration: BoxDecoration(
|
||||
color: color_bkg,
|
||||
borderRadius: BorderRadius.all(Radius.circular(200)),
|
||||
border: Border.all(width: 0, style: BorderStyle.none),
|
||||
),
|
||||
),
|
||||
SizedBox(height: ScreenUtil().setHeight(marginVer)),
|
||||
Text(text, style: TextStyle(fontSize: fontSize, color: Color.fromRGBO(139, 139, 139, 1))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool bPlaying = true;
|
||||
|
||||
void playOrPause() {
|
||||
//state : 1 播放状态,2 暂停状态
|
||||
_playerController.getPlayState().then((state) {
|
||||
print('state = $state');
|
||||
if (1 == state) {
|
||||
bPlaying = false;
|
||||
_playerController.pause();
|
||||
} else {
|
||||
bPlaying = true;
|
||||
_playerController.resume();
|
||||
}
|
||||
playerRegionProvide.changePlayerState(bPlaying);
|
||||
Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
void restartPlay(String url) async {
|
||||
_playState = 4;
|
||||
bPlaying = true;
|
||||
_playerController.resetPlayer();
|
||||
_playerController.resume();
|
||||
// //writeCurrentPosFile();
|
||||
// await player.stop();
|
||||
// await player.reset();
|
||||
// await player.setOption(FijkOption.playerCategory, "mediacodec-all-videos", 1);
|
||||
// await player.setOption(FijkOption.hostCategory, "enable-snapshot", 1);
|
||||
// await player.setOption(FijkOption.hostCategory, "request-screen-on", 1);
|
||||
// await player.setOption(FijkOption.hostCategory, "request-audio-focus", 1);
|
||||
// await player.setOption(FijkOption.hostCategory, "enable-accurate-seek", 1);
|
||||
// await player.setOption(FijkOption.hostCategory, "max-buffer-size", 500 * 1024);
|
||||
// await player.setDataSource(url, autoPlay: true).catchError((e) {
|
||||
// print("setDataSource error: $e");
|
||||
// });
|
||||
// await player.setLoop(widget.loop); //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
||||
// bPlaying = true;
|
||||
// setState(() {});
|
||||
// playerRegionProvide.changePlayerState(bPlaying);
|
||||
}
|
||||
|
||||
//生成播放控制区第2行按钮List
|
||||
// List<Widget> getDataListControl2() {
|
||||
// double _diameter = 100;
|
||||
// double _iconSize = 70;
|
||||
// double _fontSize = 14;
|
||||
// double _marginVer = 8;
|
||||
//
|
||||
// List<Widget> list = [
|
||||
// // getRoundButton(
|
||||
// // diameter: _diameter,
|
||||
// // iconSize: _iconSize,
|
||||
// // text: '快退',
|
||||
// // icon: Icons.fast_rewind,
|
||||
// // onPress: () {
|
||||
// // fastSeek(false);
|
||||
// // },
|
||||
// // ),
|
||||
// // getRoundButton(
|
||||
// // diameter: _diameter,
|
||||
// // iconSize: _iconSize,
|
||||
// // text: '快进',
|
||||
// // icon: Icons.fast_forward,
|
||||
// // onPress: () {
|
||||
// // fastSeek(true);
|
||||
// // },
|
||||
// // ),
|
||||
// getRoundButton(
|
||||
// diameter: _diameter,
|
||||
// iconSize: _iconSize,
|
||||
// fontSize: _fontSize,
|
||||
// marginVer: _marginVer,
|
||||
// text: '放大',
|
||||
// icon: Icons.zoom_in,
|
||||
// onPress: () {
|
||||
// //print('Icons.videocam');
|
||||
// //_inputDialog(context2);
|
||||
// if (10 >= playerRatioProvide.scale) {
|
||||
// playerRatioProvide.changeScale(playerRatioProvide.scale + 0.5);
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// getRoundButton(
|
||||
// diameter: _diameter,
|
||||
// iconSize: _iconSize,
|
||||
// fontSize: _fontSize,
|
||||
// marginVer: _marginVer,
|
||||
// text: '缩小',
|
||||
// icon: Icons.zoom_out,
|
||||
// onPress: () {
|
||||
// //print('Icons.videocam');
|
||||
// //_getFileDialog(context2);
|
||||
// if (1 < playerRatioProvide.scale) {
|
||||
// playerRatioProvide.changeScale(playerRatioProvide.scale - 0.5);
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// // _getIconAndTextButton(
|
||||
// // '还原',
|
||||
// // Icons.reply,
|
||||
// // Colors.orange,
|
||||
// // () {
|
||||
// // //print('Icons.videocam');
|
||||
// // //_getFileDialog(context2);
|
||||
// // // 更新当前位置
|
||||
// // playerRatioProvide.changeScale(1.0);
|
||||
// // playerRatioProvide.changeOffset(Offset(0, 0));
|
||||
// // playerRatioProvide.changeDeltaX(0.0);
|
||||
// // playerRatioProvide.changeDeltaY(0.0);
|
||||
// // },
|
||||
// // ),
|
||||
// getRoundButton(
|
||||
// diameter: _diameter,
|
||||
// iconSize: _iconSize,
|
||||
// fontSize: _fontSize,
|
||||
// marginVer: _marginVer,
|
||||
// text: '截图',
|
||||
// icon: Icons.camera_alt,
|
||||
// onPress: () {
|
||||
// //通过上面定义的key,才能准确调用该类型的该对象的方法
|
||||
// //_myFijkPanelWidgetBuilderStateKey.currentState.takeSnapshot();
|
||||
// //_fijkPanelWidgetBuilder.currentState..takeSnapshot();
|
||||
// takeSnapshot();
|
||||
// },
|
||||
// ),
|
||||
// getRoundButton(
|
||||
// diameter: _diameter,
|
||||
// iconSize: _iconSize,
|
||||
// fontSize: _fontSize,
|
||||
// marginVer: _marginVer,
|
||||
// text: '全屏',
|
||||
// icon: Icons.fullscreen,
|
||||
// onPress: () {
|
||||
// //player.enterFullScreen();
|
||||
// _playerController.toFullScreen();
|
||||
// },
|
||||
// ),
|
||||
// ];
|
||||
// return list;
|
||||
// }
|
||||
|
||||
void takeSnapshot() {
|
||||
// player.takeSnapShot().then((v) {
|
||||
// var provider = MemoryImage(v);
|
||||
// precacheImage(provider, context).then((_) {
|
||||
// setState(() {
|
||||
// myImageProvider = provider;
|
||||
// });
|
||||
// });
|
||||
// FijkLog.d("get snapshot succeed");
|
||||
//
|
||||
// //Uint8List fileData;
|
||||
// String fileFath;
|
||||
// ImageSaver.save('extended_image_cropped_image.jpg', v).then((value) {
|
||||
// fileFath = value;
|
||||
// // var fileFath = await ImagePickerSaver.saveFile(fileData: fileData);
|
||||
// print('my save fileFath : $fileFath');
|
||||
// });
|
||||
// }).catchError((e) {
|
||||
// FijkLog.d("get snapshot failed");
|
||||
// });
|
||||
}
|
||||
}
|
||||
+123
-59
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:fijkplayer/fijkplayer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/screen_util.dart';
|
||||
@@ -38,7 +39,8 @@ class SuperPlayerPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListener {
|
||||
SuperPlayerController _playerController = SuperPlayerController();
|
||||
// SuperPlayerController _playerController = SuperPlayerController();
|
||||
final FijkPlayer _playerController = FijkPlayer();
|
||||
|
||||
String _sdkVersion = 'Unknown';
|
||||
List<String> _logs = [];
|
||||
@@ -63,35 +65,78 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
|
||||
// setState(() {
|
||||
// });
|
||||
// });
|
||||
init();
|
||||
// init();
|
||||
|
||||
_playerController.setOption(FijkOption.hostCategory, "enable-snapshot", 1);
|
||||
_playerController.setOption(FijkOption.playerCategory, "mediacodec-all-videos", 1);
|
||||
startPlay();
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
await _playerController.addListener(this);
|
||||
await initPlatformState();
|
||||
void startPlay() async {
|
||||
// await _playerController.addListener(() {});
|
||||
|
||||
if (!mounted) return;
|
||||
print('mounted = ${mounted}');
|
||||
// 开启调试日志
|
||||
//await FTXPlayerController.setConsoleEnabled(true);
|
||||
// 初始化播放器
|
||||
//await _controller.initialize(onlyAudio: true);
|
||||
|
||||
await _playerController.uiHideDanmu(); // 隐藏弹幕
|
||||
//设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
||||
if (0 == widget.loop) {
|
||||
await _playerController.setLoop(true);
|
||||
await _playerController.setLoop(widget.loop); // 0无限循环,1循环一次,2循环两次,以此类推
|
||||
if (widget.loop == 0) {
|
||||
await _playerController.setOption(FijkOption.playerCategory, "mediacodec-all-videos", 1);
|
||||
await _playerController.setOption(FijkOption.hostCategory, "enable-snapshot", 1);
|
||||
await _playerController.setOption(FijkOption.hostCategory, "request-screen-on", 1);
|
||||
await _playerController.setOption(FijkOption.hostCategory, "request-audio-focus", 1);
|
||||
await _playerController.setOption(FijkOption.hostCategory, "enable-accurate-seek", 1);
|
||||
} else {
|
||||
/// fijkplayer播放点位视频延迟比较大优化-OK,改完后约1秒钟就能打开 - Being
|
||||
// 是否开启预缓冲,一般直播项目会开启,达到秒开的效果,不过带来了播放丢帧卡顿的体验
|
||||
await _playerController.setOption(FijkOption.playerCategory, "packet-buffering", 0);
|
||||
// 播放前的探测Size,默认是1024K(1M), 改小一点会出画面更快
|
||||
// await player.setOption(FijkOption.formatCategory, "probesize", 200); // 1.3S打开
|
||||
await _playerController.setOption(FijkOption.formatCategory, "probesize", 200); // 1.3S打开
|
||||
await _playerController.setOption(FijkOption.formatCategory, 'http-detect-range-support', 0);
|
||||
// 设置播放前的探测时间 1,达到首屏秒开效果
|
||||
await _playerController.setOption(FijkOption.formatCategory, "analyzeduration", 1);
|
||||
// 缩短播放的rtmp视频延迟在1s内
|
||||
await _playerController.setOption(FijkOption.formatCategory, "fflags", "nobuffer");
|
||||
// 支持硬解: 1 开启, O 关闭
|
||||
await _playerController.setOption(FijkOption.playerCategory, "mediacodec-hevc", 1);
|
||||
|
||||
/// fijkplayer播放点位视频延迟比较大优化-OK,改完后半秒钟就能打开 - End
|
||||
|
||||
await _playerController.setOption(FijkOption.hostCategory, "request-screen-on", 1);
|
||||
await _playerController.setOption(FijkOption.hostCategory, "request-audio-focus", 1);
|
||||
}
|
||||
|
||||
await _playerController.playWithModel(testSuperPlayerModel);
|
||||
//_controller.play("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
|
||||
// _controller
|
||||
// .play('rtmp://125.64.218.67:9901/rtp/gb_play_34020000001320003016_34020000001320003016');
|
||||
// 设置循环播放
|
||||
//await _controller.setLoop(true);
|
||||
// 开始播放
|
||||
//await _controller.play("http://125.64.218.67:9908/video/2_6063_20210409_140608_川Q31715.mp4");
|
||||
await _playerController.setDataSource(widget.url, autoPlay: true).catchError((e) {
|
||||
print("setDataSource error: $e");
|
||||
});
|
||||
}
|
||||
|
||||
// Future<void> init() async {
|
||||
// await _playerController.addListener(this);
|
||||
// await initPlatformState();
|
||||
// if (!mounted) return;
|
||||
// print('mounted = ${mounted}');
|
||||
// // 开启调试日志
|
||||
// //await FTXPlayerController.setConsoleEnabled(true);
|
||||
// // 初始化播放器
|
||||
// //await _controller.initialize(onlyAudio: true);
|
||||
//
|
||||
// await _playerController.uiHideDanmu(); // 隐藏弹幕
|
||||
// //设置播放循环,默认播放器的循环次数是1, 即不循环播放。如果设置循环次数0,表示无限循环。
|
||||
// if (0 == widget.loop) {
|
||||
// await _playerController.setLoop(true);
|
||||
// }
|
||||
//
|
||||
// await _playerController.playWithModel(testSuperPlayerModel);
|
||||
// //_controller.play("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
|
||||
// // _controller
|
||||
// // .play('rtmp://125.64.218.67:9901/rtp/gb_play_34020000001320003016_34020000001320003016');
|
||||
// // 设置循环播放
|
||||
// //await _controller.setLoop(true);
|
||||
// // 开始播放
|
||||
// //await _controller.play("http://125.64.218.67:9908/video/2_6063_20210409_140608_川Q31715.mp4");
|
||||
// }
|
||||
|
||||
SuperPlayerModel get testSuperPlayerModel {
|
||||
// int appId = 1252463788;
|
||||
// String fileId = "5285890781763144364";
|
||||
@@ -105,26 +150,26 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
|
||||
}
|
||||
|
||||
// Platform messages are asynchronous, so we initialize in an async method.
|
||||
Future<void> initPlatformState() async {
|
||||
String sdkVersion;
|
||||
// Platform messages may fail, so we use a try/catch PlatformException.
|
||||
try {
|
||||
sdkVersion = await FlutterSuperPlayer.sdkVersion;
|
||||
} on PlatformException {
|
||||
sdkVersion = 'Failed to get platform version.';
|
||||
}
|
||||
print('sdkVersion = ${sdkVersion}');
|
||||
print('mounted = ${mounted}');
|
||||
|
||||
// If the widget was removed from the tree while the asynchronous platform
|
||||
// message was in flight, we want to discard the reply rather than calling
|
||||
// setState to update our non-existent appearance.
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
_sdkVersion = sdkVersion;
|
||||
});
|
||||
}
|
||||
// Future<void> initPlatformState() async {
|
||||
// String sdkVersion;
|
||||
// // Platform messages may fail, so we use a try/catch PlatformException.
|
||||
// try {
|
||||
// sdkVersion = await FlutterSuperPlayer.sdkVersion;
|
||||
// } on PlatformException {
|
||||
// sdkVersion = 'Failed to get platform version.';
|
||||
// }
|
||||
// print('sdkVersion = ${sdkVersion}');
|
||||
// print('mounted = ${mounted}');
|
||||
//
|
||||
// // If the widget was removed from the tree while the asynchronous platform
|
||||
// // message was in flight, we want to discard the reply rather than calling
|
||||
// // setState to update our non-existent appearance.
|
||||
// if (!mounted) return;
|
||||
//
|
||||
// setState(() {
|
||||
// _sdkVersion = sdkVersion;
|
||||
// });
|
||||
// }
|
||||
|
||||
void _addLog(String method, dynamic data) {
|
||||
_logs.add('>>>$method');
|
||||
@@ -237,10 +282,28 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
|
||||
child: Stack(
|
||||
children: [
|
||||
_playState <= 2 ? getMoreWidget(strokeWidth: 3.0) : SizedBox.shrink(),
|
||||
SuperPlayerView(
|
||||
controller: _playerController,
|
||||
controlViewType: _kControlViewTypes[0],
|
||||
// SuperPlayerView(
|
||||
// controller: _playerController,
|
||||
// controlViewType: _kControlViewTypes[0],
|
||||
// ),
|
||||
|
||||
FijkView(
|
||||
//设置视频区域背景颜色-OK
|
||||
color: Colors.black,
|
||||
player: _playerController,
|
||||
panelBuilder: fijkPanel2Builder(snapShot: true),
|
||||
fsFit: FijkFit.fill,
|
||||
// panelBuilder: simplestUI,
|
||||
// panelBuilder: (FijkPlayer player, BuildContext context,
|
||||
// Size viewSize, Rect texturePos) {
|
||||
// return CustomFijkPanel(
|
||||
// player: player,
|
||||
// buildContext: context,
|
||||
// viewSize: viewSize,
|
||||
// texturePos: texturePos);
|
||||
// },
|
||||
),
|
||||
|
||||
//_playState < 3 ? SizedBox.shrink() : getMoreWidget(strokeWidth: 3.0),
|
||||
],
|
||||
),
|
||||
@@ -577,26 +640,27 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
|
||||
|
||||
void playOrPause() {
|
||||
//state : 1 播放状态,2 暂停状态
|
||||
_playerController.getPlayState().then((state) {
|
||||
print('state = $state');
|
||||
if (1 == state) {
|
||||
bPlaying = false;
|
||||
_playerController.pause();
|
||||
} else {
|
||||
bPlaying = true;
|
||||
_playerController.resume();
|
||||
}
|
||||
playerRegionProvide.changePlayerState(bPlaying);
|
||||
Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
||||
setState(() {});
|
||||
});
|
||||
// _playerController.getPlayState().then((state) {
|
||||
// print('state = $state');
|
||||
// if (1 == state) {
|
||||
// bPlaying = false;
|
||||
// _playerController.pause();
|
||||
// } else {
|
||||
// bPlaying = true;
|
||||
// _playerController.resume();
|
||||
// }
|
||||
// playerRegionProvide.changePlayerState(bPlaying);
|
||||
// Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
||||
// setState(() {});
|
||||
// });
|
||||
}
|
||||
|
||||
void restartPlay(String url) async {
|
||||
_playState = 4;
|
||||
bPlaying = true;
|
||||
_playerController.resetPlayer();
|
||||
_playerController.resume();
|
||||
// _playerController.resetPlayer();
|
||||
// _playerController.resume();
|
||||
|
||||
// //writeCurrentPosFile();
|
||||
// await player.stop();
|
||||
// await player.reset();
|
||||
|
||||
Reference in New Issue
Block a user