Search code examples
chromecastgoogle-castsmooth-streamingplayready

Chromecast sender as a PlayReady license provider


Let's assume we have an encrypted stream (SmoothStreaming + Playready) and a custom receiver build on googlecast/cast-custom-receiver.

I can see that device tries to get the license from the LA_URL (license acquisition URL) - extracted from stream PlayReady ProtectionHeader.

I wonder is there a way to override this behaviour? I want receiver to delegate license acquisition to sender - iOS app in my case.


Solution

  • You can achieve this by modifying the Media Player Library. The only thing that needs to be done - exposing challenge, key system, init data & sessionId though prepareLicenseRequest().

    <    this.c.prepareLicenseRequest && !this.c.prepareLicenseRequest() || this.gb()
    ---
    >    this.c.prepareLicenseRequest && !this.c.prepareLicenseRequest(this.ef, Df[this.vc], this.qb, this.hf) || this.gb()
    

    Please verify the variable names cause they can be different (they can be found in webkitAddKey() call later in the media_player.js code).

    In your receiver just define the your own prepareLicenseRequest implementation:

    window.mediaHost.prepareLicenseRequest = function(challenge,keySystem, initData, sessionId) {
      debug('drm', 'prepareLicenseRequest');
      window.initData = initData;
      window.sessionId = sessionId;
      window.keySystem = keySystem;
    
      var base64challenge = window.btoa(pack(challenge));
      window.messageBus.broadcast(base64challenge); // TODO send only to initiator
      return false // receiver will stop not request license by itself
    }                 
    

    When license acquired by sender it can send it back via the same channel. In this case receiver needs to add the license to the env:

    window.messageBus.onMessage = function(event) {
        var base64key = event['data'];
        var key = unpack(window.atob(base64key));
        window.mediaElement.webkitAddKey(window.keySystem, new Uint8Array(unpack(unbase64)), window.initData, window.sessionId);
        window.mediaElement.play(); 
    }
    

    window.messageBus in this case is a custom channel (urn:x-cast:me.trnl.cast.key)

    That's it. It works for us and it's quite fast.