Skip to main content

Chromecast

Chromecast on Quickplay platform qualifies as a device on its own and can perform device registration, content authorization and playback similar to any other conventional devices. The client sender facilitates sharing required information for device registration and content authorization to the receiver and the receiver processes the same for playback.

Overview

Casting a media using Quickplay platform requires the following to be performed in a sequence:

  • Initialize Cast Manager
  • Send User Device Information message to Receiver
  • Load Media onto Receiver

Please note, the above sequence of steps needs to be performed invariably for a new cast session inclusive of both Connect & Play and Play & Connect scenarios.

info

It is advised that the initialization of cast manager and sharing user device information be performed during application launch and load media be performed on demand.

Cast Manager

CastManager uses Google Cast Application Framework's (CAF) SessionManager instance to manage CastSession and coordinate all the Cast interactions. CastManager provides access to CastPlayer that helps in initiating and controlling playback on the Web Receiver Application, and enforces policies for accessing Quickplay Platform resources.

info

All SDK methods must be called from the main thread.

Initializing GCKCastOption

In the launch of the application you will be providing an web receiver application ID, which is used to filter discovery results and to launch the Web Receiver app when a Cast session is started.

A GCKCastOption object must be supplied when initializing the GCKCastContext. This class contains options that affect the behavior of the framework.

let criteria = GCKDiscoveryCriteria(applicationID: "<Receiver_Application_Id>")
let gckOptions = GCKCastOptions(discoveryCriteria: criteria)

Start Communicate via FLChromecast framework

Next steps to calling the api initialize() to ensure listener for receiving notifications of session manager and create default channel which would be used for sender receiver communications via our framework FLCastManager.

FLChromecastFactory.sharedCastManager.initialize()

Cast Manager Callbacks

session manager listener notifications and CAF's CastSession events will be provided in FLCastManagerDelegate call backs. Use our registerListener api to get the callbacks, You need to set a confirmed instance of FLCastManagerDelegate.

FLChromecastFactory.sharedCastManager.registerListener(_ delegate: FLCastManagerDelegate?)

List of Callbacks

    /// Initialization of GCKCastContext can be success of failure.
func onCastManagerInitializationSuccess()
func onCastManagerInitializationFailure()

/// Launch of the application the castsession which is already started or Reconnecting to a receiver session due to networking issues is also automatically handled by the Cast SDK.
func castManagerDidResume(_ session: GCKSession)

/// cast session is started succesfully without error
func castManagerDidStart(_ session: GCKCastSession)
/// cast session is failed to start
func castManagerDidFailToStart(_: GCKSession, withError error: Error)

/// cast session ended succesfully or failed with error
func castManagerDidEnd(_: GCKSession, withError error: Error?)

/// cast session registed the used device information
func castManagerDidRegisterDevice()
/// cast session failed to registed the used device information
func castManagerDidFailToRegisterDevice(with _: Error)

Cast Session Management

For the CAF a CastSession combines the steps of connecting to a device, launching (or joining), connecting to the Receiver Application, and initializing a media control channel if appropriate. The media control channel is how the Cast framework sends and receives messages from the Receiver Media Player. The CastSession will be started automatically, when user clicks the Cast button and selects a device from the list, and will be stopped automatically when user disconnects. Reconnecting to a receiver session due to networking issues is also automatically handled by the Cast SDK.

Device Registration

The Sender Application requires CastPlayer instance to initiate content playback, but before casting any media, the Cast Device must be registered with Quickplay Platform. The status of Device Registration will be notified to the sender application via the attached FLCastManagerDelegate.

Send User Device Information

Once a session has been established successfully, one must share the User Device Information to the Receiver. This is a mandate step, so that the receiver can register the device with Quickplay platform and perform authorization while loading media.

The Sender Application should call CastManager.registerUserData to perform the user data, that includes the Cast Device ID, registration. The registration should be done just after CastManager notifies the Sender Application that the CastSession has be started. After the user data registration the Sender Application should proceed with loading media on the Receiver Application. If the user data registration failed then the Sender Application will be notified, with an error, when the first attempt is made to load media on the Receiver Application.

Required Inputs of Device Registration

Property NameTypeDescription
castDeviceIDStringcast device Id for the cast session.
platformClientPlatformClientThe sender client device
authTokenStringThe user authentication token.
func castManagerDidStart(session: GCKCastSession) {
// Register user device information
castManager.registerUserData(
clientDevice: device,
castDeviceID: session.device.deviceID,
authToken: authToken
)
}

func castManagerDidFailToStart(session: GCKSession, withError error: Error) {
// Session failed to start with error
}

Load Media

The Cast Player with Cast Manager is analogous to the remote media player of Receiver. The same is available upon successful initialization of Cast Manager. To load media one should create a CastPlatformAsset which describes the media that needs to be authorized with Quickplay platform and played upon successful authorization. One can load GCKMediaMetadata and GCKMediaTrack optionally while loading media.

CastPlatformAsset and CastAsset

CastPlatformAsset encapsulates all the information required by receiver to authorize the content and start the playback.

Property NameTypeMandatory?Description
mediaIDStringYesThe unique id of the content to cast.
consumptionTypeConsumptionTypeYesThe ConsumptionType of the content. It can be ConsumptionType.LIVE or ConsumptionType.VOD.
catalogTypeStringYesThe catalog type of the content.
mediaTypeMediaTypeYesThe MediaType of the content. It can be MediaType.DASH, MediaType.SMOOTH_STREAMING or MediaType.HLS.
drmSchemeDrmTypeNoThe DrmType of the content. Default value for the Android platform is DrmType.WIDEVINE.
playbackModePlaybackMode?NoOne of the PlaybackMode values i.e. PlaybackMode.LIVE, PlaybackMode.RESTART or PlaybackMode.CATCHUP. This is mandatory only for the live playback.
eventIdString?NoThe unique identifier of the live event/channel.
startTimeString?NoThe live event start time in ISO 8601 format(in milliseconds). This is mandatory when playing in restart and catchup modes, otherwise not required.
endTimeString?NoThe live event end time in ISO 8601 format(in milliseconds). This is mandatory when playing in catchup mode, otherwise not required..
urlParametersLongNolist of custom parameters. For example, ads parameters prefixed with "ads.".

CastAsset binds additional information along with the CastPlatformAsset. This object should necessarily be passed to the loadMedia API that starts the playback.

Property NameTypeMandatory?Description
userAuthTokenStringYesThe user authentication token.
platformAssetCastPlatformAssetYesThe CastPlatformAsset object associated with the playback.
headersDictionary<String, String>?NoThe Key-Value pair sent as HTTP Request Header.
flAnalyticsDataDictionary<String, String>?NoAny additional analytics attributes that has to be shared with chromecast receiver.
videoAnalyticsDataDictionary<String, String>?NoAny additional video analytics metadata that has to be shared with chromecast receiver.
metadataDictionary<String, Any>?NoTVOD data to be shared with chromecast receiver (optional)
customAdMetadataDictionary<String, String>?NoAny additional ad metadata that has to be shared with chromecast receiver.

Custom metadata can be sent to newrelic via loadMedia API through 'flAnalyticsData'. Similarly custom metadata can be sent to video analytics via loadMedia API through 'videoAnalyticsData'.

After building the CastAsset and MediaMetadata objects along with a successful CastSession, the sender application can try to start loading using the CastPlayer.loadMedia API.

let mediaMetadata = GCKMediaMetadata()
metadata.setString("Pass prefered value", forKey: kGCKMetadataKeyTitle)
let metadata = ["streamType": platformAsset.contentType.rawValue.capitalized, "userType": "subscriber", "platform": "castclient" ]

let castAsset = CastAssetWithAnalytics<[String: String], [String: String], [String: String], [String: String]>(
userAuthToken: authToken,
platformAsset: castPlatformAsset,
headers: [:],
flAnalyticsData: flAnalyticsData,
videoAnalyticsData: videoAnalyticsData,
customAdMetadata: customAdMetadata,
metadata: metadata,
bookmarkData: bookmarkData)

castPlayer?.loadMedia(castAsset: castAsset, metadata: mediaMetadata)

The above snipped demonstrates creating a DASH/Widevine Movie content for authorization and playback. The supported combinations might differ based on individual projects. The Receiver upon receiving this information attempts to authorize the asset with Quickplay platform and plays the content.

Cast Player and Events

The CastPlayer extends Player interface and provides the benefit of having same APIs as conventional Player from FLPlayer library. Some of the player APIs are no-op with CastPlayer, due to constraints with underlying player, Remote Media Client in this case.

The following APIs with Player interface are no-op as of today:

  • replaceAsset(:)
  • load()
  • seek(to date:)
  • all PiP APIs
  • all track manipulation APIs accepting MediaType
  • set(preferences:)
// access remote player
FLChromecastFactory.sharedCastManager.castPlayer

To listen to player events, implement the player delegate and listen for callbacks. Media load failures will also be notified via player delegate.

Cast Player UI

FLChomecast library does not wrap GoogleCast SDK to provide all functionalities that GoogleCast SDK offers. UI components from GoogleCast SDK can be used to render cast buttons. The integrators have complete control over player UI rendering and can enjoy the same luxury of integrating GoogleCast SDK directly. Most of the integrators prefer using their own UI for player which can double up as remote Cast Player and local Player. The integration is a breeze due to the fact that both players, FLPlayer(local playback) and CastPlayer(Remote playback) has same public interface.

E2E Integration

Here is the snippet comprising all the above sequence of steps.


//********** Initialize cast Manager at app launch *********

// GCK Options
let criteria = GCKDiscoveryCriteria(applicationID: <Receiver_Application_Id>)
let options = GCKCastOptions(discoveryCriteria: criteria)

// Set delegate to receive callbacks from CastManager
FLChromecastFactory.sharedCastManager.registerListener(_ delegate: FLCastManagerDelegate?)
FLChromecastFactory.sharedCastManager.initialize()

//********** Send user device information to Receiver on Cast Manager initialization delegate callback *********

func castManagerDidStart(session: GCKCastSession) {
// Register user device information
castManager.registerUserData(
clientDevice: device,
castDeviceID: session.device.deviceID,
authToken: authToken
)
}

func castManagerDidFailToStart(session: GCKSession, withError error: Error) {
// Session not started
}

//********** Load Media *********

let castPlatformAsset = CastPlatformAsset(
mediaID: "myMediaID", // pass preferred value
consumptionType: ConsumptionType.LIVE, // pass preferred value
catalogType: "myCatalogType", // pass preferred value
mediaType: MediaType.DASH, // pass preferred value
drmScheme: DrmType.WIDEVINE, // pass preferred value
playbackMode: PlaybackMode.RESTART, // pass preferred value. mandatory for any LIVE playback.
eventId: "myEventID", // pass preferred value
startTime: "9999-12-30T12:59:59Z", // program start time in yyyy-MM-dd'T'HH:mm:ss'Z' format. mandatory for RESTART and CATCHUP playbacks.
endTime:"9999-12-31T12:59:59Z", // program end time in yyyy-MM-dd'T'HH:mm:ss'Z' format. mandatory for RESTART and CATCHUP playbacks.
urlParameters: asset.urlParameters // pass preferred value
)

// configure metadata
let metadata = GCKMediaMetadata()

// any additional custom metadata for analytics. below is the expected schema for New Relic:
// sends data to newrelic
let flAnalyticsData = [
'appBuild': 'test_id',
'channelID': 'D6C06257-3532-4431-93AB-C55A38f9EF0',
'contentID': 'SH021648050000',
'contentName': 'content-title',
'channelName': 'Sports HD',
'pageID': 'MyContent',
'seriesName': '',
'serviceID': '',
'silentLogin': 'true',
'tabName': 'movies',
],
// sends data to conviva
let videoAnalyticsData = [
'viewerId': 'userID / mobileNumber / emailId', // mandatory
'assetName': 'Name of the content', //mandatory
'tags': customTags, // customTags is a Key value pair that provide additional information about the content and it is optional.
]

// sends ad metadata
let customAdMetadata = [
'idType': 'The type of device.(eg: 'idfa')', // mandatory
'rdId': 'Apple IDFA (eg: '123e4567-e89b-12d3-a456-426655440000')', //mandatory
'isLat': 'Limit Ad Tracking (LAT) lets users to opt-out and therefore restrict advertisers from targeting based on user behavior. (eg: boolean either 0 or 1)' //mandatory
]

let mediaMetadata = GCKMediaMetadata()
metadata.setString("Pass prefered value", forKey: kGCKMetadataKeyTitle)
let metadata = ["streamType": platformAsset.contentType.rawValue.capitalized, "userType": "subscriber", "platform": "castclient" ]

let castAsset = CastAssetWithAnalytics<[String: String], [String: String], [String: String], [String: String]>(
userAuthToken: authToken,
platformAsset: castPlatformAsset,
headers: [:],
flAnalyticsData: flAnalyticsData,
videoAnalyticsData: videoAnalyticsData,
customAdMetadata: customAdMetadata,
metadata: metadata,
bookmarkData: bookmarkData)

castPlayer?.loadMedia(castAsset: castAsset, metadata: mediaMetadata)