Unsupported URL when trying to retrieve content key context

.Hi. I'm wondering if anyone else has gotten this error and what they may've done about it.


I'm simply loading the movie asset into the player, like so:

NSURL *assetURL = [NSURL URLWithString:encodedUrlString];
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:assetURL];
[self.player replaceCurrentItemWithPlayerItem:item];


but the video won't load. I've been able to extract the following from the errorLog.

2018-09-11 13:36:30.239589-0400 tvOSApp[757:2933640] AVPlayerItem Error:
#Version: 1.0
#Software: AppleCoreMedia/1.0.0.15M73 (Apple TV; U; CPU OS 11_4_1 like Mac OS X; en_us)
#Date: 2018/09/11 13:36:30.030
#Fields: date time uri cs-guid s-ip status domain comment cs-iftype
2018/09/11 13:36:30.030 skd://myid.keydelivery.eastus.media.azure.net/FairPlay/?kid=81de6e48-fake-ckey-bc88-1234567890ab 6CFC0495-EF90-4DE7-87DE-4D4F33CEE105 - -1002 "CoreMediaErrorDomain" "unsupported URL" wifi-infra


I've been wracking my brain trying to find an answer to this problem. I don't quite understand why this is an unsupported URL, especially when the documentation at Azure Media Services states that iOS (and I assume by extension, tvOS) only allows skd://.


Two more things. One is that I was using code I'd found elsewhere to utilize AVAssetResourceLoaderDelegate, but to no avail. Additionally, trying to Google® an answer just has my search correcting to "SDK" issues but I digress. 😂


If you can help out, please do. I've spent the latter half of the day trying to figure this out.

I should also note that when manually generating the SPC and calling the license acquisition URL with an https:// URL scheme, I have no problems with retrieving the CKC. However, with this implementation, my video player was not playing the video.


You will have seen code similar to this at https://gist.github.com/fousa/5709fb7c84e5b53dbdae508c9cb4fadc.

-(BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest
{
    NSData *certificateData = [NSData dataWithContentsOfURL:certificateURL];

    NSURL *loadingRequestURL = loadingRequest.request.URL;
    NSString *host = loadingRequestURL.host;
    NSString *contentId = host;
    NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding];

    NSData *spcData = [loadingRequest streamingContentKeyRequestDataForApp:certificateData
                                                         contentIdentifier:contentIdData
                                                                   options:nil
                                                                     error:&spcError];

    AVAssetResourceLoadingDataRequest *dataRequest = loadingRequest.dataRequest;
   
    // Create HTTP request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:licenseRequestURL];
    [request setHTTPMethod:@"POST"];
   
    // Create Request HTTP body:
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    NSString *spcString = [spcData base64EncodedStringWithOptions:nil];
    NSString *httpBodyString = [NSString stringWithFormat:@"spc=%@&assetId=%@",
                                [spcString stringByAddingPercentEncodingWithAllowedCharacters:
                                 [[NSCharacterSet characterSetWithCharactersInString:@"="] invertedSet]], contentId];
    [request setHTTPBody:[httpBodyString dataUsingEncoding:NSUTF8StringEncoding]];
   
    NSURLSession *session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration
                                                          delegate:self
                                                     delegateQueue:nil];
    NSURLSessionTask *task = [session dataTaskWithRequest:request
    completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;

        if (error) {
            NSLog(@"%@", error);
            [self displayGenericError];
        } else if ([httpResponse statusCode] != 200) {
            [self displayErrorWithTitle:@"Playback Failed"
                             andMessage:@"We were unable to retrieve the Content Key for you to watch this title."];
        }
        [dataRequest respondWithData:data];
        [loadingRequest finishLoading];
    }];
    [task resume];
   
    return YES;
}

Hi,
> I should also note that when manually generating the SPC and calling the license acquisition URL with an https:// URL scheme, I have no problems with retrieving the CKC. However, with this implementation, my video player was not playing the video.


This is the correct approach. AVFoundation has no way to know where your KSM is hosted so it can't handle skd:// by itself.
I think you should have a look at the FairPlay Streaming Server SDK (4.2.0) from https://developer.apple.com/streaming/fps/ .
It contains a client example.


/ Anders