123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- //
- // TBloaderURLConnection.m
- // avplayerSavebufferData
- //
- // Created by qianjianeng on 15/9/15.
- // Copyright (c) 2015年 qianjianeng. All rights reserved.
- //
- //// github地址:https://github.com/suifengqjn/TBPlayer
- #import "TBloaderURLConnection.h"
- #import <Foundation/Foundation.h>
- #import <MobileCoreServices/MobileCoreServices.h>
- #import "TBVideoRequestTask.h"
- @interface TBloaderURLConnection ()<TBVideoRequestTaskDelegate>
- @property (nonatomic, strong) NSMutableArray *pendingRequests;
- @property (nonatomic, copy ) NSString *videoPath;
- @end
- @implementation TBloaderURLConnection
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- _pendingRequests = [NSMutableArray array];
- NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
- _videoPath = [document stringByAppendingPathComponent:@"temp.mp4"];
- }
- return self;
- }
- - (void)fillInContentInformation:(AVAssetResourceLoadingContentInformationRequest *)contentInformationRequest
- {
- NSString *mimeType = self.task.mimeType;
- CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)(mimeType), NULL);
- contentInformationRequest.byteRangeAccessSupported = YES;
- contentInformationRequest.contentType = CFBridgingRelease(contentType);
- contentInformationRequest.contentLength = self.task.videoLength;
- }
- #pragma mark - AVURLAsset resource loader methods
- - (void)processPendingRequests
- {
- NSMutableArray *requestsCompleted = [NSMutableArray array]; //请求完成的数组
- //每次下载一块数据都是一次请求,把这些请求放到数组,遍历数组
- for (AVAssetResourceLoadingRequest *loadingRequest in self.pendingRequests)
- {
- [self fillInContentInformation:loadingRequest.contentInformationRequest]; //对每次请求加上长度,文件类型等信息
-
- BOOL didRespondCompletely = [self respondWithDataForRequest:loadingRequest.dataRequest]; //判断此次请求的数据是否处理完全
-
- if (didRespondCompletely) {
- [requestsCompleted addObject:loadingRequest]; //如果完整,把此次请求放进 请求完成的数组
- [loadingRequest finishLoading];
-
- }
- }
- [self.pendingRequests removeObjectsInArray:requestsCompleted]; //在所有请求的数组中移除已经完成的
-
- }
- - (BOOL)respondWithDataForRequest:(AVAssetResourceLoadingDataRequest *)dataRequest
- {
- long long startOffset = dataRequest.requestedOffset;
- if (dataRequest.currentOffset != 0) {
- startOffset = dataRequest.currentOffset;
- }
-
- if ((self.task.offset +self.task.downLoadingOffset) < startOffset)
- {
- //NSLog(@"NO DATA FOR REQUEST");
- return NO;
- }
-
- if (startOffset < self.task.offset) {
- return NO;
- }
-
- NSData *filedata = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_videoPath] options:NSDataReadingMappedIfSafe error:nil];
-
- // This is the total data we have from startOffset to whatever has been downloaded so far
- NSUInteger unreadBytes = self.task.downLoadingOffset - ((NSInteger)startOffset - self.task.offset);
-
- // Respond with whatever is available if we can't satisfy the request fully yet
- NSUInteger numberOfBytesToRespondWith = MIN((NSUInteger)dataRequest.requestedLength, unreadBytes);
-
-
- [dataRequest respondWithData:[filedata subdataWithRange:NSMakeRange((NSUInteger)startOffset- self.task.offset, (NSUInteger)numberOfBytesToRespondWith)]];
-
-
-
- long long endOffset = startOffset + dataRequest.requestedLength;
- BOOL didRespondFully = (self.task.offset + self.task.downLoadingOffset) >= endOffset;
- return didRespondFully;
-
-
- }
- /**
- * 必须返回Yes,如果返回NO,则resourceLoader将会加载出现故障的数据
- * 这里会出现很多个loadingRequest请求, 需要为每一次请求作出处理
- * @param resourceLoader 资源管理器
- * @param loadingRequest 每一小块数据的请求
- *
- */
- - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
- {
- [self.pendingRequests addObject:loadingRequest];
- [self dealWithLoadingRequest:loadingRequest];
- NSLog(@"----%@", loadingRequest);
- return YES;
- }
- - (void)dealWithLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest
- {
- NSURL *interceptedURL = [loadingRequest.request URL];
- NSRange range = NSMakeRange((NSUInteger)loadingRequest.dataRequest.currentOffset, NSUIntegerMax);
-
- if (self.task.downLoadingOffset > 0) {
- [self processPendingRequests];
- }
-
- if (!self.task) {
- self.task = [[TBVideoRequestTask alloc] init];
- self.task.delegate = self;
- [self.task setUrl:interceptedURL offset:0];
- } else {
- // 如果新的rang的起始位置比当前缓存的位置还大300k,则重新按照range请求数据
- if (self.task.offset + self.task.downLoadingOffset + 1024 * 300 < range.location ||
- // 如果往回拖也重新请求
- range.location < self.task.offset) {
- [self.task setUrl:interceptedURL offset:range.location];
- }
- }
-
-
- }
- - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest
- {
- [self.pendingRequests removeObject:loadingRequest];
-
- }
- - (NSURL *)getSchemeVideoURL:(NSURL *)url
- {
- NSURLComponents *components = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
- components.scheme = @"streaming";
- return [components URL];
- }
- #pragma mark - TBVideoRequestTaskDelegate
- - (void)task:(TBVideoRequestTask *)task didReceiveVideoLength:(NSUInteger)ideoLength mimeType:(NSString *)mimeType
- {
-
- }
- - (void)didReceiveVideoDataWithTask:(TBVideoRequestTask *)task
- {
- [self processPendingRequests];
-
- }
- - (void)didFinishLoadingWithTask:(TBVideoRequestTask *)task
- {
- if ([self.delegate respondsToSelector:@selector(didFinishLoadingWithTask:)]) {
- [self.delegate didFinishLoadingWithTask:task];
- }
- }
- - (void)didFailLoadingWithTask:(TBVideoRequestTask *)task WithError:(NSInteger)errorCode
- {
- if ([self.delegate respondsToSelector:@selector(didFailLoadingWithTask:WithError:)]) {
- [self.delegate didFailLoadingWithTask:task WithError:errorCode];
- }
-
- }
- @end
|