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.
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.
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 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. 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 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 i.e. 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
. This object should necessarily be passed 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 has to be shared with chromecast receiver. |
videoAnalyticsData | Dictionary<String, String>? | No | Any additional video analytics metadata that has to 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 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)