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

Cth*_*utu 10 objective-c avfoundation ios

我试图哄骗AVFoundation从自定义URL读取.自定义网址的工作原理.下面的代码创建一个带有电影文件的NSData:

NSData* movieData = [NSData dataWithContentsOfURL:@"memory://video"];
Run Code Online (Sandbox Code Playgroud)

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

NSURL* url = [NSURL URLWithString:@"memory://video"];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetResourceLoader* loader = [asset resourceLoader];
[loader setDelegate:self queue:mDispatchQueue];
Run Code Online (Sandbox Code Playgroud)

调度队列是并发的.

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

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);
Run Code Online (Sandbox Code Playgroud)

但是,当我运行此代码时,我会得到:

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)}
Run Code Online (Sandbox Code Playgroud)

委托方法的实现是:

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

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

谢谢.

编辑:我正在拍摄的电影是一部单帧电影.

Gly*_*ams 8

我已经实现了这个方法的工作版本.我花了一段时间才弄明白.但现在的应用程序正常运行.这表明代码没问题.

我的应用程序包含一个媒体文件,我不想在未加密的包中发送.我想动态解密文件.(一次一块).

该方法必须响应内容请求(告诉玩家它正在加载什么)和数据请求(给玩家一些数据).第一次调用该方法时,始终存在内容请求.然后会有一系列数据请求.

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

我交出媒体播放器的数据块.通常一次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;
}
Run Code Online (Sandbox Code Playgroud)


Aar*_*ger 0

您需要创建一个 NSURLResponse 对象来传回。你正路过回来nil。没有它,AVAssetResourceLoader 不知道如何处理您交给它的数据(也就是说,它不知道它是什么类型的数据 - 错误消息、jpeg 等)。在假设成功之前,您还应该真正使用-[NSData dataWithContentsOfURL:options:error:]并检查错误。