androidcastingchromecastgoogle-castcustom-receiver

Creating a custom receiver with the Google Cast - Media Player Library


I would like to implement media player functionality to my custom receiver. On the google developer website, I found a description to implement a sender and a styled media receiver application.

I have done this sample, and it works fine. I can cast a MP3 file hosted on Google Drive to my chromecast device.

Now, I have implemented a custom receiver (see attachment) which should be able to play an URL refered to a m3u8 file. For this, I am using the Media Player Library as suggested from Google.

<body>
<div>
<p id='text'> </p>
<video id='vid'> </video>
</div>
<script type="text/javascript" src="https://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/cast/sdk/libs/mediaplayer/1.0.0/media_player.js"></script>



<script type="text/javascript">
// If you set ?Debug=true in the URL, such as a different App ID in the
// developer console, include debugging information.
if (window.location.href.indexOf('Debug=true') != -1) {
    cast.receiver.logger.setLevelValue(cast.receiver.LoggerLevel.DEBUG);
    cast.player.api.setLoggerLevel(cast.player.api.LoggerLevel.DEBUG);
}

console.log("mediaElement set");
var mediaElement = document.getElementById('vid');

// Create the media manager. This will handle all media messages by default.
window.mediaManager = new cast.receiver.MediaManager(mediaElement);

// Remember the default value for the Receiver onLoad, so this sample can Play
// non-adaptive media as well.
window.defaultOnLoad = mediaManager.onLoad;

mediaManager.onLoad = function (event) {
    // The Media Player Library requires that you call player unload between
    // different invocations.
    if (window.player !== null) {
        player.unload();    // Must unload before starting again.
        window.player = null;
    }
    // This trivial parser is by no means best practice, it shows how to access
    // event data, and uses the a string search of the suffix, rather than looking
    // at the MIME type which would be better.  In practice, you will know what
    // content you are serving while writing your player.


    if (event.data['media'] && event.data['media']['contentId']) {
    console.log('Starting media application');


    var t = document.getElementById('text');
    t.innerHTML = event.data['media'];
    console.log("EventData: "+event.data);
    console.log("EventData-Media: "+event.data['media']);
    console.log("EventData-ContendID: "+event.data['media']['contentId']);

    var url = event.data['media']['contentId'];
    console.log("URL: "+url);

    // Create the Host - much of your interaction with the library uses the Host and
    // methods you provide to it.
    window.host = new cast.player.api.Host(
        {'mediaElement':mediaElement, 'url':url});
    var ext = url.substring(url.lastIndexOf('.'), url.length);
    var initStart = event.data['media']['currentTime'] || 0;
    var autoplay = event.data['autoplay'] || true;
    var protocol = null;
    mediaElement.autoplay = autoplay;  // Make sure autoplay get's set

    protocol = cast.player.api.CreateHlsStreamingProtocol(host);

    host.onError = function(errorCode) {
      console.log("Fatal Error - "+errorCode);
      if (window.player) {
        window.player.unload();
        window.player = null;
      }
    };
    // If you need cookies, then set withCredentials = true also set any header
    // information you need.  If you don't need them, there can be some unexpected
    // effects by setting this value.
    //      host.updateSegmentRequestInfo = function(requestInfo) {
    //        requestInfo.withCredentials = true;
    //      };
    console.log("we have protocol "+ext);
    if (protocol !== null) {
      console.log("Starting Media Player Library");
      window.player = new cast.player.api.Player(host);
      window.player.load(protocol, initStart);
    }
    else {
      window.defaultOnLoad(event);    // do the default process
    }
  }   
}

window.player = null;
console.log('Application is ready, starting system');
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
castReceiverManager.start();
</script>
</body>

I've figured out, that it's just possible to cast .m3u8, .ism and .mpd files with the Media Player Library. So I created a m3u8 file as follows, host it to Google Drive, and tried to cast it to my custom receiver.

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=173952
https://www.googledrive.com/host/0B1x31lLRAxTMRndtNkhSWVdGLVE

But it doesn't works. I used the Goolge Cast Developer Console to debug the custom receiver. By exceuting the

window.player.load(protocol, initStart);

command, I get an FATAL ERROR on the console.

I think the problem is on the custom receiver code because the sender application from the google documentation works fine with the styled media receiver.

Is there anyone who know this problem or see some issue on the custom receiver code? Has anyone a idea how I could debug the styled media player? It would be much easier if I could see which messages are exchanged with the styled media player but if I activate the debugging I can´t see the exchanged messages.


Solution

  • If you turn on the debugging, you can see message exchanges (see here, under the Debugging section). There is a full fledged receiver sample project on our github repo as well.