├── .gitignore ├── .travis.yml ├── AVPlayerCacheLibrary.podspec ├── AVPlayerCacheLibrary ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── ReplaceMe.m │ ├── TPlayerView.h │ ├── TPlayerView.m │ ├── TVideoDownOperation.h │ ├── TVideoDownOperation.m │ ├── TVideoDownQueue.h │ ├── TVideoDownQueue.m │ ├── TVideoFileManager.h │ ├── TVideoFileManager.m │ ├── TVideoLoadManager.h │ ├── TVideoLoadManager.m │ ├── TVideoLoader.h │ └── TVideoLoader.m ├── Example ├── AVPlayerCacheLibrary.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── AVPlayerCacheLibrary-Example.xcscheme ├── AVPlayerCacheLibrary.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── AVPlayerCacheLibrary │ ├── AVPlayerCacheLibrary-Info.plist │ ├── AVPlayerCacheLibrary-Prefix.pch │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── NSString+Helper.h │ ├── NSString+Helper.m │ ├── TAppDelegate.h │ ├── TAppDelegate.m │ ├── TViewController.h │ ├── TViewController.m │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── AVPlayerCacheLibrary.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Target Support Files │ │ ├── AVPlayerCacheLibrary │ │ ├── AVPlayerCacheLibrary-dummy.m │ │ ├── AVPlayerCacheLibrary-prefix.pch │ │ ├── AVPlayerCacheLibrary-umbrella.h │ │ ├── AVPlayerCacheLibrary.modulemap │ │ ├── AVPlayerCacheLibrary.xcconfig │ │ └── Info.plist │ │ ├── Pods-AVPlayerCacheLibrary_Example │ │ ├── Info.plist │ │ ├── Pods-AVPlayerCacheLibrary_Example-acknowledgements.markdown │ │ ├── Pods-AVPlayerCacheLibrary_Example-acknowledgements.plist │ │ ├── Pods-AVPlayerCacheLibrary_Example-dummy.m │ │ ├── Pods-AVPlayerCacheLibrary_Example-frameworks.sh │ │ ├── Pods-AVPlayerCacheLibrary_Example-resources.sh │ │ ├── Pods-AVPlayerCacheLibrary_Example-umbrella.h │ │ ├── Pods-AVPlayerCacheLibrary_Example.debug.xcconfig │ │ ├── Pods-AVPlayerCacheLibrary_Example.modulemap │ │ └── Pods-AVPlayerCacheLibrary_Example.release.xcconfig │ │ └── Pods-AVPlayerCacheLibrary_Tests │ │ ├── Info.plist │ │ ├── Pods-AVPlayerCacheLibrary_Tests-acknowledgements.markdown │ │ ├── Pods-AVPlayerCacheLibrary_Tests-acknowledgements.plist │ │ ├── Pods-AVPlayerCacheLibrary_Tests-dummy.m │ │ ├── Pods-AVPlayerCacheLibrary_Tests-frameworks.sh │ │ ├── Pods-AVPlayerCacheLibrary_Tests-resources.sh │ │ ├── Pods-AVPlayerCacheLibrary_Tests-umbrella.h │ │ ├── Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig │ │ ├── Pods-AVPlayerCacheLibrary_Tests.modulemap │ │ └── Pods-AVPlayerCacheLibrary_Tests.release.xcconfig └── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ └── InfoPlist.strings ├── LICENSE ├── README.md └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | # Pods/ 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -workspace Example/AVPlayerCacheLibrary.xcworkspace -scheme AVPlayerCacheLibrary-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint AVPlayerCacheLibrary.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'AVPlayerCacheLibrary' 11 | s.version = '0.1.0' 12 | s.summary = 'AVPlayerCacheLibrary can cache avplayer video data' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | TODO: Add long description of the pod here. 22 | DESC 23 | 24 | s.homepage = 'https://github.com/hailong9/AVPlayerCacheLibrary' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'hailong9' => 'hailong9@staff.sina.com.cn' } 28 | s.source = { :git => 'https://github.com/taohailong/AVPlayerCache.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '7.0' 32 | 33 | s.source_files = 'AVPlayerCacheLibrary/Classes/**/*' 34 | 35 | # s.resource_bundles = { 36 | # 'AVPlayerCacheLibrary' => ['AVPlayerCacheLibrary/Assets/*.png'] 37 | # } 38 | 39 | # s.public_header_files = 'Pod/Classes/**/*.h' 40 | # s.frameworks = 'UIKit', 'MapKit' 41 | # s.dependency 'AFNetworking', '~> 2.3' 42 | end 43 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taohailong/AVPlayerCache/4b33c593e5bc2cb472a95f946afc42cc7e6eeba6/AVPlayerCacheLibrary/Assets/.gitkeep -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taohailong/AVPlayerCache/4b33c593e5bc2cb472a95f946afc42cc7e6eeba6/AVPlayerCacheLibrary/Classes/.gitkeep -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/ReplaceMe.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taohailong/AVPlayerCache/4b33c593e5bc2cb472a95f946afc42cc7e6eeba6/AVPlayerCacheLibrary/Classes/ReplaceMe.m -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TPlayerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPlayerView.h 3 | // Pods 4 | // 5 | // Created by hailong9 on 2017/9/19. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | @protocol PlayerDelegate 12 | @optional 13 | - (void)playerVideoTotalTime:(int64_t)seconds; 14 | - (void)playerTimeObserverCallBack:(int64_t)currentSeconds; 15 | - (void)playerCacheDataRangeChangedCallBack:(int64_t)totalSeconds; 16 | - (void)playerStartLoadingCallBack; 17 | - (void)playerAlreadToPlay; // 可以获取到播放的视频信息了 18 | - (void)playerBeginDisplay; //视频开始播放了 19 | - (void)playerPlayCallBack; 20 | - (void)playerOccureErrorCallBack; 21 | - (void)playerPauseCallBack; 22 | - (void)playerSeekCallBack:(int64_t)currentSeconds; 23 | - (void)playerMonitorTimeCallBack:(int64_t)monitorTime; 24 | - (void)playerPlayOver; 25 | @end 26 | 27 | @interface TPlayerView : UIView 28 | @property (nonatomic, weak) id delegate; 29 | 30 | 31 | - (instancetype)initWithFrame:(CGRect)frame withDelegate:(id)delegate; 32 | - (void)loadVideoDataWithUrl:(NSString*)url withVideoName:(NSString*)videoName; 33 | 34 | // 加载视频 35 | - (void)loadVideoData; 36 | - (void)setPreSeekTime:(NSUInteger)processTime; 37 | - (int64_t)getPlayerTime; 38 | - (BOOL)isAlreadyBegin; 39 | // 视频播放控制 40 | - (BOOL)isMute; 41 | - (void)setVolume:(CGFloat)volume; 42 | - (void)play; 43 | - (void)pause; 44 | - (void)setViewFillMode:(UIViewContentMode)mode; 45 | 46 | - (void)reset; 47 | - (UIImage *)getVideoPlayerScreenshot; 48 | - (void)playerSeekToSecond:(float)value; 49 | - (void)setVideoMonitorTime:(NSUInteger)seconds; 50 | //- (UIViewContentMode)playerContentMode; 51 | //- (void)setVideoFillMode:(NSString *)fillMode; 52 | @end 53 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TPlayerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TPlayerView.m 3 | // Pods 4 | // 5 | // Created by hailong9 on 2017/9/19. 6 | // 7 | // 8 | 9 | #import "TPlayerView.h" 10 | #import "TVideoLoadManager.h" 11 | #import "TVideoFileManager.h" 12 | @interface TPlayerView() 13 | { 14 | NSUInteger _preSeekTime; 15 | TVideoLoadManager* _videoLoader; 16 | } 17 | @property (nonatomic, strong, nullable) AVPlayerItem *avPlayerItem; 18 | @property (nonatomic, strong, nullable) AVPlayer *avPlayer; 19 | 20 | @end 21 | @implementation TPlayerView{ 22 | BOOL _isPaused; 23 | NSString* _videoName; 24 | NSString* _videoUrl; 25 | id _timeObserver; 26 | id _playbackTimeObserver; 27 | BOOL _isMute; 28 | NSInteger _monitorTime; 29 | } 30 | - (instancetype)initWithFrame:(CGRect)frame withDelegate:(id)delegate 31 | { 32 | self = [super initWithFrame:frame]; 33 | if (self) { 34 | self.delegate = delegate; 35 | [self.layer addObserver:self forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionNew context:nil]; 36 | // 监听播放结束 37 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoPlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 38 | } 39 | return self; 40 | } 41 | 42 | + (Class)layerClass 43 | { 44 | return [AVPlayerLayer class]; 45 | } 46 | 47 | 48 | - (void)loadVideoDataWithUrl:(NSString*)url withVideoName:(NSString*)videoName 49 | { 50 | _videoUrl = url; 51 | _videoName = videoName; 52 | [self loadVideoData]; 53 | } 54 | 55 | - (void)setVideoMonitorTime:(NSUInteger)seconds 56 | { 57 | if (_avPlayerItem && _avPlayerItem.duration.timescale != 0) { 58 | [self addPlayerTimeObserve:seconds]; 59 | }else{ 60 | _monitorTime = seconds; 61 | } 62 | } 63 | 64 | - (void)addPlayerTimeObserve:(NSUInteger)seconds 65 | { 66 | if (seconds ==0 || [self.delegate respondsToSelector:@selector(playerMonitorTimeCallBack:)] == NO || _timeObserver) { 67 | return; 68 | } 69 | NSUInteger value = CMTimeGetSeconds(_avPlayerItem.duration); 70 | if (value durationSeconds + startSeconds) { 284 | return NO; 285 | } 286 | return YES; 287 | } 288 | return NO; 289 | } 290 | 291 | #pragma mark- videoStatusChanged 292 | 293 | 294 | - (void)playerStatusLoadedTimeRangeChanged 295 | { 296 | NSTimeInterval timeInterval = [self availableDuration]; 297 | if ([self.delegate respondsToSelector:@selector(playerCacheDataRangeChangedCallBack:)]) { 298 | [self.delegate playerCacheDataRangeChangedCallBack:timeInterval]; 299 | } 300 | } 301 | 302 | 303 | - (void)playerStatusStartLoading 304 | { 305 | if ([self.delegate respondsToSelector:@selector(playerStartLoadingCallBack)]) { 306 | [self.delegate playerStartLoadingCallBack]; 307 | } 308 | } 309 | 310 | - (void)playerStatusOccureError 311 | { 312 | if ([self.delegate respondsToSelector:@selector(playerOccureErrorCallBack)]) { 313 | [self.delegate playerOccureErrorCallBack]; 314 | } 315 | } 316 | 317 | 318 | - (void)detectPlayerError:(AVPlayerItem*)playerItem 319 | { 320 | [self playerStatusOccureError]; 321 | return; 322 | } 323 | 324 | #pragma mark - 对外回调接口 325 | 326 | - (void)setPreSeekTime:(NSUInteger)processTime 327 | { 328 | _preSeekTime = processTime; 329 | } 330 | 331 | - (BOOL)isMute 332 | { 333 | return _isMute; 334 | } 335 | 336 | - (void)setVolume:(CGFloat)volume 337 | { 338 | if (volume == 0) { 339 | self.avPlayer.muted = YES; 340 | _isMute = YES; 341 | } 342 | if (volume == 1) { 343 | self.avPlayer.muted = NO; 344 | _isMute = NO; 345 | } 346 | } 347 | 348 | 349 | - (BOOL)isAlreadyBegin 350 | { 351 | return self.avPlayerItem.status == AVPlayerItemStatusReadyToPlay ? YES:NO; 352 | } 353 | 354 | - (int64_t)getPlayerTime 355 | { 356 | if (self.avPlayerItem.duration.value == self.avPlayerItem.currentTime.value) { 357 | //已经播放到最后 返回时间为0 358 | return 0; 359 | } 360 | if (self.avPlayerItem.currentTime.timescale == 0) { 361 | return 0; 362 | } 363 | int64_t currentSecond = self.avPlayerItem.currentTime.value / self.avPlayerItem.currentTime.timescale; 364 | return currentSecond; 365 | } 366 | 367 | - (void)playerSeekToSecond:(float)value 368 | { 369 | if (value < 0) { 370 | return; 371 | } 372 | if (self.avPlayerItem.status == AVPlayerItemStatusReadyToPlay) { 373 | // 跳至指定帧 374 | __weak typeof(self) blockSelf = self; 375 | [_avPlayerItem cancelPendingSeeks]; 376 | [self.avPlayer pause]; 377 | __weak typeof(_videoLoader) weak__videoLoader = _videoLoader; 378 | [self playerStatusStartLoading]; 379 | [_avPlayer seekToTime:CMTimeMakeWithSeconds(value, NSEC_PER_SEC) completionHandler:^(BOOL finished) { 380 | 381 | if ([blockSelf.delegate respondsToSelector:@selector(playerSeekCallBack:)]) { 382 | [blockSelf.delegate playerSeekCallBack:value]; 383 | } 384 | 385 | if (blockSelf.avPlayerItem.currentTime.timescale == 0 || finished == NO) { 386 | return ; 387 | } 388 | if ([weak__videoLoader netWorkError] == YES) { 389 | if ( [blockSelf checkCacheIsCoverSeekTime:value] == NO) { 390 | [blockSelf playerStatusOccureError]; 391 | return; 392 | } 393 | } 394 | [blockSelf play]; 395 | }]; 396 | } 397 | } 398 | 399 | - (void)readyToPlay:(AVPlayerItem *)playerItem 400 | { 401 | if (playerItem == nil || playerItem.duration.timescale == 0) { 402 | [self playerStatusOccureError]; 403 | return; 404 | } 405 | if ([self.delegate respondsToSelector:@selector(playerAlreadToPlay)]) { 406 | [self.delegate playerAlreadToPlay]; 407 | } 408 | [self play]; 409 | 410 | CGFloat totalSecond = 0; // 计算视频时长 411 | if (playerItem.duration.timescale != 0) { 412 | totalSecond = playerItem.duration.value / playerItem.duration.timescale; 413 | } 414 | [self addPlayerTimeObserve:_monitorTime]; // 时间回调 415 | 416 | if (_preSeekTime) { 417 | [self playerSeekToSecond:_preSeekTime]; 418 | _preSeekTime = 0; 419 | } 420 | if ( [self.delegate respondsToSelector:@selector(playerVideoTotalTime:)]) { 421 | [self.delegate playerVideoTotalTime:totalSecond]; 422 | } 423 | 424 | // 添加定期观察者,更新播放进度UI 425 | [self monitoringPlayback:playerItem]; 426 | 427 | } 428 | 429 | - (void)startLoadingInPlay 430 | { 431 | if ([self.delegate respondsToSelector:@selector(playerStartLoadingCallBack)]) { 432 | [self.delegate playerStartLoadingCallBack]; 433 | } 434 | } 435 | 436 | 437 | - (void)monitoringPlayback:(AVPlayerItem *)playerItem 438 | { 439 | if (!_playbackTimeObserver) { 440 | __weak typeof(self) blockSelf = self; 441 | _playbackTimeObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) { 442 | // 拖拽进度时,不更新播放进度 443 | if ([blockSelf.delegate respondsToSelector:@selector(playerTimeObserverCallBack:)]) { 444 | int64_t currentSecond = time.value / time.timescale; 445 | [blockSelf.delegate playerTimeObserverCallBack:currentSecond]; 446 | } 447 | }]; 448 | } 449 | } 450 | 451 | #pragma mark - VideoPlayer API 452 | 453 | - (void)loadVideoData 454 | { 455 | [self initAVElements]; 456 | } 457 | 458 | 459 | - (void)play 460 | { 461 | if (self.avPlayerItem.status == AVPlayerStatusReadyToPlay) { 462 | if ([self.delegate respondsToSelector:@selector(playerPlayCallBack)]) { 463 | [self.delegate playerPlayCallBack]; 464 | } 465 | [self.avPlayer play]; 466 | } 467 | _isPaused = NO; 468 | } 469 | 470 | - (void)pause 471 | { 472 | _isPaused = YES; 473 | if (self.avPlayerItem.status == AVPlayerStatusReadyToPlay) { 474 | [self.avPlayer pause]; 475 | } 476 | } 477 | 478 | - (void)reset 479 | { 480 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 481 | [_videoLoader cancelDownLoad]; 482 | _videoLoader = nil; 483 | [self.avPlayerItem.asset cancelLoading]; 484 | }); 485 | 486 | AVURLAsset* temp = (AVURLAsset*)self.avPlayerItem.asset; 487 | [temp.resourceLoader setDelegate:nil queue:nil]; 488 | if ([NSThread isMainThread] == NO) { 489 | dispatch_sync(dispatch_get_main_queue(), ^{ 490 | AVPlayerLayer* layer = (AVPlayerLayer* )self.layer; 491 | [layer setPlayer:nil]; 492 | }); 493 | }else{ 494 | AVPlayerLayer* layer = (AVPlayerLayer* ) self.layer; 495 | [layer setPlayer:nil]; 496 | } 497 | [self removeAVObservers]; 498 | self.avPlayer = nil; 499 | 500 | } 501 | 502 | - (UIImage *)getVideoPlayerScreenshot { 503 | AVURLAsset *asset = (AVURLAsset *)self.avPlayerItem.asset; 504 | AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 505 | imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 506 | imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 507 | CGImageRef thumb = [imageGenerator copyCGImageAtTime:self.avPlayerItem.currentTime 508 | actualTime:NULL 509 | error:NULL]; 510 | UIImage *videoImage = [UIImage imageWithCGImage:thumb]; 511 | CGImageRelease(thumb); 512 | return videoImage; 513 | } 514 | 515 | 516 | - (void)dealloc 517 | { 518 | [self removeAVObservers]; 519 | [self.layer removeObserver:self forKeyPath:@"readyForDisplay" context:nil]; 520 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 521 | } 522 | 523 | - (void)videoPlayDidEnd:(NSNotification *)notification 524 | { 525 | if (self.avPlayerItem != notification.object) { 526 | return; 527 | } 528 | if ([self.delegate respondsToSelector:@selector(playerPlayOver)]) { 529 | [self.delegate playerPlayOver]; 530 | } 531 | } 532 | /* 533 | // Only override drawRect: if you perform custom drawing. 534 | // An empty implementation adversely affects performance during animation. 535 | - (void)drawRect:(CGRect)rect { 536 | // Drawing code 537 | } 538 | */ 539 | 540 | @end 541 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoDownOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoDownOperation.h 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 17/1/2. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | typedef void (^VideoOperationStartBk)(NSMutableURLRequest* request); 12 | typedef void (^VideoLoaderProcessBk)(NSUInteger offset,NSData*data); 13 | typedef void (^VideoLoaderCompleteBk)(NSError* error,NSUInteger offset,NSUInteger length); 14 | typedef void(^VideoLoaderRespondBk)(NSUInteger length,NSString*meidaType); 15 | 16 | @interface TVideoDownOperation : NSOperation 17 | @property (assign,nonatomic) BOOL netReachable; 18 | - (instancetype)initWithUrl:(NSURL*)url withRange:(NSRange)range; 19 | 20 | - (NSUInteger)requestOffset; 21 | - (NSUInteger)cacheLength; 22 | //- (NSUInteger)requestLength; 23 | - (void)setOperationStartBk:(VideoOperationStartBk)bk; 24 | - (void)setDownCompleteBk:(VideoLoaderCompleteBk)bk; 25 | - (void)setDownProcessBk:(VideoLoaderProcessBk)bk; 26 | - (void)setDownRespondBk:(VideoLoaderRespondBk)bk; 27 | //- (void)done; 28 | @end 29 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoDownOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoDownOperation.m 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 17/1/2. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TVideoDownOperation.h" 10 | #import 11 | @interface TVideoDownOperation () 12 | 13 | @property (assign, nonatomic, getter = isExecuting) BOOL executing; 14 | @property (assign, nonatomic, getter = isFinished) BOOL finished; 15 | @end 16 | @implementation TVideoDownOperation 17 | { 18 | VideoLoaderCompleteBk _completeBk; 19 | VideoLoaderProcessBk _processBk; 20 | VideoLoaderRespondBk _respondBk; 21 | VideoOperationStartBk _startBk; 22 | 23 | NSRange _range; 24 | NSUInteger _cacheLength; 25 | NSURLSession * _session; //会话对象 26 | NSURLSessionDataTask * _task; 27 | NSURL* _downLoadUrl; 28 | OSSpinLock _oslock; 29 | } 30 | @synthesize executing = _executing; 31 | @synthesize finished = _finished; 32 | //@synthesize cancelled = _cancelled; 33 | @synthesize netReachable; 34 | 35 | - (instancetype)initWithUrl:(NSURL *)url withRange:(NSRange)range { 36 | self = [super init]; 37 | 38 | _range = range; 39 | _executing = NO; 40 | _finished = NO; 41 | _downLoadUrl = url; 42 | self.netReachable = true; 43 | _oslock = OS_SPINLOCK_INIT; 44 | #if DEBUG 45 | if (_range.length < 1 ) { 46 | NSAssert(false, @"video downOperation range error"); 47 | } 48 | #endif 49 | // NSLog(@"creat operation %@",self); 50 | return self; 51 | } 52 | 53 | //- (void)netWorkChangedNotic:(NSNotification*)notic 54 | //{ 55 | // self.netReachable = true; 56 | //} 57 | 58 | - (void)setOperationStartBk:(VideoOperationStartBk)bk 59 | { 60 | _startBk = bk; 61 | } 62 | 63 | - (void)setDownCompleteBk:(VideoLoaderCompleteBk)bk 64 | { 65 | _completeBk = bk; 66 | } 67 | 68 | - (void)setDownProcessBk:(VideoLoaderProcessBk)bk 69 | { 70 | _processBk = bk; 71 | } 72 | 73 | - (void)setDownRespondBk:(VideoLoaderRespondBk)bk 74 | { 75 | _respondBk = bk; 76 | } 77 | 78 | - (NSUInteger)requestOffset 79 | { 80 | return _range.location; 81 | } 82 | 83 | - (NSUInteger)cacheLength 84 | { 85 | return _cacheLength; 86 | } 87 | 88 | - (void)start 89 | { 90 | OSSpinLockLock(&_oslock); 91 | if (self.isCancelled) { 92 | self.finished = YES; 93 | return; 94 | } 95 | 96 | NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:_downLoadUrl cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10]; 97 | 98 | if (_startBk) { 99 | _startBk(request); 100 | } 101 | // if (_range.length != 2) { 102 | NSString* rangeStr = [NSString stringWithFormat:@"bytes=%ld-%ld", _range.location+_cacheLength, _range.length+_range.location-1]; 103 | [request addValue:rangeStr forHTTPHeaderField:@"Range"]; 104 | // } 105 | 106 | // NSLog(@"http setRang %@ ",request.allHTTPHeaderFields); 107 | NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 108 | configuration.HTTPMaximumConnectionsPerHost = 6; 109 | _session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; 110 | _task = [_session dataTaskWithRequest:request]; 111 | [_task resume]; 112 | 113 | 114 | OSSpinLockUnlock(&_oslock); 115 | } 116 | 117 | 118 | - (void)cancelInternal { 119 | 120 | if (self.isFinished) return; 121 | [super cancel]; 122 | [self reset]; 123 | if (self.isExecuting) self.executing = NO; 124 | } 125 | 126 | - (void)cancel { 127 | 128 | OSSpinLockLock(&_oslock); 129 | [self cancelInternal]; 130 | OSSpinLockUnlock(&_oslock); 131 | } 132 | 133 | 134 | - (void)done { 135 | 136 | if (self.isFinished ) { 137 | return; 138 | } 139 | self.finished = YES; 140 | self.executing = NO; 141 | [self reset]; 142 | // NSLog(@"done operaton %@ ",self); 143 | } 144 | 145 | - (void)reset { 146 | if (_session) { 147 | [_session invalidateAndCancel]; 148 | _session = nil; 149 | } 150 | } 151 | 152 | - (void)setFinished:(BOOL)finished { 153 | [self willChangeValueForKey:@"isFinished"]; 154 | _finished = finished; 155 | [self didChangeValueForKey:@"isFinished"]; 156 | } 157 | 158 | - (void)setExecuting:(BOOL)executing { 159 | [self willChangeValueForKey:@"isExecuting"]; 160 | _executing = executing; 161 | [self didChangeValueForKey:@"isExecuting"]; 162 | } 163 | 164 | 165 | - (void)startRunLoop 166 | { 167 | self.netReachable = false; 168 | if (self.isCancelled) { 169 | [self done]; 170 | return; 171 | } 172 | 173 | NSRunLoop * runLoop = [NSRunLoop currentRunLoop]; 174 | NSMachPort* port = [[NSMachPort alloc]init]; 175 | [runLoop addPort:port forMode:NSRunLoopCommonModes]; 176 | 177 | while(self.netReachable == false){ 178 | 179 | if (self.isCancelled) { 180 | break; 181 | } 182 | [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]]; 183 | } 184 | [runLoop removePort:port forMode:NSRunLoopCommonModes]; 185 | [self start]; 186 | } 187 | 188 | 189 | - (BOOL)isConcurrent { 190 | return YES; 191 | } 192 | 193 | #pragma mark - NSURLSessionDataDelegate 194 | //服务器响应 195 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler { 196 | 197 | NSUInteger code = ((NSHTTPURLResponse *)response).statusCode; 198 | if (code == 404) { 199 | [self cancelInternal]; 200 | return; 201 | } 202 | 203 | if (_respondBk) { 204 | NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *)response; 205 | NSUInteger contentLength = [[[httpResponse allHeaderFields] objectForKey:@"Content-Length"] longLongValue]; 206 | NSString* contentRange = [[httpResponse allHeaderFields] objectForKey:@"Content-Range"]; 207 | NSUInteger fileLength = [[[contentRange componentsSeparatedByString:@"/"] lastObject] longLongValue]; 208 | // NSLog(@"contentLength %ld %ld ",contentLength,fileLength); 209 | _respondBk(contentLength>fileLength?contentLength:fileLength,response.MIMEType); 210 | } 211 | completionHandler(NSURLSessionResponseAllow); 212 | } 213 | 214 | //服务器返回数据 可能会调用多次 215 | - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { 216 | 217 | NSUInteger offset = _cacheLength + _range.location; 218 | _cacheLength = _cacheLength + data.length; 219 | 220 | if (_processBk) { 221 | _processBk(offset,data); 222 | } 223 | } 224 | 225 | //请求完成会调用该方法,请求失败则error有值 226 | - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { 227 | 228 | // NSLog(@"alread down load %@ data from %ld-%ld request %ld-%ld",self,_range.location,_range.location+_cacheLength-1,_range.location,_range.length-1); 229 | // if (error.code < 0 && error.code != -999) { 230 | // 231 | // if (_completeBk) { 232 | // _completeBk(error,_range.location,_cacheLength); 233 | // } 234 | // [_session finishTasksAndInvalidate]; //startRunLoop 注意顺序 否则 线程循环嵌套 导致内存无法释放 235 | //// [self startRunLoop]; 236 | // sleep(5); 237 | // [self start]; 238 | // return; 239 | // } 240 | if (_completeBk) { 241 | _completeBk(nil,_range.location,_cacheLength); 242 | } 243 | 244 | [self done]; 245 | } 246 | 247 | - (void)dealloc 248 | { 249 | // NSLog(@"nsoperation dealloc %@",self); 250 | } 251 | @end 252 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoDownQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoDownQueue.h 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 17/1/2. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "TVideoFileManager.h" 12 | @class TVideoDownQueue; 13 | @protocol TVideoDownQueueProtocol 14 | @optional 15 | - (void)loadNetError:(TVideoDownQueue*)downQueue; 16 | @end 17 | 18 | @interface TVideoDownQueue : NSObject 19 | @property (nonatomic,assign) BOOL isNetworkError; 20 | @property(nonatomic,strong)AVAssetResourceLoadingRequest*assetResource; 21 | @property (nonatomic,weak) iddelegate; 22 | - (instancetype)initWithFileManager:(TVideoFileManager *)fileManager WithLoadingRequest:(AVAssetResourceLoadingRequest *)resource loadingUrl:(NSURL*)url withHttpHead:(NSDictionary*)httpHead; 23 | - (AVAssetResourceLoadingRequest*)assetResource; 24 | - (void)sychronizeProcessToConfigure; 25 | - (void)cancelDownLoad; 26 | - (void)reloadAssetResource:(AVAssetResourceLoadingRequest*)request; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoDownQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoDownQueue.m 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 17/1/2. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TVideoDownQueue.h" 10 | #import "TVideoDownOperation.h" 11 | #import 12 | @interface TVideoDownQueue() 13 | @property (nonatomic,weak) TVideoDownOperation* currentDownLoadOperation; 14 | @property (nonatomic,copy) NSDictionary* httpHeader; 15 | @property (nonatomic,strong) TVideoFileManager* fileManager; 16 | @end 17 | @implementation TVideoDownQueue 18 | { 19 | NSOperationQueue* _downQueue; 20 | // TVideoFileManager* _fileManager; 21 | NSURL* _requestUrl; 22 | } 23 | 24 | - (instancetype)initWithFileManager:(TVideoFileManager *)fileManager WithLoadingRequest:(AVAssetResourceLoadingRequest *)resource loadingUrl:(NSURL*)url withHttpHead:(NSDictionary *)httpHead 25 | { 26 | self = [super init]; 27 | _downQueue = [[NSOperationQueue alloc]init]; 28 | _downQueue.maxConcurrentOperationCount = 1; 29 | self.fileManager = fileManager; 30 | _requestUrl = url; 31 | self.assetResource = resource; 32 | self.httpHeader = httpHead; 33 | [self addReuqestOperation]; 34 | return self; 35 | } 36 | 37 | - (void)reloadAssetResource:(AVAssetResourceLoadingRequest*)request 38 | { 39 | NSAssert(request.dataRequest.requestedOffset == 0, @"reloadAssetResource error"); 40 | NSUInteger offset = [self.currentDownLoadOperation requestOffset]; 41 | NSUInteger length = [self.currentDownLoadOperation cacheLength]; 42 | self.assetResource = request; 43 | NSData* temp = [self.fileManager readTempFileDataWithOffset:offset length:length]; 44 | [self.assetResource.dataRequest respondWithData:temp]; 45 | } 46 | 47 | - (void)addReuqestOperation 48 | { 49 | NSInteger requestLength = 0; 50 | if ([self.assetResource respondsToSelector:@selector(requestsAllDataToEndOfResource)] && self.assetResource.dataRequest.requestsAllDataToEndOfResource == YES) { 51 | requestLength = [self.fileManager getFileLength] - 1; 52 | }else{ 53 | requestLength = self.assetResource.dataRequest.requestedLength-self.assetResource.dataRequest.currentOffset+self.assetResource.dataRequest.requestedOffset; 54 | } 55 | 56 | NSArray* segmentArr = [self.fileManager getSegmentsFromFile: NSMakeRange(self.assetResource.dataRequest.currentOffset,requestLength) ]; 57 | // NSLog(@"read segmentArr %@ current offset %ld-%ld",segmentArr,self.assetResource.dataRequest.currentOffset,self.assetResource.dataRequest.requestedOffset+self.assetResource.dataRequest.requestedLength-1); 58 | 59 | // __weak TVideoFileManager* wFileManager = _fileManager; 60 | __weak typeof (self) wself = self; 61 | for (NSArray* element in segmentArr) { 62 | 63 | NSNumber* start = element[0]; 64 | NSNumber* end = element[1]; 65 | BOOL isSave = [element[2] boolValue]; 66 | if (isSave) { 67 | 68 | [_downQueue addOperationWithBlock:^{ 69 | 70 | if(wself.assetResource.isFinished == true || wself.assetResource.isCancelled == true){ 71 | [wself cancelDownLoad]; 72 | return ; 73 | } 74 | NSUInteger startInteger = start.unsignedIntegerValue; 75 | NSUInteger totalLength = end.unsignedIntegerValue - startInteger + 1; 76 | NSData* data = nil; 77 | 78 | int bufSize = 1024000; 79 | while (totalLength > bufSize) { 80 | if (wself.assetResource.isCancelled || wself.assetResource.isFinished) { 81 | [wself cancelDownLoad]; 82 | return; 83 | } 84 | data = [wself.fileManager readTempFileDataWithOffset:startInteger length:bufSize]; 85 | [wself.assetResource.dataRequest respondWithData:data]; 86 | [NSThread sleepForTimeInterval:0.1]; 87 | startInteger = startInteger + bufSize; 88 | totalLength = totalLength - bufSize; 89 | } 90 | data = [wself.fileManager readTempFileDataWithOffset:startInteger length:totalLength]; 91 | [wself.assetResource.dataRequest respondWithData:data]; 92 | if ([wself getCurrentOperaton] == 1) { 93 | [wself.assetResource finishLoading]; 94 | } 95 | 96 | }]; 97 | } 98 | else 99 | { 100 | TVideoDownOperation* requestOperation = [[TVideoDownOperation alloc]initWithUrl:_requestUrl withRange:NSMakeRange(start.unsignedIntegerValue, end.unsignedIntegerValue - start.unsignedIntegerValue + 1)]; 101 | __weak TVideoDownOperation* wRequestOperation = requestOperation; 102 | [requestOperation setOperationStartBk:^(NSMutableURLRequest *request) { 103 | request.allHTTPHeaderFields = wself.httpHeader; 104 | wself.currentDownLoadOperation = wRequestOperation; 105 | }]; 106 | 107 | 108 | [requestOperation setDownRespondBk:^(NSUInteger length, NSString *meidaType) { 109 | wself.isNetworkError = NO; 110 | if (wself.assetResource.contentInformationRequest) { 111 | wself.assetResource.contentInformationRequest.contentLength = length; 112 | [wself.fileManager setFileLength:length]; 113 | [wself.assetResource finishLoading]; 114 | } 115 | }]; 116 | 117 | [requestOperation setDownProcessBk:^(NSUInteger offset, NSData *data) { 118 | 119 | [wself.fileManager writeFileData:offset data:data]; 120 | if(wself.assetResource.isFinished != true && wself.assetResource.isCancelled != true ) 121 | { 122 | [wself.assetResource.dataRequest respondWithData:data]; 123 | } 124 | else 125 | { 126 | if (wself.assetResource.dataRequest.requestedLength != 2) { 127 | [wself cancelDownLoad]; 128 | } 129 | } 130 | }]; 131 | 132 | [requestOperation setDownCompleteBk:^(NSError *error, NSUInteger offset, NSUInteger length) { 133 | 134 | [wself.fileManager saveSegmentData:offset length:length]; 135 | if (error == nil && wself.assetResource.isFinished != true && wself.assetResource.isCancelled != true && [wself getCurrentOperaton] == 1) { 136 | [wself.assetResource finishLoading]; 137 | } 138 | if (error == nil) { 139 | wself.currentDownLoadOperation = nil; 140 | } else { 141 | wself.isNetworkError = YES; 142 | if ([wself.delegate respondsToSelector:@selector(loadNetError:)]) { 143 | [wself.delegate loadNetError:wself]; 144 | } 145 | } 146 | }]; 147 | [_downQueue addOperation:requestOperation]; 148 | } 149 | } 150 | 151 | } 152 | 153 | 154 | - (NSUInteger)getCurrentOperaton 155 | { 156 | return [_downQueue operationCount] ; 157 | } 158 | 159 | - (void)cancelDownLoad 160 | { 161 | @synchronized (self) { 162 | if (_downQueue) { 163 | [_downQueue cancelAllOperations]; 164 | _downQueue = nil; 165 | } 166 | self.fileManager = nil; 167 | self.assetResource = nil; 168 | } 169 | } 170 | 171 | - (void)sychronizeProcessToConfigure 172 | { 173 | if (self.currentDownLoadOperation) { 174 | NSUInteger offset = [self.currentDownLoadOperation requestOffset]; 175 | NSUInteger length = [self.currentDownLoadOperation cacheLength]; 176 | [self.fileManager saveSegmentData:offset length:length]; 177 | } 178 | } 179 | 180 | - (void)dealloc 181 | { 182 | [self sychronizeProcessToConfigure]; 183 | [self cancelDownLoad]; 184 | } 185 | @end 186 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoFileManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoFileManager.h 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/27. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface TVideoFileManager : NSObject 11 | 12 | - (instancetype)initWithFileName:(NSString*)fileName; 13 | - (void)writeFileData:(NSUInteger)offset data:(NSData*)data; 14 | - (void)writeTempFileData:(NSData *)data ; 15 | - (void)writeFinish; 16 | - (NSData *)readTempFileDataWithOffset:(NSUInteger)offset length:(NSUInteger)length; 17 | - (NSData*)readToEndWithOffset:(NSUInteger)offset; 18 | 19 | - (void)setFileLength:(NSUInteger)length; 20 | - (NSUInteger)getFileLength; 21 | 22 | - (NSArray*)getSegmentsFromFile:(NSRange)range; 23 | - (void)saveSegmentData:(NSUInteger)offset length:(NSUInteger)length; 24 | 25 | + (void)setVideoCachePath:(NSString*)path; 26 | + (NSURL *)cacheFileExistsWithName:(NSString *)fileName; 27 | + (BOOL)hasFinishedVideoCache:(NSString*)fileName; 28 | + (BOOL)clearCache; 29 | + (NSString *)cacheFolderPath; 30 | @end 31 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoFileManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoFileManager.m 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/27. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TVideoFileManager.h" 10 | #import 11 | #import "pthread.h" 12 | static NSString* VideoCachePath = nil; 13 | @implementation TVideoFileManager 14 | { 15 | NSFileHandle * _writeFileHandle; 16 | NSFileHandle * _readFileHandle; 17 | NSString* _fileName; 18 | NSUInteger _fileLength; 19 | NSMutableArray* _segmentArr; 20 | __block OSSpinLock oslock; 21 | } 22 | pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 23 | - (instancetype)initWithFileName:(NSString*)fileName 24 | { 25 | self = [super init]; 26 | _fileName = fileName; 27 | oslock = OS_SPINLOCK_INIT; 28 | 29 | NSString * path = [TVideoFileManager creatCacheDirectory]; 30 | // NSLog(@"document path %@",path); 31 | NSString* videoPath = [NSString stringWithFormat:@"%@/%@.mp4",path,fileName]; 32 | NSString* segmentPath = [NSString stringWithFormat:@"%@/%@.plist",path,fileName]; 33 | BOOL creatError = [self createTempFile:videoPath]; 34 | #if DEBUG 35 | if (creatError == false) { 36 | NSAssert(false, @"creat vide file error"); 37 | } 38 | #endif 39 | 40 | _segmentArr = [[NSMutableArray alloc]init]; 41 | NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:segmentPath]; 42 | if (dic) { 43 | NSNumber* length = dic[@"fileLength"]; 44 | _fileLength = [length unsignedIntegerValue]; 45 | [_segmentArr addObjectsFromArray:dic[@"fileArr"]] ; 46 | } 47 | _writeFileHandle = [NSFileHandle fileHandleForWritingAtPath:videoPath]; 48 | _readFileHandle = [NSFileHandle fileHandleForReadingAtPath:videoPath]; 49 | return self; 50 | } 51 | 52 | - (void)saveSegmentToPlist 53 | { 54 | NSString * path = [TVideoFileManager cacheFolderPath]; 55 | NSString* segmentPath = [NSString stringWithFormat:@"%@/%@.plist",path,_fileName]; 56 | NSDictionary* dic = @{@"fileLength":@(_fileLength), @"fileArr":_segmentArr}; 57 | [dic writeToFile:segmentPath atomically:YES]; 58 | } 59 | 60 | - (void)setFileLength:(NSUInteger)length 61 | { 62 | _fileLength = length; 63 | } 64 | 65 | - (NSUInteger)getFileLength 66 | { 67 | return _fileLength; 68 | } 69 | 70 | 71 | 72 | - (void)writeTempFileData:(NSData *)data { 73 | 74 | pthread_rwlock_wrlock(&rwlock); 75 | [_writeFileHandle seekToEndOfFile]; 76 | [_writeFileHandle writeData:data]; 77 | pthread_rwlock_unlock(&rwlock); 78 | } 79 | 80 | 81 | - (void)writeFileData:(NSUInteger)offset data:(NSData *)data 82 | { 83 | pthread_rwlock_wrlock(&rwlock); 84 | [_writeFileHandle seekToFileOffset:offset]; 85 | [_writeFileHandle writeData:data]; 86 | pthread_rwlock_unlock(&rwlock); 87 | // [self saveSegmentData:offset length:data.length]; 88 | } 89 | 90 | - (void)writeFinish 91 | { 92 | [_writeFileHandle closeFile]; 93 | _writeFileHandle = nil; 94 | } 95 | 96 | 97 | - (NSData *)readTempFileDataWithOffset:(NSUInteger)offset length:(NSUInteger)length { 98 | 99 | #if DEBUG 100 | if (length < 1 ) { 101 | NSAssert(false, @"videofile read data length error"); 102 | } 103 | #endif 104 | 105 | pthread_rwlock_rdlock(&rwlock); 106 | [_readFileHandle seekToFileOffset:offset]; 107 | NSData* data = [_readFileHandle readDataOfLength:length]; 108 | pthread_rwlock_unlock(&rwlock); 109 | return data; 110 | } 111 | 112 | - (NSData*)readToEndWithOffset:(NSUInteger)offset 113 | { 114 | [_readFileHandle seekToFileOffset:offset]; 115 | return [_readFileHandle readDataToEndOfFile]; 116 | } 117 | 118 | 119 | - (void)dealloc 120 | { 121 | [_writeFileHandle closeFile]; 122 | [_readFileHandle closeFile]; 123 | } 124 | 125 | #pragma mark------cache append 、subRange 126 | 127 | - (void)saveSegmentData:(NSUInteger)offset length:(NSUInteger)length 128 | { 129 | if (length == 0) { 130 | return; 131 | } 132 | // NSLog(@"download length %ld-%ld",offset,offset+length-1); 133 | NSNumber* start = [NSNumber numberWithUnsignedInteger:offset]; 134 | NSNumber* end = [NSNumber numberWithUnsignedInteger:offset+length-1]; 135 | 136 | dispatch_async(dispatch_get_global_queue(0, 0), ^{ 137 | 138 | OSSpinLockLock(&oslock); 139 | 140 | if (_segmentArr.count == 0) { 141 | 142 | NSArray* insertArr = @[start,end]; 143 | [_segmentArr addObject:insertArr]; 144 | [self saveSegmentToPlist]; 145 | OSSpinLockUnlock(&oslock); 146 | return ; 147 | } 148 | 149 | //这里是 对区间段start-1 、end +1 ,进行边界融合 150 | NSUInteger searchStart = start.unsignedIntegerValue==0 ? 0 : start.unsignedIntegerValue-1; 151 | NSUInteger searchEnd = end.unsignedIntegerValue ==_fileLength-1?_fileLength-1: end.unsignedIntegerValue+1; 152 | 153 | float startIndex = [self searchSemgentIndex:searchStart withArr:_segmentArr]; 154 | float endIndex = [self searchSemgentIndex:searchEnd withArr:_segmentArr]; 155 | 156 | if (startIndex == endIndex) { // 有两种情况 一个是在同一区间段 ,一个是在空白区域 ,不涉及跨区域 157 | 158 | NSArray* insertArr = @[start,end]; 159 | if (startIndex<0) { 160 | startIndex = 0; 161 | [_segmentArr insertObject:insertArr atIndex:0]; 162 | } 163 | else 164 | { 165 | if ( [self hasDecimal:startIndex]) { // 没有小数部分说明 这个区间段处于别的包含中 不需要更新 166 | [_segmentArr insertObject:insertArr atIndex:startIndex+0.5]; 167 | } 168 | } 169 | } 170 | else 171 | { //需要合并的区间段 172 | NSUInteger insertFileStart = 0; 173 | NSUInteger insertFileEnd = 0; 174 | 175 | if ( [self hasDecimal:startIndex] ) { 176 | insertFileStart = start.unsignedIntegerValue; 177 | startIndex = startIndex + 0.5; 178 | } 179 | else 180 | { 181 | int index = startIndex; 182 | NSArray* temp = _segmentArr[index]; 183 | NSNumber* s = temp[0]; 184 | insertFileStart = s.unsignedIntegerValue; 185 | } 186 | 187 | if ([self hasDecimal:endIndex]) { 188 | insertFileEnd = end.unsignedIntegerValue; 189 | endIndex = endIndex - 0.5; 190 | } 191 | else 192 | { 193 | int index = endIndex; 194 | NSArray* temp = _segmentArr[index]; 195 | NSNumber* s = temp[1]; 196 | insertFileEnd = s.unsignedIntegerValue; 197 | } 198 | 199 | NSArray* insertArr = @[[NSNumber numberWithUnsignedInteger:insertFileStart],[NSNumber numberWithUnsignedInteger:insertFileEnd]]; 200 | 201 | NSMutableArray* removeArr = [NSMutableArray arrayWithCapacity:0]; 202 | for (int i = startIndex ; i <= endIndex ;i++) { 203 | [removeArr addObject:_segmentArr[i]]; 204 | } 205 | [_segmentArr removeObjectsInArray:removeArr]; 206 | [_segmentArr insertObject:insertArr atIndex:startIndex]; 207 | } 208 | [self saveSegmentToPlist]; 209 | OSSpinLockUnlock(&oslock); 210 | }); 211 | } 212 | 213 | - (BOOL)hasDecimal:(float)number 214 | { 215 | number = number * 10; 216 | int intNumber = number; 217 | int result = intNumber % 10; 218 | if ( result == 0) { 219 | return false; 220 | } 221 | return true; 222 | } 223 | 224 | 225 | - (float)searchSemgentIndex:(NSUInteger)fileIndex withArr:(NSArray*)segmentArr 226 | { 227 | float searchIndex = 0; 228 | for (int index = 0; index fileIndex ) { 235 | searchIndex = index - 0.5; 236 | break; 237 | } 238 | else if (temp_end.unsignedIntegerValue < fileIndex) 239 | { 240 | if (index == segmentArr.count - 1) { 241 | return index + 0.5; 242 | }// /循环到最后超出所有的区域 为最大数 243 | } 244 | else 245 | { 246 | searchIndex = index; 247 | break; 248 | } 249 | } 250 | return searchIndex; 251 | 252 | } 253 | 254 | 255 | - (NSArray*)getSegmentsFromFile:(NSRange)range 256 | { 257 | NSNumber* start = [NSNumber numberWithUnsignedInteger:range.location]; 258 | NSNumber* end = [NSNumber numberWithUnsignedInteger:range.location+range.length-1]; 259 | OSSpinLockLock(&oslock); 260 | 261 | if (_segmentArr.count == 0) { 262 | OSSpinLockUnlock(&oslock); 263 | return @[[self creatReadSegmentArr:start end:end isSave:NO]]; 264 | } 265 | 266 | float startIndex = [self searchSemgentIndex:start.unsignedIntegerValue withArr:_segmentArr]; 267 | float endIndex = [self searchSemgentIndex:end.unsignedIntegerValue withArr:_segmentArr]; 268 | 269 | if (startIndex == endIndex) { // 有两种情况 一个是在同一区间段 ,一个是在空白区域 ,不涉及跨区域 270 | OSSpinLockUnlock(&oslock); 271 | if ([self hasDecimal:startIndex]) { 272 | 273 | return @[[self creatReadSegmentArr:start end:end isSave:NO]]; 274 | } 275 | else 276 | { 277 | // 没有小数部分说明 这个区间段处于别的包含中 278 | return @[[self creatReadSegmentArr:start end:end isSave:YES]]; 279 | } 280 | } 281 | else{ //需要合并的区间段 282 | 283 | 284 | NSMutableArray* newSegmengArr = [NSMutableArray arrayWithCapacity:0]; 285 | if ([self hasDecimal:startIndex]) { 286 | 287 | startIndex = startIndex + 0.5; 288 | NSArray* current = _segmentArr[(int)startIndex]; 289 | NSNumber* current_start = current[0]; 290 | [newSegmengArr addObject:[self creatReadSegmentArr:start end:@(current_start.unsignedIntegerValue-1) isSave:false]]; 291 | } 292 | 293 | NSArray* endArr = nil; 294 | // 295 | if ([self hasDecimal:endIndex]) { 296 | 297 | endIndex = endIndex - 0.5; 298 | NSArray* current = _segmentArr[(int)endIndex]; 299 | NSNumber* current_end = current[1]; 300 | endArr = [self creatReadSegmentArr:@(current_end.unsignedIntegerValue+1) end: end isSave:false]; 301 | } 302 | 303 | NSUInteger lastOffset = 0; 304 | for (int i = startIndex ;i<=endIndex;i++) { 305 | 306 | NSArray* current = _segmentArr[i]; 307 | NSNumber* s = current[0]; 308 | NSNumber* e = current[1]; 309 | 310 | if (lastOffset != 0) { 311 | [newSegmengArr addObject:[self creatReadSegmentArr:@(lastOffset+1) end: @(s.unsignedIntegerValue-1) isSave:NO]]; 312 | } 313 | [newSegmengArr addObject:[self creatReadSegmentArr:s end:e isSave:YES]]; 314 | lastOffset = e.unsignedIntegerValue; 315 | } 316 | if (endArr) { 317 | [newSegmengArr addObject:endArr]; 318 | } 319 | 320 | 321 | // newSegmengArr里 已经是填好的空白段和 数据段 只需要把头尾两端数据 重新一次判断 截取有用数据段 322 | 323 | NSArray* current = newSegmengArr.firstObject; 324 | 325 | BOOL isSave = [current[2] boolValue]; 326 | if (isSave) { 327 | 328 | NSNumber* currentEnd = current[1]; 329 | NSArray* replaceArr = [self creatReadSegmentArr:start end:currentEnd isSave:[current[2] boolValue]]; 330 | [newSegmengArr replaceObjectAtIndex:0 withObject:replaceArr]; 331 | } 332 | 333 | 334 | current = newSegmengArr.lastObject; 335 | isSave = [current[2] boolValue]; 336 | if (isSave) { 337 | 338 | NSArray* replaceArr = [self creatReadSegmentArr:current[0] end:end isSave:[current[2] boolValue]]; 339 | [newSegmengArr replaceObjectAtIndex:newSegmengArr.count-1 withObject:replaceArr]; 340 | 341 | } 342 | OSSpinLockUnlock(&oslock); 343 | return newSegmengArr; 344 | } 345 | } 346 | 347 | - (NSArray*)creatReadSegmentArr:(NSNumber*)start end:(NSNumber*)end isSave:(BOOL)save 348 | { 349 | NSUInteger startInteger = start.unsignedIntegerValue; 350 | NSUInteger endInteger = end.unsignedIntegerValue; 351 | NSArray* arr = @[@(startInteger),@(endInteger),@(save)]; 352 | return arr; 353 | } 354 | 355 | 356 | #pragma mark--- FilePath 357 | 358 | - (BOOL)createTempFile:(NSString*)path { 359 | 360 | NSFileManager * manager = [NSFileManager defaultManager]; 361 | if ([manager fileExistsAtPath:path]) { 362 | return true; 363 | } 364 | return [manager createFileAtPath:path contents:nil attributes:nil]; 365 | } 366 | 367 | + (NSString*)creatCacheDirectory{ 368 | 369 | NSFileManager * manager = [NSFileManager defaultManager]; 370 | NSString * cacheFolderPath = [TVideoFileManager cacheFolderPath]; 371 | if ([manager fileExistsAtPath:cacheFolderPath] == NO) { 372 | [manager createDirectoryAtPath:cacheFolderPath withIntermediateDirectories:YES attributes:nil error:nil]; 373 | } 374 | return cacheFolderPath; 375 | } 376 | 377 | 378 | + (NSURL *)cacheFileExistsWithName:(NSString *)fileName { 379 | 380 | NSFileManager * manager = [NSFileManager defaultManager]; 381 | NSString * cacheFolderPath = [TVideoFileManager cacheFolderPath]; 382 | NSString* videoPath = [NSString stringWithFormat:@"%@/%@.mp4",cacheFolderPath,fileName]; 383 | if ([manager fileExistsAtPath:videoPath] == NO) { 384 | return nil; 385 | } 386 | NSURL *url = [[manager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] firstObject]; 387 | NSURL *path = [url URLByAppendingPathComponent:[NSString stringWithFormat:@"Caches/video_cache/%@.mp4",fileName]]; 388 | return path; 389 | } 390 | 391 | 392 | + (BOOL)hasFinishedVideoCache:(NSString *)fileName{ 393 | NSString * path = [TVideoFileManager cacheFolderPath]; 394 | NSString* segmentPath = [NSString stringWithFormat:@"%@/%@.plist",path,fileName]; 395 | NSDictionary * dic = [NSDictionary dictionaryWithContentsOfFile:segmentPath]; 396 | if (dic) { 397 | NSArray* segments = dic[@"fileArr"]; 398 | if (segments.count == 1) { 399 | NSNumber* length = dic[@"fileLength"]; 400 | NSUInteger fileLength = [length unsignedIntegerValue]; 401 | NSArray* seg = segments.firstObject; 402 | if ([seg[0] unsignedIntegerValue] == 0 && [seg[1] unsignedIntegerValue] + 1 == fileLength) { 403 | return YES; 404 | } 405 | } 406 | } 407 | return NO; 408 | } 409 | 410 | + (BOOL)clearCache { 411 | NSFileManager * manager = [NSFileManager defaultManager]; 412 | return [manager removeItemAtPath:[TVideoFileManager cacheFolderPath] error:nil]; 413 | } 414 | 415 | + (void)setVideoCachePath:(NSString*)path 416 | { 417 | VideoCachePath = path; 418 | } 419 | 420 | + (NSString *)cacheFolderPath { 421 | 422 | if (VideoCachePath) { 423 | return VideoCachePath; 424 | } 425 | NSArray *allCachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, 426 | NSUserDomainMask, YES); 427 | NSString* cache = [[allCachePaths objectAtIndex:0] stringByAppendingPathComponent:@"video_cache"]; 428 | VideoCachePath = cache; 429 | return cache; 430 | // return [[NSHomeDirectory( ) stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"VideoCaches"]; 431 | } 432 | 433 | @end 434 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoLoadManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoLoadManager.h 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/27. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "TVideoLoader.h" 12 | #import "TVideoDownQueue.h" 13 | @protocol VideoLoadManagerProtocol 14 | @optional 15 | - (void)requestNetError; 16 | @end 17 | 18 | @interface TVideoLoadManager : NSObject 19 | @property (nonatomic,weak) iddelegate; 20 | + (NSString*)encryptionDownLoadUrl:(NSString*)url; 21 | - (instancetype)initWithFileName:(NSString*)fileName; 22 | - (BOOL)netWorkError; 23 | - (void)setHTTPHeaderField:(NSDictionary*)header; 24 | - (void)cancelDownLoad; 25 | //- (void)networkReachable; //断网重连 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoLoadManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoLoadManager.m 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/27. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TVideoLoadManager.h" 10 | #import "TVideoFileManager.h" 11 | #import 12 | #import "TVideoDownOperation.h" 13 | #import 14 | @implementation TVideoLoadManager 15 | { 16 | NSUInteger _fileLength; 17 | NSUInteger _cancelLength; 18 | TVideoFileManager* _fileManager; 19 | NSMutableArray* _requestArr; 20 | OSSpinLock oslock ; 21 | NSData* resourceData; 22 | NSDictionary* _httpHeader; 23 | } 24 | 25 | 26 | 27 | - (instancetype)initWithFileName:(NSString*)fileName 28 | { 29 | self = [super init]; 30 | _fileManager = [[TVideoFileManager alloc]initWithFileName:fileName]; 31 | _requestArr = [NSMutableArray arrayWithCapacity:0]; 32 | oslock = OS_SPINLOCK_INIT; 33 | return self; 34 | } 35 | 36 | + (NSString*)decodeDownLoadUrl:(NSString*)url 37 | { 38 | return [NSString stringWithFormat:@"http%@",url]; 39 | } 40 | + (NSString*)encryptionDownLoadUrl:(NSString *)url 41 | { 42 | if ([url hasPrefix:@"http"]) { 43 | return [url substringFromIndex:4]; 44 | } 45 | return nil; 46 | } 47 | 48 | - (void)cancelDownLoad{ 49 | OSSpinLockLock(&oslock); 50 | for (TVideoDownQueue* temp in _requestArr) { 51 | AVAssetResourceLoadingRequest * compare = [temp assetResource]; 52 | if (compare.isCancelled == NO && compare.isFinished == NO) { 53 | [compare finishLoadingWithError:nil]; 54 | } 55 | [temp cancelDownLoad]; 56 | } 57 | [_requestArr removeAllObjects]; 58 | OSSpinLockUnlock(&oslock); 59 | } 60 | 61 | - (BOOL)netWorkError 62 | { 63 | OSSpinLockLock(&oslock); 64 | for (TVideoDownQueue* temp in _requestArr) { 65 | if (temp.isNetworkError == YES) { 66 | OSSpinLockUnlock(&oslock); 67 | return YES; 68 | } 69 | } 70 | OSSpinLockUnlock(&oslock); 71 | return NO; 72 | } 73 | #if 1 74 | - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest 75 | { 76 | // NSLog(@"loadingRequest %ld-%ld ", loadingRequest.dataRequest.requestedOffset,loadingRequest.dataRequest.requestedLength+loadingRequest.dataRequest.requestedOffset-1); 77 | [self checkResourceLoader]; 78 | if (loadingRequest.contentInformationRequest) { 79 | CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(@"video/mp4"), NULL); 80 | loadingRequest.contentInformationRequest.contentType = CFBridgingRelease(contentType); 81 | loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES; 82 | } 83 | 84 | OSSpinLockLock(&oslock); 85 | 86 | if ([_fileManager getFileLength] != 0 ) { 87 | 88 | if (loadingRequest.dataRequest.requestedLength == 2) { 89 | 90 | loadingRequest.contentInformationRequest.contentLength = [_fileManager getFileLength]; 91 | NSData* data = [_fileManager readTempFileDataWithOffset:0 length:2]; 92 | [loadingRequest.dataRequest respondWithData:data]; 93 | [loadingRequest finishLoading]; 94 | OSSpinLockUnlock(&oslock); 95 | return true; 96 | } 97 | } 98 | 99 | NSString* downUrl = [TVideoLoadManager decodeDownLoadUrl:loadingRequest.request.URL.absoluteString]; 100 | TVideoDownQueue* downLoad = [[TVideoDownQueue alloc]initWithFileManager:_fileManager WithLoadingRequest:loadingRequest loadingUrl:[NSURL URLWithString:downUrl] withHttpHead:_httpHeader]; 101 | downLoad.delegate = self; 102 | [_requestArr addObject:downLoad]; 103 | OSSpinLockUnlock(&oslock); 104 | return YES; 105 | } 106 | 107 | 108 | #else 109 | 110 | - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest 111 | { 112 | NSLog(@"loadingRequest %ld-%ld toend %d", loadingRequest.dataRequest.requestedOffset,loadingRequest.dataRequest.requestedLength+loadingRequest.dataRequest.requestedOffset-1,loadingRequest.dataRequest.requestsAllDataToEndOfResource); 113 | 114 | [self checkResourceLoader]; 115 | CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(@"video/mp4"), NULL); 116 | loadingRequest.contentInformationRequest.contentType = CFBridgingRelease(contentType); 117 | loadingRequest.contentInformationRequest.byteRangeAccessSupported = NO; 118 | //exist video cache 119 | if ([_fileManager getFileLength] != 0 ) { 120 | 121 | if (loadingRequest.dataRequest.requestedLength == 2) { 122 | 123 | loadingRequest.contentInformationRequest.contentLength = [_fileManager getFileLength]; 124 | NSData* data = [_fileManager readTempFileDataWithOffset:0 length:2]; 125 | [loadingRequest.dataRequest respondWithData:data]; 126 | [loadingRequest finishLoading]; 127 | 128 | } 129 | else if(_downLoad &&(loadingRequest.dataRequest.requestedOffset == 0 || loadingRequest.dataRequest.requestedOffset == 2)) 130 | { 131 | _downLoad.assetResource = loadingRequest; 132 | } 133 | else 134 | { 135 | 136 | if (_downLoad) { 137 | [_downLoad videoLoaderSychronizeProcessToConfigure]; 138 | [_downLoad cancel]; 139 | _downLoad = nil; 140 | } 141 | 142 | OSSpinLockLock(&oslock); 143 | NSString* downUrl = [VideoLoadManager decodeDownLoadUrl:loadingRequest.request.URL.absoluteString]; 144 | VideoDownQueue* downLoad = [[VideoDownQueue alloc]initWithFileManager:_fileManager WithLoadingRequest:loadingRequest loadingUrl:[NSURL URLWithString:downUrl]]; 145 | [_requestArr addObject:downLoad]; 146 | OSSpinLockUnlock(&oslock); 147 | 148 | } 149 | return true; 150 | } 151 | 152 | if (loadingRequest.dataRequest.requestedOffset == 0 || loadingRequest.dataRequest.requestedOffset == 2) { 153 | 154 | NSString* downUrl = [VideoLoadManager decodeDownLoadUrl:loadingRequest.request.URL.absoluteString]; 155 | _downLoad = [[VideoLoader alloc]initWithUrl:[NSURL URLWithString:downUrl] withRange:NSMakeRange(loadingRequest.dataRequest.requestedOffset, loadingRequest.dataRequest.requestedLength)]; 156 | _downLoad.assetResource = loadingRequest; 157 | _downLoad.fileManager = _fileManager; 158 | [_downLoad start]; 159 | return true; 160 | } 161 | 162 | return true; 163 | } 164 | 165 | #endif 166 | 167 | - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest 168 | { 169 | // NSLog(@"didCancelLoadingRequest %ld-%ld",loadingRequest.dataRequest.requestedOffset,loadingRequest.dataRequest.requestedOffset+loadingRequest.dataRequest.requestedLength-1); 170 | OSSpinLockLock(&oslock); 171 | NSMutableArray* removeAr = [NSMutableArray arrayWithCapacity:0]; 172 | for (TVideoDownQueue* temp in _requestArr) { 173 | AVAssetResourceLoadingRequest * compare = [temp assetResource] ; 174 | if (compare == loadingRequest || compare.isFinished) { 175 | [temp cancelDownLoad]; 176 | [removeAr addObject:temp]; 177 | } 178 | } 179 | [_requestArr removeObjectsInArray:removeAr]; 180 | OSSpinLockUnlock(&oslock); 181 | } 182 | 183 | 184 | - (void)checkResourceLoader 185 | { 186 | OSSpinLockLock(&oslock); 187 | NSMutableArray* removeAr = [NSMutableArray arrayWithCapacity:0]; 188 | for (TVideoDownQueue* temp in _requestArr) { 189 | AVAssetResourceLoadingRequest * compare = [temp assetResource] ; 190 | if (compare.isCancelled || compare.isFinished) { 191 | [removeAr addObject:temp]; 192 | [temp cancelDownLoad]; 193 | [temp sychronizeProcessToConfigure]; 194 | } else { 195 | // [compare finishLoadingWithError:nil]; 196 | } 197 | } 198 | [_requestArr removeObjectsInArray:removeAr]; 199 | OSSpinLockUnlock(&oslock); 200 | 201 | } 202 | 203 | 204 | - (void)setHTTPHeaderField:(NSDictionary *)header{ 205 | _httpHeader = header; 206 | } 207 | 208 | #pragma mark -DownloadQueue delegate 209 | 210 | - (void)loadNetError:(TVideoDownQueue *)downQueue{ 211 | if ([self.delegate respondsToSelector:@selector(requestNetError)]) { 212 | [self.delegate requestNetError]; 213 | } 214 | } 215 | 216 | - (void)dealloc 217 | { 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoLoader.h 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/26. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "TVideoFileManager.h" 12 | typedef void (^VideoLoaderProcessBk)(NSUInteger offset,NSData*data); 13 | typedef void (^VideoLoaderCompleteBk)(NSError* error,NSUInteger offset,NSUInteger length); 14 | typedef void(^VideoLoaderRespondBk)(NSUInteger length,NSString*meidaType); 15 | @protocol VideoLoaderProtocol 16 | @optional 17 | - (void)videoLoaderConfigure:(NSMutableURLRequest*)request; 18 | - (void)videoLoaderProcessOffset:(NSUInteger)offset data:(NSData*)receiveData; 19 | - (void)videoLoaderComplete:(NSError*)error; 20 | - (void)videoLoaderRespond:(NSUInteger)length withMediaType:(NSString*)type; 21 | @end 22 | 23 | @interface TVideoLoader : NSObject 24 | { 25 | } 26 | @property(nonatomic,strong) AVAssetResourceLoadingRequest* assetResource; 27 | @property(nonatomic,weak) TVideoFileManager* fileManager; 28 | 29 | - (instancetype)initWithUrl:(NSURL*)url withRange:(NSRange)range WithDelegate:(id)delegate; 30 | - (instancetype)initWithUrl:(NSURL*)url withRange:(NSRange)range; 31 | 32 | - (void)setCompleteBk:(VideoLoaderCompleteBk)bk; 33 | - (void)setProcessBk:(VideoLoaderProcessBk)bk; 34 | - (void)setRespondBk:(VideoLoaderRespondBk)bk; 35 | 36 | - (NSUInteger)requestOffset; 37 | - (NSUInteger)cacheLength; 38 | - (NSUInteger)requestLength; 39 | 40 | - (void)start; 41 | - (void)cancel; 42 | - (void)videoLoaderSychronizeProcessToConfigure; 43 | @end 44 | -------------------------------------------------------------------------------- /AVPlayerCacheLibrary/Classes/TVideoLoader.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoLoader.m 3 | // AVPlayerController 4 | // 5 | // Created by hailong9 on 16/12/26. 6 | // Copyright © 2016年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TVideoLoader.h" 10 | 11 | @implementation TVideoLoader 12 | { 13 | VideoLoaderCompleteBk _completeBk; 14 | VideoLoaderProcessBk _processBk; 15 | VideoLoaderRespondBk _respondBk; 16 | 17 | NSRange _range; 18 | __weak id_delegate; 19 | NSUInteger _cacheLength; 20 | NSURLSession * session; //会话对象 21 | NSURLSessionDataTask * task; 22 | NSOperationQueue* _operateQueue; 23 | BOOL _cancel; 24 | NSMutableURLRequest* _request; 25 | NSError* _netError; 26 | } 27 | @synthesize fileManager; 28 | @synthesize assetResource; 29 | - (instancetype)initWithUrl:(NSURL *)url withRange:(NSRange)range WithDelegate:(id)delegate 30 | { 31 | self = [self initWithUrl:url withRange:range]; 32 | _delegate = delegate; 33 | return self; 34 | } 35 | 36 | 37 | - (instancetype)initWithUrl:(NSURL *)url withRange:(NSRange)range withRespondBk:(VideoLoaderRespondBk)respond withProcessBk:(VideoLoaderProcessBk)processBk withCompleteBk:(VideoLoaderCompleteBk)bk 38 | { 39 | self = [self initWithUrl:url withRange:range]; 40 | return self; 41 | } 42 | 43 | 44 | - (instancetype)initWithUrl:(NSURL *)url withRange:(NSRange)range 45 | { 46 | self = [super init]; 47 | _range = range; 48 | 49 | _request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];; 50 | 51 | if (range.length != 2 && range.location != 0) { 52 | 53 | NSString* rangeStr = [NSString stringWithFormat:@"bytes=%ld-%ld", range.location, range.length - 1 + range.location]; 54 | [_request addValue:rangeStr forHTTPHeaderField:@"Range"]; 55 | } 56 | if ([_delegate respondsToSelector:@selector(videoLoaderConfigure:)]) { 57 | [_delegate videoLoaderConfigure:_request]; 58 | } 59 | 60 | _operateQueue = [[NSOperationQueue alloc]init]; 61 | return self; 62 | } 63 | 64 | 65 | - (void)start 66 | { 67 | session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:_operateQueue]; 68 | task = [session dataTaskWithRequest:_request]; 69 | [task resume]; 70 | } 71 | 72 | //- (void)startRunLoop 73 | //{ 74 | // NSRunLoop * runLoop = [NSRunLoop currentRunLoop]; 75 | // NSMachPort* port = [[NSMachPort alloc]init]; 76 | // [runLoop addPort:port forMode:NSRunLoopCommonModes]; 77 | // 78 | // while(_netError.code == -1001){ 79 | // NSLog(@"isrun "); 80 | // [self start]; 81 | // [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]]; 82 | // } 83 | // [runLoop removePort:port forMode:NSRunLoopCommonModes]; 84 | // 85 | //} 86 | 87 | 88 | - (void)videoLoaderSychronizeProcessToConfigure 89 | { 90 | if (_cacheLength < 1) { 91 | return; 92 | } 93 | [self.fileManager saveSegmentData:_range.location length:_cacheLength]; 94 | } 95 | 96 | - (void)fillDataToAssetResource 97 | { 98 | // NSLog(@"fillDataToAssetResource"); 99 | if (self.assetResource == nil || self.assetResource.isFinished || self.assetResource.isCancelled) { 100 | return; 101 | } 102 | if (self.assetResource.dataRequest.requestedLength == 2 ) { 103 | return; 104 | } 105 | 106 | NSUInteger offset = self.assetResource.dataRequest.currentOffset; 107 | if (_cacheLength+_range.location-1<=offset) { 108 | return; 109 | } 110 | 111 | if (_cacheLength /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 330 | showEnvVarsInLog = 0; 331 | }; 332 | 1EB9777BA4C9AA790955C561 /* [CP] Copy Pods Resources */ = { 333 | isa = PBXShellScriptBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | ); 337 | inputPaths = ( 338 | ); 339 | name = "[CP] Copy Pods Resources"; 340 | outputPaths = ( 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | shellPath = /bin/sh; 344 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-resources.sh\"\n"; 345 | showEnvVarsInLog = 0; 346 | }; 347 | 3D5DDABF8B4FC25F689EB3E6 /* [CP] Copy Pods Resources */ = { 348 | isa = PBXShellScriptBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | ); 352 | inputPaths = ( 353 | ); 354 | name = "[CP] Copy Pods Resources"; 355 | outputPaths = ( 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | shellPath = /bin/sh; 359 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-resources.sh\"\n"; 360 | showEnvVarsInLog = 0; 361 | }; 362 | 3E9FE9B8CCA34C5B0EE2FA3A /* [CP] Embed Pods Frameworks */ = { 363 | isa = PBXShellScriptBuildPhase; 364 | buildActionMask = 2147483647; 365 | files = ( 366 | ); 367 | inputPaths = ( 368 | ); 369 | name = "[CP] Embed Pods Frameworks"; 370 | outputPaths = ( 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | shellPath = /bin/sh; 374 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-frameworks.sh\"\n"; 375 | showEnvVarsInLog = 0; 376 | }; 377 | 97159FF6B35619A498B01EDB /* [CP] Check Pods Manifest.lock */ = { 378 | isa = PBXShellScriptBuildPhase; 379 | buildActionMask = 2147483647; 380 | files = ( 381 | ); 382 | inputPaths = ( 383 | ); 384 | name = "[CP] Check Pods Manifest.lock"; 385 | outputPaths = ( 386 | ); 387 | runOnlyForDeploymentPostprocessing = 0; 388 | shellPath = /bin/sh; 389 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 390 | showEnvVarsInLog = 0; 391 | }; 392 | D56829580549710A07B62A54 /* [CP] Embed Pods Frameworks */ = { 393 | isa = PBXShellScriptBuildPhase; 394 | buildActionMask = 2147483647; 395 | files = ( 396 | ); 397 | inputPaths = ( 398 | ); 399 | name = "[CP] Embed Pods Frameworks"; 400 | outputPaths = ( 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | shellPath = /bin/sh; 404 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-frameworks.sh\"\n"; 405 | showEnvVarsInLog = 0; 406 | }; 407 | /* End PBXShellScriptBuildPhase section */ 408 | 409 | /* Begin PBXSourcesBuildPhase section */ 410 | 6003F586195388D20070C39A /* Sources */ = { 411 | isa = PBXSourcesBuildPhase; 412 | buildActionMask = 2147483647; 413 | files = ( 414 | 6003F59E195388D20070C39A /* TAppDelegate.m in Sources */, 415 | 6003F5A7195388D20070C39A /* TViewController.m in Sources */, 416 | 6003F59A195388D20070C39A /* main.m in Sources */, 417 | 299F1DB61E6EC0CE000F04CC /* NSString+Helper.m in Sources */, 418 | ); 419 | runOnlyForDeploymentPostprocessing = 0; 420 | }; 421 | 6003F5AA195388D20070C39A /* Sources */ = { 422 | isa = PBXSourcesBuildPhase; 423 | buildActionMask = 2147483647; 424 | files = ( 425 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | /* End PBXSourcesBuildPhase section */ 430 | 431 | /* Begin PBXTargetDependency section */ 432 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 433 | isa = PBXTargetDependency; 434 | target = 6003F589195388D20070C39A /* AVPlayerCacheLibrary_Example */; 435 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 436 | }; 437 | /* End PBXTargetDependency section */ 438 | 439 | /* Begin PBXVariantGroup section */ 440 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 441 | isa = PBXVariantGroup; 442 | children = ( 443 | 6003F597195388D20070C39A /* en */, 444 | ); 445 | name = InfoPlist.strings; 446 | sourceTree = ""; 447 | }; 448 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 449 | isa = PBXVariantGroup; 450 | children = ( 451 | 6003F5B9195388D20070C39A /* en */, 452 | ); 453 | name = InfoPlist.strings; 454 | sourceTree = ""; 455 | }; 456 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = { 457 | isa = PBXVariantGroup; 458 | children = ( 459 | 71719F9E1E33DC2100824A3D /* Base */, 460 | ); 461 | name = LaunchScreen.storyboard; 462 | sourceTree = ""; 463 | }; 464 | /* End PBXVariantGroup section */ 465 | 466 | /* Begin XCBuildConfiguration section */ 467 | 6003F5BD195388D20070C39A /* Debug */ = { 468 | isa = XCBuildConfiguration; 469 | buildSettings = { 470 | ALWAYS_SEARCH_USER_PATHS = NO; 471 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 472 | CLANG_CXX_LIBRARY = "libc++"; 473 | CLANG_ENABLE_MODULES = YES; 474 | CLANG_ENABLE_OBJC_ARC = YES; 475 | CLANG_WARN_BOOL_CONVERSION = YES; 476 | CLANG_WARN_CONSTANT_CONVERSION = YES; 477 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 478 | CLANG_WARN_EMPTY_BODY = YES; 479 | CLANG_WARN_ENUM_CONVERSION = YES; 480 | CLANG_WARN_INT_CONVERSION = YES; 481 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 482 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 483 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 484 | COPY_PHASE_STRIP = NO; 485 | ENABLE_TESTABILITY = YES; 486 | GCC_C_LANGUAGE_STANDARD = gnu99; 487 | GCC_DYNAMIC_NO_PIC = NO; 488 | GCC_OPTIMIZATION_LEVEL = 0; 489 | GCC_PREPROCESSOR_DEFINITIONS = ( 490 | "DEBUG=1", 491 | "$(inherited)", 492 | ); 493 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 494 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 495 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 496 | GCC_WARN_UNDECLARED_SELECTOR = YES; 497 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 498 | GCC_WARN_UNUSED_FUNCTION = YES; 499 | GCC_WARN_UNUSED_VARIABLE = YES; 500 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 501 | ONLY_ACTIVE_ARCH = YES; 502 | SDKROOT = iphoneos; 503 | TARGETED_DEVICE_FAMILY = "1,2"; 504 | }; 505 | name = Debug; 506 | }; 507 | 6003F5BE195388D20070C39A /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ALWAYS_SEARCH_USER_PATHS = NO; 511 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 512 | CLANG_CXX_LIBRARY = "libc++"; 513 | CLANG_ENABLE_MODULES = YES; 514 | CLANG_ENABLE_OBJC_ARC = YES; 515 | CLANG_WARN_BOOL_CONVERSION = YES; 516 | CLANG_WARN_CONSTANT_CONVERSION = YES; 517 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 518 | CLANG_WARN_EMPTY_BODY = YES; 519 | CLANG_WARN_ENUM_CONVERSION = YES; 520 | CLANG_WARN_INT_CONVERSION = YES; 521 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 522 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 523 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 524 | COPY_PHASE_STRIP = YES; 525 | ENABLE_NS_ASSERTIONS = NO; 526 | GCC_C_LANGUAGE_STANDARD = gnu99; 527 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 528 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 529 | GCC_WARN_UNDECLARED_SELECTOR = YES; 530 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 531 | GCC_WARN_UNUSED_FUNCTION = YES; 532 | GCC_WARN_UNUSED_VARIABLE = YES; 533 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 534 | SDKROOT = iphoneos; 535 | TARGETED_DEVICE_FAMILY = "1,2"; 536 | VALIDATE_PRODUCT = YES; 537 | }; 538 | name = Release; 539 | }; 540 | 6003F5C0195388D20070C39A /* Debug */ = { 541 | isa = XCBuildConfiguration; 542 | baseConfigurationReference = 1733E21D723C6CCA86C31FFC /* Pods-AVPlayerCacheLibrary_Example.debug.xcconfig */; 543 | buildSettings = { 544 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 545 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 546 | CODE_SIGN_STYLE = Automatic; 547 | DEVELOPMENT_TEAM = A8L79FH6QB; 548 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 549 | GCC_PREFIX_HEADER = "AVPlayerCacheLibrary/AVPlayerCacheLibrary-Prefix.pch"; 550 | INFOPLIST_FILE = "AVPlayerCacheLibrary/AVPlayerCacheLibrary-Info.plist"; 551 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 552 | MODULE_NAME = ExampleApp; 553 | PRODUCT_BUNDLE_IDENTIFIER = com.taohailong.avplayer; 554 | PRODUCT_NAME = "$(TARGET_NAME)"; 555 | PROVISIONING_PROFILE = ""; 556 | PROVISIONING_PROFILE_SPECIFIER = ""; 557 | WRAPPER_EXTENSION = app; 558 | }; 559 | name = Debug; 560 | }; 561 | 6003F5C1195388D20070C39A /* Release */ = { 562 | isa = XCBuildConfiguration; 563 | baseConfigurationReference = 6E72B0F235168F569F146F66 /* Pods-AVPlayerCacheLibrary_Example.release.xcconfig */; 564 | buildSettings = { 565 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 566 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 567 | CODE_SIGN_STYLE = Automatic; 568 | DEVELOPMENT_TEAM = A8L79FH6QB; 569 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 570 | GCC_PREFIX_HEADER = "AVPlayerCacheLibrary/AVPlayerCacheLibrary-Prefix.pch"; 571 | INFOPLIST_FILE = "AVPlayerCacheLibrary/AVPlayerCacheLibrary-Info.plist"; 572 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 573 | MODULE_NAME = ExampleApp; 574 | PRODUCT_BUNDLE_IDENTIFIER = com.taohailong.avplayer; 575 | PRODUCT_NAME = "$(TARGET_NAME)"; 576 | PROVISIONING_PROFILE = ""; 577 | PROVISIONING_PROFILE_SPECIFIER = ""; 578 | WRAPPER_EXTENSION = app; 579 | }; 580 | name = Release; 581 | }; 582 | 6003F5C3195388D20070C39A /* Debug */ = { 583 | isa = XCBuildConfiguration; 584 | baseConfigurationReference = 55140F6A55DE1D91B40869B6 /* Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig */; 585 | buildSettings = { 586 | BUNDLE_LOADER = "$(TEST_HOST)"; 587 | FRAMEWORK_SEARCH_PATHS = ( 588 | "$(SDKROOT)/Developer/Library/Frameworks", 589 | "$(inherited)", 590 | "$(DEVELOPER_FRAMEWORKS_DIR)", 591 | ); 592 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 593 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 594 | GCC_PREPROCESSOR_DEFINITIONS = ( 595 | "DEBUG=1", 596 | "$(inherited)", 597 | ); 598 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 599 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVPlayerCacheLibrary_Example.app/AVPlayerCacheLibrary_Example"; 602 | WRAPPER_EXTENSION = xctest; 603 | }; 604 | name = Debug; 605 | }; 606 | 6003F5C4195388D20070C39A /* Release */ = { 607 | isa = XCBuildConfiguration; 608 | baseConfigurationReference = E694239EC8CD6A3B30F791F0 /* Pods-AVPlayerCacheLibrary_Tests.release.xcconfig */; 609 | buildSettings = { 610 | BUNDLE_LOADER = "$(TEST_HOST)"; 611 | FRAMEWORK_SEARCH_PATHS = ( 612 | "$(SDKROOT)/Developer/Library/Frameworks", 613 | "$(inherited)", 614 | "$(DEVELOPER_FRAMEWORKS_DIR)", 615 | ); 616 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 617 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 618 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 619 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 620 | PRODUCT_NAME = "$(TARGET_NAME)"; 621 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVPlayerCacheLibrary_Example.app/AVPlayerCacheLibrary_Example"; 622 | WRAPPER_EXTENSION = xctest; 623 | }; 624 | name = Release; 625 | }; 626 | /* End XCBuildConfiguration section */ 627 | 628 | /* Begin XCConfigurationList section */ 629 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "AVPlayerCacheLibrary" */ = { 630 | isa = XCConfigurationList; 631 | buildConfigurations = ( 632 | 6003F5BD195388D20070C39A /* Debug */, 633 | 6003F5BE195388D20070C39A /* Release */, 634 | ); 635 | defaultConfigurationIsVisible = 0; 636 | defaultConfigurationName = Release; 637 | }; 638 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "AVPlayerCacheLibrary_Example" */ = { 639 | isa = XCConfigurationList; 640 | buildConfigurations = ( 641 | 6003F5C0195388D20070C39A /* Debug */, 642 | 6003F5C1195388D20070C39A /* Release */, 643 | ); 644 | defaultConfigurationIsVisible = 0; 645 | defaultConfigurationName = Release; 646 | }; 647 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "AVPlayerCacheLibrary_Tests" */ = { 648 | isa = XCConfigurationList; 649 | buildConfigurations = ( 650 | 6003F5C3195388D20070C39A /* Debug */, 651 | 6003F5C4195388D20070C39A /* Release */, 652 | ); 653 | defaultConfigurationIsVisible = 0; 654 | defaultConfigurationName = Release; 655 | }; 656 | /* End XCConfigurationList section */ 657 | }; 658 | rootObject = 6003F582195388D10070C39A /* Project object */; 659 | } 660 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary.xcodeproj/xcshareddata/xcschemes/AVPlayerCacheLibrary-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 79 | 80 | 81 | 82 | 83 | 84 | 90 | 92 | 98 | 99 | 100 | 101 | 103 | 104 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/AVPlayerCacheLibrary-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | 32 | UIFileSharingEnabled 33 | 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIMainStoryboardFile 37 | Main 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/AVPlayerCacheLibrary-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/NSString+Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Helper.h 3 | // Test 4 | // 5 | // Created by hailong9 on 17/3/7. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Helper) 12 | +(NSString *) localWiFiIPAddress; 13 | + (NSString *) currentWifiSSID; 14 | + (NSString*)lookupHostIPAddressForURL:(NSURL*)url; 15 | @end 16 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/NSString+Helper.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Helper.m 3 | // Test 4 | // 5 | // Created by hailong9 on 17/3/7. 6 | // Copyright © 2017年 hailong9. All rights reserved. 7 | // 8 | 9 | #import "NSString+Helper.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #import 15 | #import 16 | 17 | @implementation NSString (Helper) 18 | + (NSString*)lookupHostIPAddressForURL:(NSURL*)url 19 | { 20 | NSLock * lock = [[NSLock alloc]init]; 21 | [lock lock]; 22 | // Ask the unix subsytem to query the DNS 23 | struct hostent *remoteHostEnt = gethostbyname([[url host] UTF8String]); 24 | // Get address info from host entry 25 | struct in_addr *remoteInAddr = (struct in_addr *) remoteHostEnt->h_addr_list[0]; 26 | // Convert numeric addr to ASCII string 27 | char *sRemoteInAddr = inet_ntoa(*remoteInAddr); 28 | // hostIP 29 | NSString* hostIP = [NSString stringWithUTF8String:sRemoteInAddr]; 30 | [lock unlock]; 31 | return hostIP; 32 | } 33 | 34 | 35 | -(NSString *) getIPWithHostName:(const NSString *)hostName 36 | { 37 | const char *hostN= [hostName UTF8String]; 38 | struct hostent* phot; 39 | 40 | @try { 41 | phot = gethostbyname(hostN); 42 | 43 | } 44 | @catch (NSException *exception) { 45 | return nil; 46 | } 47 | 48 | struct in_addr ip_addr; 49 | memcpy(&ip_addr, phot->h_addr_list[0], 4); 50 | char ip[20] = {0}; 51 | inet_ntop(AF_INET, &ip_addr, ip, sizeof(ip)); 52 | 53 | NSString* strIPAddress = [NSString stringWithUTF8String:ip]; 54 | return strIPAddress; 55 | } 56 | 57 | 58 | +(NSString *) currentWifiSSID 59 | { 60 | #if TARGET_OS_SIMULATOR 61 | return @"(simulator)"; 62 | #else 63 | NSArray *ifs = (__bridge id)CNCopySupportedInterfaces(); 64 | 65 | id info = nil; 66 | for (NSString *ifnam in ifs) { 67 | info = (__bridge id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam); 68 | if (info && [info count]) { 69 | break; 70 | } 71 | } 72 | NSDictionary *dctySSID = (NSDictionary *)info; 73 | NSString *ssid = [dctySSID objectForKey:@"SSID"] ; 74 | 75 | return ssid; 76 | #endif 77 | } 78 | +(NSString *) localWiFiIPAddress 79 | { 80 | BOOL success; 81 | struct ifaddrs * addrs; 82 | const struct ifaddrs * cursor; 83 | 84 | success = getifaddrs(&addrs) == 0; 85 | if (success) { 86 | cursor = addrs; 87 | while (cursor != NULL) { 88 | // the second test keeps from picking up the loopback address 89 | if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) 90 | { 91 | NSString *name = [NSString stringWithUTF8String:cursor->ifa_name]; 92 | if ([name isEqualToString:@"en0"]) // Wi-Fi adapter 93 | return [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)]; 94 | } 95 | cursor = cursor->ifa_next; 96 | } 97 | freeifaddrs(addrs); 98 | } 99 | return nil; 100 | } 101 | @end 102 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/TAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // TAppDelegate.h 3 | // AVPlayerCacheLibrary 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface TAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/TAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // TAppDelegate.m 3 | // AVPlayerCacheLibrary 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TAppDelegate.h" 10 | 11 | @implementation TAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/TViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TViewController.h 3 | // AVPlayerCacheLibrary 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface TViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/TViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TViewController.m 3 | // AVPlayerCacheLibrary 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | #import "TViewController.h" 10 | #import 11 | #import 12 | //#import 13 | @interface TViewController () 14 | { 15 | // AVPlayerItem* _playerItem; 16 | // AVPlayer* _player; 17 | // TVideoLoadManager* _downLoadManager; 18 | 19 | int _currentTime; 20 | UISlider* timeProgress; 21 | TPlayerView* _player; 22 | } 23 | @end 24 | 25 | @implementation TViewController 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | 31 | // _playerItem = [AVPlayerItem playerItemWithAsset:[self generatePlayItem:@"http://gslb.miaopai.com/stream/p2H9cJpKXYlFCW9O93O0gw__.mp4?yx=&KID=unistore,video&Expires=1488963625&ssig=ygmImhzt%2FO"]]; 32 | 33 | // BOOL finish = [TVideoFileManager hasFinishedVideoCache:@"temp2"]; 34 | 35 | // _playerItem = [AVPlayerItem playerItemWithAsset:[self generatePlayItem:@"http://gslb.miaopai.com/stream/QgZbuZjY70~LOyicMJz9NQ__.mp4?yx=&KID=unistore,video&Expires=1488340984&ssig=9xbm%2BqHngF"]]; 36 | // http://us.sinaimg.cn/0042YuPwjx07fyprKe9101040100Wfxu0k01.mp4?label=mp4_hd&KID=unistore,video&Expires=1511351294&ssig=WqGRXnxe9w 37 | NSString* url = @"http://gslb.miaopai.com/stream/QgZbuZjY70~LOyicMJz9NQ__.mp4?yx=&KID=unistore,video&Expires=1488340984&ssig=9xbm%2BqHngF"; 38 | // url = @"http://alcdn.hls.xiaoka.tv/2018614/e11/279/usLFjccI7tBScB0P/index.m3u8?Expires=1528954910&ssig=qZXqmORrTY&KID=unistore,video"; 39 | _player = [[TPlayerView alloc]initWithFrame:self.view.bounds withDelegate:self]; 40 | [_player loadVideoDataWithUrl:url withVideoName:@"temp"]; 41 | [self.view addSubview:_player]; 42 | 43 | 44 | UIButton* bt = [UIButton buttonWithType:UIButtonTypeCustom]; 45 | [bt setTitle:@"清理缓存" forState:UIControlStateNormal]; 46 | bt.frame = CGRectMake(50, self.view.frame.size.height - 60, 80, 30); 47 | [self.view addSubview:bt]; 48 | bt.backgroundColor = [UIColor redColor]; 49 | [bt addTarget:self action:@selector(playerSkip) forControlEvents:UIControlEventTouchUpInside]; 50 | 51 | 52 | UIButton* bt1 = [UIButton buttonWithType:UIButtonTypeCustom]; 53 | [bt1 setTitle:@"start" forState:UIControlStateNormal]; 54 | bt1.frame = CGRectMake(250, self.view.frame.size.height - 100, 80, 30); 55 | [self.view addSubview:bt1]; 56 | bt1.backgroundColor = [UIColor redColor]; 57 | [bt1 addTarget:self action:@selector(startPlay) forControlEvents:UIControlEventTouchUpInside]; 58 | 59 | 60 | timeProgress = [[UISlider alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 30, self.view.frame.size.width, 30)]; 61 | timeProgress.minimumValue = 0; 62 | timeProgress.maximumValue = 0; 63 | [self.view addSubview:timeProgress]; 64 | [timeProgress addTarget:self action:@selector(sliderChange:) forControlEvents:UIControlEventTouchUpInside]; 65 | 66 | // Do any additional setup after loading the view, typically from a nib. 67 | } 68 | - (void)startPlay 69 | { 70 | [_player loadVideoData]; 71 | } 72 | 73 | 74 | - (void)playerSkip 75 | { 76 | [_player pause]; 77 | [TVideoFileManager clearCache]; 78 | UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"确定重新启动" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; 79 | [alert show]; 80 | } 81 | 82 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 83 | exit(0); 84 | } 85 | 86 | - (void)playerSeekTo:(NSUInteger)value 87 | { 88 | [_player playerSeekToSecond:value]; 89 | 90 | } 91 | 92 | - (void)sliderChange:(UISlider*)value 93 | { 94 | [self playerSeekTo:value.value]; 95 | } 96 | 97 | #pragma mark ---playerDelegate - 98 | 99 | - (void)playerVideoTotalTime:(int64_t)seconds{ 100 | timeProgress.maximumValue = seconds; 101 | } 102 | 103 | - (void)playerPlayOver{ 104 | 105 | } 106 | - (void)didReceiveMemoryWarning 107 | { 108 | [super didReceiveMemoryWarning]; 109 | // Dispose of any resources that can be recreated. 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/AVPlayerCacheLibrary/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AVPlayerCacheLibrary 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "TAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([TAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'AVPlayerCacheLibrary_Example' do 4 | pod 'AVPlayerCacheLibrary', :path => '../' 5 | 6 | target 'AVPlayerCacheLibrary_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AVPlayerCacheLibrary (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - AVPlayerCacheLibrary (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | AVPlayerCacheLibrary: 9 | :path: ../ 10 | 11 | SPEC CHECKSUMS: 12 | AVPlayerCacheLibrary: a04640935a1e54d702f26d46afa0235ff8fd4a99 13 | 14 | PODFILE CHECKSUM: 2e922b1ca5fd1e394d6e1b41719f7fc17a0eeac2 15 | 16 | COCOAPODS: 1.1.1 17 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/AVPlayerCacheLibrary.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AVPlayerCacheLibrary", 3 | "version": "0.1.0", 4 | "summary": "AVPlayerCacheLibrary can cache avplayer video data", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com/hailong9/AVPlayerCacheLibrary", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "hailong9": "hailong9@staff.sina.com.cn" 13 | }, 14 | "source": { 15 | "git": "https://github.com/taohailong/AVPlayerCache.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "7.0" 20 | }, 21 | "source_files": "AVPlayerCacheLibrary/Classes/**/*" 22 | } 23 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AVPlayerCacheLibrary (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - AVPlayerCacheLibrary (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | AVPlayerCacheLibrary: 9 | :path: ../ 10 | 11 | SPEC CHECKSUMS: 12 | AVPlayerCacheLibrary: a04640935a1e54d702f26d46afa0235ff8fd4a99 13 | 14 | PODFILE CHECKSUM: 2e922b1ca5fd1e394d6e1b41719f7fc17a0eeac2 15 | 16 | COCOAPODS: 1.1.1 17 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 052F0D08D8D7BA2E98789F3EF6ADB644 /* TVideoDownQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 57EF1871A471CB57C8398568D33CB189 /* TVideoDownQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 15D49D0B3703E76EFCF777BF82633821 /* Pods-AVPlayerCacheLibrary_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BD25E863778BC52B085FB426D90C43FB /* Pods-AVPlayerCacheLibrary_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | 1B58B214B54AB3E3964D1F57EE58276B /* Pods-AVPlayerCacheLibrary_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 325F295AB4104D4E0D99986B5E0F6B2B /* Pods-AVPlayerCacheLibrary_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 1BB7D770F8DB229E0F40668939C049FF /* Pods-AVPlayerCacheLibrary_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B7B6235028DBF45E841BB2128F172D13 /* Pods-AVPlayerCacheLibrary_Example-dummy.m */; }; 14 | 25E6A8D73C1DEC03A1FC7EEA16E187D2 /* TVideoLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC2EDB0EA856D22C7D0F1B1D4C48F41 /* TVideoLoader.m */; }; 15 | 28DE7B9A5E64759BB2060BCFA8395C25 /* TVideoFileManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDD70744C31D09E8C23DAB4F65D886 /* TVideoFileManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | 4224A6B6CED71C5984060E4B33B48A77 /* Pods-AVPlayerCacheLibrary_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2F5EEB122D69144D58BD5BAB5CFE1D3 /* Pods-AVPlayerCacheLibrary_Tests-dummy.m */; }; 17 | 57AB5637BA4C2B9AEEEAF9E751432C91 /* TVideoDownQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = A1C8BD3B5E36880EB8D94287BC5D3E60 /* TVideoDownQueue.m */; }; 18 | 5BCF0BCA7A97D5E76BF4551A6564EB8E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 19 | 5F9C060E0008ACB6A5277F727BE2F311 /* TVideoLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F29FF7CFF8266EB0C4AC40D7CFA98EB5 /* TVideoLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | 8B6CEB0B88EA7012A905C3512F565249 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 21 | 8BD65E10DC66D623B1CE2A1F6D7B0579 /* TVideoFileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C9DBA014659BE91F72517BBB30139B31 /* TVideoFileManager.m */; }; 22 | 964F4C5F745B4941282C9FD428C18DF6 /* AVPlayerCacheLibrary-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5795518C0D090336F6BA6C0B1F2D0C94 /* AVPlayerCacheLibrary-dummy.m */; }; 23 | 983F921F956D85FBF0682CAA135067A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */; }; 24 | AB6B73349934FA4F3FED2F6BFD8E9DA8 /* TVideoLoadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D48F3823F7350408C90EC65F13AE7F7 /* TVideoLoadManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | D43B599879C63C03E681902320E1F6FB /* TVideoDownOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BA3BD6F45498AFE653C27350F93984 /* TVideoDownOperation.m */; }; 26 | DE82A7A195F037CA647AC9B258F96102 /* ReplaceMe.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EDEFE4F1D3A16B1B12319AAAE967A65 /* ReplaceMe.m */; }; 27 | DF6A576FAD3C48E54F5A576E4C1E5E08 /* TVideoLoadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECFE38695B38789768643C1C3DF8C8 /* TVideoLoadManager.m */; }; 28 | E146725B8180C1474EA92E664E94FE8C /* TPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = F22ED793BCB3A005A7BCF7F0DCC38788 /* TPlayerView.m */; }; 29 | EA9630C841B26376FA10AAD6C8C34D21 /* AVPlayerCacheLibrary-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CE46284EB11CD22C9AA0C584276A57E8 /* AVPlayerCacheLibrary-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | FBBA0DB225BEB58F8BC5395926909778 /* TVideoDownOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = BA7039803D3D5F057A7FC9AFE4C4568A /* TVideoDownOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 31 | FCBF9CB50C953B60F60C82A32D7E2F14 /* TPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = AD1A0CF8147C602E88B7A096D06680AE /* TPlayerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32 | /* End PBXBuildFile section */ 33 | 34 | /* Begin PBXContainerItemProxy section */ 35 | 4AE175E31AC1711E680E98300C6194CF /* PBXContainerItemProxy */ = { 36 | isa = PBXContainerItemProxy; 37 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 38 | proxyType = 1; 39 | remoteGlobalIDString = DA28F951CE3F21F38667485005CC06B5; 40 | remoteInfo = AVPlayerCacheLibrary; 41 | }; 42 | /* End PBXContainerItemProxy section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | 0130B8F8DCEE876F45E8C44737EF5334 /* Pods-AVPlayerCacheLibrary_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-AVPlayerCacheLibrary_Example-acknowledgements.plist"; sourceTree = ""; }; 46 | 03BA3BD6F45498AFE653C27350F93984 /* TVideoDownOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TVideoDownOperation.m; sourceTree = ""; }; 47 | 04BDD70744C31D09E8C23DAB4F65D886 /* TVideoFileManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TVideoFileManager.h; sourceTree = ""; }; 48 | 13095B9C2A6D98322893E4988A4EB252 /* AVPlayerCacheLibrary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = AVPlayerCacheLibrary.framework; path = AVPlayerCacheLibrary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 1C72B1CB344525D201DDB5D454CAEB1B /* Pods-AVPlayerCacheLibrary_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-AVPlayerCacheLibrary_Example.release.xcconfig"; sourceTree = ""; }; 50 | 20F5329723388244095039CB26D39A40 /* Pods-AVPlayerCacheLibrary_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-AVPlayerCacheLibrary_Example-resources.sh"; sourceTree = ""; }; 51 | 225FAD93BB6663FE718CAA7617709732 /* Pods-AVPlayerCacheLibrary_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-AVPlayerCacheLibrary_Tests-acknowledgements.markdown"; sourceTree = ""; }; 52 | 2540822E2FA479D3B54543294772F9A8 /* Pods-AVPlayerCacheLibrary_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-AVPlayerCacheLibrary_Tests.modulemap"; sourceTree = ""; }; 53 | 2D48F3823F7350408C90EC65F13AE7F7 /* TVideoLoadManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TVideoLoadManager.h; sourceTree = ""; }; 54 | 325F295AB4104D4E0D99986B5E0F6B2B /* Pods-AVPlayerCacheLibrary_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-AVPlayerCacheLibrary_Tests-umbrella.h"; sourceTree = ""; }; 55 | 3538CAA6B03CBFF2BAF910671B89CC55 /* Pods-AVPlayerCacheLibrary_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-AVPlayerCacheLibrary_Example.debug.xcconfig"; sourceTree = ""; }; 56 | 3B8E7DEF39F108385958D426FE9E4FC6 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 3C48E7A87FB23008F7FC3BDB6B53C507 /* AVPlayerCacheLibrary-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AVPlayerCacheLibrary-prefix.pch"; sourceTree = ""; }; 58 | 472991DB7968CA363ADEBBE4FDC99786 /* Pods_AVPlayerCacheLibrary_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_AVPlayerCacheLibrary_Example.framework; path = "Pods-AVPlayerCacheLibrary_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 513C4F3E7DF68887B3B26DC6DBDBBB24 /* Pods-AVPlayerCacheLibrary_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-AVPlayerCacheLibrary_Example.modulemap"; sourceTree = ""; }; 60 | 5795518C0D090336F6BA6C0B1F2D0C94 /* AVPlayerCacheLibrary-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AVPlayerCacheLibrary-dummy.m"; sourceTree = ""; }; 61 | 57EF1871A471CB57C8398568D33CB189 /* TVideoDownQueue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TVideoDownQueue.h; sourceTree = ""; }; 62 | 667421D72E06ED90940BDBBC831FC46E /* Pods-AVPlayerCacheLibrary_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-AVPlayerCacheLibrary_Tests-resources.sh"; sourceTree = ""; }; 63 | 75B351DCBCED384CE9FB6C10DF59F9EA /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 7EDEFE4F1D3A16B1B12319AAAE967A65 /* ReplaceMe.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = ReplaceMe.m; sourceTree = ""; }; 65 | 84CF08BAADD1DD8888E38781E97EE798 /* Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig"; sourceTree = ""; }; 66 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 67 | 9DF26FCC1E976BC4C72AD8846B6B2FFC /* Pods-AVPlayerCacheLibrary_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-AVPlayerCacheLibrary_Example-frameworks.sh"; sourceTree = ""; }; 68 | A1C8BD3B5E36880EB8D94287BC5D3E60 /* TVideoDownQueue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TVideoDownQueue.m; sourceTree = ""; }; 69 | A31AE5D35FA0004A89AAAEA623627218 /* Pods-AVPlayerCacheLibrary_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-AVPlayerCacheLibrary_Tests.release.xcconfig"; sourceTree = ""; }; 70 | A656542F31BD6572227E14B33AE6ED05 /* AVPlayerCacheLibrary.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = AVPlayerCacheLibrary.modulemap; sourceTree = ""; }; 71 | ABC2EDB0EA856D22C7D0F1B1D4C48F41 /* TVideoLoader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TVideoLoader.m; sourceTree = ""; }; 72 | AD1A0CF8147C602E88B7A096D06680AE /* TPlayerView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TPlayerView.h; sourceTree = ""; }; 73 | B4E621DEAEF98526AD61901F89C3C48B /* Pods-AVPlayerCacheLibrary_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-AVPlayerCacheLibrary_Example-acknowledgements.markdown"; sourceTree = ""; }; 74 | B7B6235028DBF45E841BB2128F172D13 /* Pods-AVPlayerCacheLibrary_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-AVPlayerCacheLibrary_Example-dummy.m"; sourceTree = ""; }; 75 | BA7039803D3D5F057A7FC9AFE4C4568A /* TVideoDownOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TVideoDownOperation.h; sourceTree = ""; }; 76 | BD25E863778BC52B085FB426D90C43FB /* Pods-AVPlayerCacheLibrary_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-AVPlayerCacheLibrary_Example-umbrella.h"; sourceTree = ""; }; 77 | C2F5EEB122D69144D58BD5BAB5CFE1D3 /* Pods-AVPlayerCacheLibrary_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-AVPlayerCacheLibrary_Tests-dummy.m"; sourceTree = ""; }; 78 | C9DBA014659BE91F72517BBB30139B31 /* TVideoFileManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TVideoFileManager.m; sourceTree = ""; }; 79 | CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 80 | CE46284EB11CD22C9AA0C584276A57E8 /* AVPlayerCacheLibrary-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AVPlayerCacheLibrary-umbrella.h"; sourceTree = ""; }; 81 | D080BC9C972300225503DF5946D4F5C8 /* Pods_AVPlayerCacheLibrary_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_AVPlayerCacheLibrary_Tests.framework; path = "Pods-AVPlayerCacheLibrary_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | D4ECFE38695B38789768643C1C3DF8C8 /* TVideoLoadManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TVideoLoadManager.m; sourceTree = ""; }; 83 | D7372FB0F9F377CA7F935A9093515C5F /* AVPlayerCacheLibrary.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AVPlayerCacheLibrary.xcconfig; sourceTree = ""; }; 84 | DD735400EFCB8B905301336D7109767E /* Pods-AVPlayerCacheLibrary_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-AVPlayerCacheLibrary_Tests-acknowledgements.plist"; sourceTree = ""; }; 85 | F22ED793BCB3A005A7BCF7F0DCC38788 /* TPlayerView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = TPlayerView.m; sourceTree = ""; }; 86 | F29FF7CFF8266EB0C4AC40D7CFA98EB5 /* TVideoLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = TVideoLoader.h; sourceTree = ""; }; 87 | F57C6383A397995218BCF946DB431A03 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 88 | F5F259DFA01D5B30C98DB6594C174393 /* Pods-AVPlayerCacheLibrary_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-AVPlayerCacheLibrary_Tests-frameworks.sh"; sourceTree = ""; }; 89 | /* End PBXFileReference section */ 90 | 91 | /* Begin PBXFrameworksBuildPhase section */ 92 | BB4E02E77F991F8A77CF1E2818A3CFFD /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | 983F921F956D85FBF0682CAA135067A7 /* Foundation.framework in Frameworks */, 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | EAC4218735D981C95D8D2BCADE57360E /* Frameworks */ = { 101 | isa = PBXFrameworksBuildPhase; 102 | buildActionMask = 2147483647; 103 | files = ( 104 | 5BCF0BCA7A97D5E76BF4551A6564EB8E /* Foundation.framework in Frameworks */, 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | FB9C1922F4281F504F48445E08615413 /* Frameworks */ = { 109 | isa = PBXFrameworksBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | 8B6CEB0B88EA7012A905C3512F565249 /* Foundation.framework in Frameworks */, 113 | ); 114 | runOnlyForDeploymentPostprocessing = 0; 115 | }; 116 | /* End PBXFrameworksBuildPhase section */ 117 | 118 | /* Begin PBXGroup section */ 119 | 063B2415893857BD9D74ACFE73126FE5 /* AVPlayerCacheLibrary */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 72BA2F5344C102B402D667A2B7DF2CFB /* AVPlayerCacheLibrary */, 123 | C5732DCB8C4E5B16A48438A0E54EC1C5 /* Support Files */, 124 | ); 125 | name = AVPlayerCacheLibrary; 126 | path = ../..; 127 | sourceTree = ""; 128 | }; 129 | 4B1176080A857ECF6E08D6DEA600DFC2 /* Targets Support Files */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | ACEF76640FC41A9B032062E84A05BA17 /* Pods-AVPlayerCacheLibrary_Example */, 133 | F77D0D452B6925DC1C6A592439E36633 /* Pods-AVPlayerCacheLibrary_Tests */, 134 | ); 135 | name = "Targets Support Files"; 136 | sourceTree = ""; 137 | }; 138 | 6F903CAC5E18522C7329869DD42284B6 /* Products */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 13095B9C2A6D98322893E4988A4EB252 /* AVPlayerCacheLibrary.framework */, 142 | 472991DB7968CA363ADEBBE4FDC99786 /* Pods_AVPlayerCacheLibrary_Example.framework */, 143 | D080BC9C972300225503DF5946D4F5C8 /* Pods_AVPlayerCacheLibrary_Tests.framework */, 144 | ); 145 | name = Products; 146 | sourceTree = ""; 147 | }; 148 | 72BA2F5344C102B402D667A2B7DF2CFB /* AVPlayerCacheLibrary */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | FD9B828FDB527E9894FF90BC8E03444C /* Classes */, 152 | ); 153 | name = AVPlayerCacheLibrary; 154 | path = AVPlayerCacheLibrary; 155 | sourceTree = ""; 156 | }; 157 | 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | CBB3DE36805AF21409EC968A9691732F /* Foundation.framework */, 161 | ); 162 | name = iOS; 163 | sourceTree = ""; 164 | }; 165 | 7DB346D0F39D3F0E887471402A8071AB = { 166 | isa = PBXGroup; 167 | children = ( 168 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 169 | 8ECAC0D0CEB8F6F936461A38E6FF67EB /* Development Pods */, 170 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 171 | 6F903CAC5E18522C7329869DD42284B6 /* Products */, 172 | 4B1176080A857ECF6E08D6DEA600DFC2 /* Targets Support Files */, 173 | ); 174 | sourceTree = ""; 175 | }; 176 | 8ECAC0D0CEB8F6F936461A38E6FF67EB /* Development Pods */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 063B2415893857BD9D74ACFE73126FE5 /* AVPlayerCacheLibrary */, 180 | ); 181 | name = "Development Pods"; 182 | sourceTree = ""; 183 | }; 184 | ACEF76640FC41A9B032062E84A05BA17 /* Pods-AVPlayerCacheLibrary_Example */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | 75B351DCBCED384CE9FB6C10DF59F9EA /* Info.plist */, 188 | 513C4F3E7DF68887B3B26DC6DBDBBB24 /* Pods-AVPlayerCacheLibrary_Example.modulemap */, 189 | B4E621DEAEF98526AD61901F89C3C48B /* Pods-AVPlayerCacheLibrary_Example-acknowledgements.markdown */, 190 | 0130B8F8DCEE876F45E8C44737EF5334 /* Pods-AVPlayerCacheLibrary_Example-acknowledgements.plist */, 191 | B7B6235028DBF45E841BB2128F172D13 /* Pods-AVPlayerCacheLibrary_Example-dummy.m */, 192 | 9DF26FCC1E976BC4C72AD8846B6B2FFC /* Pods-AVPlayerCacheLibrary_Example-frameworks.sh */, 193 | 20F5329723388244095039CB26D39A40 /* Pods-AVPlayerCacheLibrary_Example-resources.sh */, 194 | BD25E863778BC52B085FB426D90C43FB /* Pods-AVPlayerCacheLibrary_Example-umbrella.h */, 195 | 3538CAA6B03CBFF2BAF910671B89CC55 /* Pods-AVPlayerCacheLibrary_Example.debug.xcconfig */, 196 | 1C72B1CB344525D201DDB5D454CAEB1B /* Pods-AVPlayerCacheLibrary_Example.release.xcconfig */, 197 | ); 198 | name = "Pods-AVPlayerCacheLibrary_Example"; 199 | path = "Target Support Files/Pods-AVPlayerCacheLibrary_Example"; 200 | sourceTree = ""; 201 | }; 202 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 7531C8F8DE19F1AA3C8A7AC97A91DC29 /* iOS */, 206 | ); 207 | name = Frameworks; 208 | sourceTree = ""; 209 | }; 210 | C5732DCB8C4E5B16A48438A0E54EC1C5 /* Support Files */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | A656542F31BD6572227E14B33AE6ED05 /* AVPlayerCacheLibrary.modulemap */, 214 | D7372FB0F9F377CA7F935A9093515C5F /* AVPlayerCacheLibrary.xcconfig */, 215 | 5795518C0D090336F6BA6C0B1F2D0C94 /* AVPlayerCacheLibrary-dummy.m */, 216 | 3C48E7A87FB23008F7FC3BDB6B53C507 /* AVPlayerCacheLibrary-prefix.pch */, 217 | CE46284EB11CD22C9AA0C584276A57E8 /* AVPlayerCacheLibrary-umbrella.h */, 218 | 3B8E7DEF39F108385958D426FE9E4FC6 /* Info.plist */, 219 | ); 220 | name = "Support Files"; 221 | path = "Example/Pods/Target Support Files/AVPlayerCacheLibrary"; 222 | sourceTree = ""; 223 | }; 224 | F77D0D452B6925DC1C6A592439E36633 /* Pods-AVPlayerCacheLibrary_Tests */ = { 225 | isa = PBXGroup; 226 | children = ( 227 | F57C6383A397995218BCF946DB431A03 /* Info.plist */, 228 | 2540822E2FA479D3B54543294772F9A8 /* Pods-AVPlayerCacheLibrary_Tests.modulemap */, 229 | 225FAD93BB6663FE718CAA7617709732 /* Pods-AVPlayerCacheLibrary_Tests-acknowledgements.markdown */, 230 | DD735400EFCB8B905301336D7109767E /* Pods-AVPlayerCacheLibrary_Tests-acknowledgements.plist */, 231 | C2F5EEB122D69144D58BD5BAB5CFE1D3 /* Pods-AVPlayerCacheLibrary_Tests-dummy.m */, 232 | F5F259DFA01D5B30C98DB6594C174393 /* Pods-AVPlayerCacheLibrary_Tests-frameworks.sh */, 233 | 667421D72E06ED90940BDBBC831FC46E /* Pods-AVPlayerCacheLibrary_Tests-resources.sh */, 234 | 325F295AB4104D4E0D99986B5E0F6B2B /* Pods-AVPlayerCacheLibrary_Tests-umbrella.h */, 235 | 84CF08BAADD1DD8888E38781E97EE798 /* Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig */, 236 | A31AE5D35FA0004A89AAAEA623627218 /* Pods-AVPlayerCacheLibrary_Tests.release.xcconfig */, 237 | ); 238 | name = "Pods-AVPlayerCacheLibrary_Tests"; 239 | path = "Target Support Files/Pods-AVPlayerCacheLibrary_Tests"; 240 | sourceTree = ""; 241 | }; 242 | FD9B828FDB527E9894FF90BC8E03444C /* Classes */ = { 243 | isa = PBXGroup; 244 | children = ( 245 | 7EDEFE4F1D3A16B1B12319AAAE967A65 /* ReplaceMe.m */, 246 | AD1A0CF8147C602E88B7A096D06680AE /* TPlayerView.h */, 247 | F22ED793BCB3A005A7BCF7F0DCC38788 /* TPlayerView.m */, 248 | BA7039803D3D5F057A7FC9AFE4C4568A /* TVideoDownOperation.h */, 249 | 03BA3BD6F45498AFE653C27350F93984 /* TVideoDownOperation.m */, 250 | 57EF1871A471CB57C8398568D33CB189 /* TVideoDownQueue.h */, 251 | A1C8BD3B5E36880EB8D94287BC5D3E60 /* TVideoDownQueue.m */, 252 | 04BDD70744C31D09E8C23DAB4F65D886 /* TVideoFileManager.h */, 253 | C9DBA014659BE91F72517BBB30139B31 /* TVideoFileManager.m */, 254 | F29FF7CFF8266EB0C4AC40D7CFA98EB5 /* TVideoLoader.h */, 255 | ABC2EDB0EA856D22C7D0F1B1D4C48F41 /* TVideoLoader.m */, 256 | 2D48F3823F7350408C90EC65F13AE7F7 /* TVideoLoadManager.h */, 257 | D4ECFE38695B38789768643C1C3DF8C8 /* TVideoLoadManager.m */, 258 | ); 259 | name = Classes; 260 | path = Classes; 261 | sourceTree = ""; 262 | }; 263 | /* End PBXGroup section */ 264 | 265 | /* Begin PBXHeadersBuildPhase section */ 266 | 0DF9751FB85856539DDE45FDDF77648C /* Headers */ = { 267 | isa = PBXHeadersBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | 1B58B214B54AB3E3964D1F57EE58276B /* Pods-AVPlayerCacheLibrary_Tests-umbrella.h in Headers */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | 76EE857771E1D8C5902A223428083C9D /* Headers */ = { 275 | isa = PBXHeadersBuildPhase; 276 | buildActionMask = 2147483647; 277 | files = ( 278 | 15D49D0B3703E76EFCF777BF82633821 /* Pods-AVPlayerCacheLibrary_Example-umbrella.h in Headers */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | 8EB83AC177FD0239B9A54045EB7E2627 /* Headers */ = { 283 | isa = PBXHeadersBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | EA9630C841B26376FA10AAD6C8C34D21 /* AVPlayerCacheLibrary-umbrella.h in Headers */, 287 | FCBF9CB50C953B60F60C82A32D7E2F14 /* TPlayerView.h in Headers */, 288 | FBBA0DB225BEB58F8BC5395926909778 /* TVideoDownOperation.h in Headers */, 289 | 052F0D08D8D7BA2E98789F3EF6ADB644 /* TVideoDownQueue.h in Headers */, 290 | 28DE7B9A5E64759BB2060BCFA8395C25 /* TVideoFileManager.h in Headers */, 291 | 5F9C060E0008ACB6A5277F727BE2F311 /* TVideoLoader.h in Headers */, 292 | AB6B73349934FA4F3FED2F6BFD8E9DA8 /* TVideoLoadManager.h in Headers */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | /* End PBXHeadersBuildPhase section */ 297 | 298 | /* Begin PBXNativeTarget section */ 299 | AAF2912EE4116EE414D899F45A7B0E00 /* Pods-AVPlayerCacheLibrary_Tests */ = { 300 | isa = PBXNativeTarget; 301 | buildConfigurationList = 146627D1C1B27875A335C1254CF9427B /* Build configuration list for PBXNativeTarget "Pods-AVPlayerCacheLibrary_Tests" */; 302 | buildPhases = ( 303 | 4A8F2544455950A552E36DC120757231 /* Sources */, 304 | EAC4218735D981C95D8D2BCADE57360E /* Frameworks */, 305 | 0DF9751FB85856539DDE45FDDF77648C /* Headers */, 306 | ); 307 | buildRules = ( 308 | ); 309 | dependencies = ( 310 | ); 311 | name = "Pods-AVPlayerCacheLibrary_Tests"; 312 | productName = "Pods-AVPlayerCacheLibrary_Tests"; 313 | productReference = D080BC9C972300225503DF5946D4F5C8 /* Pods_AVPlayerCacheLibrary_Tests.framework */; 314 | productType = "com.apple.product-type.framework"; 315 | }; 316 | DA28F951CE3F21F38667485005CC06B5 /* AVPlayerCacheLibrary */ = { 317 | isa = PBXNativeTarget; 318 | buildConfigurationList = FCAC95011AA0FB89AABEC12B4DFD66F0 /* Build configuration list for PBXNativeTarget "AVPlayerCacheLibrary" */; 319 | buildPhases = ( 320 | E56FF25140606193E1260812661ADA8E /* Sources */, 321 | FB9C1922F4281F504F48445E08615413 /* Frameworks */, 322 | 8EB83AC177FD0239B9A54045EB7E2627 /* Headers */, 323 | ); 324 | buildRules = ( 325 | ); 326 | dependencies = ( 327 | ); 328 | name = AVPlayerCacheLibrary; 329 | productName = AVPlayerCacheLibrary; 330 | productReference = 13095B9C2A6D98322893E4988A4EB252 /* AVPlayerCacheLibrary.framework */; 331 | productType = "com.apple.product-type.framework"; 332 | }; 333 | FF852645389FC6867053B5B7B77C2EE7 /* Pods-AVPlayerCacheLibrary_Example */ = { 334 | isa = PBXNativeTarget; 335 | buildConfigurationList = 51ABAEE0FA0CAD5893D903B8A480B106 /* Build configuration list for PBXNativeTarget "Pods-AVPlayerCacheLibrary_Example" */; 336 | buildPhases = ( 337 | F5FA155DA4131097E82AE0F351C978AF /* Sources */, 338 | BB4E02E77F991F8A77CF1E2818A3CFFD /* Frameworks */, 339 | 76EE857771E1D8C5902A223428083C9D /* Headers */, 340 | ); 341 | buildRules = ( 342 | ); 343 | dependencies = ( 344 | 333BB48B102A84D7948E00D273AB4412 /* PBXTargetDependency */, 345 | ); 346 | name = "Pods-AVPlayerCacheLibrary_Example"; 347 | productName = "Pods-AVPlayerCacheLibrary_Example"; 348 | productReference = 472991DB7968CA363ADEBBE4FDC99786 /* Pods_AVPlayerCacheLibrary_Example.framework */; 349 | productType = "com.apple.product-type.framework"; 350 | }; 351 | /* End PBXNativeTarget section */ 352 | 353 | /* Begin PBXProject section */ 354 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 355 | isa = PBXProject; 356 | attributes = { 357 | LastSwiftUpdateCheck = 0730; 358 | LastUpgradeCheck = 0700; 359 | }; 360 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 361 | compatibilityVersion = "Xcode 3.2"; 362 | developmentRegion = English; 363 | hasScannedForEncodings = 0; 364 | knownRegions = ( 365 | en, 366 | ); 367 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 368 | productRefGroup = 6F903CAC5E18522C7329869DD42284B6 /* Products */; 369 | projectDirPath = ""; 370 | projectRoot = ""; 371 | targets = ( 372 | DA28F951CE3F21F38667485005CC06B5 /* AVPlayerCacheLibrary */, 373 | FF852645389FC6867053B5B7B77C2EE7 /* Pods-AVPlayerCacheLibrary_Example */, 374 | AAF2912EE4116EE414D899F45A7B0E00 /* Pods-AVPlayerCacheLibrary_Tests */, 375 | ); 376 | }; 377 | /* End PBXProject section */ 378 | 379 | /* Begin PBXSourcesBuildPhase section */ 380 | 4A8F2544455950A552E36DC120757231 /* Sources */ = { 381 | isa = PBXSourcesBuildPhase; 382 | buildActionMask = 2147483647; 383 | files = ( 384 | 4224A6B6CED71C5984060E4B33B48A77 /* Pods-AVPlayerCacheLibrary_Tests-dummy.m in Sources */, 385 | ); 386 | runOnlyForDeploymentPostprocessing = 0; 387 | }; 388 | E56FF25140606193E1260812661ADA8E /* Sources */ = { 389 | isa = PBXSourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | 964F4C5F745B4941282C9FD428C18DF6 /* AVPlayerCacheLibrary-dummy.m in Sources */, 393 | DE82A7A195F037CA647AC9B258F96102 /* ReplaceMe.m in Sources */, 394 | E146725B8180C1474EA92E664E94FE8C /* TPlayerView.m in Sources */, 395 | D43B599879C63C03E681902320E1F6FB /* TVideoDownOperation.m in Sources */, 396 | 57AB5637BA4C2B9AEEEAF9E751432C91 /* TVideoDownQueue.m in Sources */, 397 | 8BD65E10DC66D623B1CE2A1F6D7B0579 /* TVideoFileManager.m in Sources */, 398 | 25E6A8D73C1DEC03A1FC7EEA16E187D2 /* TVideoLoader.m in Sources */, 399 | DF6A576FAD3C48E54F5A576E4C1E5E08 /* TVideoLoadManager.m in Sources */, 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | }; 403 | F5FA155DA4131097E82AE0F351C978AF /* Sources */ = { 404 | isa = PBXSourcesBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | 1BB7D770F8DB229E0F40668939C049FF /* Pods-AVPlayerCacheLibrary_Example-dummy.m in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | /* End PBXSourcesBuildPhase section */ 412 | 413 | /* Begin PBXTargetDependency section */ 414 | 333BB48B102A84D7948E00D273AB4412 /* PBXTargetDependency */ = { 415 | isa = PBXTargetDependency; 416 | name = AVPlayerCacheLibrary; 417 | target = DA28F951CE3F21F38667485005CC06B5 /* AVPlayerCacheLibrary */; 418 | targetProxy = 4AE175E31AC1711E680E98300C6194CF /* PBXContainerItemProxy */; 419 | }; 420 | /* End PBXTargetDependency section */ 421 | 422 | /* Begin XCBuildConfiguration section */ 423 | 06B2D3E348CA1CC5910825BFB556DD88 /* Debug */ = { 424 | isa = XCBuildConfiguration; 425 | baseConfigurationReference = D7372FB0F9F377CA7F935A9093515C5F /* AVPlayerCacheLibrary.xcconfig */; 426 | buildSettings = { 427 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 428 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 429 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 430 | CURRENT_PROJECT_VERSION = 1; 431 | DEBUG_INFORMATION_FORMAT = dwarf; 432 | DEFINES_MODULE = YES; 433 | DYLIB_COMPATIBILITY_VERSION = 1; 434 | DYLIB_CURRENT_VERSION = 1; 435 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 436 | ENABLE_STRICT_OBJC_MSGSEND = YES; 437 | GCC_NO_COMMON_BLOCKS = YES; 438 | GCC_PREFIX_HEADER = "Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary-prefix.pch"; 439 | INFOPLIST_FILE = "Target Support Files/AVPlayerCacheLibrary/Info.plist"; 440 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 441 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 442 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 443 | MODULEMAP_FILE = "Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary.modulemap"; 444 | MTL_ENABLE_DEBUG_INFO = YES; 445 | PRODUCT_NAME = AVPlayerCacheLibrary; 446 | SDKROOT = iphoneos; 447 | SKIP_INSTALL = YES; 448 | TARGETED_DEVICE_FAMILY = "1,2"; 449 | VERSIONING_SYSTEM = "apple-generic"; 450 | VERSION_INFO_PREFIX = ""; 451 | }; 452 | name = Debug; 453 | }; 454 | 3E60A7B9AF058D2E5995A67E948E39C7 /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = A31AE5D35FA0004A89AAAEA623627218 /* Pods-AVPlayerCacheLibrary_Tests.release.xcconfig */; 457 | buildSettings = { 458 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 460 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 461 | CURRENT_PROJECT_VERSION = 1; 462 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 463 | DEFINES_MODULE = YES; 464 | DYLIB_COMPATIBILITY_VERSION = 1; 465 | DYLIB_CURRENT_VERSION = 1; 466 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 467 | ENABLE_STRICT_OBJC_MSGSEND = YES; 468 | GCC_NO_COMMON_BLOCKS = YES; 469 | INFOPLIST_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Info.plist"; 470 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 471 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 473 | MACH_O_TYPE = staticlib; 474 | MODULEMAP_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests.modulemap"; 475 | MTL_ENABLE_DEBUG_INFO = NO; 476 | OTHER_LDFLAGS = ""; 477 | OTHER_LIBTOOLFLAGS = ""; 478 | PODS_ROOT = "$(SRCROOT)"; 479 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 480 | PRODUCT_NAME = Pods_AVPlayerCacheLibrary_Tests; 481 | SDKROOT = iphoneos; 482 | SKIP_INSTALL = YES; 483 | TARGETED_DEVICE_FAMILY = "1,2"; 484 | VERSIONING_SYSTEM = "apple-generic"; 485 | VERSION_INFO_PREFIX = ""; 486 | }; 487 | name = Release; 488 | }; 489 | 8DED8AD26D381A6ACFF202E5217EC498 /* Release */ = { 490 | isa = XCBuildConfiguration; 491 | buildSettings = { 492 | ALWAYS_SEARCH_USER_PATHS = NO; 493 | CLANG_ANALYZER_NONNULL = YES; 494 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 495 | CLANG_CXX_LIBRARY = "libc++"; 496 | CLANG_ENABLE_MODULES = YES; 497 | CLANG_ENABLE_OBJC_ARC = YES; 498 | CLANG_WARN_BOOL_CONVERSION = YES; 499 | CLANG_WARN_CONSTANT_CONVERSION = YES; 500 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 501 | CLANG_WARN_EMPTY_BODY = YES; 502 | CLANG_WARN_ENUM_CONVERSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 505 | CLANG_WARN_UNREACHABLE_CODE = YES; 506 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 507 | CODE_SIGNING_REQUIRED = NO; 508 | COPY_PHASE_STRIP = YES; 509 | ENABLE_NS_ASSERTIONS = NO; 510 | GCC_C_LANGUAGE_STANDARD = gnu99; 511 | GCC_PREPROCESSOR_DEFINITIONS = ( 512 | "POD_CONFIGURATION_RELEASE=1", 513 | "$(inherited)", 514 | ); 515 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 516 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 517 | GCC_WARN_UNDECLARED_SELECTOR = YES; 518 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 519 | GCC_WARN_UNUSED_FUNCTION = YES; 520 | GCC_WARN_UNUSED_VARIABLE = YES; 521 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 522 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 523 | STRIP_INSTALLED_PRODUCT = NO; 524 | SYMROOT = "${SRCROOT}/../build"; 525 | VALIDATE_PRODUCT = YES; 526 | }; 527 | name = Release; 528 | }; 529 | 9E1E4E48AF2EAB23169E611BF694090A /* Debug */ = { 530 | isa = XCBuildConfiguration; 531 | buildSettings = { 532 | ALWAYS_SEARCH_USER_PATHS = NO; 533 | CLANG_ANALYZER_NONNULL = YES; 534 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 535 | CLANG_CXX_LIBRARY = "libc++"; 536 | CLANG_ENABLE_MODULES = YES; 537 | CLANG_ENABLE_OBJC_ARC = YES; 538 | CLANG_WARN_BOOL_CONVERSION = YES; 539 | CLANG_WARN_CONSTANT_CONVERSION = YES; 540 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 541 | CLANG_WARN_EMPTY_BODY = YES; 542 | CLANG_WARN_ENUM_CONVERSION = YES; 543 | CLANG_WARN_INT_CONVERSION = YES; 544 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 545 | CLANG_WARN_UNREACHABLE_CODE = YES; 546 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 547 | CODE_SIGNING_REQUIRED = NO; 548 | COPY_PHASE_STRIP = NO; 549 | ENABLE_TESTABILITY = YES; 550 | GCC_C_LANGUAGE_STANDARD = gnu99; 551 | GCC_DYNAMIC_NO_PIC = NO; 552 | GCC_OPTIMIZATION_LEVEL = 0; 553 | GCC_PREPROCESSOR_DEFINITIONS = ( 554 | "POD_CONFIGURATION_DEBUG=1", 555 | "DEBUG=1", 556 | "$(inherited)", 557 | ); 558 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 559 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 560 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 561 | GCC_WARN_UNDECLARED_SELECTOR = YES; 562 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 563 | GCC_WARN_UNUSED_FUNCTION = YES; 564 | GCC_WARN_UNUSED_VARIABLE = YES; 565 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 566 | ONLY_ACTIVE_ARCH = YES; 567 | PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; 568 | STRIP_INSTALLED_PRODUCT = NO; 569 | SYMROOT = "${SRCROOT}/../build"; 570 | }; 571 | name = Debug; 572 | }; 573 | ACAB249F72403370A3D61667E70C77AA /* Release */ = { 574 | isa = XCBuildConfiguration; 575 | baseConfigurationReference = D7372FB0F9F377CA7F935A9093515C5F /* AVPlayerCacheLibrary.xcconfig */; 576 | buildSettings = { 577 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 578 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 579 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 580 | CURRENT_PROJECT_VERSION = 1; 581 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 582 | DEFINES_MODULE = YES; 583 | DYLIB_COMPATIBILITY_VERSION = 1; 584 | DYLIB_CURRENT_VERSION = 1; 585 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 586 | ENABLE_STRICT_OBJC_MSGSEND = YES; 587 | GCC_NO_COMMON_BLOCKS = YES; 588 | GCC_PREFIX_HEADER = "Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary-prefix.pch"; 589 | INFOPLIST_FILE = "Target Support Files/AVPlayerCacheLibrary/Info.plist"; 590 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 591 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 592 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 593 | MODULEMAP_FILE = "Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary.modulemap"; 594 | MTL_ENABLE_DEBUG_INFO = NO; 595 | PRODUCT_NAME = AVPlayerCacheLibrary; 596 | SDKROOT = iphoneos; 597 | SKIP_INSTALL = YES; 598 | TARGETED_DEVICE_FAMILY = "1,2"; 599 | VERSIONING_SYSTEM = "apple-generic"; 600 | VERSION_INFO_PREFIX = ""; 601 | }; 602 | name = Release; 603 | }; 604 | BEDE4F3C387E40806B86A34998B8CFFA /* Release */ = { 605 | isa = XCBuildConfiguration; 606 | baseConfigurationReference = 1C72B1CB344525D201DDB5D454CAEB1B /* Pods-AVPlayerCacheLibrary_Example.release.xcconfig */; 607 | buildSettings = { 608 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 609 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 610 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 611 | CURRENT_PROJECT_VERSION = 1; 612 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 613 | DEFINES_MODULE = YES; 614 | DYLIB_COMPATIBILITY_VERSION = 1; 615 | DYLIB_CURRENT_VERSION = 1; 616 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 617 | ENABLE_STRICT_OBJC_MSGSEND = YES; 618 | GCC_NO_COMMON_BLOCKS = YES; 619 | INFOPLIST_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Example/Info.plist"; 620 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 621 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 622 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 623 | MACH_O_TYPE = staticlib; 624 | MODULEMAP_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example.modulemap"; 625 | MTL_ENABLE_DEBUG_INFO = NO; 626 | OTHER_LDFLAGS = ""; 627 | OTHER_LIBTOOLFLAGS = ""; 628 | PODS_ROOT = "$(SRCROOT)"; 629 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 630 | PRODUCT_NAME = Pods_AVPlayerCacheLibrary_Example; 631 | SDKROOT = iphoneos; 632 | SKIP_INSTALL = YES; 633 | TARGETED_DEVICE_FAMILY = "1,2"; 634 | VERSIONING_SYSTEM = "apple-generic"; 635 | VERSION_INFO_PREFIX = ""; 636 | }; 637 | name = Release; 638 | }; 639 | C17B489567BC41148E2B844A8BC758D6 /* Debug */ = { 640 | isa = XCBuildConfiguration; 641 | baseConfigurationReference = 3538CAA6B03CBFF2BAF910671B89CC55 /* Pods-AVPlayerCacheLibrary_Example.debug.xcconfig */; 642 | buildSettings = { 643 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 644 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 645 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 646 | CURRENT_PROJECT_VERSION = 1; 647 | DEBUG_INFORMATION_FORMAT = dwarf; 648 | DEFINES_MODULE = YES; 649 | DYLIB_COMPATIBILITY_VERSION = 1; 650 | DYLIB_CURRENT_VERSION = 1; 651 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 652 | ENABLE_STRICT_OBJC_MSGSEND = YES; 653 | GCC_NO_COMMON_BLOCKS = YES; 654 | INFOPLIST_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Example/Info.plist"; 655 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 656 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 657 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 658 | MACH_O_TYPE = staticlib; 659 | MODULEMAP_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example.modulemap"; 660 | MTL_ENABLE_DEBUG_INFO = YES; 661 | OTHER_LDFLAGS = ""; 662 | OTHER_LIBTOOLFLAGS = ""; 663 | PODS_ROOT = "$(SRCROOT)"; 664 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 665 | PRODUCT_NAME = Pods_AVPlayerCacheLibrary_Example; 666 | SDKROOT = iphoneos; 667 | SKIP_INSTALL = YES; 668 | TARGETED_DEVICE_FAMILY = "1,2"; 669 | VERSIONING_SYSTEM = "apple-generic"; 670 | VERSION_INFO_PREFIX = ""; 671 | }; 672 | name = Debug; 673 | }; 674 | E1EE37EF21821AF6BF4F07EF8A7B12C6 /* Debug */ = { 675 | isa = XCBuildConfiguration; 676 | baseConfigurationReference = 84CF08BAADD1DD8888E38781E97EE798 /* Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig */; 677 | buildSettings = { 678 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 679 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 680 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 681 | CURRENT_PROJECT_VERSION = 1; 682 | DEBUG_INFORMATION_FORMAT = dwarf; 683 | DEFINES_MODULE = YES; 684 | DYLIB_COMPATIBILITY_VERSION = 1; 685 | DYLIB_CURRENT_VERSION = 1; 686 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 687 | ENABLE_STRICT_OBJC_MSGSEND = YES; 688 | GCC_NO_COMMON_BLOCKS = YES; 689 | INFOPLIST_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Info.plist"; 690 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 691 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 692 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 693 | MACH_O_TYPE = staticlib; 694 | MODULEMAP_FILE = "Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests.modulemap"; 695 | MTL_ENABLE_DEBUG_INFO = YES; 696 | OTHER_LDFLAGS = ""; 697 | OTHER_LIBTOOLFLAGS = ""; 698 | PODS_ROOT = "$(SRCROOT)"; 699 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 700 | PRODUCT_NAME = Pods_AVPlayerCacheLibrary_Tests; 701 | SDKROOT = iphoneos; 702 | SKIP_INSTALL = YES; 703 | TARGETED_DEVICE_FAMILY = "1,2"; 704 | VERSIONING_SYSTEM = "apple-generic"; 705 | VERSION_INFO_PREFIX = ""; 706 | }; 707 | name = Debug; 708 | }; 709 | /* End XCBuildConfiguration section */ 710 | 711 | /* Begin XCConfigurationList section */ 712 | 146627D1C1B27875A335C1254CF9427B /* Build configuration list for PBXNativeTarget "Pods-AVPlayerCacheLibrary_Tests" */ = { 713 | isa = XCConfigurationList; 714 | buildConfigurations = ( 715 | E1EE37EF21821AF6BF4F07EF8A7B12C6 /* Debug */, 716 | 3E60A7B9AF058D2E5995A67E948E39C7 /* Release */, 717 | ); 718 | defaultConfigurationIsVisible = 0; 719 | defaultConfigurationName = Release; 720 | }; 721 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 722 | isa = XCConfigurationList; 723 | buildConfigurations = ( 724 | 9E1E4E48AF2EAB23169E611BF694090A /* Debug */, 725 | 8DED8AD26D381A6ACFF202E5217EC498 /* Release */, 726 | ); 727 | defaultConfigurationIsVisible = 0; 728 | defaultConfigurationName = Release; 729 | }; 730 | 51ABAEE0FA0CAD5893D903B8A480B106 /* Build configuration list for PBXNativeTarget "Pods-AVPlayerCacheLibrary_Example" */ = { 731 | isa = XCConfigurationList; 732 | buildConfigurations = ( 733 | C17B489567BC41148E2B844A8BC758D6 /* Debug */, 734 | BEDE4F3C387E40806B86A34998B8CFFA /* Release */, 735 | ); 736 | defaultConfigurationIsVisible = 0; 737 | defaultConfigurationName = Release; 738 | }; 739 | FCAC95011AA0FB89AABEC12B4DFD66F0 /* Build configuration list for PBXNativeTarget "AVPlayerCacheLibrary" */ = { 740 | isa = XCConfigurationList; 741 | buildConfigurations = ( 742 | 06B2D3E348CA1CC5910825BFB556DD88 /* Debug */, 743 | ACAB249F72403370A3D61667E70C77AA /* Release */, 744 | ); 745 | defaultConfigurationIsVisible = 0; 746 | defaultConfigurationName = Release; 747 | }; 748 | /* End XCConfigurationList section */ 749 | }; 750 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 751 | } 752 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_AVPlayerCacheLibrary : NSObject 3 | @end 4 | @implementation PodsDummy_AVPlayerCacheLibrary 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "TPlayerView.h" 6 | #import "TVideoDownOperation.h" 7 | #import "TVideoDownQueue.h" 8 | #import "TVideoFileManager.h" 9 | #import "TVideoLoader.h" 10 | #import "TVideoLoadManager.h" 11 | 12 | FOUNDATION_EXPORT double AVPlayerCacheLibraryVersionNumber; 13 | FOUNDATION_EXPORT const unsigned char AVPlayerCacheLibraryVersionString[]; 14 | 15 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary.modulemap: -------------------------------------------------------------------------------- 1 | framework module AVPlayerCacheLibrary { 2 | umbrella header "AVPlayerCacheLibrary-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/AVPlayerCacheLibrary.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | PODS_BUILD_DIR = $BUILD_DIR 5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 8 | SKIP_INSTALL = YES 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/AVPlayerCacheLibrary/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## AVPlayerCacheLibrary 5 | 6 | Copyright (c) 2017 hailong9 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2017 hailong9 <hailong9@staff.sina.com.cn> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | AVPlayerCacheLibrary 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_AVPlayerCacheLibrary_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_AVPlayerCacheLibrary_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | install_resource() 27 | { 28 | if [[ "$1" = /* ]] ; then 29 | RESOURCE_PATH="$1" 30 | else 31 | RESOURCE_PATH="${PODS_ROOT}/$1" 32 | fi 33 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 34 | cat << EOM 35 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 36 | EOM 37 | exit 1 38 | fi 39 | case $RESOURCE_PATH in 40 | *.storyboard) 41 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 42 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 43 | ;; 44 | *.xib) 45 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 46 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 47 | ;; 48 | *.framework) 49 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 50 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 51 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 52 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | ;; 54 | *.xcdatamodel) 55 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 56 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 57 | ;; 58 | *.xcdatamodeld) 59 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 60 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 61 | ;; 62 | *.xcmappingmodel) 63 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 64 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 65 | ;; 66 | *.xcassets) 67 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 68 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 69 | ;; 70 | *) 71 | echo "$RESOURCE_PATH" 72 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 73 | ;; 74 | esac 75 | } 76 | 77 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 78 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 79 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 80 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | fi 83 | rm -f "$RESOURCES_TO_COPY" 84 | 85 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 86 | then 87 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 88 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 89 | while read line; do 90 | if [[ $line != "${PODS_ROOT}*" ]]; then 91 | XCASSET_FILES+=("$line") 92 | fi 93 | done <<<"$OTHER_XCASSETS" 94 | 95 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | fi 97 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_AVPlayerCacheLibrary_ExampleVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_AVPlayerCacheLibrary_ExampleVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "AVPlayerCacheLibrary" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_AVPlayerCacheLibrary_Example { 2 | umbrella header "Pods-AVPlayerCacheLibrary_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Example/Pods-AVPlayerCacheLibrary_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "AVPlayerCacheLibrary" 7 | PODS_BUILD_DIR = $BUILD_DIR 8 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_ROOT = ${SRCROOT}/Pods 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_AVPlayerCacheLibrary_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_AVPlayerCacheLibrary_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | install_resource() 27 | { 28 | if [[ "$1" = /* ]] ; then 29 | RESOURCE_PATH="$1" 30 | else 31 | RESOURCE_PATH="${PODS_ROOT}/$1" 32 | fi 33 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 34 | cat << EOM 35 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 36 | EOM 37 | exit 1 38 | fi 39 | case $RESOURCE_PATH in 40 | *.storyboard) 41 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 42 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 43 | ;; 44 | *.xib) 45 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 46 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 47 | ;; 48 | *.framework) 49 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 50 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 51 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 52 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 53 | ;; 54 | *.xcdatamodel) 55 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 56 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 57 | ;; 58 | *.xcdatamodeld) 59 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 60 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 61 | ;; 62 | *.xcmappingmodel) 63 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 64 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 65 | ;; 66 | *.xcassets) 67 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 68 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 69 | ;; 70 | *) 71 | echo "$RESOURCE_PATH" 72 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 73 | ;; 74 | esac 75 | } 76 | 77 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 78 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 79 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 80 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 82 | fi 83 | rm -f "$RESOURCES_TO_COPY" 84 | 85 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 86 | then 87 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 88 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 89 | while read line; do 90 | if [[ $line != "${PODS_ROOT}*" ]]; then 91 | XCASSET_FILES+=("$line") 92 | fi 93 | done <<<"$OTHER_XCASSETS" 94 | 95 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | fi 97 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | 6 | FOUNDATION_EXPORT double Pods_AVPlayerCacheLibrary_TestsVersionNumber; 7 | FOUNDATION_EXPORT const unsigned char Pods_AVPlayerCacheLibrary_TestsVersionString[]; 8 | 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework/Headers" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_AVPlayerCacheLibrary_Tests { 2 | umbrella header "Pods-AVPlayerCacheLibrary_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-AVPlayerCacheLibrary_Tests/Pods-AVPlayerCacheLibrary_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/AVPlayerCacheLibrary/AVPlayerCacheLibrary.framework/Headers" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AVPlayerCacheLibraryTests.m 3 | // AVPlayerCacheLibraryTests 4 | // 5 | // Created by hailong9 on 02/24/2017. 6 | // Copyright (c) 2017 hailong9. All rights reserved. 7 | // 8 | 9 | @import XCTest; 10 | 11 | @interface Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Tests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 hailong9 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # AVPlayerCacheLibrary 4 | 5 | [![CI Status](http://img.shields.io/travis/hailong9/AVPlayerCacheLibrary.svg?style=flat)](https://travis-ci.org/hailong9/AVPlayerCacheLibrary) 6 | [![Version](https://img.shields.io/cocoapods/v/AVPlayerCacheLibrary.svg?style=flat)](http://cocoapods.org/pods/AVPlayerCacheLibrary) 7 | [![License](https://img.shields.io/cocoapods/l/AVPlayerCacheLibrary.svg?style=flat)](http://cocoapods.org/pods/AVPlayerCacheLibrary) 8 | [![Platform](https://img.shields.io/cocoapods/p/AVPlayerCacheLibrary.svg?style=flat)](http://cocoapods.org/pods/AVPlayerCacheLibrary) 9 | 10 | ## Example 11 | 12 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 13 | 14 | ## Requirements 15 | 16 | ## Installation 17 | 18 | AVPlayerCacheLibrary is available through [CocoaPods](http://cocoapods.org). To install 19 | it, simply add the following line to your Podfile: 20 | 21 | 使用pod构建项目添加方法 22 | 23 | ```ruby 24 | pod 'AVPlayerCacheLibrary', :git => 'https://github.com/taohailong/AVPlayerCache.git' 25 | ``` 26 | 27 | ## Author 28 | 29 | hailong9, 邮箱地址: hailong9@staff.sina.com.cn 30 | 31 | ## License 32 | 33 | AVPlayerCacheLibrary is available under the MIT license. See the LICENSE file for more info. 34 | 35 | 36 | 37 |    在iOS系统中使用播放器有时候挺尴尬的,系统播放器功能不足,扩展性、可定制化程度很低,使用ijkplayer又很重。 权衡利弊,只能矬子里面找将军。本文讲解的就是对avplayer添加缓存。 38 | 39 | 在系统播放器中,avplayer无疑是可定制化程度最高的,AVPlayer 创建时需要有一个数据源 AVPlayerItem, 40 | AVURLAsset *videoAsset = [self generateAVURLAsset]; 41 | self.avPlayerItem = [AVPlayerItem playerItemWithAsset:videoAsset]; 42 | self.avPlayer = [AVPlayer playerWithPlayerItem:weak_self.avPlayerItem]; 43 | 44 |    首先创建AVPlayer 需要使用AVPlayerItem ,而AVPlayerItem的创建需要使用AVURLAsset,这个类有代理 45 | - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource: (AVAssetResourceLoadingRequest *)loadingRequest 46 |       47 |   这个代理的作用就是提供数据,然后把数据交给播放器。根据这个代理我们就可以自己做缓存,当播放器要数据时,如果没有就去下载,一边下载一边缓存。如果有就读取存储的数据交给播放器播放。这是avplayer 缓存的基本原理。 48 | 49 |   那播放器怎样要数据,我们又怎么给它相应的数据呢?  50 | 51 |     - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource: (AVAssetResourceLoadingRequest *)loadingRequest { 52 | 53 | }  54 | loadingRequest是数据传输的载体,这里需要注意的是,在第一次传输数据时 需要填写 loadingRequest.contentInformationRequest 中的信息,以便播放器更好的处理, loadingRequest.contentInformationRequest.contentType = @"video/mp4";(视频类型) 55 | loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;(是否支持分段获取)。loadingRequest.contentInformationRequest.contentLength = [_fileManager getFileLength];(视频的大小) 56 | 57 | 用 loadingRequest.dataRequest传递数据, loadingRequest.dataRequest.currentOffset(当前的数据节点)loadingRequest.dataRequest.requestedLength(本次请求的数据长度)loadingRequest.dataRequest.requestedOffset(本次请求的数据节点) 58 | 根据以上的这几个区间段获取视频的data流, 赋值 [loadingRequest.dataRequest respondWithData:data]; 完成后结束掉 [loadingRequest finishLoading]; 59 | 60 | AVPlayerCacheLibrary 如何处理缓存的,loadingRequest.dataRequest 请求时,发起下载视频的请求,根据下载的区间段分段下载视频同时进行储存,如果视频是顺序播放理论上只需要一个线程下载就够了。但是如果播放器快进时会有不同的loadingRequest.dataRequest ,还会有请求数据段的交叉重叠,在频繁的快进后退时会产生大量的碎片化数据段,如何保证这些零碎的数据利用上是AVPlayerCacheLibrary解决的核心问题。 61 | 62 | 【0-1000】{1001-1499} 【1500-2000】{2001-2499}【2500-4000】 63 | 上面的是简单的数据段,【】表示已经下载的数据段,{}中代表是没有下载的空白数据段,如果loadingRequest.dataRequest 的请求是500-3000时数据应该如何请求处理,如果是800 - 1200 时又该如何处理呢? 64 | 65 | 为了最大限度的利用已经下载过的数据,AVPlayerCacheLibrary下载数据后会有一个数据段的plist文件,里面记录了,有效的数据区间。比如loadingRequest.dataRequest请求的0 - 1000的数据,当下载完成后,plist文件中就会有【0 -1000】的数据记录。这里还有一套算法计算出请求区间内的有效区间段和无效区间段。处理完成后返回一个有顺序的数组。例如上面的区间请求500-3000时 算法会从plist 文件中查询计算出区间是【500-1000】{1001-1499} 【1500-2000】{2001-2499}【2500-3000】 66 | 67 | 当拿到这样的一个数组后,交给 TVideoDownQueue 它是一个NSOperationQueue 串行,对数组中的每一个区间段创建相应的NSOperation,去执行有效区间内的直接去储存中读取,无效区间的直接下载,每一次读区或者下载后的数据要及时传递给 loadingRequest.dataRequest。 68 | 69 | 以上就是AVPlayerCacheLibrary的缓存处理过程。开发过程中更多的是多线程的并发下载,文件的读取加锁,NSOperationQueue 取消 内存管理。 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------