Remove DRM->DASH dependency in prep for DASH module split

Also renamed releaseResources->release to be consistent with the
rest of the library, and added some synchronization to ensure
correct usage.

Issue: #2139

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=150753414
This commit is contained in:
olly 2017-03-21 08:10:42 -07:00 committed by Oliver Woodman
parent 065d3dc523
commit b1a2ae1856
6 changed files with 190 additions and 175 deletions

View File

@ -23,17 +23,9 @@ import android.test.InstrumentationTestCase;
import android.test.MoreAsserts;
import android.util.Pair;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays;
import java.util.HashMap;
import org.mockito.Mock;
@ -50,89 +42,57 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
@Override
protected void setUp() throws Exception {
TestUtil.setUpMockito(this);
when(mediaDrm.openSession()).thenReturn(new byte[] {1, 2, 3});
offlineLicenseHelper = new OfflineLicenseHelper<>(mediaDrm, mediaDrmCallback, null);
}
@Override
protected void tearDown() throws Exception {
offlineLicenseHelper.releaseResources();
offlineLicenseHelper.release();
offlineLicenseHelper = null;
}
public void testDownloadRenewReleaseKey() throws Exception {
DashManifest manifest = newDashManifestWithAllElements();
setStubLicenseAndPlaybackDurationValues(1000, 200);
byte[] keySetId = {2, 5, 8};
setStubKeySetId(keySetId);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(newDrmInitData());
assertOfflineLicenseKeySetIdEqual(keySetId, offlineLicenseKeySetId);
byte[] keySetId2 = {6, 7, 0, 1, 4};
setStubKeySetId(keySetId2);
byte[] offlineLicenseKeySetId2 = offlineLicenseHelper.renew(offlineLicenseKeySetId);
byte[] offlineLicenseKeySetId2 = offlineLicenseHelper.renewLicense(offlineLicenseKeySetId);
assertOfflineLicenseKeySetIdEqual(keySetId2, offlineLicenseKeySetId2);
offlineLicenseHelper.release(offlineLicenseKeySetId2);
offlineLicenseHelper.releaseLicense(offlineLicenseKeySetId2);
}
public void testDownloadFailsIfThereIsNoInitData() throws Exception {
setDefaultStubValues();
DashManifest manifest =
newDashManifest(newPeriods(newAdaptationSets(newRepresentations(null /*no init data*/))));
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
assertNull(offlineLicenseKeySetId);
public void testDownloadLicenseFailsIfNullInitData() throws Exception {
try {
offlineLicenseHelper.downloadLicense(null);
fail();
} catch (IllegalArgumentException e) {
// Expected.
}
}
public void testDownloadFailsIfThereIsNoRepresentation() throws Exception {
setDefaultStubValues();
DashManifest manifest = newDashManifest(newPeriods(newAdaptationSets(/*no representation*/)));
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
assertNull(offlineLicenseKeySetId);
}
public void testDownloadFailsIfThereIsNoAdaptationSet() throws Exception {
setDefaultStubValues();
DashManifest manifest = newDashManifest(newPeriods(/*no adaptation set*/));
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
assertNull(offlineLicenseKeySetId);
}
public void testDownloadFailsIfThereIsNoPeriod() throws Exception {
setDefaultStubValues();
DashManifest manifest = newDashManifest(/*no periods*/);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
assertNull(offlineLicenseKeySetId);
}
public void testDownloadFailsIfNoKeySetIdIsReturned() throws Exception {
public void testDownloadLicenseFailsIfNoKeySetIdIsReturned() throws Exception {
setStubLicenseAndPlaybackDurationValues(1000, 200);
DashManifest manifest = newDashManifestWithAllElements();
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(newDrmInitData());
assertNull(offlineLicenseKeySetId);
}
public void testDownloadDoesNotFailIfDurationNotAvailable() throws Exception {
public void testDownloadLicenseDoesNotFailIfDurationNotAvailable() throws Exception {
setDefaultStubKeySetId();
DashManifest manifest = newDashManifestWithAllElements();
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(newDrmInitData());
assertNotNull(offlineLicenseKeySetId);
}
@ -142,9 +102,8 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
int playbackDuration = 200;
setStubLicenseAndPlaybackDurationValues(licenseDuration, playbackDuration);
setDefaultStubKeySetId();
DashManifest manifest = newDashManifestWithAllElements();
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(newDrmInitData());
Pair<Long, Long> licenseDurationRemainingSec = offlineLicenseHelper
.getLicenseDurationRemainingSec(offlineLicenseKeySetId);
@ -158,9 +117,8 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
int playbackDuration = 0;
setStubLicenseAndPlaybackDurationValues(licenseDuration, playbackDuration);
setDefaultStubKeySetId();
DashManifest manifest = newDashManifestWithAllElements();
byte[] offlineLicenseKeySetId = offlineLicenseHelper.download(httpDataSource, manifest);
byte[] offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(newDrmInitData());
Pair<Long, Long> licenseDurationRemainingSec = offlineLicenseHelper
.getLicenseDurationRemainingSec(offlineLicenseKeySetId);
@ -169,12 +127,6 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
assertEquals(playbackDuration, (long) licenseDurationRemainingSec.second);
}
private void setDefaultStubValues()
throws android.media.NotProvisionedException, android.media.DeniedByServerException {
setDefaultStubKeySetId();
setStubLicenseAndPlaybackDurationValues(1000, 200);
}
private void setDefaultStubKeySetId()
throws android.media.NotProvisionedException, android.media.DeniedByServerException {
setStubKeySetId(new byte[] {2, 5, 8});
@ -201,34 +153,9 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
when(mediaDrm.queryKeyStatus(any(byte[].class))).thenReturn(keyStatus);
}
private static DashManifest newDashManifestWithAllElements() {
return newDashManifest(newPeriods(newAdaptationSets(newRepresentations(newDrmInitData()))));
}
private static DashManifest newDashManifest(Period... periods) {
return new DashManifest(0, 0, 0, false, 0, 0, 0, null, null, Arrays.asList(periods));
}
private static Period newPeriods(AdaptationSet... adaptationSets) {
return new Period("", 0, Arrays.asList(adaptationSets));
}
private static AdaptationSet newAdaptationSets(Representation... representations) {
return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations), null);
}
private static Representation newRepresentations(DrmInitData drmInitData) {
Format format = Format.createVideoContainerFormat("id", MimeTypes.VIDEO_MP4,
MimeTypes.VIDEO_H264, "", Format.NO_VALUE, 1024, 768, Format.NO_VALUE, null, 0);
if (drmInitData != null) {
format = format.copyWithDrmInitData(drmInitData);
}
return Representation.newInstance("", 0, format, "", new SingleSegmentBase());
}
private static DrmInitData newDrmInitData() {
return new DrmInitData(new SchemeData(C.WIDEVINE_UUID, "mimeType",
new byte[]{1, 4, 7, 0, 3, 6}));
new byte[] {1, 4, 7, 0, 3, 6}));
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.dash;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
import com.google.android.exoplayer2.testutil.FakeDataSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import java.util.Arrays;
import junit.framework.TestCase;
/**
* Unit tests for {@link DashUtil}.
*/
public final class DashUtilTest extends TestCase {
public void testLoadDrmInitDataFromManifest() throws Exception {
Period period = newPeriod(newAdaptationSets(newRepresentations(newDrmInitData())));
DrmInitData drmInitData = DashUtil.loadDrmInitData(newDataSource(), period);
assertEquals(newDrmInitData(), drmInitData);
}
public void testLoadDrmInitDataMissing() throws Exception {
Period period = newPeriod(newAdaptationSets(newRepresentations(null /* no init data */)));
DrmInitData drmInitData = DashUtil.loadDrmInitData(newDataSource(), period);
assertNull(drmInitData);
}
public void testLoadDrmInitDataNoRepresentations() throws Exception {
Period period = newPeriod(newAdaptationSets(/* no representation */));
DrmInitData drmInitData = DashUtil.loadDrmInitData(newDataSource(), period);
assertNull(drmInitData);
}
public void testLoadDrmInitDataNoAdaptationSets() throws Exception {
Period period = newPeriod(/* no adaptation set */);
DrmInitData drmInitData = DashUtil.loadDrmInitData(newDataSource(), period);
assertNull(drmInitData);
}
private static Period newPeriod(AdaptationSet... adaptationSets) {
return new Period("", 0, Arrays.asList(adaptationSets));
}
private static AdaptationSet newAdaptationSets(Representation... representations) {
return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations), null);
}
private static Representation newRepresentations(DrmInitData drmInitData) {
Format format = Format.createVideoContainerFormat("id", MimeTypes.VIDEO_MP4,
MimeTypes.VIDEO_H264, "", Format.NO_VALUE, 1024, 768, Format.NO_VALUE, null, 0);
if (drmInitData != null) {
format = format.copyWithDrmInitData(drmInitData);
}
return Representation.newInstance("", 0, format, "", new SingleSegmentBase());
}
private static DrmInitData newDrmInitData() {
return new DrmInitData(new SchemeData(C.WIDEVINE_UUID, "mimeType",
new byte[]{1, 4, 7, 0, 3, 6}));
}
private static DataSource newDataSource() {
// TODO: Use DummyDataSource when available.
FakeDataSource fakeDataSource = new FakeDataSource();
fakeDataSource.getDataSet().newDefaultData().appendReadError(new IOException("Unexpected"));
return fakeDataSource;
}
}

View File

@ -22,15 +22,9 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.util.Pair;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.EventListener;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.source.dash.DashUtil;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource.Factory;
import com.google.android.exoplayer2.util.Assertions;
@ -38,8 +32,7 @@ import java.io.IOException;
import java.util.HashMap;
/**
* Helper class to download, renew and release offline licenses. It utilizes {@link
* DefaultDrmSessionManager}.
* Helper class to download, renew and release offline licenses.
*/
public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
@ -48,8 +41,8 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
private final HandlerThread handlerThread;
/**
* Instantiates a new instance which uses Widevine CDM. Call {@link #releaseResources()} when
* you're done with the helper instance.
* Instantiates a new instance which uses Widevine CDM. Call {@link #release()} when the instance
* is no longer required.
*
* @param licenseUrl The default license URL.
* @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances.
@ -64,8 +57,8 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
}
/**
* Instantiates a new instance which uses Widevine CDM. Call {@link #releaseResources()} when
* you're done with the helper instance.
* Instantiates a new instance which uses Widevine CDM. Call {@link #release()} when the instance
* is no longer required.
*
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
@ -84,7 +77,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
}
/**
* Constructs an instance. Call {@link #releaseResources()} when you're done with it.
* Constructs an instance. Call {@link #release()} when the instance is no longer required.
*
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
@ -97,7 +90,6 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
HashMap<String, String> optionalKeyRequestParameters) {
handlerThread = new HandlerThread("OfflineLicenseHelper");
handlerThread.start();
conditionVariable = new ConditionVariable();
EventListener eventListener = new EventListener() {
@Override
@ -124,67 +116,23 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
optionalKeyRequestParameters, new Handler(handlerThread.getLooper()), eventListener);
}
/** Releases the used resources. */
public void releaseResources() {
/** Releases the helper. Should be called when the helper is no longer required. */
public void release() {
handlerThread.quit();
}
/**
* Downloads an offline license.
*
* @param dataSource The {@link HttpDataSource} to be used for download.
* @param manifestUriString The URI of the manifest to be read.
* @return The downloaded offline license key set id.
* @param drmInitData The {@link DrmInitData} for the content whose license is to be downloaded.
* @return The key set id for the downloaded license.
* @throws IOException If an error occurs reading data from the stream.
* @throws InterruptedException If the thread has been interrupted.
* @throws DrmSessionException Thrown when there is an error during DRM session.
* @throws DrmSessionException Thrown when a DRM session error occurs.
*/
public byte[] download(HttpDataSource dataSource, String manifestUriString)
throws IOException, InterruptedException, DrmSessionException {
return download(dataSource, DashUtil.loadManifest(dataSource, manifestUriString));
}
/**
* Downloads an offline license.
*
* @param dataSource The {@link HttpDataSource} to be used for download.
* @param dashManifest The {@link DashManifest} of the DASH content.
* @return The downloaded offline license key set id.
* @throws IOException If an error occurs reading data from the stream.
* @throws InterruptedException If the thread has been interrupted.
* @throws DrmSessionException Thrown when there is an error during DRM session.
*/
public byte[] download(HttpDataSource dataSource, DashManifest dashManifest)
throws IOException, InterruptedException, DrmSessionException {
// Get DrmInitData
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
if (dashManifest.getPeriodCount() < 1) {
return null;
}
Period period = dashManifest.getPeriod(0);
int adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_VIDEO);
if (adaptationSetIndex == C.INDEX_UNSET) {
adaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_AUDIO);
if (adaptationSetIndex == C.INDEX_UNSET) {
return null;
}
}
AdaptationSet adaptationSet = period.adaptationSets.get(adaptationSetIndex);
if (adaptationSet.representations.isEmpty()) {
return null;
}
Representation representation = adaptationSet.representations.get(0);
DrmInitData drmInitData = representation.format.drmInitData;
if (drmInitData == null) {
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
if (sampleFormat != null) {
drmInitData = sampleFormat.drmInitData;
}
if (drmInitData == null) {
return null;
}
}
public synchronized byte[] downloadLicense(DrmInitData drmInitData) throws IOException,
InterruptedException, DrmSessionException {
Assertions.checkArgument(drmInitData != null);
blockingKeyRequest(DefaultDrmSessionManager.MODE_DOWNLOAD, null, drmInitData);
return drmSessionManager.getOfflineLicenseKeySetId();
}
@ -193,10 +141,11 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
* Renews an offline license.
*
* @param offlineLicenseKeySetId The key set id of the license to be renewed.
* @return Renewed offline license key set id.
* @throws DrmSessionException Thrown when there is an error during DRM session.
* @return The renewed offline license key set id.
* @throws DrmSessionException Thrown when a DRM session error occurs.
*/
public byte[] renew(byte[] offlineLicenseKeySetId) throws DrmSessionException {
public synchronized byte[] renewLicense(byte[] offlineLicenseKeySetId)
throws DrmSessionException {
Assertions.checkNotNull(offlineLicenseKeySetId);
blockingKeyRequest(DefaultDrmSessionManager.MODE_DOWNLOAD, offlineLicenseKeySetId, null);
return drmSessionManager.getOfflineLicenseKeySetId();
@ -206,19 +155,22 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
* Releases an offline license.
*
* @param offlineLicenseKeySetId The key set id of the license to be released.
* @throws DrmSessionException Thrown when there is an error during DRM session.
* @throws DrmSessionException Thrown when a DRM session error occurs.
*/
public void release(byte[] offlineLicenseKeySetId) throws DrmSessionException {
public synchronized void releaseLicense(byte[] offlineLicenseKeySetId)
throws DrmSessionException {
Assertions.checkNotNull(offlineLicenseKeySetId);
blockingKeyRequest(DefaultDrmSessionManager.MODE_RELEASE, offlineLicenseKeySetId, null);
}
/**
* Returns license and playback durations remaining in seconds of the given offline license.
* Returns the remaining license and playback durations in seconds, for an offline license.
*
* @param offlineLicenseKeySetId The key set id of the license.
* @return The remaining license and playback durations, in seconds.
* @throws DrmSessionException Thrown when a DRM session error occurs.
*/
public Pair<Long, Long> getLicenseDurationRemainingSec(byte[] offlineLicenseKeySetId)
public synchronized Pair<Long, Long> getLicenseDurationRemainingSec(byte[] offlineLicenseKeySetId)
throws DrmSessionException {
Assertions.checkNotNull(offlineLicenseKeySetId);
DrmSession<T> session = openBlockingKeyRequest(DefaultDrmSessionManager.MODE_QUERY,

View File

@ -38,7 +38,7 @@ public final class WidevineUtil {
* @throws IllegalStateException If called when a session isn't opened.
* @param drmSession
*/
public static Pair<Long, Long> getLicenseDurationRemainingSec(DrmSession drmSession) {
public static Pair<Long, Long> getLicenseDurationRemainingSec(DrmSession<?> drmSession) {
Map<String, String> keyStatus = drmSession.queryKeyStatus();
return new Pair<>(
getDurationRemainingSec(keyStatus, PROPERTY_LICENSE_DURATION_REMAINING),

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.dash;
import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.extractor.ChunkIndex;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
@ -26,6 +27,7 @@ import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper;
import com.google.android.exoplayer2.source.chunk.InitializationChunk;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.upstream.DataSource;
@ -34,6 +36,7 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import java.util.List;
/**
* Utility methods for DASH streams.
@ -46,8 +49,7 @@ public final class DashUtil {
* @param dataSource The {@link HttpDataSource} from which the manifest should be read.
* @param manifestUriString The URI of the manifest to be read.
* @return An instance of {@link DashManifest}.
* @throws IOException If an error occurs reading data from the stream.
* @see DashManifestParser
* @throws IOException Thrown when there is an error while loading.
*/
public static DashManifest loadManifest(DataSource dataSource, String manifestUriString)
throws IOException {
@ -63,8 +65,35 @@ public final class DashUtil {
}
/**
* Loads initialization data for the {@code representation} and returns the sample {@link
* Format}.
* Loads {@link DrmInitData} for a given period in a DASH manifest.
*
* @param dataSource The {@link HttpDataSource} from which data should be loaded.
* @param period The {@link Period}.
* @return The loaded {@link DrmInitData}, or null if none is defined.
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
throws IOException, InterruptedException {
Representation representation = getFirstRepresentation(period, C.TRACK_TYPE_VIDEO);
if (representation == null) {
representation = getFirstRepresentation(period, C.TRACK_TYPE_AUDIO);
if (representation == null) {
return null;
}
}
DrmInitData drmInitData = representation.format.drmInitData;
if (drmInitData != null) {
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
return drmInitData;
}
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
return sampleFormat == null ? null : sampleFormat.drmInitData;
}
/**
* Loads initialization data for the {@code representation} and returns the sample {@link Format}.
*
* @param dataSource The source from which the data should be loaded.
* @param representation The representation which initialization chunk belongs to.
@ -155,6 +184,15 @@ public final class DashUtil {
return new ChunkExtractorWrapper(extractor, format);
}
private static Representation getFirstRepresentation(Period period, int type) {
int index = period.getAdaptationSetIndex(type);
if (index == C.INDEX_UNSET) {
return null;
}
List<Representation> representations = period.adaptationSets.get(index).representations;
return representations.isEmpty() ? null : representations.get(0);
}
private DashUtil() {}
}

View File

@ -18,11 +18,15 @@ package com.google.android.exoplayer2.playbacktests.gts;
import android.media.MediaDrm.MediaDrmStateException;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Pair;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.drm.OfflineLicenseHelper;
import com.google.android.exoplayer2.playbacktests.util.ActionSchedule;
import com.google.android.exoplayer2.playbacktests.util.HostActivity;
import com.google.android.exoplayer2.source.dash.DashUtil;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
@ -72,7 +76,7 @@ public final class DashWidevineOfflineTest extends ActivityInstrumentationTestCa
releaseLicense();
}
if (offlineLicenseHelper != null) {
offlineLicenseHelper.releaseResources();
offlineLicenseHelper.release();
}
offlineLicenseHelper = null;
httpDataSourceFactory = null;
@ -89,7 +93,7 @@ public final class DashWidevineOfflineTest extends ActivityInstrumentationTestCa
testRunner.run();
// Renew license after playback should still work
offlineLicenseKeySetId = offlineLicenseHelper.renew(offlineLicenseKeySetId);
offlineLicenseKeySetId = offlineLicenseHelper.renewLicense(offlineLicenseKeySetId);
Assert.assertNotNull(offlineLicenseKeySetId);
}
@ -164,15 +168,18 @@ public final class DashWidevineOfflineTest extends ActivityInstrumentationTestCa
}
private void downloadLicense() throws InterruptedException, DrmSessionException, IOException {
offlineLicenseKeySetId = offlineLicenseHelper.download(
httpDataSourceFactory.createDataSource(), DashTestData.WIDEVINE_H264_MANIFEST);
DataSource dataSource = httpDataSourceFactory.createDataSource();
DashManifest dashManifest = DashUtil.loadManifest(dataSource,
DashTestData.WIDEVINE_H264_MANIFEST);
DrmInitData drmInitData = DashUtil.loadDrmInitData(dataSource, dashManifest.getPeriod(0));
offlineLicenseKeySetId = offlineLicenseHelper.downloadLicense(drmInitData);
Assert.assertNotNull(offlineLicenseKeySetId);
Assert.assertTrue(offlineLicenseKeySetId.length > 0);
testRunner.setOfflineLicenseKeySetId(offlineLicenseKeySetId);
}
private void releaseLicense() throws DrmSessionException {
offlineLicenseHelper.release(offlineLicenseKeySetId);
offlineLicenseHelper.releaseLicense(offlineLicenseKeySetId);
offlineLicenseKeySetId = null;
}