diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 42ddce0b87..d12b369eb4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -6,6 +6,7 @@ * Add new `ExoPlaybackException` types for remote exceptions and out-of-memory errors. * HLS: + * Work around lack of LA_URL attribute in PlayReady key request init data. * Prevent unnecessary reloads of initialization segments. * Form an adaptive track group out of audio renditions with matching name. * Support encrypted initialization segments diff --git a/library/core/src/main/java/com/google/android/exoplayer2/C.java b/library/core/src/main/java/com/google/android/exoplayer2/C.java index 2eed9f03a9..c3619f1dc3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/C.java @@ -101,6 +101,9 @@ public final class C { */ public static final String UTF16_NAME = "UTF-16"; + /** The name of the UTF-16 little-endian charset. */ + public static final String UTF16LE_NAME = "UTF-16LE"; + /** * The name of the serif font family. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java index ede979fc43..615aa0e7b1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java @@ -29,8 +29,13 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.extractor.mp4.PsshAtomUtil; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; +import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -44,6 +49,10 @@ import java.util.UUID; public final class FrameworkMediaDrm implements ExoMediaDrm { private static final String CENC_SCHEME_MIME_TYPE = "cenc"; + private static final String MOCK_LA_URL_VALUE = "https://x"; + private static final String MOCK_LA_URL = "" + MOCK_LA_URL_VALUE + ""; + private static final int UTF_16_BYTES_PER_CHARACTER = 2; + private static final String TAG = "FrameworkMediaDrm"; private final UUID uuid; private final MediaDrm mediaDrm; @@ -139,6 +148,9 @@ public final class FrameworkMediaDrm implements ExoMediaDrm")) { + // LA_URL already present. Do nothing. + return data; + } + // This PlayReady object record does not include an LA_URL. We add a mock value for it. + int endOfDataTagIndex = xml.indexOf(""); + if (endOfDataTagIndex == -1) { + Log.w(TAG, "Could not find the tag. Skipping LA_URL workaround."); + } + String xmlWithMockLaUrl = + xml.substring(/* beginIndex= */ 0, /* endIndex= */ endOfDataTagIndex) + + MOCK_LA_URL + + xml.substring(/* beginIndex= */ endOfDataTagIndex); + int extraBytes = MOCK_LA_URL.length() * UTF_16_BYTES_PER_CHARACTER; + ByteBuffer newData = ByteBuffer.allocate(length + extraBytes); + newData.order(ByteOrder.LITTLE_ENDIAN); + newData.putInt(length + extraBytes); + newData.putShort((short) objectRecordCount); + newData.putShort((short) recordType); + newData.putShort((short) (xmlWithMockLaUrl.length() * UTF_16_BYTES_PER_CHARACTER)); + newData.put(xmlWithMockLaUrl.getBytes(Charset.forName(C.UTF16LE_NAME))); + return newData.array(); + } }