For reasons irrelevant to my question I have to implement an AVPlayer
playing back AVURLAssets
using a custom AVAssetResourceLoader
. In general my implementation works well, but when attempting external playback via AirPlay
(not mirroring):
self.player.allowsExternalPlayback = YES;
self.player.usesExternalPlaybackWhileExternalScreenIsActive = YES;
The playback fails with an error message on the AppleTV
and an error message posted via AVPlayerItemFailedToPlayToEndTimeNotification
.
I am able to reproduce the same issue with a trivial AVAssetResourceLoader
implementation which simply hands out the requested data of a local media file (included in the App Bundle). Here is my implementation:
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest; {
AVAssetResourceLoadingDataRequest *dataRequest = loadingRequest.dataRequest;
AVAssetResourceLoadingContentInformationRequest *contentRequest = loadingRequest.contentInformationRequest;
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"localfile" withExtension:@"mov"];
if (contentRequest)
{
NSString *extension = [fileURL pathExtension];
NSString *contentTypeString = (NSString*)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)extension,NULL);
contentRequest.contentType = contentTypeString;
contentRequest.contentLength = [[[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:nil] fileSize];
contentRequest.byteRangeAccessSupported = YES;
}
if (dataRequest)
{
NSInteger length = [dataRequest requestedLength];
if (length>1024*1024*20)
{
// limiting to 20MB here because iOS sometimes requests the whole file which would not fit in memory
length = 1024*1024*20;
}
NSFileHandle *fh = [NSFileHandle fileHandleForReadingFromURL:fileURL error:nil];
[fh seekToFileOffset:[dataRequest requestedOffset]];
NSData *fileData = [fh readDataOfLength:length];
[dataRequest respondWithData:fileData];
[fh closeFile];
}
[loadingRequest finishLoading];
return YES;}
This code plays back fine on the device directly. If AirPlay is enabled, the resourceloader is called with content and data requests about 4-5 times, requesting the first 8kb of the item. The callbacks then stop and eventually I get a error message on the Apple TV and a few AVPlayerItemFailedToPlayToEndTimeNotifications
. The first notification contains a "media not supported" error.
(Playing the same piece of media by adding it to the AVPlayer
as a normal file based item plays fine via AirPlay
as well).
Any input would be much appreciated, thanks!
I have now received a response from Apple (via a TSI) to this question. Video AirPlay is not supported when using a custom resource loader.