summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java425
1 files changed, 425 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java
new file mode 100644
index 0000000000..2a25d1deb4
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/drm/DrmInitData.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2016 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 org.mozilla.thirdparty.com.google.android.exoplayer2.drm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Util;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Initialization data for one or more DRM schemes.
+ */
+public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
+
+ /**
+ * Merges {@link DrmInitData} obtained from a media manifest and a media stream.
+ *
+ * <p>The result is generated as follows.
+ *
+ * <ol>
+ * <li>Include all {@link SchemeData}s from {@code manifestData} where {@link
+ * SchemeData#hasData()} is true.
+ * <li>Include all {@link SchemeData}s in {@code mediaData} where {@link SchemeData#hasData()}
+ * is true and for which we did not include an entry from the manifest targeting the same
+ * UUID.
+ * <li>If available, the scheme type from the manifest is used. If not, the scheme type from the
+ * media is used.
+ * </ol>
+ *
+ * @param manifestData DRM session acquisition data obtained from the manifest.
+ * @param mediaData DRM session acquisition data obtained from the media.
+ * @return A {@link DrmInitData} obtained from merging a media manifest and a media stream.
+ */
+ public static @Nullable DrmInitData createSessionCreationData(
+ @Nullable DrmInitData manifestData, @Nullable DrmInitData mediaData) {
+ ArrayList<SchemeData> result = new ArrayList<>();
+ String schemeType = null;
+ if (manifestData != null) {
+ schemeType = manifestData.schemeType;
+ for (SchemeData data : manifestData.schemeDatas) {
+ if (data.hasData()) {
+ result.add(data);
+ }
+ }
+ }
+
+ if (mediaData != null) {
+ if (schemeType == null) {
+ schemeType = mediaData.schemeType;
+ }
+ int manifestDatasCount = result.size();
+ for (SchemeData data : mediaData.schemeDatas) {
+ if (data.hasData() && !containsSchemeDataWithUuid(result, manifestDatasCount, data.uuid)) {
+ result.add(data);
+ }
+ }
+ }
+
+ return result.isEmpty() ? null : new DrmInitData(schemeType, result);
+ }
+
+ private final SchemeData[] schemeDatas;
+
+ // Lazily initialized hashcode.
+ private int hashCode;
+
+ /** The protection scheme type, or null if not applicable or unknown. */
+ @Nullable public final String schemeType;
+
+ /**
+ * Number of {@link SchemeData}s.
+ */
+ public final int schemeDataCount;
+
+ /**
+ * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
+ */
+ public DrmInitData(List<SchemeData> schemeDatas) {
+ this(null, false, schemeDatas.toArray(new SchemeData[0]));
+ }
+
+ /**
+ * @param schemeType See {@link #schemeType}.
+ * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
+ */
+ public DrmInitData(@Nullable String schemeType, List<SchemeData> schemeDatas) {
+ this(schemeType, false, schemeDatas.toArray(new SchemeData[0]));
+ }
+
+ /**
+ * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
+ */
+ public DrmInitData(SchemeData... schemeDatas) {
+ this(null, schemeDatas);
+ }
+
+ /**
+ * @param schemeType See {@link #schemeType}.
+ * @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
+ */
+ public DrmInitData(@Nullable String schemeType, SchemeData... schemeDatas) {
+ this(schemeType, true, schemeDatas);
+ }
+
+ private DrmInitData(@Nullable String schemeType, boolean cloneSchemeDatas,
+ SchemeData... schemeDatas) {
+ this.schemeType = schemeType;
+ if (cloneSchemeDatas) {
+ schemeDatas = schemeDatas.clone();
+ }
+ this.schemeDatas = schemeDatas;
+ schemeDataCount = schemeDatas.length;
+ // Sorting ensures that universal scheme data (i.e. data that applies to all schemes) is matched
+ // last. It's also required by the equals and hashcode implementations.
+ Arrays.sort(this.schemeDatas, this);
+ }
+
+ /* package */
+ DrmInitData(Parcel in) {
+ schemeType = in.readString();
+ schemeDatas = Util.castNonNull(in.createTypedArray(SchemeData.CREATOR));
+ schemeDataCount = schemeDatas.length;
+ }
+
+ /**
+ * Retrieves data for a given DRM scheme, specified by its UUID.
+ *
+ * @deprecated Use {@link #get(int)} and {@link SchemeData#matches(UUID)} instead.
+ * @param uuid The DRM scheme's UUID.
+ * @return The initialization data for the scheme, or null if the scheme is not supported.
+ */
+ @Deprecated
+ @Nullable
+ public SchemeData get(UUID uuid) {
+ for (SchemeData schemeData : schemeDatas) {
+ if (schemeData.matches(uuid)) {
+ return schemeData;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves the {@link SchemeData} at a given index.
+ *
+ * @param index The index of the scheme to return. Must not exceed {@link #schemeDataCount}.
+ * @return The {@link SchemeData} at the specified index.
+ */
+ public SchemeData get(int index) {
+ return schemeDatas[index];
+ }
+
+ /**
+ * Returns a copy with the specified protection scheme type.
+ *
+ * @param schemeType A protection scheme type. May be null.
+ * @return A copy with the specified protection scheme type.
+ */
+ public DrmInitData copyWithSchemeType(@Nullable String schemeType) {
+ if (Util.areEqual(this.schemeType, schemeType)) {
+ return this;
+ }
+ return new DrmInitData(schemeType, false, schemeDatas);
+ }
+
+ /**
+ * Returns an instance containing the {@link #schemeDatas} from both this and {@code other}. The
+ * {@link #schemeType} of the instances being merged must either match, or at least one scheme
+ * type must be {@code null}.
+ *
+ * @param drmInitData The instance to merge.
+ * @return The merged result.
+ */
+ public DrmInitData merge(DrmInitData drmInitData) {
+ Assertions.checkState(
+ schemeType == null
+ || drmInitData.schemeType == null
+ || TextUtils.equals(schemeType, drmInitData.schemeType));
+ String mergedSchemeType = schemeType != null ? this.schemeType : drmInitData.schemeType;
+ SchemeData[] mergedSchemeDatas =
+ Util.nullSafeArrayConcatenation(schemeDatas, drmInitData.schemeDatas);
+ return new DrmInitData(mergedSchemeType, mergedSchemeDatas);
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = (schemeType == null ? 0 : schemeType.hashCode());
+ result = 31 * result + Arrays.hashCode(schemeDatas);
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ DrmInitData other = (DrmInitData) obj;
+ return Util.areEqual(schemeType, other.schemeType)
+ && Arrays.equals(schemeDatas, other.schemeDatas);
+ }
+
+ @Override
+ public int compare(SchemeData first, SchemeData second) {
+ return C.UUID_NIL.equals(first.uuid) ? (C.UUID_NIL.equals(second.uuid) ? 0 : 1)
+ : first.uuid.compareTo(second.uuid);
+ }
+
+ // Parcelable implementation.
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(schemeType);
+ dest.writeTypedArray(schemeDatas, 0);
+ }
+
+ public static final Parcelable.Creator<DrmInitData> CREATOR =
+ new Parcelable.Creator<DrmInitData>() {
+
+ @Override
+ public DrmInitData createFromParcel(Parcel in) {
+ return new DrmInitData(in);
+ }
+
+ @Override
+ public DrmInitData[] newArray(int size) {
+ return new DrmInitData[size];
+ }
+
+ };
+
+ // Internal methods.
+
+ private static boolean containsSchemeDataWithUuid(
+ ArrayList<SchemeData> datas, int limit, UUID uuid) {
+ for (int i = 0; i < limit; i++) {
+ if (datas.get(i).uuid.equals(uuid)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Scheme initialization data.
+ */
+ public static final class SchemeData implements Parcelable {
+
+ // Lazily initialized hashcode.
+ private int hashCode;
+
+ /**
+ * The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is universal (i.e.
+ * applies to all schemes).
+ */
+ private final UUID uuid;
+ /** The URL of the server to which license requests should be made. May be null if unknown. */
+ @Nullable public final String licenseServerUrl;
+ /** The mimeType of {@link #data}. */
+ public final String mimeType;
+ /** The initialization data. May be null for scheme support checks only. */
+ @Nullable public final byte[] data;
+
+ /**
+ * @param uuid The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is
+ * universal (i.e. applies to all schemes).
+ * @param mimeType See {@link #mimeType}.
+ * @param data See {@link #data}.
+ */
+ public SchemeData(UUID uuid, String mimeType, @Nullable byte[] data) {
+ this(uuid, /* licenseServerUrl= */ null, mimeType, data);
+ }
+
+ /**
+ * @param uuid The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is
+ * universal (i.e. applies to all schemes).
+ * @param licenseServerUrl See {@link #licenseServerUrl}.
+ * @param mimeType See {@link #mimeType}.
+ * @param data See {@link #data}.
+ */
+ public SchemeData(
+ UUID uuid, @Nullable String licenseServerUrl, String mimeType, @Nullable byte[] data) {
+ this.uuid = Assertions.checkNotNull(uuid);
+ this.licenseServerUrl = licenseServerUrl;
+ this.mimeType = Assertions.checkNotNull(mimeType);
+ this.data = data;
+ }
+
+ /* package */ SchemeData(Parcel in) {
+ uuid = new UUID(in.readLong(), in.readLong());
+ licenseServerUrl = in.readString();
+ mimeType = Util.castNonNull(in.readString());
+ data = in.createByteArray();
+ }
+
+ /**
+ * Returns whether this initialization data applies to the specified scheme.
+ *
+ * @param schemeUuid The scheme {@link UUID}.
+ * @return Whether this initialization data applies to the specified scheme.
+ */
+ public boolean matches(UUID schemeUuid) {
+ return C.UUID_NIL.equals(uuid) || schemeUuid.equals(uuid);
+ }
+
+ /**
+ * Returns whether this {@link SchemeData} can be used to replace {@code other}.
+ *
+ * @param other A {@link SchemeData}.
+ * @return Whether this {@link SchemeData} can be used to replace {@code other}.
+ */
+ public boolean canReplace(SchemeData other) {
+ return hasData() && !other.hasData() && matches(other.uuid);
+ }
+
+ /**
+ * Returns whether {@link #data} is non-null.
+ */
+ public boolean hasData() {
+ return data != null;
+ }
+
+ /**
+ * Returns a copy of this instance with the specified data.
+ *
+ * @param data The data to include in the copy.
+ * @return The new instance.
+ */
+ public SchemeData copyWithData(@Nullable byte[] data) {
+ return new SchemeData(uuid, licenseServerUrl, mimeType, data);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (!(obj instanceof SchemeData)) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ SchemeData other = (SchemeData) obj;
+ return Util.areEqual(licenseServerUrl, other.licenseServerUrl)
+ && Util.areEqual(mimeType, other.mimeType)
+ && Util.areEqual(uuid, other.uuid)
+ && Arrays.equals(data, other.data);
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ int result = uuid.hashCode();
+ result = 31 * result + (licenseServerUrl == null ? 0 : licenseServerUrl.hashCode());
+ result = 31 * result + mimeType.hashCode();
+ result = 31 * result + Arrays.hashCode(data);
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ // Parcelable implementation.
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(uuid.getMostSignificantBits());
+ dest.writeLong(uuid.getLeastSignificantBits());
+ dest.writeString(licenseServerUrl);
+ dest.writeString(mimeType);
+ dest.writeByteArray(data);
+ }
+
+ public static final Parcelable.Creator<SchemeData> CREATOR =
+ new Parcelable.Creator<SchemeData>() {
+
+ @Override
+ public SchemeData createFromParcel(Parcel in) {
+ return new SchemeData(in);
+ }
+
+ @Override
+ public SchemeData[] newArray(int size) {
+ return new SchemeData[size];
+ }
+
+ };
+
+ }
+
+}