title: Fairplay implementation in Swift, AVAssetResourceDelegate
body: <p>I watched Apple FairPlay introduction videos, I read a this code:
  <a href="https://gist.github.com/fousa/5709fb7c84e5b53dbdae508c9cb4fadc" rel="nofollow noreferrer">https://gist.github.com/fousa/5709fb7c84e5b53dbdae508c9cb4fadc</a>
  And I also went through HLS Catalog from apple and with the last the problem is that I need only playing DRM videos without any downloading and all this stuff so I started from GitHub example.
  I have a certificate, videos in FairPlay and the key server module.
  My first and main problem is that AVResourceDelegate isn't calling when I'm giving AVURLAsset with video url. I read at stack that I need to change scheme to sth else, e.g "DRM" from https and right AVResourceDelegate calling then but I don't have .m3u8 file because video link is wrong!
  Could you please guys/girls help me.</p>
  
  <pre><code>import Foundation
  import AVKit
  import NotificationCenter
  
  public struct DRMVideoData{
     var drmKey: String?
     var proxyFairPlay: String
     var fileFairPlay: String
     var idVideo: String
  }
  
  class VODDRMImplementation: NSObject, AVAssetResourceLoaderDelegate {
  
  let domain = "DRMDelegate.ContentKeyQueue"
  let contentKeyDelegateQueue = DispatchQueue(label: "DRMDelegate.ContentKeyQueue")
  
  var drmData: DRMVideoData?
  
  func startPlayerWithDRM(_ videoDRM: DRMVideoData,_ player: AVPlayer?,_ playerLayer: AVPlayerLayer?, c: @escaping (AVPlayer?, AVPlayerLayer?) -&gt; Void) {
  
      var urlcomp = URLComponents(string: videoDRM.fileFairPlay)
  
      urlcomp?.scheme = "drm"
  
      if let url = try? urlcomp?.asURL(){
  
          self.drmData = videoDRM
  
          let url = url
  
          let asset = AVURLAsset(url: url!)
          asset.resourceLoader.setDelegate(self, queue: self.contentKeyDelegateQueue)
  
          let playerItem = AVPlayerItem(asset: asset)
          let player = AVPlayer(playerItem: playerItem)
          let playerLayer = AVPlayerLayer(player: player)
          player.pause()
  
          c(player, playerLayer)
      }else{
          c(nil, nil)
      }
  
      }
  
  func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -&gt; Bool {
      log.debug("DRM: started")
  
      // getting data for KSM server
      guard let urlToConvert = loadingRequest.request.url,
          let drmData = drmData else {
              log.debug("DRM: unable to read URL from loadingRequest")
              loadingRequest.finishLoading(with: NSError(domain: domain, code: -1, userInfo: nil))
              return false
      }
  
      do{
  
          log.debug("DRM: video link \(urlToVideo)")
  
          guard let certificateData = getCertificateFromServer() else {
                  log.debug("DRM: false to get public certificate")
                  loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
                  return false
          }
  
          let contentId = drmData.idVideo // content id
          guard let contentIdData = contentId.data(using: String.Encoding.utf8),
              let spcData = try? loadingRequest.streamingContentKeyRequestData(forApp: certificateData, contentIdentifier: contentIdData, options: nil),
              let dataRequest = loadingRequest.dataRequest else {
                  loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
                  log.debug("DRM: false to get SPC Data from video")
                  return false
          }
  
          let ksmServer = URL(string: drmData.proxyFairPlay)! // KSM link
          var request = URLRequest(url: ksmServer)
          request.httpMethod = "GET"
          request.httpBody = spcData
          let session = URLSession(configuration: .default)
          let task = session.dataTask(with: request) { data, response, error in
              guard let data = data else {
                  log.debug("DRM: unable to fetch ckc key :/")
                  loadingRequest.finishLoading(with: NSError(domain: self.domain, code: -4, userInfo: nil))
                  return
              }
              dataRequest.respond(with: data)
              loadingRequest.finishLoading()
          }
          task.resume()
  
      }catch{
          loadingRequest.finishLoading(with: NSError(domain: domain, code: -3, userInfo: nil))
          log.debug("DRM: cannot generate url to video")
          return false
      }
  
  
      return true
  
  
  }
  
  func takeURLFromId(_ videoLink: String) -&gt; URL{
      let urlString = videoLink
      let url = URLComponents(string: urlString)
      do{
          let urlToReturn = try url?.asURL()
          guard let urlToReturn2 = urlToReturn else {
              let error = NSError(domain: domain, code: 0, userInfo: nil)
              throw error }
          return urlToReturn2
      }catch{
          if let url = NSURL(string: videoLink){
              return url as URL
          }else{
              return NSURL(string: videoLink)! as URL
          }
      }
  
  }
  
  func getCertificateFromServer() -&gt; Data?{
      let filePath = Bundle.main.path(forResource: "privatekey", ofType: "pem")
  
      guard let data = try? Data(contentsOf: URL(string: filePath!)!) else {
          return nil
      }
  
      return data
  }
  
  }
  </code></pre>