hyzp_ybqx-Commit001:代码刚转换好,编译通过

This commit is contained in:
WinUser01
2021-12-09 20:24:36 +08:00
commit 8c74b14e5c
800 changed files with 66912 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/flutter_export_environment.sh
@@ -0,0 +1,33 @@
//
// SuperPlayerView.h
//
// Created by Lijy91 on 2020/9/4.
//
#import <Flutter/Flutter.h>
#import "SuperPlayer.h"
NS_ASSUME_NONNULL_BEGIN
// FLTSuperPlayerViewController
@interface FLTSuperPlayerViewController : NSObject <FlutterPlatformView, FlutterStreamHandler, SuperPlayerDelegate>
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
- (UIView*)view;
@end
// FLTSuperPlayerViewFactory
@interface FLTSuperPlayerViewFactory : NSObject
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
@end
// FLTSuperPlayerView
@interface FLTSuperPlayerView : SuperPlayerView
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,322 @@
//
// FLTSuperPlayerView.m
//
// Created by Lijy91 on 2020/9/4.
//
#import "FLTSuperPlayerView.h"
// FLTSuperPlayerViewController
@implementation FLTSuperPlayerViewController {
UIView* _containerView;
FLTSuperPlayerView* _superPlayerView;
int64_t _viewId;
FlutterMethodChannel* _channel;
FlutterEventChannel* _eventChannel;
FlutterEventSink _eventSink;
}
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
if (self = [super init]) {
_viewId = viewId;
NSString* channelName = [NSString stringWithFormat:@"leanflutter.org/superplayer_view/channel_%lld", viewId];
_channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger];
NSString* eventChannelName = [NSString stringWithFormat:@"leanflutter.org/superplayer_view/event_channel_%lld", viewId];
_eventChannel = [FlutterEventChannel eventChannelWithName:eventChannelName
binaryMessenger:messenger];
[_eventChannel setStreamHandler:self];
__weak __typeof__(self) weakSelf = self;
[_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[weakSelf onMethodCall:call result:result];
}];
_containerView = [[UIView alloc] initWithFrame:frame];
_superPlayerView = [[FLTSuperPlayerView alloc] init];
_superPlayerView.fatherView = _containerView;
_superPlayerView.delegate = self;
[self setControlViewType:args[@"controlViewType"]];
}
return self;
}
- (UIView*)view {
return _containerView;
}
- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
_eventSink = eventSink;
return nil;
}
- (FlutterError*)onCancelWithArguments:(id)arguments {
_eventSink = nil;
return nil;
}
- (void)setControlViewType:(NSString *)controlViewType
{
if ([controlViewType isEqualToString:@"without"]) {
_superPlayerView.controlView = [[SPWithoutControlView alloc] initWithFrame:CGRectZero];
} else {
_superPlayerView.controlView = [[SPDefaultControlView alloc] initWithFrame:CGRectZero];
}
}
- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([[call method] isEqualToString:@"getPlayMode"]) {
[self getPlayMode:call result: result];
} else if ([[call method] isEqualToString:@"getPlayState"]) {
[self getPlayState:call result: result];
} else if ([[call method] isEqualToString:@"getPlayRate"]) {
[self getPlayRate:call result: result];
} else if ([[call method] isEqualToString:@"setPlayRate"]) {
[self setPlayRate:call result: result];
} else if ([[call method] isEqualToString:@"resetPlayer"]) {
[self resetPlayer:call result: result];
} else if ([[call method] isEqualToString:@"requestPlayMode"]) {
[self requestPlayMode:call result: result];
} else if ([[call method] isEqualToString:@"playWithModel"]) {
[self playWithModel:call result: result];
} else if ([[call method] isEqualToString:@"pause"]) {
[self pause:call result: result];
} else if ([[call method] isEqualToString:@"resume"]) {
[self resume:call result: result];
} else if ([[call method] isEqualToString:@"release"]) {
[self release:call result: result];
} else if ([[call method] isEqualToString:@"seekTo"]) {
[self seekTo:call result: result];
} else if ([[call method] isEqualToString:@"setLoop"]) {
[self setLoop:call result: result];
} else if ([[call method] isEqualToString:@"uiHideDanmu"]) {
[self uiHideDanmu:call result: result];
} else if ([[call method] isEqualToString:@"uiHideReplay"]) {
[self uiHideReplay:call result: result];
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)getPlayMode:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView setPlayerConfig:nil];
}
- (void)getPlayState:(FlutterMethodCall*)call
result:(FlutterResult)result
{
result([NSNumber numberWithInt:_superPlayerView.state]);
}
- (void)getPlayRate:(FlutterMethodCall*)call
result:(FlutterResult)result
{
CGFloat playRate = [[_superPlayerView playerConfig] playRate];
result([NSNumber numberWithDouble:playRate]);
}
- (void)setPlayRate:(FlutterMethodCall*)call
result:(FlutterResult)result
{
NSNumber *playRate = call.arguments[@"playRate"];
[_superPlayerView setPlayRate:playRate.floatValue];
}
- (void)resetPlayer:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView resetPlayer];
}
- (void)requestPlayMode:(FlutterMethodCall*)call
result:(FlutterResult)result
{
// skip
}
- (void)playWithModel:(FlutterMethodCall*)call
result:(FlutterResult)result
{
SuperPlayerModel *model = [[SuperPlayerModel alloc] init];
NSNumber *appId = call.arguments[@"appId"];
NSString *url = call.arguments[@"url"];
if (appId)
[model setAppId: appId.longValue];
if (url)
[model setVideoURL:url];
NSDictionary *videoIdJson = call.arguments[@"videoId"];
if (videoIdJson) {
NSString *fileId = videoIdJson[@"fileId"];
SuperPlayerVideoId *videoId = [[SuperPlayerVideoId alloc] init];
if (fileId)
[videoId setFileId:fileId];
[model setVideoId:videoId];
}
[_superPlayerView playWithModel:model];
}
- (void)pause:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView pause];
}
- (void)resume:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView resume];
}
- (void)release:(FlutterMethodCall*)call
result:(FlutterResult)result
{
// skip
}
- (void)seekTo:(FlutterMethodCall*)call
result:(FlutterResult)result
{
NSNumber *time = call.arguments[@"time"];
[_superPlayerView seekToTime:time.intValue];
}
- (void)setLoop:(FlutterMethodCall*)call
result:(FlutterResult)result
{
NSNumber *isLoop = call.arguments[@"isLoop"];
[_superPlayerView setLoop:isLoop.boolValue];
}
- (void) uiHideDanmu:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView uiHideDanmu];
}
- (void) uiHideReplay:(FlutterMethodCall*)call
result:(FlutterResult)result
{
[_superPlayerView uiHideReplay];
}
/// 返回事件
- (void)superPlayerBackAction:(SuperPlayerView *)player {
NSDictionary<NSString *, id> *eventData = @{
@"listener": @"SuperPlayerListener",
@"method": @"onClickSmallReturnBtn",
};
self->_eventSink(eventData);
}
/// 全屏改变通知
- (void)superPlayerFullScreenChanged:(SuperPlayerView *)player {
NSDictionary<NSString *, id> *eventData = @{
@"listener": @"SuperPlayerListener",
@"method": @"onFullScreenChange",
@"data": @{
@"isFullScreen": [NSNumber numberWithBool:[player isFullScreen]],
},
};
self->_eventSink(eventData);
}
/// 播放开始通知
- (void)superPlayerDidStart:(SuperPlayerView *)player {
}
/// 播放结束通知
- (void)superPlayerDidEnd:(SuperPlayerView *)player {
}
/// 播放错误通知
- (void)superPlayerError:(SuperPlayerView *)player errCode:(int)code errMessage:(NSString *)why {
}
/// 播放状态发生变化
- (void)onPlayStateChange:(int) playState {
NSDictionary<NSString *, id> *eventData = @{
@"listener": @"SuperPlayerListener",
@"method": @"onPlayStateChange",
@"data": @{
@"playState": [NSNumber numberWithInt:playState],
},
};
self->_eventSink(eventData);
}
/// 播放进度发生变化
- (void)onPlayProgressChange:(int) current duration:(int) duration {
NSDictionary<NSString *, id> *eventData = @{
@"listener": @"SuperPlayerListener",
@"method": @"onPlayProgressChange",
@"data": @{
@"current": [NSNumber numberWithInt:current],
@"duration": [NSNumber numberWithInt:duration],
},
};
self->_eventSink(eventData);
}
@end
// FLTSuperPlayerViewFactory
@implementation FLTSuperPlayerViewFactory{
NSObject<FlutterBinaryMessenger>* _messenger;
}
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
self = [super init];
if (self) {
_messenger = messenger;
}
return self;
}
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
return [FlutterStandardMessageCodec sharedInstance];
}
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args {
FLTSuperPlayerViewController* superPlayerViewController = [[FLTSuperPlayerViewController alloc] initWithFrame:frame
viewIdentifier:viewId
arguments:args
binaryMessenger:_messenger];
return superPlayerViewController;
}
@end
// FLTSuperPlayerView
@implementation FLTSuperPlayerView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
}
@end
@@ -0,0 +1,5 @@
#import <Flutter/Flutter.h>
#import "FLTSuperPlayerView.h"
@interface FlutterSuperplayerPlugin : NSObject<FlutterPlugin>
@end
@@ -0,0 +1,23 @@
#import "FlutterSuperplayerPlugin.h"
@implementation FlutterSuperplayerPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_superplayer"
binaryMessenger:[registrar messenger]];
FlutterSuperplayerPlugin* instance = [[FlutterSuperplayerPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
FLTSuperPlayerViewFactory* platformViewFactory = [[FLTSuperPlayerViewFactory alloc] initWithMessenger:registrar.messenger];
[registrar registerViewFactory:platformViewFactory withId:@"leanflutter.org/superplayer_view"];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getSDKVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
@@ -0,0 +1,31 @@
//
// NSString+URL.h
// SuperPlayer
//
// Created by xcoderliu on 12/10/20.
// Copyright © 2020 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (URL)
/// 获取 URL GET 参数
/// @param parameter key
/// @param originUrl url
+ (NSString *)getParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl;
/// 删除 URL GET 参数
/// @param parameter key
/// @param originUrl url
+ (NSString *)deleteParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl;
/// 追加 URL GET 参数
/// @param queryString (@"key=value")
/// @param originUrl url
+ (NSString *)appendParameter:(NSString *)queryString WithOriginUrl:(NSString *)originUrl;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,54 @@
//
// NSString+URL.m
// SuperPlayer
//
// Created by xcoderliu on 12/10/20.
// Copyright © 2020 annidy. All rights reserved.
//
#import "NSString+URL.h"
@implementation NSString (URL)
+ (NSString *)getParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl {
NSError *error;
if (originUrl.length == 0) {
return @"";
}
NSString *regTags = [[NSString alloc] initWithFormat:@"(^|&|\\?)+%@=+([^&]*)(&|$)",parameter];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regTags options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:originUrl options:0 range:NSMakeRange(0, [originUrl length])];
for (NSTextCheckingResult *match in matches) {
NSString *tagValue = [originUrl substringWithRange:[match rangeAtIndex:2]];
return tagValue;
}
return @"";
}
+ (NSString *)deleteParameter:(NSString *)parameter WithOriginUrl:(NSString *)originUrl {
NSString *finalStr = [NSString string];
NSMutableString * mutStr = [NSMutableString stringWithString:originUrl];
NSArray *strArray = [mutStr componentsSeparatedByString:parameter];
NSMutableString *firstStr = [strArray objectAtIndex:0];
NSMutableString *lastStr = [strArray lastObject];
NSRange characterRange = [lastStr rangeOfString:@"&"];
if (characterRange.location !=NSNotFound) {
NSArray *lastArray = [lastStr componentsSeparatedByString:@"&"];
NSMutableArray *mutArray = [NSMutableArray arrayWithArray:lastArray];
[mutArray removeObjectAtIndex:0];
NSString *modifiedStr = [mutArray componentsJoinedByString:@"&"];
finalStr = [[strArray objectAtIndex:0]stringByAppendingString:modifiedStr];
} else {
finalStr = [firstStr substringToIndex:[firstStr length] -1];
}
return finalStr;
}
+ (NSString *)appendParameter:(NSString *)queryString WithOriginUrl:(NSString *)originUrl {
if (![queryString length]) {
return originUrl;
}
return [NSString stringWithFormat:@"%@%@%@", originUrl,
[originUrl rangeOfString:@"?"].length > 0 ? @"&" : @"?", queryString];
}
@end
@@ -0,0 +1,6 @@
#import <UIKit/UIKit.h>
@interface UINavigationController (SuperPlayerRotation)<UIGestureRecognizerDelegate>
@end
@@ -0,0 +1,34 @@
#import "UINavigationController+SuperPlayerRotation.h"
#import <objc/runtime.h>
@implementation UINavigationController (SuperPlayerRotation)
/**
* 如果window的根视图是UINavigationController,则会先调用这个Category,然后调用UIViewController+SuperPlayerRotation
* 只需要在支持除竖屏以外方向的页面重新下边三个方法
*/
// 是否支持自动转屏
- (BOOL)shouldAutorotate {
return [self.topViewController shouldAutorotate];
}
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
- (UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
@@ -0,0 +1,93 @@
//
// UIView+MM.h
/*
杜蒙 iOS开发
annidy
*/
#define m_weakify(object) autoreleasepool {} __weak typeof(object) weak##object = object
#define m_strongify(object) autoreleasepool {} __strong typeof(weak##object) object = weak##object
#import <UIKit/UIKit.h>
@class MMLayout;
@interface UIView (Layout)
@property (strong , nonatomic , readonly) MMLayout *mm_selfLayout;
- (void)setMm_x:(CGFloat)mm_x; ///<< set frame.x
- (CGFloat)mm_x; ///<< get frame.x
- (void)setMm_y:(CGFloat)mm_y; ///<< set frame.y
- (CGFloat)mm_y; ///<< get frame.y
- (void)setMm_w:(CGFloat)mm_w; ///<< set frame.bounds.size.width
- (CGFloat)mm_w; ///<< get frame.bounds.size.width
- (void)setMm_h:(CGFloat)mm_h; ///<< set frame.bounds.size.height
- (CGFloat)mm_h; ///<< get frame.bounds.size.height
- (void)setMm_center:(CGPoint )mm_center; ///<< set frame.origin
- (CGPoint)mm_center; ///<< get frame origin
- (CGFloat)mm_centerX; ///<< get self.center.x
- (CGFloat)mm_centerY; ///<< get self.center.y
- (CGFloat)mm_maxY; ///<< get CGRectGetMaxY
- (CGFloat)mm_minY; ///<< get CGRectGetMinY
- (CGFloat)mm_maxX; ///<< get CGRectGetMaxX
- (CGFloat)mm_minX; ///<< get CGRectGetMinX
- (CGFloat)mm_halfW; ///<< get self.width / 2
- (CGFloat)mm_halfH; ///<< get self.height / 2
- (CGFloat)mm_halfX; ///<< get self.x / 2
- (CGFloat)mm_halfY; ///<< get self.y / 2
- (CGFloat)mm_halfCenterX; ///<< get self.centerX / 2
- (CGFloat)mm_halfCenterY; ///<< get self.centerY / 2
- (void)setMm_size:(CGSize)mm_size;
- (CGSize)mm_size; ///<< get self.bounds.size
// iPhoneX adapt
@property (readonly) CGFloat mm_safeAreaBottomGap;
@property (readonly) CGFloat mm_safeAreaTopGap;
@property (readonly) CGFloat mm_safeAreaLeftGap;
@property (readonly) CGFloat mm_safeAreaRightGap;
/*
示例链接编程
self.m_width(100).m_height(100).m_left(10).m_top(10)
*/
- (UIView * (^)(CGFloat top))m_top; ///< set frame y
- (UIView * (^)(CGFloat right))m_flexToTop; ///< set frame y by change height
- (UIView * (^)(CGFloat bottom))m_bottom; ///< set frame y
- (UIView * (^)(CGFloat right))m_flexToBottom; ///< set frame y by change height
- (UIView * (^)(CGFloat left))m_left; ///< set frame x
- (UIView * (^)(CGFloat right))m_flexToLeft; ///< set frame right by chang width
- (UIView * (^)(CGFloat right))m_right; ///< set frame x
- (UIView * (^)(CGFloat right))m_flexToRight; ///< set frame right by chang width
- (UIView * (^)(CGFloat width))m_width; ///< set frame width
- (UIView * (^)(CGFloat height))m_height; ///< set frame height
- (UIView * (^)(CGSize size))m_size; ///< set frame size
- (UIView * (^)(CGPoint center))m__center; ///< set frame center point
- (UIView * (^)(void))m_center; ///< set frame center 前提是有w h 调用次方法居中父类
- (UIView * (^)(void))m_centerY; ///< set frame Ycenter 前提是有h调用次方法居中父类
- (UIView * (^)(void))m_centerX; ///< set frame Xcenter 前提是有w调用次方法居中父类
/*
相对父View
*/
-(UIView *(^)(void))m_fill; ///< 填充
- (UIView * (^)(UIView *obj))m_equalToFrame; /// equalTo frame
- (UIView * (^)(UIView *obj))m_equalToTop; /// equalTo top
- (UIView * (^)(UIView *obj))m_equalToBottom; /// equalTo Bottom
- (UIView * (^)(UIView *obj))m_equalToLeft; /// equalTo left
- (UIView * (^)(UIView *obj))m_equalToRight; /// equalTo right
- (UIView * (^)(UIView *obj))m_equalToWidth; /// equalTo width
- (UIView * (^)(UIView *obj))m_equalToHeight; /// equalTo height
- (UIView * (^)(UIView *obj))m_equalToSize; /// equalTo size
- (UIView * (^)(UIView *obj))m_equalToCenter; /// equalTo center
- (UIView * (^)(void))m_sizeToFit; /// call sizeToFit
- (NSData *)mm_createPDF;/// create self PDF
- (UIViewController *)viewController; //self Responder UIViewControler
@end
@@ -0,0 +1,525 @@
#import "UIView+MMLayout.h"
#import <objc/runtime.h>
#pragma mark - MMLayout
@interface MMLayout : NSObject
/*
@LayoutView 传入进去 View
*/
-(instancetype)initWithLayoutView:(UIView *)LayoutView;
@property (assign , nonatomic) CGFloat top; ///<< frame y
@property (assign , nonatomic) CGFloat bottom; ///<< y = super.h - LayoutView.h - bottom
@property (assign , nonatomic) CGFloat left; ///<< frame x
@property (assign , nonatomic) CGFloat right; ///<< x = super.w - LayoutView.h - right
@property (assign , nonatomic) CGFloat width; ///<< frame w
@property (assign , nonatomic) CGFloat height; ///<< frame height
@property (assign , nonatomic) CGSize size; ///<< frame bounds size width height
@property (assign , nonatomic) CGPoint point; ///<< frame point
- (void)center; ///<<调用此方法前必须先设置自己的宽高 (默认是居中父控件)
- (void)centerX; ///<<调用此方法前必须先设置自己的宽 (默认是居中父控件)
- (void)centerY; ///<<调用此方法前必须先设置自己的高 (默认是居中父控件)
@property (weak , nonatomic) UIView *layoutView;
@end
@implementation MMLayout
-(instancetype)initWithLayoutView:(UIView *)LayoutView{
if (self=[super init]) {
self.layoutView = LayoutView;
}
return self;
}
-(void)setLeft:(CGFloat)left{
CGRect frame = self.layoutView.frame;
frame.origin.x = left;
self.layoutView.frame = frame;
}
- (CGFloat)left {
return self.layoutView.frame.origin.x;
}
-(void)setTop:(CGFloat)top{
_top = top;
CGRect frame = self.layoutView.frame;
frame.origin.y = top;
self.layoutView.frame = frame;
}
-(void)setRight:(CGFloat)right{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_w - self.layoutView.mm_w - right;
}
- (CGFloat)right {
UIView *superview = self.layoutView.superview;
return superview.mm_w - self.layoutView.mm_x - self.layoutView.mm_w;
}
-(void)setBottom:(CGFloat)bottom{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_y = superview.mm_h - self.layoutView.mm_h - bottom;
}
- (CGFloat)bottom {
UIView *superview = self.layoutView.superview;
return superview.mm_h - self.layoutView.mm_maxY;
}
-(void)setHeight:(CGFloat)height{
_height = height;
CGRect frame = self.layoutView.frame;
frame.size.height = height;
self.layoutView.frame = frame;
}
-(void)setWidth:(CGFloat)width{
_width = width;
CGRect frame = self.layoutView.frame;
frame.size.width = width;
self.layoutView.frame = frame;
}
-(void)setPoint:(CGPoint)point{
CGRect frame = self.layoutView.frame;
frame.origin = point;
self.layoutView.frame = frame;
}
-(CGPoint)point{
return CGPointMake(self.layoutView.mm_x, self.layoutView.mm_w);
}
-(void)setSize:(CGSize )size{
CGRect frame = self.layoutView.frame;
frame.size = size;
self.layoutView.frame = frame;
}
-(CGSize)size{
return self.layoutView.mm_size;
}
-(void)setCenter:(CGPoint)center{
CGRect frame = self.layoutView.frame;
frame.origin = CGPointMake(center.x-frame.size.width/2, center.y-frame.size.height/2);
self.layoutView.frame = frame;
}
-(void)center{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_halfW - self.layoutView.mm_halfW;
self.layoutView.mm_y = superview.mm_halfH - self.layoutView.mm_halfH;
}
-(void)centerY{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_y = superview.mm_halfH - self.layoutView.mm_halfH;
}
-(void)centerX{
UIView *superview = self.layoutView.superview;
self.layoutView.mm_x = superview.mm_halfW - self.layoutView.mm_halfW;
}
@end
const void *_layoutKey;
@implementation UIView (Layout)
#pragma mark - frame
- (void)setMm_x:(CGFloat)mm_x{
[self mm_selfLayout].left = mm_x;
}
- (CGFloat)mm_x{
return self.frame.origin.x;
}
- (void)setMm_y:(CGFloat)mm_y{
[self mm_selfLayout].top = mm_y;
}
- (CGFloat)mm_y{
return self.frame.origin.y;
}
- (void)setMm_w:(CGFloat)mm_w{
[self mm_selfLayout].width = mm_w;
}
- (CGFloat)mm_w{
return self.frame.size.width;
}
- (void)setMm_h:(CGFloat)mm_h{
[self mm_selfLayout].height = mm_h;
}
- (CGFloat)mm_h{
return self.frame.size.height;
}
-(void)setMm_center:(CGPoint)mm_center{
[self mm_selfLayout].point = mm_center;
}
-(CGPoint)mm_center{
return self.frame.origin;
}
-(CGFloat)mm_centerX{
return self.center.x;
}
-(CGFloat)mm_centerY{
return self.center.y;
}
- (CGFloat)mm_maxY{
return CGRectGetMaxY(self.frame);
}
- (CGFloat)mm_minY{
return CGRectGetMinY(self.frame);
}
- (CGFloat)mm_maxX{
return CGRectGetMaxX(self.frame);
}
- (CGFloat)mm_minX{
return CGRectGetMinX(self.frame);
}
- (CGFloat)mm_halfW{
return self.mm_w / 2;
}
- (CGFloat)mm_halfH{
return self.mm_h / 2;
}
- (CGFloat)mm_halfX{
return self.mm_x / 2;
}
- (CGFloat)mm_halfY{
return self.mm_y / 2;
}
-(CGFloat)mm_halfCenterX{
return self.mm_centerX / 2;
}
-(CGFloat)mm_halfCenterY{
return self.mm_centerY / 2;
}
-(void)setMm_size:(CGSize)mm_size{
[self mm_selfLayout].size = mm_size;
}
-(CGSize)mm_size{
return self.bounds.size;
}
#pragma mark - set_ frame
- (MMLayout *)mm_selfLayout{
MMLayout *layout = objc_getAssociatedObject(self, &_layoutKey);
if (layout == nil) {
layout = [[MMLayout alloc] initWithLayoutView:self];
objc_setAssociatedObject(self, &_layoutKey, layout, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return layout;
}
-(UIView *(^)(CGFloat))m_top{
@m_weakify(self);
return ^(CGFloat m_top){
@m_strongify(self);
[self mm_selfLayout].top = m_top;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToTop{
@m_weakify(self);
return ^(CGFloat m_flexToTop){
@m_strongify(self);
CGFloat top = [self mm_selfLayout].top;
[self mm_selfLayout].top = m_flexToTop;
[self mm_selfLayout].height += top-m_flexToTop;
return self;
};
}
-(UIView *(^)(CGFloat))m_bottom{
@m_weakify(self);
return ^(CGFloat m_bottom){
@m_strongify(self);
[self mm_selfLayout].bottom = m_bottom;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToBottom{
@m_weakify(self);
return ^(CGFloat m_flexToBottom){
@m_strongify(self);
CGFloat bottom = [self mm_selfLayout].bottom;
[self mm_selfLayout].height += bottom-m_flexToBottom;
return self;
};
}
-(UIView *(^)(CGFloat))m_left{
@m_weakify(self);
return ^(CGFloat m_left){
@m_strongify(self);
[self mm_selfLayout].left = m_left;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToLeft{
@m_weakify(self);
return ^(CGFloat m_flexToLeft){
@m_strongify(self);
CGFloat left = [self mm_selfLayout].left;
[self mm_selfLayout].left = m_flexToLeft;
[self mm_selfLayout].width += left-m_flexToLeft;
return self;
};
}
-(UIView *(^)(CGFloat))m_right{
@m_weakify(self);
return ^(CGFloat m_right){
@m_strongify(self);
[self mm_selfLayout].right = m_right;
return self;
};
}
-(UIView *(^)(CGFloat))m_flexToRight{
@m_weakify(self);
return ^(CGFloat m_flexToRight){
@m_strongify(self);
CGFloat right = [self mm_selfLayout].right;
[self mm_selfLayout].width += right-m_flexToRight;
return self;
};
}
-(UIView *(^)(CGFloat))m_width{
@m_weakify(self);
return ^(CGFloat m_width){
@m_strongify(self);
[self mm_selfLayout].width = m_width;
return self;
};
}
-(UIView *(^)(CGFloat))m_height{
@m_weakify(self);
return ^(CGFloat m_height){
@m_strongify(self);
[self mm_selfLayout].height = m_height;
return self;
};
}
-(UIView *(^)(CGSize))m_size{
@m_weakify(self);
return ^(CGSize m_size){
@m_strongify(self);
[self mm_selfLayout].size = m_size;
return self;
};
}
- (UIView *(^)(CGPoint))m__center{
@m_weakify(self);
return ^(CGPoint m__center){
@m_strongify(self);
[self mm_selfLayout].center = m__center;
return self;
};
}
-(UIView *(^)(void))m_center{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] center];
return self;
};
}
-(UIView *(^)(void))m_centerY{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] centerY];
return self;
};
}
-(UIView *(^)(void))m_centerX{
@m_weakify(self);
return ^{
@m_strongify(self);
[[self mm_selfLayout] centerX];
return self;
};
}
-(UIView *(^)(void))m_fill {
@m_weakify(self);
return ^{
@m_strongify(self);
if (self.superview) {
self.mm_x = self.mm_y = 0;
self.mm_w = self.superview.mm_w;
self.mm_h = self.superview.mm_h;
}
return self;
};
}
#pragma mark - m_equalTo
-(UIView *(^)(UIView *))m_equalToFrame{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.frame = obj.frame;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToTop{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.top = obj.mm_selfLayout.top;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToBottom{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.bottom = obj.mm_selfLayout.bottom;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToLeft{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.left = obj.mm_selfLayout.left;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToRight{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.right = obj.mm_selfLayout.right;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToWidth{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.width = obj.mm_selfLayout.width;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToHeight{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
self.mm_selfLayout.height = obj.mm_selfLayout.height;
return self;
};
}
-(UIView *(^)(UIView *))m_equalToSize{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
[self mm_selfLayout].size = obj.mm_selfLayout.size;
return self;
};
}
- (UIView *(^)(UIView *))m_equalToCenter{
@m_weakify(self);
return ^(UIView *obj){
@m_strongify(self);
[self mm_selfLayout].point = obj.mm_selfLayout.point;
return self;
};
}
- (UIView *(^)(void))m_sizeToFit{
@m_weakify(self);
return ^(void){
@m_strongify(self);
[self sizeToFit];
return self;
};
}
- (NSData *)mm_createPDF{
CGRect bounds = self.bounds;
NSMutableData *data = [NSMutableData data];
CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((__bridge CFMutableDataRef)data);
CGContextRef context = CGPDFContextCreate(consumer, &bounds, NULL);
CGDataConsumerRelease(consumer);
if (!context) return nil;
CGPDFContextBeginPage(context, NULL);
CGContextTranslateCTM(context, 0, bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[self.layer renderInContext:context];
CGPDFContextEndPage(context);
CGPDFContextClose(context);
CGContextRelease(context);
return data;
}
- (UIViewController *)viewController {
UIView *view = self;
while (view) {
UIResponder *nextResponder = [view nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
view = view.superview;
}
return nil;
}
static void *kUIViewLayoutMethodPropertyBottomGap = &kUIViewLayoutMethodPropertyBottomGap;
static void *kUIViewLayoutMethodPropertyTopGap = &kUIViewLayoutMethodPropertyTopGap;
static void *kUIViewLayoutMethodPropertyLeftGap = &kUIViewLayoutMethodPropertyLeftGap;
static void *kUIViewLayoutMethodPropertyRightGap = &kUIViewLayoutMethodPropertyRightGap;
- (CGFloat)mm_safeAreaBottomGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
if (self.superview.safeAreaLayoutGuide.layoutFrame.size.height > 0) {
gap = @((self.superview.mm_h - self.superview.safeAreaLayoutGuide.layoutFrame.origin.y - self.superview.safeAreaLayoutGuide.layoutFrame.size.height));
} else {
gap = nil;
}
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyBottomGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaTopGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.y);
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyTopGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaLeftGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @(self.superview.safeAreaLayoutGuide.layoutFrame.origin.x);
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyLeftGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
- (CGFloat)mm_safeAreaRightGap
{
NSNumber *gap = objc_getAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap);
if (gap == nil) {
if (@available(iOS 11, *)) {
gap = @((self.superview.mm_w - self.superview.safeAreaLayoutGuide.layoutFrame.origin.x - self.superview.safeAreaLayoutGuide.layoutFrame.size.width));
} else {
gap = @(0);
}
objc_setAssociatedObject(self, kUIViewLayoutMethodPropertyRightGap, gap, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return gap.floatValue;
}
@end
@@ -0,0 +1,5 @@
#import <UIKit/UIKit.h>
@interface UIViewController (SuperPlayerRotation)
@end
@@ -0,0 +1,19 @@
#import "UIViewController+SuperPlayerRotation.h"
@implementation UIViewController (SuperPlayerRotation)
/**
* 默认所有都不支持转屏,如需个别页面支持除竖屏外的其他方向,请在viewController重新下边这三个方法
*/
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
@end
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -0,0 +1,18 @@
//
// AdaptiveStream.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface AdaptiveStream : NSObject
@property NSString *url;
@property NSString *drmType;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// AdaptiveStream.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "AdaptiveStream.h"
@implementation AdaptiveStream
@end
@@ -0,0 +1,69 @@
//
// SPPlayCGIParseResult.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
//#import "SPResolutionDefination.h"
#import "SPSubStreamInfo.h"
#import "AdaptiveStream.h"
#import "SuperPlayerSprite.h"
#import "SPVideoFrameDescription.h"
#import "SuperPlayerUrl.h"
@class TXImageSprite;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, SPDrmType) {
SPDrmTypeNone,
SPDrmTypeSimpleAES
};
@interface SPPlayCGIParseResult : NSObject
/// 视频播放url
@property (strong, nonatomic) NSString *url;
/// 视频名称
@property (strong, nonatomic) NSString *name;
/// 雪略图对象
@property (strong, nonatomic) TXImageSprite *imageSprite;
/// 雪略图打点帧信息
@property (strong, nonatomic) NSArray<SPVideoFrameDescription *> *keyFrameDescList;
/// 字流画质信息
@property (strong, nonatomic) NSArray<SPSubStreamInfo *> *resolutionArray;
/// 原视频时长
@property (assign, nonatomic) NSTimeInterval originalDuration;
/// 预留字段,暂不使用
@property (strong, nonatomic) NSArray<AdaptiveStream *> *adaptiveStreamArray;
/// V2协议的多码率URL列表
@property (strong, nonatomic) NSArray<SuperPlayerUrl *> *multiVideoURLs;
/// 加密类型,用于 Drm
@property (assign, nonatomic) SPDrmType drmType;
/// 加密令牌,用于 Drm
@property (copy, nonatomic) NSString *drmToken;
+ (SPDrmType)drmTypeFromString:(NSString *)typeString;
/**
* 获取画质信息
*
* @return 画质信息数组
List<TCVideoQuality> getVideoQualityList();
* 获取默认画质信息
*
* @return 默认画质信息对象
TCVideoQuality getDefaultVideoQuality();
*/
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,20 @@
//
// SPPlayCGIParseResult.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParseResult.h"
#import "TXImageSprite.h"
@implementation SPPlayCGIParseResult
+ (SPDrmType)drmTypeFromString:(NSString *)typeString {
BOOL isSimpleAES = [typeString caseInsensitiveCompare:@"SimpleAES"] == NSOrderedSame;
if (isSimpleAES) {
return SPDrmTypeSimpleAES;
}
return SPDrmTypeNone;
}
@end
@@ -0,0 +1,22 @@
//
// SPSubStreamInfo.h
// SuperPlayer
//
// Created by Steven Choi on 2020/2/11.
// Copyright © 2020 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
/// 自适应码流子流信息
@interface SPSubStreamInfo : NSObject
@property (assign, nonatomic) CGSize size;
@property (copy, nonatomic) NSString *resolutionName;
@property (copy, nonatomic) NSString *type;
+ (instancetype)infoWithDictionary:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,21 @@
//
// SPSubStreamInfo.m
// SuperPlayer
//
// Created by Steven Choi on 2020/2/11.
// Copyright © 2020 annidy. All rights reserved.
//
#import "SPSubStreamInfo.h"
#import "J2Obj.h"
@implementation SPSubStreamInfo
+ (instancetype)infoWithDictionary:(NSDictionary *)dict {
SPSubStreamInfo *info = [[SPSubStreamInfo alloc] init];
double width = [J2Num(dict[@"width"]) doubleValue];
double height = [J2Num(dict[@"height"]) doubleValue];
info.size = CGSizeMake(width, height);
info.resolutionName = J2Str(dict[@"name"]);
info.type = J2Str(dict[@"type"]);
return info;
}
@end
@@ -0,0 +1,21 @@
//
// SPVideoFrameDescription.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SPVideoFrameDescription : NSObject
// updates in SuperPlayerView
@property double where;
@property NSString *text;
@property double time;
+ (instancetype)instanceFromDictionary:(NSDictionary *)dict;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,22 @@
//
// SPVideoFrameDescription.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPVideoFrameDescription.h"
#import "J2Obj.h"
@implementation SPVideoFrameDescription
+ (instancetype)instanceFromDictionary:(NSDictionary *)keyFrameDesc {
if (![keyFrameDesc isKindOfClass:[NSDictionary class]]) {
return nil;
}
SPVideoFrameDescription *ret = [[SPVideoFrameDescription alloc] init];
ret.time = [J2Num([keyFrameDesc valueForKeyPath:@"timeOffset"]) intValue]/1000.0;
ret.text = [J2Str([keyFrameDesc valueForKeyPath:@"content"]) stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return ret;
}
@end
@@ -0,0 +1,18 @@
//
// SuperPlayerSprite.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SuperPlayerSprite : NSObject
@property (strong, nonatomic) NSArray<NSString *> *imageURLs;
@property (strong, nonatomic) NSString *webVttURL;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// SuperPlayerSprite.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SuperPlayerSprite.h"
@implementation SuperPlayerSprite
@end
@@ -0,0 +1,23 @@
//
// SuperPlayerUrl.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
* 多码率地址
* 用于有多个播放地址的多清晰度视频的播放
*/
@interface SuperPlayerUrl : NSObject
/// 播放器展示的对应标题,如“高清”、“低清”等
@property NSString *title;
/// 播放地址
@property NSString *url;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,13 @@
//
// SuperPlayerUrl.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SuperPlayerUrl.h"
@implementation SuperPlayerUrl
@end
@@ -0,0 +1,18 @@
//
// SPPlayCGIParser.h
// SuperPlayer
//
// Created by cui on 2019/12/26.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser : NSObject
+ (Class<SPPlayCGIParserProtocol>)parserOfVersion:(NSInteger)version;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,22 @@
//
// 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<SPPlayCGIParserProtocol>)parserOfVersion:(NSInteger)version {
if (version == 2) {
return [SPPlayCGIParser_V2 class];
} else if (version == 4) {
return [SPPlayCGIParser_V4 class];
}
return Nil;
}
@end
@@ -0,0 +1,18 @@
//
// PlayCGIParserProtocol.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParseResult.h"
NS_ASSUME_NONNULL_BEGIN
@protocol SPPlayCGIParserProtocol <NSObject>
+ (SPPlayCGIParseResult *)parseResponse:(NSDictionary *)jsonResp;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,18 @@
//
// SPPlayCGIParser_V2.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser_V2 : NSObject <SPPlayCGIParserProtocol>
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,105 @@
//
// 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<SuperPlayerUrl *> *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<SPVideoFrameDescription *> *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
@@ -0,0 +1,18 @@
//
// PlayCGIV4Parser.h
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "SPPlayCGIParserProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@interface SPPlayCGIParser_V4 : NSObject <SPPlayCGIParserProtocol>
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,122 @@
//
// PlayCGIV4Parser.m
// SuperPlayer
//
// Created by cui on 2019/12/25.
// Copyright © 2019 annidy. All rights reserved.
//
#import "SPPlayCGIParser_V4.h"
//#import "SPResolutionDefination.h"
#import "SPSubStreamInfo.h"
#import "AdaptiveStream.h"
#import "TXImageSprite.h"
#import "J2Obj.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"];
NSDictionary *streamInfo = [media valueForKeyPath:@"streamingInfo.plainOutput"];
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"];
}
if (streamInfo == nil) {
return nil;
}
NSNumber *duration = [media valueForKeyPath:@"basicInfo.duration"];
if ([duration isKindOfClass:[NSNumber class]]) {
ret.originalDuration = duration.doubleValue;
}
// 解析分辨率名称
NSArray *subStreamDictArray = J2Array(streamInfo[@"subStreams"]);
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];
}
ret.multiVideoURLs = subStreamInfoArray;
//解析视频播放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<NSURL *> *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) {
NSMutableArray<SPVideoFrameDescription *> *videoPoints = [NSMutableArray array];
for (NSDictionary *jsonObject in keyFrameDescList) {
SPVideoFrameDescription *point = [SPVideoFrameDescription instanceFromDictionary:jsonObject];
if (point) {
[videoPoints addObject:point];
}
}
ret.keyFrameDescList = videoPoints;
}
}
} while (0);
}
return ret;
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More