Playback of FPS encrypted content

The OTVAVPlayer class extends the native AVPlayer class and makes it easy to enable FPS playback. It extends all of the functionality of AVPlayer, and because FPS is the native DRM, it can support HD and 4K playback.

This page provides an overview of the tasks that you need to perform to enable FairPlay Streaming in your application, with code examples to show how the licence delegation can be implemented and the framework used to playback encrypted content. This section should be used alongside the supplied encrypted-playback-advanced example code.

Prerequisites

  • An understanding of Apple’s FairPlay technology, (see Apple's FPS page)
  • The certificate that is provided by Apple when an operator wants to use FPS by submitting an X.509 Certificate Signing Request linked to the private key. This certificate will be used when requesting a key request to the OS (returned with SPC (Server Playback Context)).
  • Key Server Module (KSM)
  • NAGRA’s OpenTV FPS SDK for iOS
  • The encrypted-playback-advanced example code.
  • A handheld device (simulator not supported).

    Playback of FPS-encrypted streams is not possible on device simulators.

Implementation

To enable FairPlay Streaming in your app, you need to create a new Xcode project and then:

These steps are described in detail in the following sections.

Implementing OTVLicenseDelegate

Implement the OTVLicenseDelegate protocol as follows:

final class OTVDelegate: NSObject, OTVLicenseDelegate {
    func contentIdentifier(url: URL) -> Data? {}
    func certificate() -> Data? {}
    func ckcMessage(spc: Data) -> Data? {}
    func scheme() -> String? {}
}

That is, you must implement the following methods:

  • contentIdentifier() – given a licence server URL (the URI specified in the playlist's EXT-X-KEY tag), this should get and return the content identifier used on the server side.
  • certificate() – should fetch and return the application certificate. This is supplied by Apple and is used with the content identifier to request a key request from the OS.
  • ckcMessage() – should fetch and return the Content Key Context (CKC) message that contains the encrypted key that is used to decrypt the FairPlay stream.
  • scheme() – should return the name of the URI scheme (specified in the EXT-X-KEY URI).

The exact contents of each method will depend on the licence server used.

Instantiating an OTVDRMManager

Instantiate an OTVDRMManager object:

private let drmManager = OTVDRMManager:shared

Registering the delegate

Register the delegate to the OTVDRMManager:

private let licenseDelegate = OTVDelegate()
drmManager.setLicenseDelegate(licenseDelegate)

Loading the OTVSDK object with the licence token

Before any other operation, the OTVSDK class must have one of its load() method called. Either:

  • Ensure the opy_licence file is present in the project and call the OTVSDK.load() method, or:
  • Call the OTVSDK.load(licence:) passing the licence as a String.

Instantiating an OTVAVPlayer

Instantiate an OTVAVPlayer then call its init() method:

private let player = OTVAVPlayer()
player.init(item)
/// or:
private let player = OTVAVPlayer()
player.init(url)

The init() method takes one of the following:

  • an OTVAVPlayerItem object
  • the URL of a content stream.

You should now be able to use the OTVAVPlayer object to play back FPS-encrypted content in exactly the same way as with AVPlayer.

Enabling playback of FPS encrypted content

The central part of enabling playback of FairPlay-encrypted content is to implement the following methods of the OTVLicenseDelegate protocol:

  • contentIdentifier(url: URL) > Data? – given a licence server URL (the URI specified in the playlist's EXT-X-KEY tag), this should get and return the content identifier used on the server side.
  • certificate() > Data? – should get and return the application certificate. This is supplied by Apple and is used with the content identifier to request a key request from the OS.
  • ckcMessage(spc: Data) > Data? – should get and return the Content Key Context (CKC) message that contains the encrypted key that is used to decrypt the FairPlay stream.
  • scheme() > String? – should return the name of the URI scheme (specified in the EXT-X-KEY URI).

The exact contents of each method is implementation-specific and will depend on the licence server used.

Example code

The example code provided with this package contains an Xcode project demonstrating the entire process for acquiring a license for, and playing back an encrypted HLS stream. All tokens and URLs in the example code are hard-coded, but in real applications they might be fetched from external sources. The license server used in this example is a NAGRA Security Services Platform (SSP) head-end.

The app has an SSPFairplayLicenseDelegate class, which is an SSP-specific implementation of an OTVLicenseDelegate. Alongside this class there are some other helper classes assisting the handling of licenses, tokens and certificates used to enable FPS playback:

  • ContentIdentifierGenerator - a class responsible for associating a URL with its ContentId.
  • FairPlayApplicationCertificateDownloader - a helper class responsible for acquiring the authentication certificate. This certificate is issued by Apple to the license provider, and used later on to authenticate the association between the license server and the player.
  • PlayerCertificateAuthenticator - a class to download and store the SSP Certificate that authenticates the player against the license server (using FairPlayApplicationCertificateDownloader). This certificate only needs to be acquired once.
  • StreamLicenceAuthenticator - a class for authenticating an encrypted stream and providing its license in the form of an encrypted CKC message. The content token used in this authenticator is an SSP-specific implementation. It authenticates the contentId, and may have additional information such as license duration and expiry. Note that this authentication needs to be done for each stream, so you are likely to instantiate this class every 'zapping'.

Much of the code is enriched with comments explaining all the steps.