简体   繁体   English

在iOS中使用AVPlayer播放加密视频

[英]Playing Encrypted Videos using AVPlayer in iOS

So, I'm trying to play an encrypted video using AVplayer, and nothing shows up in the player. 所以,我正在尝试使用AVplayer播放加密视频,播放器中没有任何内容。

So my progress towards that project is as follows: 所以我在该项目上取得的进展如下:

1.Implemented an AVPlayer that will have a UIView which is going to play the AV content (this is working fine for playing non encrypted files.) 1.实现了一个AVPlayer,它将有一个UIView,它将播放AV内容(这对于播放非加密文件很有效。)

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileURL options:nil]; //local file url with custom scheme         
AVAssetResourceLoader *loader = [asset resourceLoader];
[loader setDelegate:self queue:dispatch_get_main_queue()];
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
[self.playerView setPlayer:self.player];

From the above code, I know that my following resource loader method is being called: 从上面的代码中,我知道我正在调用以下资源加载器方法:

2.Implemented the AVAssetResourceLoaderDelegate protocol, and I've implemented the resource loader method as follows. 2.实现了AVAssetResourceLoaderDelegate协议,我已经实现了如下资源加载器方法。

- (BOOL) resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest 
{
    NSURLRequest* request = loadingRequest.request;
    AVAssetResourceLoadingDataRequest* dataRequest = loadingRequest.dataRequest;
    AVAssetResourceLoadingContentInformationRequest* contentRequest = loadingRequest.contentInformationRequest;
    NSMutableData *data;
    //handle content request
    if (contentRequest)
    {
        contentRequest.contentType = @"mov";
        contentRequest.contentLength = movieFileLengthInBytes
        contentRequest.byteRangeAccessSupported = YES;
    }
    if (dataRequest)
    {
        DecryptedStream* readStream = [FS getReadStream:filename error:nil];
        if (readStream)
        {
            while ([readStream hasBytesAvailable])
            {
                NSInteger nRead;
                uint8_t buffer[kBufferReadSize];
                nRead = [readStream read:buffer maxLength:kBufferReadSize];
                NSMutableData *data = [NSMutableData data];
                [data appendBytes:buffer length:nRead];
                [dataRequest respondWithData:data];
            }
        }
        [loadingRequest finishLoading];
    }
    return YES;
}

Based on the above code, and from other further reading in apple documents for resourceloader: "During loading, the resource loader object may be asked to assist in the loading of a resource. For example, a resource that requires decryption might result in the resource loader being asked to provide the appropriate decryption keys. You can assign a delegate object to the resource loader object and use your delegate to intercept these requests and provide an appropriate response" which is basically what I'm doing. 基于上面的代码,以及从资源加载器的苹果文档中的其他进一步阅读:“在加载期间,可能会要求资源加载器对象协助加载资源。例如,需要解密的资源可能导致资源要求加载程序提供适当的解密密钥。您可以将委托对象分配给资源加载器对象,并使用您的委托拦截这些请求并提供适当的响应“这基本上就是我正在做的事情。 However, I can't get my video to play. 但是,我无法播放我的视频。 I made sure data that I've decrypted is correct (ie, I can write it to a tmp file and can play my mov). 我确保我解密的数据是正确的(即,我可以将它写入tmp文件并可以播放我的mov)。

I am also stuck on this task for several day. 我也坚持了几天这个任务。 It is not difficult, but there isn't enough information (or clearly information) of how to use AVAssetResourceLoader and AVAssetResourceLoaderDelegate . 这并不困难,但是没有足够的信息(或清楚信息)如何使用AVAssetResourceLoaderAVAssetResourceLoaderDelegate Here is something I get when doing this task: 这是我在完成这项任务时得到的:

  1. If you are loading a local video file, you must provide a custom scheme for your fileURL in order to be able to use AVAssetResourceLoaderDelegate . 如果要加载本地视频文件,则必须为fileURL提供自定义方案,以便能够使用AVAssetResourceLoaderDelegate

     let urlComponents = NSURLComponents(URL: fileURL, resolvingAgainstBaseURL: false) urlComponents?.scheme = "enc" let asset = AVURLAsset(URL: urlComponents!.URL!, options: nil) 

    Simple use let asset = AVURLAsset(URL: fileURL, options: nil) won't trigger any of AVAssetResourceLoaderDelegate 简单使用let asset = AVURLAsset(URL: fileURL, options: nil)不会触发任何AVAssetResourceLoaderDelegate

  2. In use of resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest you must provide the contentInformationRequest for loadingRequest . 在使用resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest您必须为contentInformationRequest提供loadingRequest You can find the list of video format AV Foundation Constants Reference . 您可以找到视频格式AV基础常量参考列表。 And another thing is contentLength . 另一件事是contentLength It must be set to the size of the decrypted file, not the file you are using to decrypt. 必须将其设置为解密文件的大小,而不是您用于解密的文件。
  3. The loadingRequest can request overlap data or request same data many times. loadingRequest可以请求重叠数据或多次请求相同的数据。 So that you can't simply decode and paste data to the dataRequest . 这样您就无法简单地将数据解码并粘贴到dataRequest You will need to have another buffer for decoding data. 您将需要另一个缓冲区来解码数据。 And in resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest , check if you have enough data to return or you need to decode more. resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest ,检查是否有足够的数据要返回,或者您需要解码更多。 When you decode for more data, you can clean up previous buffer to keep memory low but remember to copy any unused data in the previous buffer. 解码更多数据时,可以清理以前的缓冲区以保持较低的内存,但请记住复制前一个缓冲区中的任何未使用的数据。

And, I suggest you try to play a non-encrypted file first. 并且,我建议您先尝试播放未加密的文件。 Make sure your method to loading data for loadingRequest works properly before jumping into encrypted file. 确保加载loadingRequest数据的方法在跳转到加密文件之前正常工作。 At the end you will find it is very fun and interesting in doing task like this. 最后你会发现做这样的任务非常有趣和有趣。 Happy coding :) 快乐编码:)

in the line 在线

contentRequest.contentType = @"mov";

you have to set valid UTI of decrypted content like 你必须设置有效的解密内容UTI

contentRequest.contentType = @"public.mpeg-4";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM