TBloaderURLConnection.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //
  2. // TBloaderURLConnection.m
  3. // avplayerSavebufferData
  4. //
  5. // Created by qianjianeng on 15/9/15.
  6. // Copyright (c) 2015年 qianjianeng. All rights reserved.
  7. //
  8. //// github地址:https://github.com/suifengqjn/TBPlayer
  9. #import "TBloaderURLConnection.h"
  10. #import <Foundation/Foundation.h>
  11. #import <MobileCoreServices/MobileCoreServices.h>
  12. #import "TBVideoRequestTask.h"
  13. @interface TBloaderURLConnection ()<TBVideoRequestTaskDelegate>
  14. @property (nonatomic, strong) NSMutableArray *pendingRequests;
  15. @property (nonatomic, copy ) NSString *videoPath;
  16. @end
  17. @implementation TBloaderURLConnection
  18. - (instancetype)init
  19. {
  20. self = [super init];
  21. if (self) {
  22. _pendingRequests = [NSMutableArray array];
  23. NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
  24. _videoPath = [document stringByAppendingPathComponent:@"temp.mp4"];
  25. }
  26. return self;
  27. }
  28. - (void)fillInContentInformation:(AVAssetResourceLoadingContentInformationRequest *)contentInformationRequest
  29. {
  30. NSString *mimeType = self.task.mimeType;
  31. CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(mimeType), NULL);
  32. contentInformationRequest.byteRangeAccessSupported = YES;
  33. contentInformationRequest.contentType = CFBridgingRelease(contentType);
  34. contentInformationRequest.contentLength = self.task.videoLength;
  35. }
  36. #pragma mark - AVURLAsset resource loader methods
  37. - (void)processPendingRequests
  38. {
  39. NSMutableArray *requestsCompleted = [NSMutableArray array]; //请求完成的数组
  40. //每次下载一块数据都是一次请求,把这些请求放到数组,遍历数组
  41. for (AVAssetResourceLoadingRequest *loadingRequest in self.pendingRequests)
  42. {
  43. [self fillInContentInformation:loadingRequest.contentInformationRequest]; //对每次请求加上长度,文件类型等信息
  44. BOOL didRespondCompletely = [self respondWithDataForRequest:loadingRequest.dataRequest]; //判断此次请求的数据是否处理完全
  45. if (didRespondCompletely) {
  46. [requestsCompleted addObject:loadingRequest]; //如果完整,把此次请求放进 请求完成的数组
  47. [loadingRequest finishLoading];
  48. }
  49. }
  50. [self.pendingRequests removeObjectsInArray:requestsCompleted]; //在所有请求的数组中移除已经完成的
  51. }
  52. - (BOOL)respondWithDataForRequest:(AVAssetResourceLoadingDataRequest *)dataRequest
  53. {
  54. long long startOffset = dataRequest.requestedOffset;
  55. if (dataRequest.currentOffset != 0) {
  56. startOffset = dataRequest.currentOffset;
  57. }
  58. if ((self.task.offset +self.task.downLoadingOffset) < startOffset)
  59. {
  60. //NSLog(@"NO DATA FOR REQUEST");
  61. return NO;
  62. }
  63. if (startOffset < self.task.offset) {
  64. return NO;
  65. }
  66. NSData *filedata = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_videoPath] options:NSDataReadingMappedIfSafe error:nil];
  67. // This is the total data we have from startOffset to whatever has been downloaded so far
  68. NSUInteger unreadBytes = self.task.downLoadingOffset - ((NSInteger)startOffset - self.task.offset);
  69. // Respond with whatever is available if we can't satisfy the request fully yet
  70. NSUInteger numberOfBytesToRespondWith = MIN((NSUInteger)dataRequest.requestedLength, unreadBytes);
  71. [dataRequest respondWithData:[filedata subdataWithRange:NSMakeRange((NSUInteger)startOffset- self.task.offset, (NSUInteger)numberOfBytesToRespondWith)]];
  72. long long endOffset = startOffset + dataRequest.requestedLength;
  73. BOOL didRespondFully = (self.task.offset + self.task.downLoadingOffset) >= endOffset;
  74. return didRespondFully;
  75. }
  76. /**
  77. * 必须返回Yes,如果返回NO,则resourceLoader将会加载出现故障的数据
  78. * 这里会出现很多个loadingRequest请求, 需要为每一次请求作出处理
  79. * @param resourceLoader 资源管理器
  80. * @param loadingRequest 每一小块数据的请求
  81. *
  82. */
  83. - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
  84. {
  85. [self.pendingRequests addObject:loadingRequest];
  86. [self dealWithLoadingRequest:loadingRequest];
  87. NSLog(@"----%@", loadingRequest);
  88. return YES;
  89. }
  90. - (void)dealWithLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest
  91. {
  92. NSURL *interceptedURL = [loadingRequest.request URL];
  93. NSRange range = NSMakeRange((NSUInteger)loadingRequest.dataRequest.currentOffset, NSUIntegerMax);
  94. if (self.task.downLoadingOffset > 0) {
  95. [self processPendingRequests];
  96. }
  97. if (!self.task) {
  98. self.task = [[TBVideoRequestTask alloc] init];
  99. self.task.delegate = self;
  100. [self.task setUrl:interceptedURL offset:0];
  101. } else {
  102. // 如果新的rang的起始位置比当前缓存的位置还大300k,则重新按照range请求数据
  103. if (self.task.offset + self.task.downLoadingOffset + 1024 * 300 < range.location ||
  104. // 如果往回拖也重新请求
  105. range.location < self.task.offset) {
  106. [self.task setUrl:interceptedURL offset:range.location];
  107. }
  108. }
  109. }
  110. - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest
  111. {
  112. [self.pendingRequests removeObject:loadingRequest];
  113. }
  114. - (NSURL *)getSchemeVideoURL:(NSURL *)url
  115. {
  116. NSURLComponents *components = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
  117. components.scheme = @"streaming";
  118. return [components URL];
  119. }
  120. #pragma mark - TBVideoRequestTaskDelegate
  121. - (void)task:(TBVideoRequestTask *)task didReceiveVideoLength:(NSUInteger)ideoLength mimeType:(NSString *)mimeType
  122. {
  123. }
  124. - (void)didReceiveVideoDataWithTask:(TBVideoRequestTask *)task
  125. {
  126. [self processPendingRequests];
  127. }
  128. - (void)didFinishLoadingWithTask:(TBVideoRequestTask *)task
  129. {
  130. if ([self.delegate respondsToSelector:@selector(didFinishLoadingWithTask:)]) {
  131. [self.delegate didFinishLoadingWithTask:task];
  132. }
  133. }
  134. - (void)didFailLoadingWithTask:(TBVideoRequestTask *)task WithError:(NSInteger)errorCode
  135. {
  136. if ([self.delegate respondsToSelector:@selector(didFailLoadingWithTask:WithError:)]) {
  137. [self.delegate didFailLoadingWithTask:task WithError:errorCode];
  138. }
  139. }
  140. @end