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

video preDownload support fileId

上级 4b10d489
......@@ -8,12 +8,15 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.tencent.rtmp.TXPlayInfoParams;
import com.tencent.rtmp.downloader.ITXVodDownloadListener;
import com.tencent.rtmp.downloader.ITXVodFilePreloadListener;
import com.tencent.rtmp.downloader.ITXVodPreloadListener;
import com.tencent.rtmp.downloader.TXVodDownloadDataSource;
import com.tencent.rtmp.downloader.TXVodDownloadManager;
import com.tencent.rtmp.downloader.TXVodDownloadMediaInfo;
import com.tencent.rtmp.downloader.TXVodPreloadManager;
import com.tencent.vod.flutter.messages.FtxMessages;
import com.tencent.vod.flutter.messages.FtxMessages.BoolMsg;
import com.tencent.vod.flutter.messages.FtxMessages.IntMsg;
import com.tencent.vod.flutter.messages.FtxMessages.MapMsg;
......@@ -29,6 +32,9 @@ import io.flutter.plugin.common.EventChannel;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Download management, pre-download, and offline download.
......@@ -42,6 +48,8 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final Handler mMainHandler;
private ExecutorService mPreloadPool = Executors.newCachedThreadPool();
/**
* Video download management.
*
......@@ -69,6 +77,17 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
TXVodDownloadManager.getInstance().setListener(this);
}
private void onStartEvent(long tmpTaskId, int taskId, String fileId, String url, Bundle params) {
Bundle bundle = new Bundle();
bundle.putLong("tmpTaskId", tmpTaskId);
bundle.putInt("taskId", taskId);
bundle.putString("fileId", fileId);
bundle.putString("url", url);
Map<String, Object> result = CommonUtil.getParams(FTXEvent.EVENT_PREDOWNLOAD_ON_START, bundle);
result.put("params", CommonUtil.transToMap(params));
sendSuccessEvent(result);
}
private void onCompleteEvent(int taskId, String url) {
Bundle bundle = new Bundle();
bundle.putInt("taskId", taskId);
......@@ -282,6 +301,52 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
return res;
}
@NonNull
@Override
public void startPreLoadByParams(@NonNull FtxMessages.PreLoadInfoMsg msg) {
mPreloadPool.execute(new Runnable() {
@Override
public void run() {
final boolean isUrlPreload = !TextUtils.isEmpty(msg.getPlayUrl());
TXPlayInfoParams txPlayInfoParams;
if (isUrlPreload) {
txPlayInfoParams = new TXPlayInfoParams(msg.getPlayUrl());
} else {
int appId = msg.getAppId() != null ? msg.getAppId().intValue() : 0;
txPlayInfoParams = new TXPlayInfoParams(appId, msg.getFileId(), msg.getPSign());
}
final TXVodPreloadManager downloadManager =
TXVodPreloadManager.getInstance(mFlutterPluginBinding.getApplicationContext());
int preloadSizeMB = msg.getPreloadSizeMB() != null ? msg.getPreloadSizeMB().intValue() : 0;
final long tmpTaskId = msg.getTmpPreloadTaskId() != null ? msg.getTmpPreloadTaskId() : -1;
long preferredResolution = msg.getPreferredResolution() != null ? msg.getPreferredResolution() : 0;
int retTaskID = downloadManager.startPreload(txPlayInfoParams, preloadSizeMB, preferredResolution,
new ITXVodFilePreloadListener() {
@Override
public void onStart(int taskID, String fileId, String url, Bundle bundle) {
if (tmpTaskId >= 0) {
onStartEvent(tmpTaskId, taskID, fileId, url, bundle);
}
}
@Override
public void onComplete(int taskID, String url) {
onCompleteEvent(taskID, url);
}
@Override
public void onError(int taskID, String url, int code, String msg) {
onErrorEvent(taskID, url, code, msg);
}
});
if (isUrlPreload && tmpTaskId >= 0) {
onStartEvent(tmpTaskId, retTaskID, msg.getFileId(), msg.getPlayUrl(), new Bundle());
}
}
});
}
@Override
public void stopPreLoad(@NonNull IntMsg msg) {
if (null != msg.getValue()) {
......
......@@ -36,6 +36,9 @@ public class FTXEvent {
// 视频预下载出错
public static final int EVENT_PREDOWNLOAD_ON_ERROR = 201;
// fileId preload is start, callback url、taskId and other video info
public static final int EVENT_PREDOWNLOAD_ON_START = 202;
// Video download started.
// 视频下载开始
public static final int EVENT_DOWNLOAD_START = 301;
......
......@@ -109,6 +109,19 @@ public class CommonUtil {
return param;
}
public static Map<String, Object> transToMap(Bundle bundle) {
Map<String, Object> param = new HashMap<>();
if (bundle != null && !bundle.isEmpty()) {
Set<String> keySet = bundle.keySet();
for (String key : keySet) {
Object val = bundle.get(key);
param.put(key, val);
}
}
return param;
}
public static int getDownloadEventByState(int mediaInfoDownloadState) {
Integer event = DOWNLOAD_STATE_MAP.get(mediaInfoDownloadState);
return null != event ? event : FTXEvent.EVENT_DOWNLOAD_ERROR;
......
......@@ -1703,6 +1703,16 @@ FTXPredownlodOnCompleteListener? onCompleteListener,
}) async
```
```dart
Future<void> startPreload(TXPlayInfoParams txPlayInfoParams,
final int preloadSizeMB,
final int preferredResolution, {
FTXPredownlodOnCompleteListener? onCompleteListener,
FTXPredownlodOnErrorListener? onErrorListener,
FTXPredownlodOnStartListener? onStartListener,
}) async
```
**参数说明**
| 参数名 | 类型 | 描述 |
......@@ -1713,6 +1723,15 @@ FTXPredownlodOnCompleteListener? onCompleteListener,
| onCompleteListener | FTXPredownlodOnCompleteListener? | 预下载成功回调,全局|
| onErrorListener | FTXPredownlodOnErrorListener | 预下载失败回调,全局|
TXPlayInfoParams:
| 参数名 | 类型 | 描述 |
| ------ | ------ |-----------------------------------------------------------------------|
| appId | int | 应用appId。必填 |
| fileId | String | 文件id。必填 |
| url | String | 视频url,与fileId只用填写一个,如果都填写,url优先 |
| sign | String | 防盗链签名,参考防盗链产品文档: https://cloud.tencent.com/document/product/266/11243 |
**返回值说明**
| 参数名 | 类型 | 描述 |
......
......@@ -449,6 +449,21 @@ int taskId = await TXVodDownloadController.instance.startPreLoad(palyrl, 3, 1920
TXVodDownloadController.instance.stopPreLoad(taskId);
```
fileId预下载使用示例:
```dart
TXVodDownloadController.instance.startPreload(TXPlayInfoParams(appId: 0, fileId: "your fileId"), 1, 720 * 1080,
onStartListener: (taskId, fileId, url, params) {
// TXVodDownloadController will call this block for callback taskId and videoInfo
},
onCompleteListener: (taskId, url) {
// preDownload complete
},
onErrorListener: (taskId, url, code, msg) {
// preDownload error
});
```
### 3、视频下载
视频下载支持用户在有网络的条件下下载视频,随后在无网络的环境下观看。同时播放器 SDK 提供本地加密能力,下载后的本地视频仍为加密状态,仅可通过指定播放器对视频进行解密播放,可有效防止下载后视频的非法传播,保护视频安全。
......
......@@ -44,6 +44,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb
});
LogUtils.logOpen = true;
playEventSubscription = _controller.onPlayerEventBroadcast.listen((event) async {
// Subscribe to event distribution
if (event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {
......
......@@ -12,6 +12,9 @@
@interface FTXDownloadManager ()<FlutterStreamHandler, TXVodPreloadManagerDelegate, TXVodDownloadDelegate, TXFlutterDownloadApi>
@property (nonatomic, strong) dispatch_queue_t mPreloadQueue;
@property (atomic, strong) NSMutableDictionary *mPreloadFileDic;
@end
@implementation FTXDownloadManager {
......@@ -32,6 +35,8 @@
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *path = [NSString stringWithFormat:@"%@/videoCache",cachesDir];
[[TXVodDownloadManager shareInstance] setDownloadPath:path];
self.mPreloadQueue = dispatch_queue_create(@"cloud.tencent.com.preload", NULL);
self.mPreloadFileDic = @{}.mutableCopy;
}
return self;
}
......@@ -45,6 +50,28 @@
_eventSink = nil;
}
- (void)onStartEvent:(long)tmpTaskId taskID:(int)taskID fileId:(NSString *)fileId url:(NSString *)url param:(NSDictionary *)param {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@(tmpTaskId) forKey:@"tmpTaskId"];
[dict setObject:@(taskID) forKey:@"taskId"];
[dict setObject:fileId forKey:@"fileId"];
[dict setObject:url forKey:@"url"];
[dict setObject:param forKey:@"param"];
[_eventSink success:[FTXDownloadManager getParamsWithEvent:EVENT_PREDOWNLOAD_ON_START withParams:dict]];
}
- (void)addPreloadFileStartTask:(NSString*)fileId tmpTaskId:(long)tmpTaskId {
@synchronized (self.mPreloadFileDic) {
self.mPreloadFileDic[fileId] = @(tmpTaskId);
}
}
- (void)removePreloadFileStartTask:(NSString*)fileId {
@synchronized (self.mPreloadFileDic) {
[self.mPreloadFileDic removeObjectForKey:fileId];
}
}
#pragma mark - FlutterStreamHandler
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
......@@ -80,6 +107,16 @@
#pragma mark - TXVodPreloadManager delegate
- (void)onStart:(int)taskID fileId:(NSString *)fileId url:(NSString *)url param:(NSDictionary *)param {
if (self.mPreloadFileDic[fileId] && [self.mPreloadFileDic[fileId] isKindOfClass:[NSNumber class]]) {
long tmpTaskId = [self.mPreloadFileDic[fileId] longValue];
if (tmpTaskId >= 0) {
[self onStartEvent:tmpTaskId taskID:taskID fileId:fileId url:url param:param];
[self removePreloadFileStartTask:fileId];
}
}
}
- (void)onComplete:(int)taskID url:(NSString *)url
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
......@@ -305,4 +342,31 @@
[[TXVodPreloadManager sharedManager] stopPreload:msg.value.intValue];
}
- (void)startPreLoadByParamsMsg:(PreLoadInfoMsg *)msg error:(FlutterError * _Nullable __autoreleasing *)error {
dispatch_async(self.mPreloadQueue, ^{
BOOL isUrlPreload = msg.playUrl != nil && [msg.playUrl isKindOfClass:[NSString class]] && msg.playUrl.length > 0;
int preloadSizeMB = [msg.preloadSizeMB intValue];
int preferredResolution = [msg.preferredResolution intValue];
long tmpTaskId = [msg.tmpPreloadTaskId longValue];
NSString *fileId = (msg.fileId != nil && [msg.fileId isKindOfClass:[NSString class]]) ? msg.fileId : @"";
TXPlayerAuthParams *params = [[TXPlayerAuthParams alloc] init];
params.url = msg.playUrl;
params.appId = (msg.appId != nil && [msg.appId isKindOfClass:[NSNumber class]]) ? [msg.appId intValue] : 0;
params.fileId = fileId;
params.sign = (msg.pSign != nil && [msg.pSign isKindOfClass:[NSString class]]) ? msg.pSign : @"";
[self addPreloadFileStartTask:fileId tmpTaskId:tmpTaskId];
int taskID = [[TXVodPreloadManager sharedManager] startPreloadWithModel:params
preloadSize:preloadSizeMB
preferredResolution:preferredResolution
delegate:self];
if (isUrlPreload) {
if (tmpTaskId >= 0) {
[self onStartEvent:tmpTaskId taskID:taskID fileId:fileId url:msg.playUrl param:@{}];
[self removePreloadFileStartTask:fileId];
}
}
});
}
@end
......@@ -54,6 +54,8 @@
// Video pre-download error.
// 视频预下载出错
#define EVENT_PREDOWNLOAD_ON_ERROR 201
// fileId preload is start, callback url、taskId and other video info
#define EVENT_PREDOWNLOAD_ON_START 202
// Video download started.
// 视频下载开始
......
......@@ -429,7 +429,9 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
self->isVideoFirstFrameReceived = false;
});
}
if (EvtID != PLAY_EVT_PLAY_PROGRESS) {
NSLog(@"onPlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]);
}
[_eventSink success:[FTXVodPlayer getParamsWithEvent:EvtID withParams:param]];
}
......
......@@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
@class StringMsg;
@class DoubleMsg;
@class PreLoadMsg;
@class PreLoadInfoMsg;
@class MapMsg;
/// Pigeon original component, used to generate native communication code for `messages`.
......@@ -56,11 +57,13 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId
appId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId
psign:(nullable NSString *)psign;
psign:(nullable NSString *)psign
url:(nullable NSString *)url;
@property(nonatomic, strong, nullable) NSNumber * playerId;
@property(nonatomic, strong, nullable) NSNumber * appId;
@property(nonatomic, copy, nullable) NSString * fileId;
@property(nonatomic, copy, nullable) NSString * psign;
@property(nonatomic, copy, nullable) NSString * url;
@end
@interface PipParamsPlayerMsg : NSObject
......@@ -290,6 +293,23 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, strong, nullable) NSNumber * preferredResolution;
@end
@interface PreLoadInfoMsg : NSObject
+ (instancetype)makeWithAppId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId
pSign:(nullable NSString *)pSign
playUrl:(nullable NSString *)playUrl
preloadSizeMB:(nullable NSNumber *)preloadSizeMB
preferredResolution:(nullable NSNumber *)preferredResolution
tmpPreloadTaskId:(nullable NSNumber *)tmpPreloadTaskId;
@property(nonatomic, strong, nullable) NSNumber * appId;
@property(nonatomic, copy, nullable) NSString * fileId;
@property(nonatomic, copy, nullable) NSString * pSign;
@property(nonatomic, copy, nullable) NSString * playUrl;
@property(nonatomic, strong, nullable) NSNumber * preloadSizeMB;
@property(nonatomic, strong, nullable) NSNumber * preferredResolution;
@property(nonatomic, strong, nullable) NSNumber * tmpPreloadTaskId;
@end
@interface MapMsg : NSObject
+ (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map;
@property(nonatomic, strong, nullable) NSDictionary<NSString *, NSString *> * map;
......@@ -687,6 +707,7 @@ NSObject<FlutterMessageCodec> *TXFlutterDownloadApiGetCodec(void);
///
/// @return `nil` only when `error != nil`.
- (nullable IntMsg *)startPreLoadMsg:(PreLoadMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
- (void)startPreLoadByParamsMsg:(PreLoadInfoMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
/// 停止预下载。
/// taskId: 任务id
- (void)stopPreLoadMsg:(IntMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
......
......@@ -148,6 +148,12 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
- (NSArray *)toList;
@end
@interface PreLoadInfoMsg ()
+ (PreLoadInfoMsg *)fromList:(NSArray *)list;
+ (nullable PreLoadInfoMsg *)nullableFromList:(NSArray *)list;
- (NSArray *)toList;
@end
@interface MapMsg ()
+ (MapMsg *)fromList:(NSArray *)list;
+ (nullable MapMsg *)nullableFromList:(NSArray *)list;
......@@ -204,12 +210,14 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
+ (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId
appId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId
psign:(nullable NSString *)psign {
psign:(nullable NSString *)psign
url:(nullable NSString *)url {
TXPlayInfoParamsPlayerMsg* pigeonResult = [[TXPlayInfoParamsPlayerMsg alloc] init];
pigeonResult.playerId = playerId;
pigeonResult.appId = appId;
pigeonResult.fileId = fileId;
pigeonResult.psign = psign;
pigeonResult.url = url;
return pigeonResult;
}
+ (TXPlayInfoParamsPlayerMsg *)fromList:(NSArray *)list {
......@@ -218,6 +226,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
pigeonResult.appId = GetNullableObjectAtIndex(list, 1);
pigeonResult.fileId = GetNullableObjectAtIndex(list, 2);
pigeonResult.psign = GetNullableObjectAtIndex(list, 3);
pigeonResult.url = GetNullableObjectAtIndex(list, 4);
return pigeonResult;
}
+ (nullable TXPlayInfoParamsPlayerMsg *)nullableFromList:(NSArray *)list {
......@@ -229,6 +238,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
(self.appId ?: [NSNull null]),
(self.fileId ?: [NSNull null]),
(self.psign ?: [NSNull null]),
(self.url ?: [NSNull null]),
];
}
@end
......@@ -847,6 +857,51 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
}
@end
@implementation PreLoadInfoMsg
+ (instancetype)makeWithAppId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId
pSign:(nullable NSString *)pSign
playUrl:(nullable NSString *)playUrl
preloadSizeMB:(nullable NSNumber *)preloadSizeMB
preferredResolution:(nullable NSNumber *)preferredResolution
tmpPreloadTaskId:(nullable NSNumber *)tmpPreloadTaskId {
PreLoadInfoMsg* pigeonResult = [[PreLoadInfoMsg alloc] init];
pigeonResult.appId = appId;
pigeonResult.fileId = fileId;
pigeonResult.pSign = pSign;
pigeonResult.playUrl = playUrl;
pigeonResult.preloadSizeMB = preloadSizeMB;
pigeonResult.preferredResolution = preferredResolution;
pigeonResult.tmpPreloadTaskId = tmpPreloadTaskId;
return pigeonResult;
}
+ (PreLoadInfoMsg *)fromList:(NSArray *)list {
PreLoadInfoMsg *pigeonResult = [[PreLoadInfoMsg alloc] init];
pigeonResult.appId = GetNullableObjectAtIndex(list, 0);
pigeonResult.fileId = GetNullableObjectAtIndex(list, 1);
pigeonResult.pSign = GetNullableObjectAtIndex(list, 2);
pigeonResult.playUrl = GetNullableObjectAtIndex(list, 3);
pigeonResult.preloadSizeMB = GetNullableObjectAtIndex(list, 4);
pigeonResult.preferredResolution = GetNullableObjectAtIndex(list, 5);
pigeonResult.tmpPreloadTaskId = GetNullableObjectAtIndex(list, 6);
return pigeonResult;
}
+ (nullable PreLoadInfoMsg *)nullableFromList:(NSArray *)list {
return (list) ? [PreLoadInfoMsg fromList:list] : nil;
}
- (NSArray *)toList {
return @[
(self.appId ?: [NSNull null]),
(self.fileId ?: [NSNull null]),
(self.pSign ?: [NSNull null]),
(self.playUrl ?: [NSNull null]),
(self.preloadSizeMB ?: [NSNull null]),
(self.preferredResolution ?: [NSNull null]),
(self.tmpPreloadTaskId ?: [NSNull null]),
];
}
@end
@implementation MapMsg
+ (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map {
MapMsg* pigeonResult = [[MapMsg alloc] init];
......@@ -2709,10 +2764,12 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO
case 130:
return [MapMsg fromList:[self readValue]];
case 131:
return [PreLoadMsg fromList:[self readValue]];
return [PreLoadInfoMsg fromList:[self readValue]];
case 132:
return [TXDownloadListMsg fromList:[self readValue]];
return [PreLoadMsg fromList:[self readValue]];
case 133:
return [TXDownloadListMsg fromList:[self readValue]];
case 134:
return [TXVodDownloadMediaMsg fromList:[self readValue]];
default:
return [super readValueOfType:type];
......@@ -2733,15 +2790,18 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO
} else if ([value isKindOfClass:[MapMsg class]]) {
[self writeByte:130];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[PreLoadMsg class]]) {
} else if ([value isKindOfClass:[PreLoadInfoMsg class]]) {
[self writeByte:131];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXDownloadListMsg class]]) {
} else if ([value isKindOfClass:[PreLoadMsg class]]) {
[self writeByte:132];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXVodDownloadMediaMsg class]]) {
} else if ([value isKindOfClass:[TXDownloadListMsg class]]) {
[self writeByte:133];
[self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXVodDownloadMediaMsg class]]) {
[self writeByte:134];
[self writeValue:[value toList]];
} else {
[super writeValue:value];
}
......@@ -2794,6 +2854,25 @@ void TXFlutterDownloadApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObj
[channel setMessageHandler:nil];
}
}
{
FlutterBasicMessageChannel *channel =
[[FlutterBasicMessageChannel alloc]
initWithName:@"dev.flutter.pigeon.TXFlutterDownloadApi.startPreLoadByParams"
binaryMessenger:binaryMessenger
codec:TXFlutterDownloadApiGetCodec()];
if (api) {
NSCAssert([api respondsToSelector:@selector(startPreLoadByParamsMsg:error:)], @"TXFlutterDownloadApi api (%@) doesn't respond to @selector(startPreLoadByParamsMsg:error:)", api);
[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
NSArray *args = message;
PreLoadInfoMsg *arg_msg = GetNullableObjectAtIndex(args, 0);
FlutterError *error;
[api startPreLoadByParamsMsg:arg_msg error:&error];
callback(wrapResult(nil, error));
}];
} else {
[channel setMessageHandler:nil];
}
}
/// 停止预下载。
/// taskId: 任务id
{
......
// Copyright (c) 2022 Tencent. All rights reserved.
import 'package:pigeon/pigeon.dart';
import 'package:super_player/super_player.dart';
// import 'package:pigeon/pigeon.dart';
// import 'package:super_player/super_player.dart';
/// Pigeon original component, used to generate native communication code for `messages`.
/// The generation command is as follows. When using the generation command,
/// the two import statements above need to be implemented or commented out.
......@@ -31,6 +31,7 @@ class TXPlayInfoParamsPlayerMsg {
int? appId;
String? fileId;
String? psign;
String? url;
}
class PipParamsPlayerMsg {
......@@ -266,6 +267,16 @@ class PreLoadMsg {
int? preferredResolution;
}
class PreLoadInfoMsg {
int? appId;
String? fileId;
String? pSign;
String? playUrl;
int? preloadSizeMB;
int? preferredResolution;
int? tmpPreloadTaskId;
}
class MapMsg {
Map<String?, String?>? map;
}
......@@ -640,6 +651,8 @@ abstract class TXFlutterDownloadApi {
/// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload]
IntMsg startPreLoad(PreLoadMsg msg);
void startPreLoadByParams(PreLoadInfoMsg msg);
/// 停止预下载。
/// taskId: 任务id
void stopPreLoad(IntMsg msg);
......
......@@ -315,6 +315,8 @@ abstract class TXVodPlayEvent {
// Error occurred during video pre-download.
// 视频预下载出错
static const EVENT_PREDOWNLOAD_ON_ERROR = 201;
// fileId preload is start, callback url、taskId and other video info
static const EVENT_PREDOWNLOAD_ON_START = 202;
// Video download started.
// 视频下载开始
......@@ -510,15 +512,19 @@ class DownloadQuality {
class TXPlayInfoParams {
final int appId; // Tencent Cloud video appId, required
final String fileId; // Tencent Cloud video fileId, required
final String? psign; // encent cloud video encryption signature, required for encrypted video
final String? psign; // Tencent cloud video encryption signature, required for encrypted video
// video url, only applicable for preloading. When using it, you only need to fill in either the url or fileId.
// The priority of the url is higher than that of the fileId.
final String? url;
const TXPlayInfoParams({required this.appId, required this.fileId, this.psign});
const TXPlayInfoParams({required this.appId, required this.fileId, this.psign = "", this.url = ""});
Map<String, dynamic> toJson() {
Map<String, dynamic> json = {};
json["appId"] = appId;
json["fileId"] = fileId;
json["psign"] = psign;
json["url"] = url;
return json;
}
}
......@@ -671,6 +677,8 @@ abstract class TXPlayerType {
// Video pre-download event callback listener.
// 视频预下载事件回调Listener
// onStartListener, just for fileId preload
typedef FTXPredownlodOnStartListener = void Function(int taskId, String fileId, String url, Map<dynamic, dynamic> params);
typedef FTXPredownlodOnCompleteListener = void Function(int taskId, String url);
typedef FTXPredownlodOnErrorListener = void Function(int taskId, String url, int code, String msg);
// Video download time callback listener.
......
......@@ -63,6 +63,7 @@ class TXPlayInfoParamsPlayerMsg {
this.appId,
this.fileId,
this.psign,
this.url,
});
int? playerId;
......@@ -73,12 +74,15 @@ class TXPlayInfoParamsPlayerMsg {
String? psign;
String? url;
Object encode() {
return <Object?>[
playerId,
appId,
fileId,
psign,
url,
];
}
......@@ -89,6 +93,7 @@ class TXPlayInfoParamsPlayerMsg {
appId: result[1] as int?,
fileId: result[2] as String?,
psign: result[3] as String?,
url: result[4] as String?,
);
}
}
......@@ -785,6 +790,57 @@ class PreLoadMsg {
}
}
class PreLoadInfoMsg {
PreLoadInfoMsg({
this.appId,
this.fileId,
this.pSign,
this.playUrl,
this.preloadSizeMB,
this.preferredResolution,
this.tmpPreloadTaskId,
});
int? appId;
String? fileId;
String? pSign;
String? playUrl;
int? preloadSizeMB;
int? preferredResolution;
int? tmpPreloadTaskId;
Object encode() {
return <Object?>[
appId,
fileId,
pSign,
playUrl,
preloadSizeMB,
preferredResolution,
tmpPreloadTaskId,
];
}
static PreLoadInfoMsg decode(Object result) {
result as List<Object?>;
return PreLoadInfoMsg(
appId: result[0] as int?,
fileId: result[1] as String?,
pSign: result[2] as String?,
playUrl: result[3] as String?,
preloadSizeMB: result[4] as int?,
preferredResolution: result[5] as int?,
tmpPreloadTaskId: result[6] as int?,
);
}
}
class MapMsg {
MapMsg({
this.map,
......@@ -2994,15 +3050,18 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec {
} else if (value is MapMsg) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is PreLoadMsg) {
} else if (value is PreLoadInfoMsg) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is TXDownloadListMsg) {
} else if (value is PreLoadMsg) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is TXVodDownloadMediaMsg) {
} else if (value is TXDownloadListMsg) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else if (value is TXVodDownloadMediaMsg) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
......@@ -3018,10 +3077,12 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec {
case 130:
return MapMsg.decode(readValue(buffer)!);
case 131:
return PreLoadMsg.decode(readValue(buffer)!);
return PreLoadInfoMsg.decode(readValue(buffer)!);
case 132:
return TXDownloadListMsg.decode(readValue(buffer)!);
return PreLoadMsg.decode(readValue(buffer)!);
case 133:
return TXDownloadListMsg.decode(readValue(buffer)!);
case 134:
return TXVodDownloadMediaMsg.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
......@@ -3071,6 +3132,28 @@ class TXFlutterDownloadApi {
}
}
Future<void> startPreLoadByParams(PreLoadInfoMsg arg_msg) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.TXFlutterDownloadApi.startPreLoadByParams', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_msg]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}
/// 停止预下载。
/// taskId: 任务id
Future<void> stopPreLoad(IntMsg arg_msg) async {
......
......@@ -17,11 +17,11 @@ class TXVodDownloadController {
Stream<Map<dynamic, dynamic>> get onDownloadEventBroadcast => _downloadEventStreamController.stream;
FTXPredownlodOnCompleteListener? _onPreDownloadOnCompleteListener;
FTXPredownlodOnErrorListener? _onPreDownloadOnErrorListener;
Map<int, _PreloadListener> _preloadListeners = {};
Map<int, _PreloadListener> _fileIdBeforeStartListeners = {};
FTXDownlodOnStateChangeListener? _downlodOnStateChangeListener;
FTXDownlodOnErrorListener? _downlodOnErrorListener;
AtomicInt _atomicPreloadId = AtomicInt(0);
static TXVodDownloadController _sharedInstance() {
if (_instance == null) {
......@@ -60,13 +60,38 @@ class TXVodDownloadController {
FTXPredownlodOnCompleteListener? onCompleteListener,
FTXPredownlodOnErrorListener? onErrorListener,
}) async {
_onPreDownloadOnCompleteListener = onCompleteListener;
_onPreDownloadOnErrorListener = onErrorListener;
IntMsg msg = await _api.startPreLoad(PreLoadMsg()
..playUrl = playUrl
..preloadSizeMB = preloadSizeMB
..preferredResolution = preferredResolution);
return msg.value ?? -1;
int taskId = msg.value ?? -1;
if (taskId >= 0) {
_preloadListeners[taskId] = _PreloadListener()
..onCompleteListener = onCompleteListener
..onErrorListener = onErrorListener;
}
return taskId;
}
Future<void> startPreload(TXPlayInfoParams txPlayInfoParams,
final int preloadSizeMB,
final int preferredResolution, {
FTXPredownlodOnCompleteListener? onCompleteListener,
FTXPredownlodOnErrorListener? onErrorListener,
FTXPredownlodOnStartListener? onStartListener,
}) async {
int tmpPreloadTaskId = await _atomicPreloadId.incrementAndGet();
await _api.startPreLoadByParams(PreLoadInfoMsg()
..tmpPreloadTaskId = tmpPreloadTaskId
..playUrl = txPlayInfoParams.url
..fileId = txPlayInfoParams.fileId
..appId = txPlayInfoParams.appId
..preloadSizeMB = preloadSizeMB
..preferredResolution = preferredResolution);
_fileIdBeforeStartListeners[tmpPreloadTaskId] = _PreloadListener()
..onCompleteListener = onCompleteListener
..onErrorListener = onErrorListener
..onStartListener = onStartListener;
}
/// Stop pre-downloading.
......@@ -223,9 +248,8 @@ class TXVodDownloadController {
int taskId = map['taskId'];
String url = map['url'];
LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_COMPLETE, taskID=$taskId ,url=$url');
if (_onPreDownloadOnCompleteListener != null) {
_onPreDownloadOnCompleteListener!(taskId, url);
}
_preloadListeners[taskId]?.onCompleteListener?.call(taskId, url);
_preloadListeners.remove(taskId);
break;
case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_ERROR:
int taskId = map['taskId'];
......@@ -233,8 +257,21 @@ class TXVodDownloadController {
int code = map['code'] ?? 0;
String msg = map['msg'] ?? '';
LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_ERROR, taskID=$taskId ,url=$url, code=$code , msg=$msg');
if (_onPreDownloadOnErrorListener != null) {
_onPreDownloadOnErrorListener!(taskId, url, code, msg);
_preloadListeners[taskId]?.onErrorListener?.call(taskId, url, code, msg);
_preloadListeners.remove(taskId);
break;
case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_START:
int tmpTaskId = map['tmpTaskId'];
int taskId = map['taskId'];
String fileId = map['fileId'] ?? '';
String url = map['url'] ?? '';
Map<dynamic, dynamic> bundle = map['params'] ?? {};
LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_START, tmpTaskId=$tmpTaskId, '
'taskID=$taskId ,fileId=$fileId, url=$url , bundle=$bundle');
if (_fileIdBeforeStartListeners[tmpTaskId] != null) {
_preloadListeners[taskId] = _fileIdBeforeStartListeners[tmpTaskId]!;
_preloadListeners[taskId]!.onStartListener?.call(taskId, fileId, url, bundle);
_fileIdBeforeStartListeners.remove(tmpTaskId);
}
break;
case TXVodPlayEvent.EVENT_DOWNLOAD_START:
......@@ -256,4 +293,32 @@ class TXVodDownloadController {
}
_errorHandler(error) {}
}
class _PreloadListener {
FTXPredownlodOnCompleteListener? onCompleteListener;
FTXPredownlodOnErrorListener? onErrorListener;
FTXPredownlodOnStartListener? onStartListener;
_PreloadListener({this.onCompleteListener, this.onErrorListener, this.onStartListener});
}
class AtomicInt {
int _value = 0;
final _lock = Lock();
AtomicInt(this._value);
Future<int> get() async {
return await _lock.synchronized(() async {
return _value;
});
}
Future<int> incrementAndGet() async {
return await _lock.synchronized(() async {
_value++;
return _value;
});
}
}
......@@ -7,6 +7,7 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:synchronized/synchronized.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
......
......@@ -12,6 +12,7 @@ dependencies:
flutter:
sdk: flutter
pigeon: ^9.0.1
synchronized: ^3.0.0+3
# internationalization
flutter_localizations:
sdk: flutter
......@@ -19,6 +20,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
pigeon: ^9.0.1
synchronized: ^3.0.0+3
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论