From 52ec70dd80d79396ba7bcea16422bc0dc2111200 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Tue, 22 Aug 2017 05:46:00 -0700 Subject: [PATCH] Add support for KEYFORMAT and SAMPLE-AES (only parsing, not decryption) Also add sample streams that use METHOD=SAMPLE-AES. Note that some of the streams provide alternative EXT-X-KEY's. Support for alternative decryption methods will be added in a later CL. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=166048858 --- .../exoplayer2/source/hls/HlsChunkSource.java | 3 ++- .../exoplayer2/source/hls/HlsMediaChunk.java | 27 +++++++++++-------- .../source/hls/playlist/HlsMediaPlaylist.java | 19 ++++++++++--- .../hls/playlist/HlsPlaylistParser.java | 16 ++++++++--- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index bca62ed230..4fed33eee3 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -306,7 +306,8 @@ import java.util.List; out.chunk = new HlsMediaChunk(mediaDataSource, dataSpec, initDataSpec, selectedUrl, muxedCaptionFormats, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence, - isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv); + isTimestampMaster, timestampAdjuster, previous, segment.keyFormat, encryptionKey, + encryptionIv); } /** diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index 29b7e4a6a8..e3e1bab48d 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -32,6 +32,7 @@ import com.google.android.exoplayer2.metadata.id3.Id3Decoder; import com.google.android.exoplayer2.metadata.id3.PrivFrame; import com.google.android.exoplayer2.source.chunk.MediaChunk; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl; +import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.MimeTypes; @@ -116,16 +117,19 @@ import java.util.concurrent.atomic.AtomicInteger; * @param isMasterTimestampSource True if the chunk can initialize the timestamp adjuster. * @param timestampAdjuster Adjuster corresponding to the provided discontinuity sequence number. * @param previousChunk The {@link HlsMediaChunk} that preceded this one. May be null. - * @param encryptionKey For AES encryption chunks, the encryption key. - * @param encryptionIv For AES encryption chunks, the encryption initialization vector. + * @param keyFormat A string describing the format for {@code keyData}, or null if the chunk is + * not encrypted. + * @param keyData Data specifying how to obtain the keys to decrypt the chunk, or null if the + * chunk is not encrypted. + * @param encryptionIv The AES initialization vector, or null if the chunk is not encrypted. */ public HlsMediaChunk(DataSource dataSource, DataSpec dataSpec, DataSpec initDataSpec, HlsUrl hlsUrl, List muxedCaptionFormats, int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs, int chunkIndex, int discontinuitySequenceNumber, boolean isMasterTimestampSource, - TimestampAdjuster timestampAdjuster, HlsMediaChunk previousChunk, byte[] encryptionKey, - byte[] encryptionIv) { - super(buildDataSource(dataSource, encryptionKey, encryptionIv), dataSpec, hlsUrl.format, + TimestampAdjuster timestampAdjuster, HlsMediaChunk previousChunk, String keyFormat, + byte[] keyData, byte[] encryptionIv) { + super(buildDataSource(dataSource, keyFormat, keyData, encryptionIv), dataSpec, hlsUrl.format, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex); this.discontinuitySequenceNumber = discontinuitySequenceNumber; this.initDataSpec = initDataSpec; @@ -327,15 +331,16 @@ import java.util.concurrent.atomic.AtomicInteger; // Internal factory methods. /** - * If the content is encrypted, returns an {@link Aes128DataSource} that wraps the original in - * order to decrypt the loaded data. Else returns the original. + * If the content is encrypted using the "identity" key format, returns an + * {@link Aes128DataSource} that wraps the original in order to decrypt the loaded data. Else + * returns the original. */ - private static DataSource buildDataSource(DataSource dataSource, byte[] encryptionKey, + private static DataSource buildDataSource(DataSource dataSource, String keyFormat, byte[] keyData, byte[] encryptionIv) { - if (encryptionKey == null || encryptionIv == null) { - return dataSource; + if (HlsMediaPlaylist.KEYFORMAT_IDENTITY.equals(keyFormat)) { + return new Aes128DataSource(dataSource, keyData, encryptionIv); } - return new Aes128DataSource(dataSource, encryptionKey, encryptionIv); + return dataSource; } private Extractor createExtractor() { diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java index db4f041be2..1b573f41c2 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java @@ -53,6 +53,10 @@ public final class HlsMediaPlaylist extends HlsPlaylist { * Whether the segment is encrypted, as defined by #EXT-X-KEY. */ public final boolean isEncrypted; + /** + * The key format as defined by #EXT-X-KEY, or null if the segment is not encrypted. + */ + public final String keyFormat; /** * The encryption key uri as defined by #EXT-X-KEY, or null if the segment is not encrypted. */ @@ -73,7 +77,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist { public final long byterangeLength; public Segment(String uri, long byterangeOffset, long byterangeLength) { - this(uri, 0, -1, C.TIME_UNSET, false, null, null, byterangeOffset, byterangeLength); + this(uri, 0, -1, C.TIME_UNSET, false, null, null, null, byterangeOffset, byterangeLength); } /** @@ -82,19 +86,21 @@ public final class HlsMediaPlaylist extends HlsPlaylist { * @param relativeDiscontinuitySequence See {@link #relativeDiscontinuitySequence}. * @param relativeStartTimeUs See {@link #relativeStartTimeUs}. * @param isEncrypted See {@link #isEncrypted}. + * @param keyFormat See {@link #keyFormat}. * @param encryptionKeyUri See {@link #encryptionKeyUri}. * @param encryptionIV See {@link #encryptionIV}. * @param byterangeOffset See {@link #byterangeOffset}. * @param byterangeLength See {@link #byterangeLength}. */ public Segment(String url, long durationUs, int relativeDiscontinuitySequence, - long relativeStartTimeUs, boolean isEncrypted, String encryptionKeyUri, String encryptionIV, - long byterangeOffset, long byterangeLength) { + long relativeStartTimeUs, boolean isEncrypted, String keyFormat, String encryptionKeyUri, + String encryptionIV, long byterangeOffset, long byterangeLength) { this.url = url; this.durationUs = durationUs; this.relativeDiscontinuitySequence = relativeDiscontinuitySequence; this.relativeStartTimeUs = relativeStartTimeUs; this.isEncrypted = isEncrypted; + this.keyFormat = keyFormat; this.encryptionKeyUri = encryptionKeyUri; this.encryptionIV = encryptionIV; this.byterangeOffset = byterangeOffset; @@ -110,7 +116,12 @@ public final class HlsMediaPlaylist extends HlsPlaylist { } /** - * Type of the playlist as defined by #EXT-X-PLAYLIST-TYPE. + * The identity key format, as defined by #EXT-X-KEY. + */ + public static final String KEYFORMAT_IDENTITY = "identity"; + + /** + * Type of the playlist, as defined by #EXT-X-PLAYLIST-TYPE. */ @Retention(RetentionPolicy.SOURCE) @IntDef({PLAYLIST_TYPE_UNKNOWN, PLAYLIST_TYPE_VOD, PLAYLIST_TYPE_EVENT}) diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index c5d3302eca..dc5fd96f35 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -69,7 +69,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser