mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Simplify encryption handling in HLS.
This commit is contained in:
parent
fabd470550
commit
12807a7d4b
@ -306,7 +306,7 @@ public class HlsChunkSource {
|
||||
Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url);
|
||||
|
||||
// Check if encryption is specified.
|
||||
if (HlsMediaPlaylist.ENCRYPTION_METHOD_AES_128.equals(segment.encryptionMethod)) {
|
||||
if (segment.isEncrypted) {
|
||||
Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.encryptionKeyUri);
|
||||
if (!keyUri.equals(encryptionKeyUri)) {
|
||||
// Encryption is specified and the key has changed.
|
||||
|
@ -28,24 +28,25 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* Media segment reference.
|
||||
*/
|
||||
public static final class Segment implements Comparable<Long> {
|
||||
|
||||
public final boolean discontinuity;
|
||||
public final double durationSecs;
|
||||
public final String url;
|
||||
public final long startTimeUs;
|
||||
public final String encryptionMethod;
|
||||
public final boolean isEncrypted;
|
||||
public final String encryptionKeyUri;
|
||||
public final String encryptionIV;
|
||||
public final int byterangeOffset;
|
||||
public final int byterangeLength;
|
||||
|
||||
public Segment(String uri, double durationSecs, boolean discontinuity, long startTimeUs,
|
||||
String encryptionMethod, String encryptionKeyUri, String encryptionIV,
|
||||
int byterangeOffset, int byterangeLength) {
|
||||
boolean isEncrypted, String encryptionKeyUri, String encryptionIV, int byterangeOffset,
|
||||
int byterangeLength) {
|
||||
this.url = uri;
|
||||
this.durationSecs = durationSecs;
|
||||
this.discontinuity = discontinuity;
|
||||
this.startTimeUs = startTimeUs;
|
||||
this.encryptionMethod = encryptionMethod;
|
||||
this.isEncrypted = isEncrypted;
|
||||
this.encryptionKeyUri = encryptionKeyUri;
|
||||
this.encryptionIV = encryptionIV;
|
||||
this.byterangeOffset = byterangeOffset;
|
||||
|
@ -64,6 +64,9 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
|
||||
private static final String SUBTITLES_TYPE = "SUBTITLES";
|
||||
private static final String CLOSED_CAPTIONS_TYPE = "CLOSED-CAPTIONS";
|
||||
|
||||
private static final String METHOD_NONE = "NONE";
|
||||
private static final String METHOD_AES128 = "AES-128";
|
||||
|
||||
private static final Pattern BANDWIDTH_ATTR_REGEX =
|
||||
Pattern.compile(BANDWIDTH_ATTR + "=(\\d+)\\b");
|
||||
private static final Pattern CODECS_ATTR_REGEX =
|
||||
@ -80,8 +83,9 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
|
||||
Pattern.compile(VERSION_TAG + ":(\\d+)\\b");
|
||||
private static final Pattern BYTERANGE_REGEX =
|
||||
Pattern.compile(BYTERANGE_TAG + ":(\\d+(?:@\\d+)?)\\b");
|
||||
|
||||
private static final Pattern METHOD_ATTR_REGEX =
|
||||
Pattern.compile(METHOD_ATTR + "=([^,.*]+)");
|
||||
Pattern.compile(METHOD_ATTR + "=(" + METHOD_NONE + "|" + METHOD_AES128 + ")");
|
||||
private static final Pattern URI_ATTR_REGEX =
|
||||
Pattern.compile(URI_ATTR + "=\"(.+)\"");
|
||||
private static final Pattern IV_ATTR_REGEX =
|
||||
@ -201,14 +205,14 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
|
||||
double segmentDurationSecs = 0.0;
|
||||
boolean segmentDiscontinuity = false;
|
||||
long segmentStartTimeUs = 0;
|
||||
String segmentEncryptionMethod = null;
|
||||
String segmentEncryptionKeyUri = null;
|
||||
String segmentEncryptionIV = null;
|
||||
int segmentByterangeOffset = 0;
|
||||
int segmentByterangeLength = C.LENGTH_UNBOUNDED;
|
||||
|
||||
int segmentMediaSequence = 0;
|
||||
|
||||
boolean isEncrypted = false;
|
||||
String encryptionKeyUri = null;
|
||||
String encryptionIV = null;
|
||||
|
||||
String line;
|
||||
while (iterator.hasNext()) {
|
||||
line = iterator.next();
|
||||
@ -224,15 +228,14 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
|
||||
segmentDurationSecs = HlsParserUtil.parseDoubleAttr(line, MEDIA_DURATION_REGEX,
|
||||
MEDIA_DURATION_TAG);
|
||||
} else if (line.startsWith(KEY_TAG)) {
|
||||
segmentEncryptionMethod = HlsParserUtil.parseStringAttr(line, METHOD_ATTR_REGEX,
|
||||
METHOD_ATTR);
|
||||
if (segmentEncryptionMethod.equals(HlsMediaPlaylist.ENCRYPTION_METHOD_NONE)) {
|
||||
segmentEncryptionKeyUri = null;
|
||||
segmentEncryptionIV = null;
|
||||
String method = HlsParserUtil.parseStringAttr(line, METHOD_ATTR_REGEX, METHOD_ATTR);
|
||||
isEncrypted = METHOD_AES128.equals(method);
|
||||
if (isEncrypted) {
|
||||
encryptionKeyUri = HlsParserUtil.parseStringAttr(line, URI_ATTR_REGEX, URI_ATTR);
|
||||
encryptionIV = HlsParserUtil.parseOptionalStringAttr(line, IV_ATTR_REGEX);
|
||||
} else {
|
||||
segmentEncryptionKeyUri = HlsParserUtil.parseStringAttr(line, URI_ATTR_REGEX,
|
||||
URI_ATTR);
|
||||
segmentEncryptionIV = HlsParserUtil.parseOptionalStringAttr(line, IV_ATTR_REGEX);
|
||||
encryptionKeyUri = null;
|
||||
encryptionIV = null;
|
||||
}
|
||||
} else if (line.startsWith(BYTERANGE_TAG)) {
|
||||
String byteRange = HlsParserUtil.parseStringAttr(line, BYTERANGE_REGEX, BYTERANGE_TAG);
|
||||
@ -244,21 +247,21 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
|
||||
} else if (line.equals(DISCONTINUITY_TAG)) {
|
||||
segmentDiscontinuity = true;
|
||||
} else if (!line.startsWith("#")) {
|
||||
String thisSegmentEncryptionIV;
|
||||
if (segmentEncryptionIV != null) {
|
||||
thisSegmentEncryptionIV = segmentEncryptionIV;
|
||||
} else if (HlsMediaPlaylist.ENCRYPTION_METHOD_AES_128.equals(segmentEncryptionMethod)) {
|
||||
thisSegmentEncryptionIV = Integer.toHexString(segmentMediaSequence);
|
||||
String segmentEncryptionIV;
|
||||
if (!isEncrypted) {
|
||||
segmentEncryptionIV = null;
|
||||
} else if (encryptionIV != null) {
|
||||
segmentEncryptionIV = encryptionIV;
|
||||
} else {
|
||||
thisSegmentEncryptionIV = null;
|
||||
segmentEncryptionIV = Integer.toHexString(segmentMediaSequence);
|
||||
}
|
||||
segmentMediaSequence++;
|
||||
if (segmentByterangeLength == C.LENGTH_UNBOUNDED) {
|
||||
segmentByterangeOffset = 0;
|
||||
}
|
||||
segments.add(new Segment(line, segmentDurationSecs, segmentDiscontinuity,
|
||||
segmentStartTimeUs, segmentEncryptionMethod, segmentEncryptionKeyUri,
|
||||
thisSegmentEncryptionIV, segmentByterangeOffset, segmentByterangeLength));
|
||||
segmentStartTimeUs, isEncrypted, encryptionKeyUri, segmentEncryptionIV,
|
||||
segmentByterangeOffset, segmentByterangeLength));
|
||||
segmentStartTimeUs += (long) (segmentDurationSecs * C.MICROS_PER_SECOND);
|
||||
segmentDiscontinuity = false;
|
||||
segmentDurationSecs = 0.0;
|
||||
|
@ -81,7 +81,7 @@ public class HlsMediaPlaylistParserTest extends TestCase {
|
||||
|
||||
assertEquals(false, segments.get(0).discontinuity);
|
||||
assertEquals(7.975, segments.get(0).durationSecs);
|
||||
assertEquals(null, segments.get(0).encryptionMethod);
|
||||
assertEquals(false, segments.get(0).isEncrypted);
|
||||
assertEquals(null, segments.get(0).encryptionKeyUri);
|
||||
assertEquals(null, segments.get(0).encryptionIV);
|
||||
assertEquals(51370, segments.get(0).byterangeLength);
|
||||
@ -90,7 +90,7 @@ public class HlsMediaPlaylistParserTest extends TestCase {
|
||||
|
||||
assertEquals(false, segments.get(1).discontinuity);
|
||||
assertEquals(7.975, segments.get(1).durationSecs);
|
||||
assertEquals("AES-128", segments.get(1).encryptionMethod);
|
||||
assertEquals(true, segments.get(1).isEncrypted);
|
||||
assertEquals("https://priv.example.com/key.php?r=2680", segments.get(1).encryptionKeyUri);
|
||||
assertEquals("0x1566B", segments.get(1).encryptionIV);
|
||||
assertEquals(51501, segments.get(1).byterangeLength);
|
||||
@ -99,7 +99,7 @@ public class HlsMediaPlaylistParserTest extends TestCase {
|
||||
|
||||
assertEquals(false, segments.get(2).discontinuity);
|
||||
assertEquals(7.941, segments.get(2).durationSecs);
|
||||
assertEquals(HlsMediaPlaylist.ENCRYPTION_METHOD_NONE, segments.get(2).encryptionMethod);
|
||||
assertEquals(false, segments.get(2).isEncrypted);
|
||||
assertEquals(null, segments.get(2).encryptionKeyUri);
|
||||
assertEquals(null, segments.get(2).encryptionIV);
|
||||
assertEquals(51501, segments.get(2).byterangeLength);
|
||||
@ -108,7 +108,7 @@ public class HlsMediaPlaylistParserTest extends TestCase {
|
||||
|
||||
assertEquals(true, segments.get(3).discontinuity);
|
||||
assertEquals(7.975, segments.get(3).durationSecs);
|
||||
assertEquals("AES-128", segments.get(3).encryptionMethod);
|
||||
assertEquals(true, segments.get(3).isEncrypted);
|
||||
assertEquals("https://priv.example.com/key.php?r=2682", segments.get(3).encryptionKeyUri);
|
||||
// 0xA7A == 2682.
|
||||
assertNotNull(segments.get(3).encryptionIV);
|
||||
@ -119,11 +119,11 @@ public class HlsMediaPlaylistParserTest extends TestCase {
|
||||
|
||||
assertEquals(false, segments.get(4).discontinuity);
|
||||
assertEquals(7.975, segments.get(4).durationSecs);
|
||||
assertEquals("AES-128", segments.get(4).encryptionMethod);
|
||||
assertEquals(true, segments.get(4).isEncrypted);
|
||||
assertEquals("https://priv.example.com/key.php?r=2682", segments.get(4).encryptionKeyUri);
|
||||
// 0xA7A == 2682.
|
||||
// 0xA7B == 2683.
|
||||
assertNotNull(segments.get(4).encryptionIV);
|
||||
assertEquals("A7A", segments.get(4).encryptionIV.toUpperCase(Locale.getDefault()));
|
||||
assertEquals("A7B", segments.get(4).encryptionIV.toUpperCase(Locale.getDefault()));
|
||||
assertEquals(C.LENGTH_UNBOUNDED, segments.get(4).byterangeLength);
|
||||
assertEquals(0, segments.get(4).byterangeOffset);
|
||||
assertEquals("https://priv.example.com/fileSequence2683.ts", segments.get(4).url);
|
||||
|
Loading…
x
Reference in New Issue
Block a user