有谁知道如何正确实施AVAssetResourceLoaderDelegate方法?

我试图哄AVFoundation从自定义URL读取。 自定义url的东西工作。 下面的代码创build一个带有电影文件的NSData:

NSData* movieData = [NSData dataWithContentsOfURL:@"memory://video"]; 

我使用下面的代码设置了一个AVAssetResourceLoader对象:

 NSURL* url = [NSURL URLWithString:@"memory://video"]; AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil]; AVAssetResourceLoader* loader = [asset resourceLoader]; [loader setDelegate:self queue:mDispatchQueue]; 

调度队列是并发的。

然后我尝试从电影中提取第一帧:

 AVAssetImageGenerator* imageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset]; CMTime time = CMTimeMakeWithSeconds(0, 600); NSError* error = nil; CMTime actualTime; CGImageRef image = [imageGen copyCGImageAtTime:time actualTime:&actualTime error:&error]; if (error) NSLog(@"%@", error); 

但是当我运行这个,但代码我得到:

 2013-02-21 10:02:22.197 VideoPlayer[501:907] Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x1f863090 {NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x1e575a90 "The operation couldn't be completed. (OSStatus error 268451843.)", NSLocalizedFailureReason=An unknown error occurred (268451843)} 

委托方法的实现是:

 - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest { NSData* data = [NSData dataWithContentsOfURL:loadingRequest.request.URL]; [loadingRequest finishLoadingWithResponse:nil data:data redirect:nil]; return YES; } 

现在,我的问题是,我正确实施方法? 有谁知道我做的是否正确?

谢谢。

编辑:我整个提取的电影是一个单帧电影。

我已经实现了这个方法的工作版本。 我花了一段时间才弄清楚。 但现在的应用程序现在工作。 这表明代码是好的。

我的应用程序包括一个媒体文件,我不想在未encryption的包中发货。 我想dynamic解密文件。 (一次一个块)。

该方法必须响应内容请求(告诉玩家它正在加载什么)和数据请求(给玩家一些数据)。 该方法第一次被调用时,总是有一个内容请求。 那么会有一系列的数据请求。

玩家贪婪。 它总是要求整个文件。 你没有义务提供。 它要求整个蛋糕。 你可以给它一片。

我手中的媒体播放器的数据块。 通常每次1 MB。 有一个特殊情况来处理较小的最终块。 块通常依次被要求。 但是你也需要能够处理不按顺序的请求。

 - (BOOL) resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest { NSURLRequest* request = loadingRequest.request; AVAssetResourceLoadingDataRequest* dataRequest = loadingRequest.dataRequest; AVAssetResourceLoadingContentInformationRequest* contentRequest = loadingRequest.contentInformationRequest; //handle content request if (contentRequest) { NSError* attributesError; NSString* path = request.URL.path; _fileURL = request.URL; if (_fileHandle == nil) { _fileHandle = [NSFileHandle fileHandleForReadingAtPath:path]; } // fire up the decryption here.. // for example ... if (_decryptedData == nil) { _cacheStart = 1000000000; _decryptedData = [NSMutableData dataWithLength:BUFFER_LENGTH+16]; CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, [sharedKey cStringUsingEncoding:NSISOLatin1StringEncoding], kCCKeySizeAES256, NULL, &cryptoRef); } NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&attributesError]; NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize]; _fileSize = [fileSizeNumber longLongValue]; //provide information about the content _mimeType = @"mp3"; contentRequest.contentType = _mimeType; contentRequest.contentLength = _fileSize; contentRequest.byteRangeAccessSupported = YES; } //handle data request if (dataRequest) { //decrypt a block of data (can be any size you want) //code omitted NSData* decodedData = [NSData dataWithBytes:outBuffer length:reducedLen]; [dataRequest respondWithData:decodedData]; [loadingRequest finishLoading]; } return YES; } 

我只是浪费了2个小时试图做一些非常相似的事情。

原来它只适用于设备,并不适用于iOS模拟器!

我猜在模拟器AVFoundation是“桥接”到主机的Mac AVFoundation。 不幸的是,这个API在OS X 10.8上不可用(根据WebCore上的一些提交,它将在OS X 10.9中提供),所以现在它在模拟器中不起作用。

您需要创build一个NSURLResponse对象来传回。 你回nil 。 没有它,AVAssetResourceLoader不知道该怎么处理你的数据(也就是说,它不知道它是什么types的数据 – 一个错误消息,一个JPEG等)。 你也应该真的在使用-[NSData dataWithContentsOfURL:options:error:]并在假设成功之前检查错误。

用户NSURLComponent与scheme =“enc”以便调用AVAssetResourceLoaderDelegate方法。

 let urlComponents = NSURLComponents(url: video_url, resolvingAgainstBaseURL: false) urlComponents?.scheme = "enc" let avAsset = AVURLAsset(url: (urlComponents?.url)!, options: ["AVURLAssetHTTPHeaderFieldsKey": headers]) avAsset.resourceLoader.setDelegate(self, queue: DispatchQueue(label: "AVARLDelegateDemo loader"))