VIResourceLoaderManager.m 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // VIResourceLoaderManager.m
  3. // VIMediaCacheDemo
  4. //
  5. // Created by Vito on 4/21/16.
  6. // Copyright © 2016 Vito. All rights reserved.
  7. //
  8. #import "VIResourceLoaderManager.h"
  9. #import "VIResourceLoader.h"
  10. static NSString *kCacheScheme = @"__VIMediaCache___:";
  11. @interface VIResourceLoaderManager () <VIResourceLoaderDelegate>
  12. @property (nonatomic, strong) NSMutableDictionary<id<NSCoding>, VIResourceLoader *> *loaders;
  13. @end
  14. @implementation VIResourceLoaderManager
  15. - (instancetype)init {
  16. self = [super init];
  17. if (self) {
  18. _loaders = [NSMutableDictionary dictionary];
  19. }
  20. return self;
  21. }
  22. - (void)cleanCache {
  23. [self.loaders removeAllObjects];
  24. }
  25. - (void)cancelLoaders {
  26. [self.loaders enumerateKeysAndObjectsUsingBlock:^(id<NSCoding> _Nonnull key, VIResourceLoader * _Nonnull obj, BOOL * _Nonnull stop) {
  27. [obj cancel];
  28. }];
  29. [self.loaders removeAllObjects];
  30. }
  31. #pragma mark - AVAssetResourceLoaderDelegate
  32. - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {
  33. NSURL *resourceURL = [loadingRequest.request URL];
  34. if ([resourceURL.absoluteString hasPrefix:kCacheScheme]) {
  35. VIResourceLoader *loader = [self loaderForRequest:loadingRequest];
  36. if (!loader) {
  37. NSURL *originURL = nil;
  38. NSString *originStr = [resourceURL absoluteString];
  39. originStr = [originStr stringByReplacingOccurrencesOfString:kCacheScheme withString:@""];
  40. originURL = [NSURL URLWithString:originStr];
  41. loader = [[VIResourceLoader alloc] initWithURL:originURL];
  42. loader.delegate = self;
  43. NSString *key = [self keyForResourceLoaderWithURL:resourceURL];
  44. self.loaders[key] = loader;
  45. }
  46. [loader addRequest:loadingRequest];
  47. return YES;
  48. }
  49. return NO;
  50. }
  51. - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest {
  52. VIResourceLoader *loader = [self loaderForRequest:loadingRequest];
  53. [loader removeRequest:loadingRequest];
  54. }
  55. #pragma mark - VIResourceLoaderDelegate
  56. - (void)resourceLoader:(VIResourceLoader *)resourceLoader didFailWithError:(NSError *)error {
  57. [resourceLoader cancel];
  58. if ([self.delegate respondsToSelector:@selector(resourceLoaderManagerLoadURL:didFailWithError:)]) {
  59. [self.delegate resourceLoaderManagerLoadURL:resourceLoader.url didFailWithError:error];
  60. }
  61. }
  62. #pragma mark - Helper
  63. - (NSString *)keyForResourceLoaderWithURL:(NSURL *)requestURL {
  64. if([[requestURL absoluteString] hasPrefix:kCacheScheme]){
  65. NSString *s = requestURL.absoluteString;
  66. return s;
  67. }
  68. return nil;
  69. }
  70. - (VIResourceLoader *)loaderForRequest:(AVAssetResourceLoadingRequest *)request {
  71. NSString *requestKey = [self keyForResourceLoaderWithURL:request.request.URL];
  72. VIResourceLoader *loader = self.loaders[requestKey];
  73. return loader;
  74. }
  75. @end
  76. @implementation VIResourceLoaderManager (Convenient)
  77. + (NSURL *)assetURLWithURL:(NSURL *)url {
  78. if (!url) {
  79. return nil;
  80. }
  81. NSURL *assetURL = [NSURL URLWithString:[kCacheScheme stringByAppendingString:[url absoluteString]]];
  82. return assetURL;
  83. }
  84. - (AVPlayerItem *)playerItemWithURL:(NSURL *)url {
  85. NSURL *assetURL = [VIResourceLoaderManager assetURLWithURL:url];
  86. AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
  87. [urlAsset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
  88. AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:urlAsset];
  89. if ([playerItem respondsToSelector:@selector(setCanUseNetworkResourcesForLiveStreamingWhilePaused:)]) {
  90. playerItem.canUseNetworkResourcesForLiveStreamingWhilePaused = YES;
  91. }
  92. return playerItem;
  93. }
  94. @end