diff --git a/Demo/TXLiteAVDemo/SuperPlayFeedDemo/Controller/FeedPlayViewController.m b/Demo/TXLiteAVDemo/SuperPlayFeedDemo/Controller/FeedPlayViewController.m index 3c628e3..535bda5 100644 --- a/Demo/TXLiteAVDemo/SuperPlayFeedDemo/Controller/FeedPlayViewController.m +++ b/Demo/TXLiteAVDemo/SuperPlayFeedDemo/Controller/FeedPlayViewController.m @@ -133,9 +133,11 @@ - (void)loadTestDataWithsuccess:(void(^)(NSMutableArray *list))success { fileId:obj.fileId psign:obj.pSign completion:^(NSMutableDictionary * _Nonnull dic, NSError * _Nonnull error) { - obj.videoURL = [dic objectForKey:@"videoUrl"]; - obj.multiVideoURLs = [dic objectForKey:@"multiVideoURLs"]; - dispatch_group_leave(downloadVideoGroup); + if (!error) { + obj.videoURL = [dic objectForKey:@"videoUrl"]; + obj.multiVideoURLs = [dic objectForKey:@"multiVideoURLs"]; + dispatch_group_leave(downloadVideoGroup); + } }]; }]; diff --git a/Demo/TXLiteAVDemo/SuperPlayerDemo/SuperPlayer/CacheView/VideoCacheListView/VideoCacheListView.m b/Demo/TXLiteAVDemo/SuperPlayerDemo/SuperPlayer/CacheView/VideoCacheListView/VideoCacheListView.m index 3aa6aed..5a9e8c8 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerDemo/SuperPlayer/CacheView/VideoCacheListView/VideoCacheListView.m +++ b/Demo/TXLiteAVDemo/SuperPlayerDemo/SuperPlayer/CacheView/VideoCacheListView/VideoCacheListView.m @@ -256,8 +256,10 @@ - (void)clickHelp { - (void)clickScan { self.scanVC = [[ScanQRController alloc] init]; + self.scanVC.modalPresentationStyle = UIModalPresentationFullScreen; self.scanVC.delegate = self; - [self addSubview:self.scanVC.view]; + UIViewController *currentVC = [self currentViewController]; + [currentVC presentViewController:self.scanVC animated:NO completion:nil]; } - (void)longPress:(UILongPressGestureRecognizer *)longPress { @@ -423,6 +425,7 @@ - (void)onScanResult:(NSString *)result { } - (void)cancelScanQR { + [self.scanVC dismissViewControllerAnimated:NO completion:nil]; self.scanVC = nil; } diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer.podspec b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer.podspec index 2bca9ea..79841e5 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer.podspec +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer.podspec @@ -12,7 +12,6 @@ Pod::Spec.new do |spec| spec.dependency 'SDWebImage' spec.dependency 'Masonry' - spec.dependency 'AFNetworking' #spec.dependency 'MMLayout' spec.static_framework = true @@ -42,6 +41,22 @@ Pod::Spec.new do |spec| 'SuperPlayerKitBundle' => ['SuperPlayer/SuperPlayerLocalized/**/*.strings',] } end + spec.subspec "Player_Premium" do |s| + s.exclude_files = 'SuperPlayer/SDKHeaders/**' + s.source_files = 'SuperPlayer/**/*.{h,m}' + s.private_header_files = 'SuperPlayer/Utils/TXBitrateItemHelper.h', 'SuperPlayer/Views/SuperPlayerView+Private.h' +# s.resource = 'SuperPlayer/Resource/*' +#如果要使用cocopods管理的TXLiteAVSDK_Player,就不注释这一行 +# s.dependency 'TXLiteAVSDK_Player', '= 5.3.6001' +#如果要使用最新的TXLiteAVSDK_Player,就不注释这一行 + framework_path="../../../SDK/TXLiteAVSDK_Player_Premium.framework" + s.pod_target_xcconfig={ + 'HEADER_SEARCH_PATHS'=>["$(PODS_TARGET_SRCROOT)/#{framework_path}/Headers"] + } + s.resource_bundles = { + 'SuperPlayerKitBundle' => ['SuperPlayer/SuperPlayerLocalized/**/*.strings',] + } + end spec.subspec "Professional" do |s| s.exclude_files = 'SuperPlayer/SDKHeaders/**' s.source_files = 'SuperPlayer/**/*.{h,m}' diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.h b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.h deleted file mode 100644 index ea098e0..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// SPPlayCGIParser.h -// SuperPlayer -// -// Created by cui on 2019/12/26. -// Copyright © 2019 annidy. All rights reserved. -// - -#import - -#import "SPPlayCGIParserProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SPPlayCGIParser : NSObject -+ (Class)parserOfVersion:(NSInteger)version; -@end - -NS_ASSUME_NONNULL_END - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.m deleted file mode 100644 index ae40436..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// SPPlayCGIParser.m -// SuperPlayer -// -// Created by cui on 2019/12/26. -// Copyright © 2019 annidy. All rights reserved. -// - -#import "SPPlayCGIParser.h" - -#import "SPPlayCGIParser_V2.h" -#import "SPPlayCGIParser_V4.h" - -@implementation SPPlayCGIParser -+ (Class)parserOfVersion:(NSInteger)version { - if (version == 2) { - return [SPPlayCGIParser_V2 class]; - } else { - return [SPPlayCGIParser_V4 class]; - } -} -@end - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParserProtocol.h b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParserProtocol.h deleted file mode 100644 index 8ff2d24..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParserProtocol.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PlayCGIParserProtocol.h -// SuperPlayer -// -// Created by cui on 2019/12/25. -// Copyright © 2019 annidy. All rights reserved. -// - -#import - -#import "SPPlayCGIParseResult.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol SPPlayCGIParserProtocol -+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)jsonResp; -@end - -NS_ASSUME_NONNULL_END - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.h b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.h deleted file mode 100644 index 1844144..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// SPPlayCGIParser_V2.h -// SuperPlayer -// -// Created by cui on 2019/12/25. -// Copyright © 2019 annidy. All rights reserved. -// - -#import - -#import "SPPlayCGIParserProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SPPlayCGIParser_V2 : NSObject - -@end - -NS_ASSUME_NONNULL_END - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.m deleted file mode 100644 index 38200c5..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V2.m +++ /dev/null @@ -1,105 +0,0 @@ -// -// SPPlayCGIParser_V2.m -// SuperPlayer -// -// Created by cui on 2019/12/25. -// Copyright © 2019 annidy. All rights reserved. -// - -#import "SPPlayCGIParser_V2.h" - -#import "J2Obj.h" -#import "SuperPlayerUrl.h" -#import "TXBitrateItemHelper.h" -#import "TXImageSprite.h" - -@implementation SPPlayCGIParser_V2 -+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)responseObject { - SPPlayCGIParseResult *ret = [[SPPlayCGIParseResult alloc] init]; - NSString * masterUrl = J2Str([responseObject valueForKeyPath:@"videoInfo.masterPlayList.url"]); - // masterUrl = nil; - if (masterUrl.length > 0) { - // 1. 如果有master url,优先用这个 - ret.url = masterUrl; - } else { - NSString *mainDefinition = J2Str([responseObject valueForKeyPath:@"playerInfo.defaultVideoClassification"]); - - NSArray *videoClassification = J2Array([responseObject valueForKeyPath:@"playerInfo.videoClassification"]); - NSArray *transcodeList = J2Array([responseObject valueForKeyPath:@"videoInfo.transcodeList"]); - - NSMutableArray *result = [NSMutableArray new]; - - // 2. 如果有转码的清晰度,用转码流 - for (NSDictionary *transcode in transcodeList) { - SuperPlayerUrl *subModel = [SuperPlayerUrl new]; - subModel.url = J2Str(transcode[@"url"]); - NSNumber *theDefinition = J2Num(transcode[@"definition"]); - - for (NSDictionary *definition in videoClassification) { - for (NSObject *definition2 in J2Array([definition valueForKeyPath:@"definitionList"])) { - if ([definition2 isEqual:theDefinition]) { - subModel.title = J2Str([definition valueForKeyPath:@"name"]); - NSString *definitionId = J2Str([definition valueForKeyPath:@"id"]); - // 初始播放清晰度 - if ([definitionId isEqualToString:mainDefinition]) { - if (![ret.url containsString:@".mp4"]) ret.url = subModel.url; - } - break; - } - } - } - // 同一个清晰度可能存在多个转码格式,这里只保留一种格式,且优先mp4类型 - for (SuperPlayerUrl *item in result) { - if ([item.title isEqual:subModel.title]) { - if (![item.url containsString:@".mp4"]) { - item.url = subModel.url; - } - subModel = nil; - break; - } - } - - if (subModel) { - [result addObject:subModel]; - } - } - ret.multiVideoURLs = result; - } - // 3. 以上都没有,用原始地址 - if (ret.url == nil) { - NSString *source = J2Str([responseObject valueForKeyPath:@"videoInfo.sourceVideo.url"]); - ret.url = source; - } - - NSArray *imageSprites = J2Array([responseObject valueForKeyPath:@"imageSpriteInfo.imageSpriteList"]); - if (imageSprites.count > 0) { - // id imageSpriteObj = imageSprites[0]; - id imageSpriteObj = imageSprites.lastObject; - NSString * vtt = J2Str([imageSpriteObj valueForKeyPath:@"webVttUrl"]); - NSArray * imgUrls = J2Array([imageSpriteObj valueForKeyPath:@"imageUrls"]); - NSMutableArray *imgUrlArray = @[].mutableCopy; - for (NSString *url in imgUrls) { - NSURL *nsurl = [NSURL URLWithString:url]; - if (nsurl) { - [imgUrlArray addObject:nsurl]; - } - } - - TXImageSprite *imageSprite = [[TXImageSprite alloc] init]; - [imageSprite setVTTUrl:[NSURL URLWithString:vtt] imageUrls:imgUrlArray]; - ret.imageSprite = imageSprite; - } - - NSArray *keyFrameDescList = J2Array([responseObject valueForKeyPath:@"keyFrameDescInfo.keyFrameDescList"]); - if (keyFrameDescList.count > 0) { - NSMutableArray *checkPoints = [[NSMutableArray alloc] initWithCapacity:keyFrameDescList.count]; - for (NSDictionary *info in keyFrameDescList) { - SPVideoFrameDescription *checkPoint = [SPVideoFrameDescription instanceFromDictionary:info]; - [checkPoints addObject:checkPoint]; - } - ret.keyFrameDescList = checkPoints; - } - return ret; -} -@end - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.h b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.h deleted file mode 100644 index d319645..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// PlayCGIV4Parser.h -// SuperPlayer -// -// Created by cui on 2019/12/25. -// Copyright © 2019 annidy. All rights reserved. -// - -#import - -#import "SPPlayCGIParserProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SPPlayCGIParser_V4 : NSObject - -@end - -NS_ASSUME_NONNULL_END - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.m deleted file mode 100644 index 394d7b1..0000000 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/PlayCGI/SPPlayCGIParser_V4.m +++ /dev/null @@ -1,140 +0,0 @@ -// -// PlayCGIV4Parser.m -// SuperPlayer -// -// Created by cui on 2019/12/25. -// Copyright © 2019 annidy. All rights reserved. -// - -#import "SPPlayCGIParser_V4.h" -//#import "SPResolutionDefination.h" -#import "AdaptiveStream.h" -#import "J2Obj.h" -#import "SPSubStreamInfo.h" -#import "TXImageSprite.h" - -@implementation SPPlayCGIParser_V4 - -+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)jsonResp { - SPPlayCGIParseResult *ret = [[SPPlayCGIParseResult alloc] init]; - - // 获取媒体信息 - NSDictionary *media = jsonResp[@"media"]; - if ([media isKindOfClass:[NSDictionary class]]) { - do { - //解析视频名称 - ret.name = [media valueForKeyPath:@"basicInfo.name"]; - NSString* audioVideoType = [media valueForKey:@"audioVideoType"]; - NSDictionary *streamInfo = [self getStreamInfo:audioVideoType media:media]; - if (streamInfo == nil) { - NSArray *drmOutputs = [media valueForKeyPath:@"streamingInfo.drmOutput"]; - for (NSDictionary *drmOutput in drmOutputs) { - SPDrmType type = [SPPlayCGIParseResult drmTypeFromString:J2Str(drmOutput[@"type"])]; - if (type == SPDrmTypeSimpleAES) { - streamInfo = drmOutput; - ret.drmType = SPDrmTypeSimpleAES; - break; - } - } - ret.drmToken = [media valueForKeyPath:@"streamingInfo.drmToken"]; - } - - NSNumber *duration = [media valueForKeyPath:@"basicInfo.duration"]; - if ([duration isKindOfClass:[NSNumber class]]) { - ret.originalDuration = duration.doubleValue; - } - // 解析分辨率名称 - NSArray * subStreamDictArray = J2Array(streamInfo[@"subStreams"]); - ret.multiVideoURLs = [self parseResolutionName:subStreamDictArray]; - - //解析视频播放url - NSString *url = streamInfo[@"url"]; - if ([url isKindOfClass:[NSString class]] && url.length > 0) { - //未加密直接解析出视频url - ret.url = url; - } else { - //有加密,url为空,则解析drm加密的url信息 - NSArray *urlArray = streamInfo[@"drmUrls"]; - if ([urlArray isKindOfClass:[NSArray class]] && urlArray.count > 0) { - NSMutableArray *drmURLArray = [NSMutableArray arrayWithCapacity:urlArray.count]; - for (NSDictionary *dict in urlArray) { - if ([dict isKindOfClass:[NSDictionary class]]) { - continue; - } - AdaptiveStream *stream = [[AdaptiveStream alloc] init]; - stream.url = dict[@"url"]; - stream.drmType = dict[@"type"]; - [drmURLArray addObject:stream]; - } - ret.adaptiveStreamArray = drmURLArray; - } - } - - //解析略缩图信息 - NSDictionary *imageSpriteInfo = media[@"imageSpriteInfo"]; - - if ([imageSpriteInfo isKindOfClass:[NSDictionary class]]) { - NSString * vttURLString = J2Str(imageSpriteInfo[@"webVttUrl"]); - NSURL * vttURL = [NSURL URLWithString:vttURLString]; - NSArray * imageURLStrings = J2Array(imageSpriteInfo[@"imageUrls"]); - NSMutableArray *imageURLs = [NSMutableArray arrayWithCapacity:imageURLStrings.count]; - for (NSString *urlString in imageURLStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - if (url) { - [imageURLs addObject:url]; - } - } - TXImageSprite *sprite = [[TXImageSprite alloc] init]; - [sprite setVTTUrl:vttURL imageUrls:imageURLs]; - ret.imageSprite = sprite; - } - - //解析关键帧信息 - NSDictionary *keyFrameDescInfo = media[@"keyFrameDescInfo"]; - if ([keyFrameDescInfo isKindOfClass:[NSDictionary class]]) { - NSArray *keyFrameDescList = keyFrameDescInfo[@"keyFrameDescList"]; - if ([keyFrameDescList isKindOfClass:[NSArray class]] && keyFrameDescList.count > 0) { - ret.keyFrameDescList = [self parseKeyframeData:keyFrameDescList]; - } - } - } while (0); - } - return ret; -} - -+ (NSDictionary *)getStreamInfo:(NSString*) audioVideoType media:(NSDictionary*) media{ - NSDictionary *streamInfo; - if ([audioVideoType isEqualToString:@"Original"]) { //原视频输出 - streamInfo = [media valueForKey:@"originalInfo"]; - }else if ([audioVideoType isEqualToString:@"Transcode"]){ //转码输出 - streamInfo = [media valueForKey:@"transcodeInfo"]; - }else{ //自适应码流输出 - streamInfo = [media valueForKeyPath:@"streamingInfo.plainOutput"]; - } - return streamInfo;; -} - -+(NSMutableArray *) parseResolutionName:(NSArray*)subStreamDictArray{ - NSMutableArray *subStreamInfoArray = [NSMutableArray arrayWithCapacity:subStreamDictArray.count]; - for (NSDictionary *resInfo in subStreamDictArray) { - SuperPlayerUrl *url = [[SuperPlayerUrl alloc] init]; - url.title = J2Str(resInfo[@"resolutionName"]); - // SPSubStreamInfo *info = [SPSubStreamInfo infoWithDictionary:resInfo]; - [subStreamInfoArray addObject:url]; - } - return subStreamInfoArray; -} - -+(NSMutableArray *) parseKeyframeData:(NSArray *)keyFrameDescList{ - NSMutableArray *videoPoints = [NSMutableArray array]; - for (NSDictionary *jsonObject in keyFrameDescList) { - SPVideoFrameDescription *point = [SPVideoFrameDescription instanceFromDictionary:jsonObject]; - if (point) { - [videoPoints addObject:point]; - } - } - return videoPoints; -} - -@end - diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/en.lproj/SuperPlayerLocalized.strings b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/en.lproj/SuperPlayerLocalized.strings index 6fd4172..0c6a4f4 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/en.lproj/SuperPlayerLocalized.strings +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/en.lproj/SuperPlayerLocalized.strings @@ -31,3 +31,4 @@ "SuperPlayer.openvip" = "Open VIP membership"; "SuperPlayer.tryagain" = "Try Again"; "SuperPlayer.backtolive" = "Back to Live Streaming"; +"SuperPlayer.notsupportpip" = "This device does not support picture-in-picture"; diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/zh-Hans.lproj/SuperPlayerLocalized.strings b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/zh-Hans.lproj/SuperPlayerLocalized.strings index c9829b2..1a0f717 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/zh-Hans.lproj/SuperPlayerLocalized.strings +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerLocalized/zh-Hans.lproj/SuperPlayerLocalized.strings @@ -30,3 +30,4 @@ "SuperPlayer.openvip" = "开通VIP会员"; "SuperPlayer.tryagain" = "重新试看"; "SuperPlayer.backtolive" = "返回直播"; +"SuperPlayer.notsupportpip" = "该设备不支持画中画"; diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModel.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModel.m index 21201cd..f130e27 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModel.m +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModel.m @@ -1,8 +1,7 @@ #import "SuperPlayerModel.h" -#import + #import "AdaptiveStream.h" #import "J2Obj.h" -#import "SPPlayCGIParser.h" #import "SuperPlayer.h" #import "SuperPlayerModelInternal.h" #import "TXVodPlayer.h" @@ -20,17 +19,11 @@ @implementation SuperPlayerModel { - (instancetype)init { self = [super init]; if (self) { - _sessionManager = [AFHTTPSessionManager manager]; _defaultPlayIndex = NSUIntegerMax; } return self; } -- (void)dealloc { - // [_sessionManager invalidateSessionCancelingTasks:YES]; - [_sessionManager invalidateSessionCancelingTasks:YES resetSession:NO]; -} - - (NSString *)playingDefinitionUrl { NSString *url; // 获取初始播放清晰度url @@ -87,123 +80,4 @@ - (NSInteger)playingDefinitionIndex { return 0; } -- (NSURLSessionTask *)requestWithCompletion:(void (^)(NSError *, SuperPlayerModel *model))completion { - AFHTTPSessionManager *manager = self.sessionManager; - int ver = self.videoId ? 4 : 2; - NSString * url = [NSString stringWithFormat:@"https://%@/getplayinfo/v%d/%ld/%@", kPlayCGIHostname, ver, self.appId, self.videoId ? self.videoId.fileId : self.videoIdV2.fileId]; - - // 防盗链参数 - NSDictionary *params = [self _buildParams]; - - __weak SuperPlayerModel *weakSelf = self; - - return [manager GET:url - parameters:params - headers:nil - progress:nil - success:^(NSURLSessionDataTask *_Nonnull task, id _Nullable responseObject) { - __strong SuperPlayerModel *self = weakSelf; -#if DEBUG - NSLog(@"%@", responseObject); -#endif - NSInteger code = [responseObject[@"code"] integerValue]; - if (code != 0) { - NSString *msg = responseObject[@"message"]; - NSString *requestID = responseObject[@"requestId"]; - NSString *warning = responseObject[@"warning"]; - NSError * error = [NSError errorWithDomain:kErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : msg, @"requestID" : requestID ?: @"", @"warning" : warning ?: @""}]; - if (completion) { - completion(error, self); - return; - } - return; - } - - NSInteger responseVersion = [responseObject[@"version"] integerValue]; - if (responseVersion == 0) { - responseVersion = 2; - } - Class parser = [SPPlayCGIParser parserOfVersion:responseVersion]; - SPPlayCGIParseResult * result = [parser parseResponse:responseObject]; - if (responseVersion <= 2) { - self.overlayKey = nil; - self.overlayIv = nil; - } - if (result == nil) { - if (completion) { - NSError *error = [NSError errorWithDomain:kErrorDomain code:kInvalidResponseErrorCode userInfo:@{NSLocalizedDescriptionKey : @"Invalid response."}]; - completion(error, self); - } - return; - } - self.drmType = result.drmType; - self.videoURL = result.url; - self.multiVideoURLs = result.multiVideoURLs; - self.keyFrameDescList = result.keyFrameDescList; - self.imageSprite = result.imageSprite; - - if (responseVersion == 4) { - self.drmToken = result.drmToken; - self.originalDuration = result.originalDuration; - } - if (completion) { - completion(nil, self); - } - } - failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) { - if (error.code != NSURLErrorCancelled) { - if (completion) { - completion(error, self); - } - } - }]; -} - -- (NSDictionary *)_buildParams { - NSMutableDictionary *params = [NSMutableDictionary new]; - if (self.videoId) { - if (self.videoId.psign) { - params[@"psign"] = self.videoId.psign; - self.overlayKey = [self _buildParamsRandomHexString]; - self.overlayIv = [self _buildParamsRandomHexString]; - NSString *cipheredOverlayKey = [self _buildParamsEncryptHexString:self.overlayKey]; - NSString *cipheredOverlayIv = [self _buildParamsEncryptHexString:self.overlayIv]; - if (cipheredOverlayKey.length > 0 && cipheredOverlayIv.length > 0) { - params[@"cipheredOverlayKey"] = cipheredOverlayKey; - params[@"cipheredOverlayIv"] = cipheredOverlayIv; - params[@"keyId"] = @"1"; - } - } - } else if (self.videoIdV2) { - if (self.videoIdV2.timeout) { - params[@"t"] = self.videoIdV2.timeout; - } - if (self.videoIdV2.us) { - params[@"us"] = self.videoIdV2.us; - } - if (self.videoIdV2.sign) { - params[@"sign"] = self.videoIdV2.sign; - } - if (self.videoIdV2.exper >= 0) { - params[@"exper"] = @(self.videoIdV2.exper); - } - } - return params; -} - -- (NSString *)_buildParamsRandomHexString -{ - int keyLen = 32; - NSMutableString *kenStr = [[NSMutableString alloc]initWithCapacity:keyLen]; - for (int i = 0; i < keyLen; i++) { - [kenStr appendFormat:@"%x", arc4random() % 16]; - } - return [kenStr copy]; -} - -- (NSString *)_buildParamsEncryptHexString:(NSString *)originHexStr -{ - return [TXVodPlayer getEncryptedPlayKey:originHexStr]; -} - @end diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModelInternal.h b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModelInternal.h index dc7103a..bdea524 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModelInternal.h +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerModelInternal.h @@ -10,7 +10,6 @@ #import "SPVideoFrameDescription.h" #import "SuperPlayerModel.h" #import "TXBitrateItem.h" -#import @class TXImageSprite; @@ -20,7 +19,6 @@ NS_ASSUME_NONNULL_BEGIN /// 播放配置, 为 nil 时为 "default" @property(copy, nonatomic) NSString *pcfg; -@property(strong, nonatomic) AFHTTPSessionManager *sessionManager; // 以下为 PlayCGI V4 协议解析结果 /// 正在播放的清晰度 @@ -44,9 +42,6 @@ NS_ASSUME_NONNULL_BEGIN /// 视频原时长(用于试看时返回完整视频时长) @property(assign, nonatomic) NSTimeInterval originalDuration; -/// 加载播放信息 -- (NSURLSessionTask *)requestWithCompletion:(void (^)(NSError *err, SuperPlayerModel *model))completion; - /// DRM Token @property(strong, nonatomic) NSString *drmToken; diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerView.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerView.m index d780d81..8cf64fe 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerView.m +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/SuperPlayerView.m @@ -257,27 +257,7 @@ - (void)_playWithModel:(SuperPlayerModel *)playerModel { _currentVideoUrl = nil; self.controlView.hidden = YES; - - NSString *videoURL = playerModel.playingDefinitionUrl; - if (videoURL != nil) { - [self configTXPlayer]; - } else if (playerModel.videoId || playerModel.videoIdV2) { - self.isLive = NO; - __weak __typeof(self) weakSelf = self; - _currentLoadingTask = [_playerModel requestWithCompletion:^(NSError *error, SuperPlayerModel *model) { - if (error) { - [weakSelf _onModelLoadFailed:model error:error]; - } else { - weakSelf.imageSprite = model.imageSprite; - weakSelf.keyFrameDescList = model.keyFrameDescList; - [weakSelf _onModelLoadSucceed:model]; - } - }]; - return; - } else { - NSLog(@"无播放地址"); - return; - } + [self configTXPlayer]; } - (void)_onModelLoadSucceed:(SuperPlayerModel *)model { @@ -575,9 +555,15 @@ - (void)configTXPlayer { self.liveProgressTime = self.maxLiveProgressTime = 0; - int liveType = [self livePlayerType]; - if (liveType >= 0) { - self.isLive = YES; + // 如果videoUrl存在,则是直播 + int liveType = -1; + if (self.playerModel.videoURL && self.playerModel.videoURL.length > 0) { + liveType = [self livePlayerType]; + if (liveType >= 0) { + self.isLive = YES; + } else { + self.isLive = NO; + } } else { self.isLive = NO; } @@ -585,7 +571,6 @@ - (void)configTXPlayer { self.isLoaded = NO; self.netWatcher.playerModel = self.playerModel; - NSString *videoURL = self.playerModel.playingDefinitionUrl; // 时移 [TXLiveBase setAppID:[NSString stringWithFormat:@"%ld", _playerModel.appId]]; if (self.isLive) { @@ -594,23 +579,39 @@ - (void)configTXPlayer { self.livePlayer.delegate = self; } [self setLivePlayerConfig]; - - [self.livePlayer startLivePlay:videoURL type:liveType]; - TXCUrl *curl = [[TXCUrl alloc] initWithString:videoURL]; + + [self.livePlayer startLivePlay:self.playerModel.videoURL type:liveType]; + _currentVideoUrl = self.playerModel.videoURL; + TXCUrl *curl = [[TXCUrl alloc] initWithString:self.playerModel.videoURL]; [self.livePlayer prepareLiveSeek:self.playerConfig.playShiftDomain bizId:curl.bizid]; } else { [self setVodPlayConfig]; - NSString *appParameter = [NSString stringWithFormat:@"spappid=%ld", self.playerModel.appId]; - NSString *fileidParameter = [NSString stringWithFormat:@"spfileid=%@", self.playerModel.videoId.fileId]; - NSString *drmtypeParameter = [NSString stringWithFormat:@"spdrmtype=%@", self.playerModel.drmType == SPDrmTypeSimpleAES ? @"SimpleAES" : @"plain"]; - NSString *vodParamVideoUrl = [NSString appendParameter:appParameter WithOriginUrl:videoURL]; - vodParamVideoUrl = [NSString appendParameter:fileidParameter WithOriginUrl:vodParamVideoUrl]; - vodParamVideoUrl = [NSString appendParameter:drmtypeParameter WithOriginUrl:vodParamVideoUrl]; - - [self preparePlayWithVideoUrl:([self isSupportAppendParam] ? vodParamVideoUrl : videoURL)]; - + NSString *videoUrlStr = _playerModel.videoURL; + if (videoUrlStr && videoUrlStr.length > 0) { + [self preparePlayWithUrl:videoUrlStr]; + } else { + NSArray *multiVideoURLs = _playerModel.multiVideoURLs; + if (multiVideoURLs.count > 0 && multiVideoURLs.firstObject) { + SuperPlayerUrl *videoUrl = multiVideoURLs.firstObject; + if (videoUrl.url && videoUrl.url.length > 0) { + [self preparePlayWithUrl:videoUrl.url]; + } else { + TXPlayerAuthParams *params = [[TXPlayerAuthParams alloc] init]; + params.appId = (int)_playerModel.appId; + params.fileId = _playerModel.videoId.fileId; + params.sign = _playerModel.videoId.psign; + [self preparePlayWithVideoParams:params]; + } + } else { + TXPlayerAuthParams *params = [[TXPlayerAuthParams alloc] init]; + params.appId = (int)_playerModel.appId; + params.fileId = _playerModel.videoId.fileId; + params.sign = _playerModel.videoId.psign; + [self preparePlayWithVideoParams:params]; + } + } } [self resetControlViewWithLive:self.isLive shiftPlayback:self.isShiftPlayback isPlaying:self.state == StatePlaying ? YES : NO]; self.controlView.playerConfig = self.playerConfig; @@ -679,8 +680,7 @@ - (void)setLivePlayerConfig { }]; } -- (void)preparePlayWithVideoUrl:(NSString *)videoUrl { - _currentVideoUrl = videoUrl; +- (void)preparePlayVideo { [self.controlView setProgressTime:0 totalTime:_playerModel.duration progressValue:0 playableValue:0 / _playerModel.duration]; if (_playerModel.action == PLAY_ACTION_AUTO_PLAY) { if (!SuperPlayerWindowShared.isShowing) { @@ -691,10 +691,8 @@ - (void)preparePlayWithVideoUrl:(NSString *)videoUrl { } self.isPauseByUser = NO; self.centerPlayBtn.hidden = YES; - [self startPlayWithUrl:videoUrl]; } else if (_playerModel.action == PLAY_ACTION_PRELOAD) { self.vodPlayer.isAutoPlay = NO; - [self startPlayWithUrl:videoUrl]; self.spinner.hidden = YES; self.centerPlayBtn.hidden = NO; self.coverImageView.hidden = NO; @@ -713,6 +711,33 @@ - (void)preparePlayWithVideoUrl:(NSString *)videoUrl { } } +- (void)preparePlayWithVideoParams:(TXPlayerAuthParams *)params { + [self preparePlayVideo]; + if (_playerModel.action == PLAY_ACTION_AUTO_PLAY || _playerModel.action == PLAY_ACTION_PRELOAD) { + [self.vodPlayer startVodPlayWithParams:params]; + } +} + +- (void)preparePlayWithUrl:(NSString *)videoUrl { + _currentVideoUrl = videoUrl; + [self preparePlayVideo]; + if (_playerModel.action == PLAY_ACTION_AUTO_PLAY || _playerModel.action == PLAY_ACTION_PRELOAD) { + [self.vodPlayer startVodPlay:videoUrl]; + } +} + +- (void)startPlay { + if (_currentVideoUrl) { + [self.vodPlayer startVodPlay:_currentVideoUrl]; + } else { + TXPlayerAuthParams *params = [[TXPlayerAuthParams alloc] init]; + params.appId = (int)_playerModel.appId; + params.fileId = _playerModel.videoId.fileId; + params.sign = _playerModel.videoId.psign; + [self.vodPlayer startVodPlayWithParams:params]; + } +} + - (void)setCoverImage { self.coverImageView.hidden = NO; NSURL *customUrl = [NSURL URLWithString:_playerModel.customCoverImageUrl]; @@ -722,21 +747,16 @@ - (void)setCoverImage { options:SDWebImageAvoidDecodeImage]; } -- (void)startPlayWithUrl:(NSString *)videoUrl { - [self.vodPlayer startVodPlay:videoUrl]; -} - - (void)restart { [self.spinner startAnimating]; self.centerPlayBtn.hidden = YES; self.repeatBtn.hidden = YES; self.playDidEnd = NO; - NSString *url = self.playerModel.playingDefinitionUrl; if ([self.vodPlayer supportedBitrates].count > 1) { [self.vodPlayer resume]; } else { - [self.vodPlayer startVodPlay:url]; + [self startPlay]; if (_playerModel.action == PLAY_ACTION_PRELOAD) { [self resume]; } @@ -757,7 +777,7 @@ - (void)controllViewPlayClick { if (_playerModel.action == PLAY_ACTION_MANUAL_PLAY) { [self showOrHideBackBtn:YES]; } - [self startPlayWithUrl:_currentVideoUrl]; + [self startPlay]; } else { [self resume]; } @@ -1715,10 +1735,9 @@ - (void)controlViewSwitch:(SuperPlayerControlView *)controlView withDefinition:( if ([self.playerModel.playingDefinition isEqualToString:definition]) return; self.playerModel.playingDefinition = definition; - NSString *url = self.playerModel.playingDefinitionUrl; if (self.isLive) { - [self.livePlayer switchStream:url]; + [self.livePlayer switchStream:_currentVideoUrl]; [self showMiddleBtnMsg:[NSString stringWithFormat:@"正在切换到%@...", definition] withAction:ActionNone]; } else { self.controlView.hidden = YES; @@ -1730,7 +1749,7 @@ - (void)controlViewSwitch:(SuperPlayerControlView *)controlView withDefinition:( [self.vodPlayer stopPlay]; self.state = StateStopped; [self.vodPlayer setStartTime:startTime]; - [self.vodPlayer startVodPlay:url]; + [self.vodPlayer startVodPlay:_currentVideoUrl]; if (_playerModel.action == PLAY_ACTION_PRELOAD) { [self resume]; } @@ -1885,6 +1904,13 @@ - (void)controlViewPreview:(SuperPlayerControlView *)controlView where:(CGFloat) - (void)controlViewPip:(UIView *)controlView { if (![TXVodPlayer isSupportPictureInPicture]) { + [self setPipLoadingWithText:superPlayerLocalized(@"SuperPlayer.notsupportpip")]; + [self.pipLoadingView startAnimating]; + + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (ino64_t)(0.5 * NSEC_PER_SEC)); + dispatch_after(time, dispatch_get_main_queue(), ^{ + [self.pipLoadingView stopAnimating]; + }); return; } @@ -2051,7 +2077,7 @@ - (void)onVodPlayEvent:(TXVodPlayer *)player event:(int)evtID withParam:(NSDicti } } -- (void)onNetStatus:(TXVodPlayer *)player withParam:(NSDictionary*)param +-(void) onNetStatus:(TXVodPlayer *)player withParam:(NSDictionary*)param { NSDictionary *dict = param; @@ -2203,7 +2229,7 @@ - (void)onLog:(NSString *)log LogLevel:(int)level WhichModule:(NSString *)module - (int)livePlayerType { int playType = -1; - NSString * videoURL = self.playerModel.playingDefinitionUrl; + NSString * videoURL = self.playerModel.videoURL; NSURLComponents *components = [NSURLComponents componentsWithString:videoURL]; NSString * scheme = [[components scheme] lowercaseString]; if ([scheme isEqualToString:@"rtmp"]) { diff --git a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/Utils/SuperPlayerReachability.m b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/Utils/SuperPlayerReachability.m index 67a875f..971ac25 100644 --- a/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/Utils/SuperPlayerReachability.m +++ b/Demo/TXLiteAVDemo/SuperPlayerKit/SuperPlayer/Utils/SuperPlayerReachability.m @@ -48,15 +48,9 @@ static void printReachabilityFlags(SCNetworkReachabilityFlags flags, const char* } -static void reachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +static void txSuperPlayerReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { -#pragma unused (target, flags) - NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); - NSCAssert([(__bridge NSObject*) info isKindOfClass: [SuperPlayerReachability class]], @"info was wrong class in ReachabilityCallback"); - - SuperPlayerReachability* noteObject = (__bridge SuperPlayerReachability *)info; - // Post a notification to notify the client that the network reachability changed. - [[NSNotificationCenter defaultCenter] postNotificationName: kTXSuperPlayerReachabilityChangedNotification object: noteObject]; + [[NSNotificationCenter defaultCenter] postNotificationName:kTXSuperPlayerReachabilityChangedNotification object:nil]; } @@ -128,9 +122,7 @@ + (instancetype)reachabilityForInternetConnection - (BOOL)startNotifier { BOOL returnValue = NO; - SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; - - if (SCNetworkReachabilitySetCallback(_reachabilityRef, reachabilityCallback, &context)) + if (SCNetworkReachabilitySetCallback(_reachabilityRef, txSuperPlayerReachabilityCallback, NULL)) { if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {