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 it for playback.
Overview
Casting media using Quickplay platform requires you to perform the following steps in sequence:
- Initialize Cast Manager
- Send User Device Information message to Receiver
- Load Media onto Receiver
You need to perform the above sequence of steps for a new cast session, which includes both Connect & Play and Play & Connect scenarios.
We recommend that you initialize the cast manager and share user device information during application launch, and load media 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 you initiate and control playback on the Web Receiver Application, and enforces policies for accessing Quickplay Platform resources.
All SDK methods must be called from the main thread.
Initialize GCKCastOption
In the launch of your application, provide a web receiver application ID, which is used to filter discovery results and to launch the Web Receiver app when a Cast session is started.
You must supply a GCKCastOption object 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, call the initialize() API to ensure listener for receiving notifications of session manager and create default channel which is used for sender receiver communications via the FLCastManager framework.
FLChromecastFactory.sharedCastManager.initialize()
Cast Manager callbacks
Session manager listener notifications and CAF's CastSession events are provided in FLCastManagerDelegate callbacks. Use the 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 starts automatically when you click the Cast button and select a device from the list, and stops automatically when you disconnect. Reconnecting to a receiver session due to networking issues is also automatically handled by the Cast SDK.
Device Registration
The Sender Application requires a CastPlayer instance to initiate content playback, but before casting any media, you must register the Cast Device with Quickplay Platform. The status of Device Registration is notified to the sender application via the attached FLCastManagerDelegate.
Send User Device Information
Once a session has been established successfully, you must share the User Device Information with the Receiver. This is a mandatory 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 registration, which includes the Cast Device ID. You should complete the registration just after CastManager notifies the Sender Application that the CastSession has started. After the user data registration, the Sender Application should proceed with loading media on the Receiver Application.
If the user data registration fails, the Sender Application is notified with an error when the first attempt is made to load media on the Receiver Application.
Required inputs of device registration
| Property Name | Type | Description |
|---|---|---|
| castDeviceID | String | Cast device ID for the cast session |
| platformClient | PlatformClient | The sender client device |
| authToken | String | The 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. It's available upon successful initialization of Cast Manager. To load media, you should create a CastPlatformAsset which describes the media that needs to be authorized with Quickplay platform and played upon successful authorization. You 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 Name | Type | Mandatory? | Description |
|---|---|---|---|
| mediaID | String | Yes | The unique ID of the content to cast |
| consumptionType | ConsumptionType | Yes | The ConsumptionType of the content. It can be ConsumptionType.LIVE or ConsumptionType.VOD |
| catalogType | String | Yes | The catalog type of the content |
| mediaType | MediaType | Yes | The MediaType of the content. It can be MediaType.DASH, MediaType.SMOOTH_STREAMING, or MediaType.HLS |
| drmScheme | DrmType | No | The DrmType of the content. Default value for the Android platform is DrmType.WIDEVINE |
| playbackMode | PlaybackMode? | No | One of the PlaybackMode values (that is, PlaybackMode.LIVE, PlaybackMode.RESTART, or PlaybackMode.CATCHUP). This is mandatory only for the live playback |
| eventId | String? | No | The unique identifier of the live event/channel |
| startTime | String? | No | The live event start time in ISO 8601 format (in milliseconds). This is mandatory when playing in restart and catchup modes, otherwise not required |
| endTime | String? | No | The live event end time in ISO 8601 format (in milliseconds). This is mandatory when playing in catchup mode, otherwise not required |
| urlParameters | Long | No | List of custom parameters. For example, ads parameters prefixed with "ads." |
CastAsset binds additional information along with the CastPlatformAsset. You should pass this object to the loadMedia API that starts the playback.
| Property Name | Type | Mandatory? | Description |
|---|---|---|---|
| userAuthToken | String | Yes | The user authentication token |
| platformAsset | CastPlatformAsset | Yes | The CastPlatformAsset object associated with the playback |
| headers | Dictionary<String, String>? | No | The Key-Value pair sent as HTTP Request Header |
| flAnalyticsData | Dictionary<String, String>? | No | Any additional analytics attributes that must be shared with chromecast receiver |
| videoAnalyticsData | Dictionary<String, String>? | No | Any additional video analytics metadata that must be shared with chromecast receiver |
| metadata | Dictionary<String, Any>? | No | TVOD data to be shared with chromecast receiver (optional) |
| customAdMetadata | Dictionary<String, String>? | No | Any additional ad metadata that must be shared with chromecast receiver |
You can send custom metadata to newrelic via loadMedia API through flAnalyticsData. Similarly, you can send custom metadata to video analytics via loadMedia API through videoAnalyticsData.
After building the CastAsset and MediaMetadata objects along with a successful CastSession, your 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 snippet 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 the Player interface and provides the benefit of having the same APIs as conventional Player from the FLPlayer library. Some of the player APIs are no-op with CastPlayer, due to constraints with the 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
The FLChromecast library doesn't wrap GoogleCast SDK to provide all functionalities that GoogleCast SDK offers. You can use UI components from GoogleCast SDK to render cast buttons. You have complete control over player UI rendering and can enjoy the same benefits of integrating GoogleCast SDK directly. Most integrators prefer using their own UI for player which can serve as both remote Cast Player and local Player. The integration is straightforward because both players—FLPlayer (local playback) and CastPlayer (remote playback)—have the same public interface.
E2E Integration
The following snippet demonstrates 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)