首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVAssetResourceLoaderDelegate -只请求前两个字节?

AVAssetResourceLoaderDelegate -只请求前两个字节?
EN

Stack Overflow用户
提问于 2014-07-14 21:40:36
回答 2查看 6.1K关注 0票数 10

我正在实现一个AVAssetResourceLoaderDelegate,而且我在正确操作方面遇到了一些困难。我的目标是拦截AVPlayer提出的任何请求,自己提出请求,将数据写入文件,然后用文件数据响应AVPlayer

我看到的问题是:我可以拦截第一个请求,它只要求两个字节,并响应它。在那之后,我不会再收到任何访问我的AVAssetResourceLoaderDelegate的请求了。

当我从AVAssetResourceLoadingRequest截取第一个AVPlayer时,如下所示:

代码语言:javascript
复制
<AVAssetResourceLoadingRequest: 0x17ff9e40, 
URL request = <NSMutableURLRequest: 0x17f445a0> { URL: fakeHttp://blah.com/blah/blah.mp3 },
request ID = 1, 
content information request = <AVAssetResourceLoadingContentInformationRequest: 0x17ff9f30,
content type = "(null)",
content length = 0,
byte range access supported = NO,
disk caching permitted = NO>,
data request = <AVAssetResourceLoadingDataRequest: 0x17e0d220,
requested offset = 0, 
requested length = 2, 
current offset = 0>>

如您所见,这只是对前两个字节的数据的请求。我在URL中使用fakeHttp协议,将其替换为http,并自己提出请求。

然后,下面是我在获得一些数据后如何响应请求:

代码语言:javascript
复制
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {   

     //Make the remote URL request here if needed, omitted

    CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)([self.response MIMEType]), NULL);
    loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;
    loadingRequest.contentInformationRequest.contentType = CFBridgingRelease(contentType);
    loadingRequest.contentInformationRequest.contentLength = [self.response expectedContentLength];

    //Where responseData is the appropriate NSData to respond with
    [loadingRequest.dataRequest respondWithData:responseData];

    [loadingRequest finishLoading];
    return YES;
}

我已经完成了这一步,并验证了contentInformationRequest中的所有内容都已正确填充,并且我要发送的数据是具有适当长度的NSData (在本例中是两个字节)。

不再向我的委托发送请求,播放机也不会播放(大概是因为它只有两个字节的数据,并且不再请求)。

有没有人有这方面的经验来指出我可能做错了什么?我正在运行iOS 7。

编辑:,这是我完成的请求,在我调用finishedLoading之后

代码语言:javascript
复制
<AVAssetResourceLoadingRequest: 0x16785680,
URL request = <NSMutableURLRequest: 0x166f4e90> { URL: fakeHttp://blah.com/blah/blah.mp3  },
request ID = 1,
content information request = <AVAssetResourceLoadingContentInformationRequest: 0x1788ee20,
content type = "public.mp3",
content length = 7695463,
byte range access supported = YES,
disk caching permitted = NO>,
data request = <AVAssetResourceLoadingDataRequest: 0x1788ee60,
requested offset = 0,
requested length = 2,
current offset = 2>>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-16 23:40:24

回过头来回答我自己的问题以防有人好奇。

这个问题归结为线程问题。尽管在任何地方都没有显式地记录它,但是AVAssetResourceLoaderDelegate使用线程做了一些奇怪的事情。

本质上,我的问题是在主线程上创建AVPlayerItemAVAssetResourceLoaderDelegate,但是响应后台线程上的委托调用(因为它们是网络调用的结果)。显然,AVAssetResourceLoader完全忽略了来自与预期不同线程上的响应。

我解决了这个问题,只需在同一个线程上做所有事情,包括创建AVPlayerItem

票数 7
EN

Stack Overflow用户

发布于 2014-07-14 22:13:00

代码语言:javascript
复制
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
{    
    loadingRequest.contentInformationRequest.contentType = @"public.aac-audio";
    loadingRequest.contentInformationRequest.contentLength = [self.fileData length];
    loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES;

    NSData *requestedData = [self.fileData subdataWithRange:NSMakeRange((NSUInteger)loadingRequest.dataRequest.requestedOffset,
                                                                        (NSUInteger)loadingRequest.dataRequest.requestedLength)];
    [loadingRequest.dataRequest respondWithData:requestedData];
    [loadingRequest finishLoading];

    return YES;
}

这个实现对我是有效的。它总是要求前两个字节,然后是整个数据。如果您没有得到另一个回调,这意味着您所做的第一个响应有问题。我想问题在于您使用的是MIME内容类型,而不是UTI。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24746453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档