在自定义NSURLProtocol上使用AVURLAsset
我写了一个自定义的NSURLProtocol(称为“memory:”),它允许我根据名称从NSDictionary中获取存储的NSData项。 例如,此代码注册NSURLProtocol类并添加一些数据:
[VPMemoryURLProtocol register];
[VPMemoryURLProtocol addData:data withName:@"video"];
这使我可以通过像“memory:// video”这样的URL来引用NSData。
以下是我的自定义NSURLProtocol实现:
NSMutableDictionary* gMemoryMap = nil;
@implementation VPMemoryURLProtocol
{
}
+ (void)register
{
static BOOL inited = NO;
if (!inited)
{
[NSURLProtocol registerClass:[VPMemoryURLProtocol class]];
inited = YES;
}
}
+ (void)addData:(NSData *)data withName:(NSString *)name
{
if (!gMemoryMap)
{
gMemoryMap = [NSMutableDictionary new];
}
gMemoryMap[name] = data;
}
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
NSLog(@"URL: %@, Scheme: %@",
[[request URL] absoluteString],
[[request URL] scheme]);
NSString* theScheme = [[request URL] scheme];
return [theScheme caseInsensitiveCompare:@"memory"] == NSOrderedSame;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
- (void)startLoading
{
NSString* name = [[self.request URL] path];
NSData* data = gMemoryMap[name];
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:[self.request URL]
MIMEType:@"video/mp4"
expectedContentLength:-1
textEncodingName:nil];
id<NSURLProtocolClient> client = [self client];
[client URLProtocol:self didReceiveResponse:response
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[client URLProtocol:self didLoadData:data];
[client URLProtocolDidFinishLoading:self];
}
- (void)stopLoading
{
}
我不确定这段代码是否有效,但这不是我遇到的问题。 尽管注册了自定义协议,但当我尝试在此代码中使用URL时,canInitWithRequest:永远不会被调用:
NSURL* url = [NSURL URLWithString:@"memory://video"];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator* imageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
CMTime time = CMTimeMakeWithSeconds(0, 600);
NSError* error;
CMTime actualTime;
CGImageRef image = [imageGen copyCGImageAtTime:time
actualTime:&actualTime
error:&error];
UIImage* uiImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
如果我使用“memory:// video”,图像始终为零,但如果使用“file:/// ...”,则工作正常。 我错过了什么? 为什么不能调用canInitWithRequest? AVFoundation是否仅支持特定的URL协议而不是自定义的?
谢谢
当然,过去只支持特定URL方案的基础 - 作为一名电子书开发人员,我见过这种情况发生在通过诸如epub://
或zip://
类的URL加载的任何媒体类型上。 在这些情况下,在iOS 5.x和更早的版本中,通过相关代码进行追踪将结束于QuickTime方法,该方法将URL方案与少量支持方法进行比较: file
, http
, https
, ftp
以及iTunes使用 - 我忘记了它叫什么。
在iOS 6+中,AVFoundation中有一个新的API,但它旨在帮助这里。 虽然我没有亲自使用它,但它应该如何工作:
NSURL* url = [NSURL URLWithString:@"memory://video"];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
////////////////////////////////////////////////////////////////
// NEW CODE START
AVAssetResourceLoader* loader = [asset resourceLoader];
id<AVAssetResourceLoaderDelegate> delegate = [SomeClass newInstanceWithNSURLProtocolClass: [VPMemoryURLProtocol class]];
[loader setDelegate: delegate queue: some_dispatch_queue];
// NEW CODE END
////////////////////////////////////////////////////////////////
AVAssetImageGenerator* imageGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
CMTime time = CMTimeMakeWithSeconds(0, 600);
有了这个,你只需要在某处实现AVAssetResourceLoader
协议,这很简单,因为它只包含一个方法。 既然你已经有了一个NSURLProtocol
实现,所有你真正的工作都完成了,你可以直接将实际的工作交给Cocoa加载系统或你的协议类。
再一次,我会指出,我还没有真正使用这个,所以上述完全是理论上的。
链接地址: http://www.djcxy.com/p/34831.html