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

video preDownload support fileId

上级 d1678946
...@@ -8,12 +8,15 @@ import android.text.TextUtils; ...@@ -8,12 +8,15 @@ import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.tencent.rtmp.TXPlayInfoParams;
import com.tencent.rtmp.downloader.ITXVodDownloadListener; import com.tencent.rtmp.downloader.ITXVodDownloadListener;
import com.tencent.rtmp.downloader.ITXVodFilePreloadListener;
import com.tencent.rtmp.downloader.ITXVodPreloadListener; import com.tencent.rtmp.downloader.ITXVodPreloadListener;
import com.tencent.rtmp.downloader.TXVodDownloadDataSource; import com.tencent.rtmp.downloader.TXVodDownloadDataSource;
import com.tencent.rtmp.downloader.TXVodDownloadManager; import com.tencent.rtmp.downloader.TXVodDownloadManager;
import com.tencent.rtmp.downloader.TXVodDownloadMediaInfo; import com.tencent.rtmp.downloader.TXVodDownloadMediaInfo;
import com.tencent.rtmp.downloader.TXVodPreloadManager; 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.BoolMsg;
import com.tencent.vod.flutter.messages.FtxMessages.IntMsg; import com.tencent.vod.flutter.messages.FtxMessages.IntMsg;
import com.tencent.vod.flutter.messages.FtxMessages.MapMsg; import com.tencent.vod.flutter.messages.FtxMessages.MapMsg;
...@@ -29,6 +32,9 @@ import io.flutter.plugin.common.EventChannel; ...@@ -29,6 +32,9 @@ import io.flutter.plugin.common.EventChannel;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; 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. * Download management, pre-download, and offline download.
...@@ -42,6 +48,8 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -42,6 +48,8 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink(); private final FTXPlayerEventSink mEventSink = new FTXPlayerEventSink();
private final Handler mMainHandler; private final Handler mMainHandler;
private ExecutorService mPreloadPool = Executors.newCachedThreadPool();
/** /**
* Video download management. * Video download management.
* *
...@@ -69,6 +77,17 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -69,6 +77,17 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
TXVodDownloadManager.getInstance().setListener(this); 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) { private void onCompleteEvent(int taskId, String url) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt("taskId", taskId); bundle.putInt("taskId", taskId);
...@@ -282,6 +301,52 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -282,6 +301,52 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
return res; 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 @Override
public void stopPreLoad(@NonNull IntMsg msg) { public void stopPreLoad(@NonNull IntMsg msg) {
if (null != msg.getValue()) { if (null != msg.getValue()) {
......
...@@ -36,6 +36,9 @@ public class FTXEvent { ...@@ -36,6 +36,9 @@ public class FTXEvent {
// 视频预下载出错 // 视频预下载出错
public static final int EVENT_PREDOWNLOAD_ON_ERROR = 201; 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. // Video download started.
// 视频下载开始 // 视频下载开始
public static final int EVENT_DOWNLOAD_START = 301; public static final int EVENT_DOWNLOAD_START = 301;
......
...@@ -216,6 +216,16 @@ public class FtxMessages { ...@@ -216,6 +216,16 @@ public class FtxMessages {
this.psign = setterArg; this.psign = setterArg;
} }
private @Nullable String url;
public @Nullable String getUrl() {
return url;
}
public void setUrl(@Nullable String setterArg) {
this.url = setterArg;
}
public static final class Builder { public static final class Builder {
private @Nullable Long playerId; private @Nullable Long playerId;
...@@ -246,23 +256,32 @@ public class FtxMessages { ...@@ -246,23 +256,32 @@ public class FtxMessages {
return this; return this;
} }
private @Nullable String url;
public @NonNull Builder setUrl(@Nullable String setterArg) {
this.url = setterArg;
return this;
}
public @NonNull TXPlayInfoParamsPlayerMsg build() { public @NonNull TXPlayInfoParamsPlayerMsg build() {
TXPlayInfoParamsPlayerMsg pigeonReturn = new TXPlayInfoParamsPlayerMsg(); TXPlayInfoParamsPlayerMsg pigeonReturn = new TXPlayInfoParamsPlayerMsg();
pigeonReturn.setPlayerId(playerId); pigeonReturn.setPlayerId(playerId);
pigeonReturn.setAppId(appId); pigeonReturn.setAppId(appId);
pigeonReturn.setFileId(fileId); pigeonReturn.setFileId(fileId);
pigeonReturn.setPsign(psign); pigeonReturn.setPsign(psign);
pigeonReturn.setUrl(url);
return pigeonReturn; return pigeonReturn;
} }
} }
@NonNull @NonNull
ArrayList<Object> toList() { ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<Object>(4); ArrayList<Object> toListResult = new ArrayList<Object>(5);
toListResult.add(playerId); toListResult.add(playerId);
toListResult.add(appId); toListResult.add(appId);
toListResult.add(fileId); toListResult.add(fileId);
toListResult.add(psign); toListResult.add(psign);
toListResult.add(url);
return toListResult; return toListResult;
} }
...@@ -276,6 +295,8 @@ public class FtxMessages { ...@@ -276,6 +295,8 @@ public class FtxMessages {
pigeonResult.setFileId((String) fileId); pigeonResult.setFileId((String) fileId);
Object psign = list.get(3); Object psign = list.get(3);
pigeonResult.setPsign((String) psign); pigeonResult.setPsign((String) psign);
Object url = list.get(4);
pigeonResult.setUrl((String) url);
return pigeonResult; return pigeonResult;
} }
} }
...@@ -2314,6 +2335,175 @@ public class FtxMessages { ...@@ -2314,6 +2335,175 @@ public class FtxMessages {
} }
} }
/** Generated class from Pigeon that represents data sent in messages. */
public static final class PreLoadInfoMsg {
private @Nullable Long appId;
public @Nullable Long getAppId() {
return appId;
}
public void setAppId(@Nullable Long setterArg) {
this.appId = setterArg;
}
private @Nullable String fileId;
public @Nullable String getFileId() {
return fileId;
}
public void setFileId(@Nullable String setterArg) {
this.fileId = setterArg;
}
private @Nullable String pSign;
public @Nullable String getPSign() {
return pSign;
}
public void setPSign(@Nullable String setterArg) {
this.pSign = setterArg;
}
private @Nullable String playUrl;
public @Nullable String getPlayUrl() {
return playUrl;
}
public void setPlayUrl(@Nullable String setterArg) {
this.playUrl = setterArg;
}
private @Nullable Long preloadSizeMB;
public @Nullable Long getPreloadSizeMB() {
return preloadSizeMB;
}
public void setPreloadSizeMB(@Nullable Long setterArg) {
this.preloadSizeMB = setterArg;
}
private @Nullable Long preferredResolution;
public @Nullable Long getPreferredResolution() {
return preferredResolution;
}
public void setPreferredResolution(@Nullable Long setterArg) {
this.preferredResolution = setterArg;
}
private @Nullable Long tmpPreloadTaskId;
public @Nullable Long getTmpPreloadTaskId() {
return tmpPreloadTaskId;
}
public void setTmpPreloadTaskId(@Nullable Long setterArg) {
this.tmpPreloadTaskId = setterArg;
}
public static final class Builder {
private @Nullable Long appId;
public @NonNull Builder setAppId(@Nullable Long setterArg) {
this.appId = setterArg;
return this;
}
private @Nullable String fileId;
public @NonNull Builder setFileId(@Nullable String setterArg) {
this.fileId = setterArg;
return this;
}
private @Nullable String pSign;
public @NonNull Builder setPSign(@Nullable String setterArg) {
this.pSign = setterArg;
return this;
}
private @Nullable String playUrl;
public @NonNull Builder setPlayUrl(@Nullable String setterArg) {
this.playUrl = setterArg;
return this;
}
private @Nullable Long preloadSizeMB;
public @NonNull Builder setPreloadSizeMB(@Nullable Long setterArg) {
this.preloadSizeMB = setterArg;
return this;
}
private @Nullable Long preferredResolution;
public @NonNull Builder setPreferredResolution(@Nullable Long setterArg) {
this.preferredResolution = setterArg;
return this;
}
private @Nullable Long tmpPreloadTaskId;
public @NonNull Builder setTmpPreloadTaskId(@Nullable Long setterArg) {
this.tmpPreloadTaskId = setterArg;
return this;
}
public @NonNull PreLoadInfoMsg build() {
PreLoadInfoMsg pigeonReturn = new PreLoadInfoMsg();
pigeonReturn.setAppId(appId);
pigeonReturn.setFileId(fileId);
pigeonReturn.setPSign(pSign);
pigeonReturn.setPlayUrl(playUrl);
pigeonReturn.setPreloadSizeMB(preloadSizeMB);
pigeonReturn.setPreferredResolution(preferredResolution);
pigeonReturn.setTmpPreloadTaskId(tmpPreloadTaskId);
return pigeonReturn;
}
}
@NonNull
ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<Object>(7);
toListResult.add(appId);
toListResult.add(fileId);
toListResult.add(pSign);
toListResult.add(playUrl);
toListResult.add(preloadSizeMB);
toListResult.add(preferredResolution);
toListResult.add(tmpPreloadTaskId);
return toListResult;
}
static @NonNull PreLoadInfoMsg fromList(@NonNull ArrayList<Object> list) {
PreLoadInfoMsg pigeonResult = new PreLoadInfoMsg();
Object appId = list.get(0);
pigeonResult.setAppId((appId == null) ? null : ((appId instanceof Integer) ? (Integer) appId : (Long) appId));
Object fileId = list.get(1);
pigeonResult.setFileId((String) fileId);
Object pSign = list.get(2);
pigeonResult.setPSign((String) pSign);
Object playUrl = list.get(3);
pigeonResult.setPlayUrl((String) playUrl);
Object preloadSizeMB = list.get(4);
pigeonResult.setPreloadSizeMB((preloadSizeMB == null) ? null : ((preloadSizeMB instanceof Integer) ? (Integer) preloadSizeMB : (Long) preloadSizeMB));
Object preferredResolution = list.get(5);
pigeonResult.setPreferredResolution((preferredResolution == null) ? null : ((preferredResolution instanceof Integer) ? (Integer) preferredResolution : (Long) preferredResolution));
Object tmpPreloadTaskId = list.get(6);
pigeonResult.setTmpPreloadTaskId((tmpPreloadTaskId == null) ? null : ((tmpPreloadTaskId instanceof Integer) ? (Integer) tmpPreloadTaskId : (Long) tmpPreloadTaskId));
return pigeonResult;
}
}
/** Generated class from Pigeon that represents data sent in messages. */ /** Generated class from Pigeon that represents data sent in messages. */
public static final class MapMsg { public static final class MapMsg {
private @Nullable Map<String, String> map; private @Nullable Map<String, String> map;
...@@ -4691,10 +4881,12 @@ public class FtxMessages { ...@@ -4691,10 +4881,12 @@ public class FtxMessages {
case (byte) 130: case (byte) 130:
return MapMsg.fromList((ArrayList<Object>) readValue(buffer)); return MapMsg.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 131: case (byte) 131:
return PreLoadMsg.fromList((ArrayList<Object>) readValue(buffer)); return PreLoadInfoMsg.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 132: case (byte) 132:
return TXDownloadListMsg.fromList((ArrayList<Object>) readValue(buffer)); return PreLoadMsg.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 133: case (byte) 133:
return TXDownloadListMsg.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 134:
return TXVodDownloadMediaMsg.fromList((ArrayList<Object>) readValue(buffer)); return TXVodDownloadMediaMsg.fromList((ArrayList<Object>) readValue(buffer));
default: default:
return super.readValueOfType(type, buffer); return super.readValueOfType(type, buffer);
...@@ -4712,14 +4904,17 @@ public class FtxMessages { ...@@ -4712,14 +4904,17 @@ public class FtxMessages {
} else if (value instanceof MapMsg) { } else if (value instanceof MapMsg) {
stream.write(130); stream.write(130);
writeValue(stream, ((MapMsg) value).toList()); writeValue(stream, ((MapMsg) value).toList());
} else if (value instanceof PreLoadMsg) { } else if (value instanceof PreLoadInfoMsg) {
stream.write(131); stream.write(131);
writeValue(stream, ((PreLoadInfoMsg) value).toList());
} else if (value instanceof PreLoadMsg) {
stream.write(132);
writeValue(stream, ((PreLoadMsg) value).toList()); writeValue(stream, ((PreLoadMsg) value).toList());
} else if (value instanceof TXDownloadListMsg) { } else if (value instanceof TXDownloadListMsg) {
stream.write(132); stream.write(133);
writeValue(stream, ((TXDownloadListMsg) value).toList()); writeValue(stream, ((TXDownloadListMsg) value).toList());
} else if (value instanceof TXVodDownloadMediaMsg) { } else if (value instanceof TXVodDownloadMediaMsg) {
stream.write(133); stream.write(134);
writeValue(stream, ((TXVodDownloadMediaMsg) value).toList()); writeValue(stream, ((TXVodDownloadMediaMsg) value).toList());
} else { } else {
super.writeValue(stream, value); super.writeValue(stream, value);
...@@ -4738,6 +4933,8 @@ public class FtxMessages { ...@@ -4738,6 +4933,8 @@ public class FtxMessages {
*/ */
@NonNull @NonNull
IntMsg startPreLoad(@NonNull PreLoadMsg msg); IntMsg startPreLoad(@NonNull PreLoadMsg msg);
void startPreLoadByParams(@NonNull PreLoadInfoMsg msg);
/** /**
* 停止预下载。 * 停止预下载。
* taskId: 任务id * taskId: 任务id
...@@ -4791,6 +4988,30 @@ public class FtxMessages { ...@@ -4791,6 +4988,30 @@ public class FtxMessages {
IntMsg output = api.startPreLoad(msgArg); IntMsg output = api.startPreLoad(msgArg);
wrapped.add(0, output); wrapped.add(0, output);
} }
catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.TXFlutterDownloadApi.startPreLoadByParams", getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
PreLoadInfoMsg msgArg = (PreLoadInfoMsg) args.get(0);
try {
api.startPreLoadByParams(msgArg);
wrapped.add(0, null);
}
catch (Throwable exception) { catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception); ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError; wrapped = wrappedError;
......
...@@ -109,6 +109,19 @@ public class CommonUtil { ...@@ -109,6 +109,19 @@ public class CommonUtil {
return param; 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) { public static int getDownloadEventByState(int mediaInfoDownloadState) {
Integer event = DOWNLOAD_STATE_MAP.get(mediaInfoDownloadState); Integer event = DOWNLOAD_STATE_MAP.get(mediaInfoDownloadState);
return null != event ? event : FTXEvent.EVENT_DOWNLOAD_ERROR; return null != event ? event : FTXEvent.EVENT_DOWNLOAD_ERROR;
......
...@@ -1703,6 +1703,16 @@ FTXPredownlodOnCompleteListener? onCompleteListener, ...@@ -1703,6 +1703,16 @@ FTXPredownlodOnCompleteListener? onCompleteListener,
}) async }) 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, ...@@ -1713,6 +1723,15 @@ FTXPredownlodOnCompleteListener? onCompleteListener,
| onCompleteListener | FTXPredownlodOnCompleteListener? | 预下载成功回调,全局| | onCompleteListener | FTXPredownlodOnCompleteListener? | 预下载成功回调,全局|
| onErrorListener | FTXPredownlodOnErrorListener | 预下载失败回调,全局| | 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 ...@@ -449,6 +449,21 @@ int taskId = await TXVodDownloadController.instance.startPreLoad(palyrl, 3, 1920
TXVodDownloadController.instance.stopPreLoad(taskId); 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、视频下载 ### 3、视频下载
视频下载支持用户在有网络的条件下下载视频,随后在无网络的环境下观看。同时播放器 SDK 提供本地加密能力,下载后的本地视频仍为加密状态,仅可通过指定播放器对视频进行解密播放,可有效防止下载后视频的非法传播,保护视频安全。 视频下载支持用户在有网络的条件下下载视频,随后在无网络的环境下观看。同时播放器 SDK 提供本地加密能力,下载后的本地视频仍为加密状态,仅可通过指定播放器对视频进行解密播放,可有效防止下载后视频的非法传播,保护视频安全。
......
...@@ -44,6 +44,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb ...@@ -44,6 +44,7 @@ class _DemoTXVodPlayerState extends State<DemoTXVodPlayer> with WidgetsBindingOb
}); });
LogUtils.logOpen = true; LogUtils.logOpen = true;
playEventSubscription = _controller.onPlayerEventBroadcast.listen((event) async { playEventSubscription = _controller.onPlayerEventBroadcast.listen((event) async {
// Subscribe to event distribution // Subscribe to event distribution
if (event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) { if (event["event"] == TXVodPlayEvent.PLAY_EVT_RCV_FIRST_I_FRAME) {
......
...@@ -11,7 +11,10 @@ ...@@ -11,7 +11,10 @@
#import "FtxMessages.h" #import "FtxMessages.h"
@interface FTXDownloadManager ()<FlutterStreamHandler, TXVodPreloadManagerDelegate, TXVodDownloadDelegate, TXFlutterDownloadApi> @interface FTXDownloadManager ()<FlutterStreamHandler, TXVodPreloadManagerDelegate, TXVodDownloadDelegate, TXFlutterDownloadApi>
@property (nonatomic, strong) dispatch_queue_t mPreloadQueue;
@property (atomic, strong) NSMutableDictionary *mPreloadFileDic;
@end @end
@implementation FTXDownloadManager { @implementation FTXDownloadManager {
...@@ -32,6 +35,8 @@ ...@@ -32,6 +35,8 @@
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *path = [NSString stringWithFormat:@"%@/videoCache",cachesDir]; NSString *path = [NSString stringWithFormat:@"%@/videoCache",cachesDir];
[[TXVodDownloadManager shareInstance] setDownloadPath:path]; [[TXVodDownloadManager shareInstance] setDownloadPath:path];
self.mPreloadQueue = dispatch_queue_create(@"cloud.tencent.com.preload", NULL);
self.mPreloadFileDic = @{}.mutableCopy;
} }
return self; return self;
} }
...@@ -45,6 +50,28 @@ ...@@ -45,6 +50,28 @@
_eventSink = nil; _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 #pragma mark - FlutterStreamHandler
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
...@@ -80,6 +107,16 @@ ...@@ -80,6 +107,16 @@
#pragma mark - TXVodPreloadManager delegate #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 - (void)onComplete:(int)taskID url:(NSString *)url
{ {
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; NSMutableDictionary *dict = [NSMutableDictionary dictionary];
...@@ -305,4 +342,31 @@ ...@@ -305,4 +342,31 @@
[[TXVodPreloadManager sharedManager] stopPreload:msg.value.intValue]; [[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 @end
...@@ -54,6 +54,8 @@ ...@@ -54,6 +54,8 @@
// Video pre-download error. // Video pre-download error.
// 视频预下载出错 // 视频预下载出错
#define EVENT_PREDOWNLOAD_ON_ERROR 201 #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. // Video download started.
// 视频下载开始 // 视频下载开始
......
...@@ -429,7 +429,9 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003; ...@@ -429,7 +429,9 @@ static const int CODE_ON_RECEIVE_FIRST_FRAME = 2003;
self->isVideoFirstFrameReceived = false; self->isVideoFirstFrameReceived = false;
}); });
} }
NSLog(@"onPlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]); if (EvtID != PLAY_EVT_PLAY_PROGRESS) {
NSLog(@"onPlayEvent:%i,%@", EvtID, param[EVT_PLAY_DESCRIPTION]);
}
[_eventSink success:[FTXVodPlayer getParamsWithEvent:EvtID withParams:param]]; [_eventSink success:[FTXVodPlayer getParamsWithEvent:EvtID withParams:param]];
} }
......
...@@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
@class StringMsg; @class StringMsg;
@class DoubleMsg; @class DoubleMsg;
@class PreLoadMsg; @class PreLoadMsg;
@class PreLoadInfoMsg;
@class MapMsg; @class MapMsg;
/// Pigeon original component, used to generate native communication code for `messages`. /// Pigeon original component, used to generate native communication code for `messages`.
...@@ -56,11 +57,13 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -56,11 +57,13 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId + (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId
appId:(nullable NSNumber *)appId appId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId 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 * playerId;
@property(nonatomic, strong, nullable) NSNumber * appId; @property(nonatomic, strong, nullable) NSNumber * appId;
@property(nonatomic, copy, nullable) NSString * fileId; @property(nonatomic, copy, nullable) NSString * fileId;
@property(nonatomic, copy, nullable) NSString * psign; @property(nonatomic, copy, nullable) NSString * psign;
@property(nonatomic, copy, nullable) NSString * url;
@end @end
@interface PipParamsPlayerMsg : NSObject @interface PipParamsPlayerMsg : NSObject
...@@ -290,6 +293,23 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -290,6 +293,23 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, strong, nullable) NSNumber * preferredResolution; @property(nonatomic, strong, nullable) NSNumber * preferredResolution;
@end @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 @interface MapMsg : NSObject
+ (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map; + (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map;
@property(nonatomic, strong, nullable) NSDictionary<NSString *, NSString *> * map; @property(nonatomic, strong, nullable) NSDictionary<NSString *, NSString *> * map;
...@@ -687,6 +707,7 @@ NSObject<FlutterMessageCodec> *TXFlutterDownloadApiGetCodec(void); ...@@ -687,6 +707,7 @@ NSObject<FlutterMessageCodec> *TXFlutterDownloadApiGetCodec(void);
/// ///
/// @return `nil` only when `error != nil`. /// @return `nil` only when `error != nil`.
- (nullable IntMsg *)startPreLoadMsg:(PreLoadMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error; - (nullable IntMsg *)startPreLoadMsg:(PreLoadMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
- (void)startPreLoadByParamsMsg:(PreLoadInfoMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
/// 停止预下载。 /// 停止预下载。
/// taskId: 任务id /// taskId: 任务id
- (void)stopPreLoadMsg:(IntMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error; - (void)stopPreLoadMsg:(IntMsg *)msg error:(FlutterError *_Nullable *_Nonnull)error;
......
...@@ -148,6 +148,12 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { ...@@ -148,6 +148,12 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
- (NSArray *)toList; - (NSArray *)toList;
@end @end
@interface PreLoadInfoMsg ()
+ (PreLoadInfoMsg *)fromList:(NSArray *)list;
+ (nullable PreLoadInfoMsg *)nullableFromList:(NSArray *)list;
- (NSArray *)toList;
@end
@interface MapMsg () @interface MapMsg ()
+ (MapMsg *)fromList:(NSArray *)list; + (MapMsg *)fromList:(NSArray *)list;
+ (nullable MapMsg *)nullableFromList:(NSArray *)list; + (nullable MapMsg *)nullableFromList:(NSArray *)list;
...@@ -204,12 +210,14 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { ...@@ -204,12 +210,14 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
+ (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId + (instancetype)makeWithPlayerId:(nullable NSNumber *)playerId
appId:(nullable NSNumber *)appId appId:(nullable NSNumber *)appId
fileId:(nullable NSString *)fileId fileId:(nullable NSString *)fileId
psign:(nullable NSString *)psign { psign:(nullable NSString *)psign
url:(nullable NSString *)url {
TXPlayInfoParamsPlayerMsg* pigeonResult = [[TXPlayInfoParamsPlayerMsg alloc] init]; TXPlayInfoParamsPlayerMsg* pigeonResult = [[TXPlayInfoParamsPlayerMsg alloc] init];
pigeonResult.playerId = playerId; pigeonResult.playerId = playerId;
pigeonResult.appId = appId; pigeonResult.appId = appId;
pigeonResult.fileId = fileId; pigeonResult.fileId = fileId;
pigeonResult.psign = psign; pigeonResult.psign = psign;
pigeonResult.url = url;
return pigeonResult; return pigeonResult;
} }
+ (TXPlayInfoParamsPlayerMsg *)fromList:(NSArray *)list { + (TXPlayInfoParamsPlayerMsg *)fromList:(NSArray *)list {
...@@ -218,6 +226,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { ...@@ -218,6 +226,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
pigeonResult.appId = GetNullableObjectAtIndex(list, 1); pigeonResult.appId = GetNullableObjectAtIndex(list, 1);
pigeonResult.fileId = GetNullableObjectAtIndex(list, 2); pigeonResult.fileId = GetNullableObjectAtIndex(list, 2);
pigeonResult.psign = GetNullableObjectAtIndex(list, 3); pigeonResult.psign = GetNullableObjectAtIndex(list, 3);
pigeonResult.url = GetNullableObjectAtIndex(list, 4);
return pigeonResult; return pigeonResult;
} }
+ (nullable TXPlayInfoParamsPlayerMsg *)nullableFromList:(NSArray *)list { + (nullable TXPlayInfoParamsPlayerMsg *)nullableFromList:(NSArray *)list {
...@@ -229,6 +238,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { ...@@ -229,6 +238,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
(self.appId ?: [NSNull null]), (self.appId ?: [NSNull null]),
(self.fileId ?: [NSNull null]), (self.fileId ?: [NSNull null]),
(self.psign ?: [NSNull null]), (self.psign ?: [NSNull null]),
(self.url ?: [NSNull null]),
]; ];
} }
@end @end
...@@ -847,6 +857,51 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { ...@@ -847,6 +857,51 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
} }
@end @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 @implementation MapMsg
+ (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map { + (instancetype)makeWithMap:(nullable NSDictionary<NSString *, NSString *> *)map {
MapMsg* pigeonResult = [[MapMsg alloc] init]; MapMsg* pigeonResult = [[MapMsg alloc] init];
...@@ -2709,10 +2764,12 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO ...@@ -2709,10 +2764,12 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO
case 130: case 130:
return [MapMsg fromList:[self readValue]]; return [MapMsg fromList:[self readValue]];
case 131: case 131:
return [PreLoadMsg fromList:[self readValue]]; return [PreLoadInfoMsg fromList:[self readValue]];
case 132: case 132:
return [TXDownloadListMsg fromList:[self readValue]]; return [PreLoadMsg fromList:[self readValue]];
case 133: case 133:
return [TXDownloadListMsg fromList:[self readValue]];
case 134:
return [TXVodDownloadMediaMsg fromList:[self readValue]]; return [TXVodDownloadMediaMsg fromList:[self readValue]];
default: default:
return [super readValueOfType:type]; return [super readValueOfType:type];
...@@ -2733,15 +2790,18 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO ...@@ -2733,15 +2790,18 @@ void TXFlutterLivePlayerApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSO
} else if ([value isKindOfClass:[MapMsg class]]) { } else if ([value isKindOfClass:[MapMsg class]]) {
[self writeByte:130]; [self writeByte:130];
[self writeValue:[value toList]]; [self writeValue:[value toList]];
} else if ([value isKindOfClass:[PreLoadMsg class]]) { } else if ([value isKindOfClass:[PreLoadInfoMsg class]]) {
[self writeByte:131]; [self writeByte:131];
[self writeValue:[value toList]]; [self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXDownloadListMsg class]]) { } else if ([value isKindOfClass:[PreLoadMsg class]]) {
[self writeByte:132]; [self writeByte:132];
[self writeValue:[value toList]]; [self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXVodDownloadMediaMsg class]]) { } else if ([value isKindOfClass:[TXDownloadListMsg class]]) {
[self writeByte:133]; [self writeByte:133];
[self writeValue:[value toList]]; [self writeValue:[value toList]];
} else if ([value isKindOfClass:[TXVodDownloadMediaMsg class]]) {
[self writeByte:134];
[self writeValue:[value toList]];
} else { } else {
[super writeValue:value]; [super writeValue:value];
} }
...@@ -2794,6 +2854,25 @@ void TXFlutterDownloadApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObj ...@@ -2794,6 +2854,25 @@ void TXFlutterDownloadApiSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObj
[channel setMessageHandler:nil]; [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 /// taskId: 任务id
{ {
......
// Copyright (c) 2022 Tencent. All rights reserved. // Copyright (c) 2022 Tencent. All rights reserved.
import 'package:pigeon/pigeon.dart'; // import 'package:pigeon/pigeon.dart';
import 'package:super_player/super_player.dart'; // import 'package:super_player/super_player.dart';
/// Pigeon original component, used to generate native communication code for `messages`. /// Pigeon original component, used to generate native communication code for `messages`.
/// The generation command is as follows. When using the generation command, /// The generation command is as follows. When using the generation command,
/// the two import statements above need to be implemented or commented out. /// the two import statements above need to be implemented or commented out.
...@@ -31,6 +31,7 @@ class TXPlayInfoParamsPlayerMsg { ...@@ -31,6 +31,7 @@ class TXPlayInfoParamsPlayerMsg {
int? appId; int? appId;
String? fileId; String? fileId;
String? psign; String? psign;
String? url;
} }
class PipParamsPlayerMsg { class PipParamsPlayerMsg {
...@@ -266,6 +267,16 @@ class PreLoadMsg { ...@@ -266,6 +267,16 @@ class PreLoadMsg {
int? preferredResolution; int? preferredResolution;
} }
class PreLoadInfoMsg {
int? appId;
String? fileId;
String? pSign;
String? playUrl;
int? preloadSizeMB;
int? preferredResolution;
int? tmpPreloadTaskId;
}
class MapMsg { class MapMsg {
Map<String?, String?>? map; Map<String?, String?>? map;
} }
...@@ -640,6 +651,8 @@ abstract class TXFlutterDownloadApi { ...@@ -640,6 +651,8 @@ abstract class TXFlutterDownloadApi {
/// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload] /// 返回值:任务ID,可用这个任务ID停止预下载 [stopPreload]
IntMsg startPreLoad(PreLoadMsg msg); IntMsg startPreLoad(PreLoadMsg msg);
void startPreLoadByParams(PreLoadInfoMsg msg);
/// 停止预下载。 /// 停止预下载。
/// taskId: 任务id /// taskId: 任务id
void stopPreLoad(IntMsg msg); void stopPreLoad(IntMsg msg);
......
...@@ -315,6 +315,8 @@ abstract class TXVodPlayEvent { ...@@ -315,6 +315,8 @@ abstract class TXVodPlayEvent {
// Error occurred during video pre-download. // Error occurred during video pre-download.
// 视频预下载出错 // 视频预下载出错
static const EVENT_PREDOWNLOAD_ON_ERROR = 201; 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. // Video download started.
// 视频下载开始 // 视频下载开始
...@@ -510,15 +512,19 @@ class DownloadQuality { ...@@ -510,15 +512,19 @@ class DownloadQuality {
class TXPlayInfoParams { class TXPlayInfoParams {
final int appId; // Tencent Cloud video appId, required final int appId; // Tencent Cloud video appId, required
final String fileId; // Tencent Cloud video fileId, 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> toJson() {
Map<String, dynamic> json = {}; Map<String, dynamic> json = {};
json["appId"] = appId; json["appId"] = appId;
json["fileId"] = fileId; json["fileId"] = fileId;
json["psign"] = psign; json["psign"] = psign;
json["url"] = url;
return json; return json;
} }
} }
...@@ -671,6 +677,8 @@ abstract class TXPlayerType { ...@@ -671,6 +677,8 @@ abstract class TXPlayerType {
// Video pre-download event callback listener. // Video pre-download event callback listener.
// 视频预下载事件回调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 FTXPredownlodOnCompleteListener = void Function(int taskId, String url);
typedef FTXPredownlodOnErrorListener = void Function(int taskId, String url, int code, String msg); typedef FTXPredownlodOnErrorListener = void Function(int taskId, String url, int code, String msg);
// Video download time callback listener. // Video download time callback listener.
......
...@@ -63,6 +63,7 @@ class TXPlayInfoParamsPlayerMsg { ...@@ -63,6 +63,7 @@ class TXPlayInfoParamsPlayerMsg {
this.appId, this.appId,
this.fileId, this.fileId,
this.psign, this.psign,
this.url,
}); });
int? playerId; int? playerId;
...@@ -73,12 +74,15 @@ class TXPlayInfoParamsPlayerMsg { ...@@ -73,12 +74,15 @@ class TXPlayInfoParamsPlayerMsg {
String? psign; String? psign;
String? url;
Object encode() { Object encode() {
return <Object?>[ return <Object?>[
playerId, playerId,
appId, appId,
fileId, fileId,
psign, psign,
url,
]; ];
} }
...@@ -89,6 +93,7 @@ class TXPlayInfoParamsPlayerMsg { ...@@ -89,6 +93,7 @@ class TXPlayInfoParamsPlayerMsg {
appId: result[1] as int?, appId: result[1] as int?,
fileId: result[2] as String?, fileId: result[2] as String?,
psign: result[3] as String?, psign: result[3] as String?,
url: result[4] as String?,
); );
} }
} }
...@@ -785,6 +790,57 @@ class PreLoadMsg { ...@@ -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 { class MapMsg {
MapMsg({ MapMsg({
this.map, this.map,
...@@ -2994,15 +3050,18 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec { ...@@ -2994,15 +3050,18 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec {
} else if (value is MapMsg) { } else if (value is MapMsg) {
buffer.putUint8(130); buffer.putUint8(130);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else if (value is PreLoadMsg) { } else if (value is PreLoadInfoMsg) {
buffer.putUint8(131); buffer.putUint8(131);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else if (value is TXDownloadListMsg) { } else if (value is PreLoadMsg) {
buffer.putUint8(132); buffer.putUint8(132);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else if (value is TXVodDownloadMediaMsg) { } else if (value is TXDownloadListMsg) {
buffer.putUint8(133); buffer.putUint8(133);
writeValue(buffer, value.encode()); writeValue(buffer, value.encode());
} else if (value is TXVodDownloadMediaMsg) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else { } else {
super.writeValue(buffer, value); super.writeValue(buffer, value);
} }
...@@ -3018,10 +3077,12 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec { ...@@ -3018,10 +3077,12 @@ class _TXFlutterDownloadApiCodec extends StandardMessageCodec {
case 130: case 130:
return MapMsg.decode(readValue(buffer)!); return MapMsg.decode(readValue(buffer)!);
case 131: case 131:
return PreLoadMsg.decode(readValue(buffer)!); return PreLoadInfoMsg.decode(readValue(buffer)!);
case 132: case 132:
return TXDownloadListMsg.decode(readValue(buffer)!); return PreLoadMsg.decode(readValue(buffer)!);
case 133: case 133:
return TXDownloadListMsg.decode(readValue(buffer)!);
case 134:
return TXVodDownloadMediaMsg.decode(readValue(buffer)!); return TXVodDownloadMediaMsg.decode(readValue(buffer)!);
default: default:
return super.readValueOfType(type, buffer); return super.readValueOfType(type, buffer);
...@@ -3071,6 +3132,28 @@ class TXFlutterDownloadApi { ...@@ -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 /// taskId: 任务id
Future<void> stopPreLoad(IntMsg arg_msg) async { Future<void> stopPreLoad(IntMsg arg_msg) async {
......
...@@ -17,11 +17,11 @@ class TXVodDownloadController { ...@@ -17,11 +17,11 @@ class TXVodDownloadController {
Stream<Map<dynamic, dynamic>> get onDownloadEventBroadcast => _downloadEventStreamController.stream; Stream<Map<dynamic, dynamic>> get onDownloadEventBroadcast => _downloadEventStreamController.stream;
FTXPredownlodOnCompleteListener? _onPreDownloadOnCompleteListener; Map<int, _PreloadListener> _preloadListeners = {};
FTXPredownlodOnErrorListener? _onPreDownloadOnErrorListener; Map<int, _PreloadListener> _fileIdBeforeStartListeners = {};
FTXDownlodOnStateChangeListener? _downlodOnStateChangeListener; FTXDownlodOnStateChangeListener? _downlodOnStateChangeListener;
FTXDownlodOnErrorListener? _downlodOnErrorListener; FTXDownlodOnErrorListener? _downlodOnErrorListener;
AtomicInt _atomicPreloadId = AtomicInt(0);
static TXVodDownloadController _sharedInstance() { static TXVodDownloadController _sharedInstance() {
if (_instance == null) { if (_instance == null) {
...@@ -60,13 +60,38 @@ class TXVodDownloadController { ...@@ -60,13 +60,38 @@ class TXVodDownloadController {
FTXPredownlodOnCompleteListener? onCompleteListener, FTXPredownlodOnCompleteListener? onCompleteListener,
FTXPredownlodOnErrorListener? onErrorListener, FTXPredownlodOnErrorListener? onErrorListener,
}) async { }) async {
_onPreDownloadOnCompleteListener = onCompleteListener;
_onPreDownloadOnErrorListener = onErrorListener;
IntMsg msg = await _api.startPreLoad(PreLoadMsg() IntMsg msg = await _api.startPreLoad(PreLoadMsg()
..playUrl = playUrl ..playUrl = playUrl
..preloadSizeMB = preloadSizeMB ..preloadSizeMB = preloadSizeMB
..preferredResolution = preferredResolution); ..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. /// Stop pre-downloading.
...@@ -223,9 +248,8 @@ class TXVodDownloadController { ...@@ -223,9 +248,8 @@ class TXVodDownloadController {
int taskId = map['taskId']; int taskId = map['taskId'];
String url = map['url']; String url = map['url'];
LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_COMPLETE, taskID=$taskId ,url=$url'); LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_COMPLETE, taskID=$taskId ,url=$url');
if (_onPreDownloadOnCompleteListener != null) { _preloadListeners[taskId]?.onCompleteListener?.call(taskId, url);
_onPreDownloadOnCompleteListener!(taskId, url); _preloadListeners.remove(taskId);
}
break; break;
case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_ERROR: case TXVodPlayEvent.EVENT_PREDOWNLOAD_ON_ERROR:
int taskId = map['taskId']; int taskId = map['taskId'];
...@@ -233,8 +257,21 @@ class TXVodDownloadController { ...@@ -233,8 +257,21 @@ class TXVodDownloadController {
int code = map['code'] ?? 0; int code = map['code'] ?? 0;
String msg = map['msg'] ?? ''; String msg = map['msg'] ?? '';
LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_ERROR, taskID=$taskId ,url=$url, code=$code , msg=$msg'); LogUtils.d(TAG, 'receive EVENT_PREDOWNLOAD_ON_ERROR, taskID=$taskId ,url=$url, code=$code , msg=$msg');
if (_onPreDownloadOnErrorListener != null) { _preloadListeners[taskId]?.onErrorListener?.call(taskId, url, code, msg);
_onPreDownloadOnErrorListener!(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; break;
case TXVodPlayEvent.EVENT_DOWNLOAD_START: case TXVodPlayEvent.EVENT_DOWNLOAD_START:
...@@ -256,4 +293,32 @@ class TXVodDownloadController { ...@@ -256,4 +293,32 @@ class TXVodDownloadController {
} }
_errorHandler(error) {} _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'; ...@@ -7,6 +7,7 @@ import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:synchronized/synchronized.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
......
...@@ -12,6 +12,7 @@ dependencies: ...@@ -12,6 +12,7 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
pigeon: ^9.0.1 pigeon: ^9.0.1
synchronized: ^3.0.0+3
# internationalization # internationalization
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
...@@ -19,6 +20,7 @@ dev_dependencies: ...@@ -19,6 +20,7 @@ dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
pigeon: ^9.0.1 pigeon: ^9.0.1
synchronized: ^3.0.0+3
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论