Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
40d8b29c
authored
Oct 13, 2017
by
ojw28
Committed by
GitHub
Oct 13, 2017
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #3328 from ValveSoftware/dev-v2-multiversion
Allow multiple PSSH boxes for same system
parents
cad88512
19f53d8a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
100 additions
and
42 deletions
library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java
library/core/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java
library/core/src/test/java/com/google/android/exoplayer2/drm/DrmInitDataTest.java
library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java
View file @
40d8b29c
...
...
@@ -349,7 +349,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
// If there is no scheme information, assume patternless AES-CTR.
return
true
;
}
else
if
(
C
.
CENC_TYPE_cbc1
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cbcs
.
equals
(
schemeType
)
||
C
.
CENC_TYPE_cens
.
equals
(
schemeType
))
{
||
C
.
CENC_TYPE_cens
.
equals
(
schemeType
))
{
// AES-CBC and pattern encryption are supported on API 24 onwards.
return
Util
.
SDK_INT
>=
24
;
}
...
...
@@ -357,6 +357,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
return
true
;
}
@Override
public
DrmSession
<
T
>
acquireSession
(
Looper
playbackLooper
,
DrmInitData
drmInitData
)
{
Assertions
.
checkState
(
this
.
playbackLooper
==
null
||
this
.
playbackLooper
==
playbackLooper
);
...
...
@@ -461,12 +462,34 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto> implements DrmSe
* @return The extracted {@link SchemeData}, or null if no suitable data is present.
*/
private
static
SchemeData
getSchemeData
(
DrmInitData
drmInitData
,
UUID
uuid
)
{
SchemeData
schemeData
=
drmInitData
.
get
(
uuid
);
if
(
schemeData
==
null
&&
C
.
CLEARKEY_UUID
.
equals
(
uuid
))
{
// If present, the Common PSSH box should be used for ClearKey.
schemeData
=
drmInitData
.
get
(
C
.
COMMON_PSSH_UUID
);
List
<
SchemeData
>
schemeDatas
=
new
ArrayList
<>();
// Look for matching PSSH boxes, or the common box in the case of ClearKey
for
(
int
i
=
0
;
i
<
drmInitData
.
schemeDataCount
;
++
i
)
{
SchemeData
schemeData
=
drmInitData
.
get
(
i
);
if
(
schemeData
.
matches
(
uuid
)
||
(
C
.
CLEARKEY_UUID
.
equals
(
uuid
)
&&
schemeData
.
matches
(
C
.
COMMON_PSSH_UUID
)))
{
schemeDatas
.
add
(
schemeData
);
}
}
return
schemeData
;
if
(
schemeDatas
.
isEmpty
())
{
return
null
;
}
// For Widevine, we prefer v1 init data on M and higher, v0 for lower
if
(
C
.
WIDEVINE_UUID
.
equals
(
uuid
))
{
for
(
SchemeData
schemeData
:
schemeDatas
)
{
int
version
=
PsshAtomUtil
.
parseVersion
(
schemeData
.
data
);
if
(
Util
.
SDK_INT
<
23
&&
version
==
0
)
{
return
schemeData
;
}
else
if
(
Util
.
SDK_INT
>=
23
&&
version
==
1
)
{
return
schemeData
;
}
}
}
// If we don't have any special handling for this system, we take the first scheme data found
return
schemeDatas
.
get
(
0
);
}
private
static
byte
[]
getSchemeInitData
(
SchemeData
data
,
UUID
uuid
)
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java
View file @
40d8b29c
...
...
@@ -22,6 +22,8 @@ import com.google.android.exoplayer2.C;
import
com.google.android.exoplayer2.drm.DrmInitData.SchemeData
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.List
;
...
...
@@ -78,12 +80,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
// 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
(
schemeDatas
,
this
);
// Check for no duplicates.
for
(
int
i
=
1
;
i
<
schemeDatas
.
length
;
i
++)
{
if
(
schemeDatas
[
i
-
1
].
uuid
.
equals
(
schemeDatas
[
i
].
uuid
))
{
throw
new
IllegalArgumentException
(
"Duplicate data for uuid: "
+
schemeDatas
[
i
].
uuid
);
}
}
this
.
schemeDatas
=
schemeDatas
;
schemeDataCount
=
schemeDatas
.
length
;
}
...
...
@@ -97,9 +94,11 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
/**
* Retrieves data for a given DRM scheme, specified by its UUID.
*
* @deprecated This will only get the first data found for the scheme.
* @param uuid The DRM scheme's UUID.
* @return The initialization data for the scheme, or null if the scheme is not supported.
*/
@Deprecated
public
SchemeData
get
(
UUID
uuid
)
{
for
(
SchemeData
schemeData
:
schemeDatas
)
{
if
(
schemeData
.
matches
(
uuid
))
{
...
...
@@ -112,7 +111,7 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
/**
* Retrieves the {@link SchemeData} at a given index.
*
* @param index index of the scheme to return.
* @param index index of the scheme to return.
Must not exceed {@link #schemeDataCount}.
* @return The {@link SchemeData} at the index.
*/
public
SchemeData
get
(
int
index
)
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java
View file @
40d8b29c
...
...
@@ -86,11 +86,28 @@ public final class PsshAtomUtil {
* an unsupported version.
*/
public
static
UUID
parseUuid
(
byte
[]
atom
)
{
P
air
<
UUID
,
byte
[]>
parsedAtom
=
parsePsshAtom
(
atom
);
P
sshAtom
parsedAtom
=
parsePsshAtom
(
atom
);
if
(
parsedAtom
==
null
)
{
return
null
;
}
return
parsedAtom
.
first
;
return
parsedAtom
.
uuid
;
}
/**
* Parses the version from a PSSH atom. Version 0 and 1 PSSH atoms are supported.
* <p>
* The UUID is only parsed if the data is a valid PSSH atom.
*
* @param atom The atom to parse.
* @return The parsed UUID. -1 if the input is not a valid PSSH atom, or if the PSSH atom has
* an unsupported version.
*/
public
static
int
parseVersion
(
byte
[]
atom
)
{
PsshAtom
parsedAtom
=
parsePsshAtom
(
atom
);
if
(
parsedAtom
==
null
)
{
return
-
1
;
}
return
parsedAtom
.
version
;
}
/**
...
...
@@ -105,15 +122,15 @@ public final class PsshAtomUtil {
* PSSH atom has an unsupported version, or if the PSSH atom does not match the passed UUID.
*/
public
static
byte
[]
parseSchemeSpecificData
(
byte
[]
atom
,
UUID
uuid
)
{
P
air
<
UUID
,
byte
[]>
parsedAtom
=
parsePsshAtom
(
atom
);
P
sshAtom
parsedAtom
=
parsePsshAtom
(
atom
);
if
(
parsedAtom
==
null
)
{
return
null
;
}
if
(
uuid
!=
null
&&
!
uuid
.
equals
(
parsedAtom
.
first
))
{
Log
.
w
(
TAG
,
"UUID mismatch. Expected: "
+
uuid
+
", got: "
+
parsedAtom
.
first
+
"."
);
if
(
uuid
!=
null
&&
!
uuid
.
equals
(
parsedAtom
.
uuid
))
{
Log
.
w
(
TAG
,
"UUID mismatch. Expected: "
+
uuid
+
", got: "
+
parsedAtom
.
uuid
+
"."
);
return
null
;
}
return
parsedAtom
.
second
;
return
parsedAtom
.
data
;
}
/**
...
...
@@ -125,7 +142,7 @@ public final class PsshAtomUtil {
* not a valid PSSH atom, or if the PSSH atom has an unsupported version.
*/
// TODO: Support parsing of the key ids for version 1 PSSH atoms.
private
static
P
air
<
UUID
,
byte
[]>
parsePsshAtom
(
byte
[]
atom
)
{
private
static
P
sshAtom
parsePsshAtom
(
byte
[]
atom
)
{
ParsableByteArray
atomData
=
new
ParsableByteArray
(
atom
);
if
(
atomData
.
limit
()
<
Atom
.
FULL_HEADER_SIZE
+
16
/* UUID */
+
4
/* DataSize */
)
{
// Data too short.
...
...
@@ -159,7 +176,18 @@ public final class PsshAtomUtil {
}
byte
[]
data
=
new
byte
[
dataSize
];
atomData
.
readBytes
(
data
,
0
,
dataSize
);
return
Pair
.
create
(
uuid
,
data
);
return
new
PsshAtom
(
uuid
,
atomVersion
,
data
);
}
}
private
static
class
PsshAtom
{
final
UUID
uuid
;
final
int
version
;
final
byte
[]
data
;
PsshAtom
(
final
UUID
uuid
,
final
int
version
,
final
byte
[]
data
)
{
this
.
uuid
=
uuid
;
this
.
version
=
version
;
this
.
data
=
data
;
}
}
}
\ No newline at end of file
library/core/src/test/java/com/google/android/exoplayer2/drm/DrmInitDataTest.java
View file @
40d8b29c
...
...
@@ -31,6 +31,9 @@ import org.junit.runner.RunWith;
import
org.robolectric.RobolectricTestRunner
;
import
org.robolectric.annotation.Config
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* Unit test for {@link DrmInitData}.
*/
...
...
@@ -97,6 +100,7 @@ public class DrmInitDataTest {
}
@Test
@Deprecated
public
void
testGet
()
{
// Basic matching.
DrmInitData
testInitData
=
new
DrmInitData
(
DATA_1
,
DATA_2
);
...
...
@@ -124,27 +128,22 @@ public class DrmInitDataTest {
}
@Test
public
void
testDuplicateSchemeDataRejected
()
{
try
{
new
DrmInitData
(
DATA_1
,
DATA_1
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
// Expected.
}
try
{
new
DrmInitData
(
DATA_1
,
DATA_1B
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
// Expected.
}
public
void
testGetByIndex
()
{
DrmInitData
testInitData
=
new
DrmInitData
(
DATA_1
,
DATA_2
);
assertThat
(
getAllSchemeData
(
testInitData
)).
containsAllOf
(
DATA_1
,
DATA_2
);
}
try
{
new
DrmInitData
(
DATA_1
,
DATA_2
,
DATA_1B
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
// Expected.
}
@Test
public
void
testDuplicateSchemeData
()
{
DrmInitData
testInitData
=
new
DrmInitData
(
DATA_1
,
DATA_1
);
assertThat
(
testInitData
.
schemeDataCount
).
isEqualTo
(
2
);
testInitData
=
new
DrmInitData
(
DATA_1
,
DATA_2
,
DATA_1B
);
assertThat
(
testInitData
.
schemeDataCount
).
isEqualTo
(
3
);
assertThat
(
getAllSchemeData
(
testInitData
)).
containsAllOf
(
DATA_1
,
DATA_1B
,
DATA_2
);
// Deprecated get method should return first entry
assertThat
(
testInitData
.
get
(
WIDEVINE_UUID
)).
isEqualTo
(
DATA_1
);
assertThat
(
testInitData
.
get
(
PLAYREADY_UUID
)).
isEqualTo
(
DATA_2
);
}
@Test
...
...
@@ -162,4 +161,12 @@ public class DrmInitDataTest {
assertThat
(
DATA_UNIVERSAL
.
matches
(
UUID_NIL
)).
isTrue
();
}
private
List
<
SchemeData
>
getAllSchemeData
(
DrmInitData
drmInitData
)
{
ArrayList
<
SchemeData
>
schemeDatas
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
drmInitData
.
schemeDataCount
;
i
++)
{
schemeDatas
.
add
(
drmInitData
.
get
(
i
));
}
return
schemeDatas
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment