Preacquire DRM session/download License
Our use case is a bit special.
- We have setup and
prepared()everything,ExoPlayer,DataSource,TrackSelectorandDefaultDrmSessionManager -
playWhenReadyis set to true - But we DISABLE all the renders by the following code.
for (int i = 0; i < getRendererCount(); i++) {
trackSelector.setParameters(trackSelector.buildUponParameters().setRendererDisabled(i, disabled).build());
}
The manifest URL is a dash live stream. So we do see dash manifest gets updated periodically. So everything works as expected except we are using DRMToday's Upfront token. I've noticed when both audio & video renderers are disabled, DRM License download won't be triggered. The expiration period of Upfront token is only 10 minutes.
So we are trying to manually/force trigger the DRM License downloading (renderers could remain disabled for hours). We are planning to use DefaultDrmSessionManager.preacquireSession()
Our plan is
- When
onTracksChanged()gets called, loop through all the tracks and find the WidevineDrmInitData - Use the
DrmInitDataas a param to callDefaultDrmSessionManager.preacquireSession()to manually trigger the DRM license downloading. Here are the source code.
Source code
private void onTracksChanged(Tracks tracks) {
String drmSvrUrl = "...";
DrmInitData.SchemeData widevineSchemeData = null;
outerLoop:
for (Tracks.Group group: tracks.getGroups()) {
if (group.getType() != C.TRACK_TYPE_VIDEO) {
continue;
}
for(int i = 0; i < group.length; i++) {
DrmInitData initData = group.getTrackFormat(i).drmInitData;
if (initData == null) {
continue;
}
for (int j = 0; j < initData.schemeDataCount; j++) {
DrmInitData.SchemeData schemeData = initData.get(j);
if (C.WIDEVINE_UUID.equals(schemeData.uuid)
&& !TextUtils.isEmpty(schemeData.mimeType)
&& schemeData.data != null
&& schemeData.data.length != 0
) {
widevineSchemeData = new DrmInitData.SchemeData(
schemeData.uuid,
drmSvrUrl,
schemeData.mimeType,
schemeData.data);
break outerLoop;
}
}
}
}
if (widevineSchemeData == null) {
Log.d(TAG, "no valid drmInitData found. quitting preacquire()");
return;
}
// Release it when playback is done
drmSessionRef = drmSessionManager.preacquireSession(new DrmSessionEventListener.EventDispatcher(),
new Format.Builder()
.setSampleMimeType(widevineSchemeData.mimeType)
.setDrmInitData(new DrmInitData(widevineSchemeData))
.build()
);
}
We have made a POC, it proves to work. The whole flow is as following
- Playback gets started, all renders are disabled. But dash manifest gets refreshed
- The drm license downloading(
preacquireSession()) was triggered inonTracksChanged() - Wait for 11 minutes
- Enable all renders
- The video/audio gets output as expected. Everything works fine.
Our questions are
- Do you see any pitfalls with this implementation?
- Should we tweak the
DefaultDrmSessionManager.Builder.setSessionKeepaliveMs()to make sure the session remained open long enough?
- Do you see any pitfalls with this implementation?
You don't mention when you will release the preacquired session. You need to explicitly do this, otherwise the underlying resources will be held for longer than necessary.
- Should we tweak the
DefaultDrmSessionManager.Builder.setSessionKeepaliveMs()to make sure the session remained open long enough?
Based on your description, you shouldn't need to rely on session keep-alive, since you're explicitly holding references to preacquired sessions, which will keep the underlying session open even if keep-alive is disabled (hence the need to explicitly release these preacquired sessions) - unless a contention for underlying resources causes DefaultDrmSessionManager to eagerly release sessions, in which case it will release both preacquired and kept-alive sessions - so no real difference/benefit to keep-alive.
Note that the only difference between 'preacquired' sessions and normal ones is that DefaultDrmSessionManager will eagerly release preacquired ones when it encounters a shortage of sessions in the underlying hardware (and therefore an owner of a preacquired session can't rely on it being available for decoding, but in the normal case it will remain open).
Closing due to inactivity.