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
fcc2138e
authored
Mar 31, 2015
by
ojw28
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #374 from google/dev
dev -> dev-webm-vp9-opus
parents
d27b6de1
acd1b9ac
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
185 additions
and
15 deletions
build.gradle
library/build.gradle
library/src/main/java/com/google/android/exoplayer/dash/mpd/ContentProtection.java
library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java
library/src/main/java/com/google/android/exoplayer/hls/HlsParserUtil.java
library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java
build.gradle
View file @
fcc2138e
...
@@ -17,9 +17,11 @@
...
@@ -17,9 +17,11 @@
buildscript
{
buildscript
{
repositories
{
repositories
{
mavenCentral
()
mavenCentral
()
jcenter
()
}
}
dependencies
{
dependencies
{
classpath
'com.android.tools.build:gradle:1.0.0'
classpath
'com.android.tools.build:gradle:1.0.0'
classpath
'com.novoda:bintray-release:0.2.7'
}
}
}
}
...
...
library/build.gradle
View file @
fcc2138e
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// See the License for the specific language governing permissions and
// limitations under the License.
// limitations under the License.
apply
plugin:
'com.android.library'
apply
plugin:
'com.android.library'
apply
plugin:
'bintray-release'
android
{
android
{
compileSdkVersion
21
compileSdkVersion
21
...
@@ -47,3 +48,13 @@ android.libraryVariants.all { variant ->
...
@@ -47,3 +48,13 @@ android.libraryVariants.all { variant ->
task
.
from
variant
.
javaCompile
.
destinationDir
task
.
from
variant
.
javaCompile
.
destinationDir
artifacts
.
add
(
'archives'
,
task
);
artifacts
.
add
(
'archives'
,
task
);
}
}
publish
{
repoName
=
'exoplayer'
userOrg
=
'google'
groupId
=
'com.google.android.exoplayer'
artifactId
=
'exoplayer'
version
=
'r1.2.3'
description
=
'The ExoPlayer library.'
website
=
'https://github.com/google/ExoPlayer'
}
library/src/main/java/com/google/android/exoplayer/dash/mpd/ContentProtection.java
View file @
fcc2138e
...
@@ -15,6 +15,10 @@
...
@@ -15,6 +15,10 @@
*/
*/
package
com
.
google
.
android
.
exoplayer
.
dash
.
mpd
;
package
com
.
google
.
android
.
exoplayer
.
dash
.
mpd
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.Util
;
import
java.util.Arrays
;
import
java.util.UUID
;
import
java.util.UUID
;
/**
/**
...
@@ -43,9 +47,38 @@ public class ContentProtection {
...
@@ -43,9 +47,38 @@ public class ContentProtection {
* @param data Protection scheme specific initialization data. May be null.
* @param data Protection scheme specific initialization data. May be null.
*/
*/
public
ContentProtection
(
String
schemeUriId
,
UUID
uuid
,
byte
[]
data
)
{
public
ContentProtection
(
String
schemeUriId
,
UUID
uuid
,
byte
[]
data
)
{
this
.
schemeUriId
=
schemeUriId
;
this
.
schemeUriId
=
Assertions
.
checkNotNull
(
schemeUriId
)
;
this
.
uuid
=
uuid
;
this
.
uuid
=
uuid
;
this
.
data
=
data
;
this
.
data
=
data
;
}
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(!(
obj
instanceof
ContentProtection
))
{
return
false
;
}
if
(
obj
==
this
)
{
return
true
;
}
ContentProtection
other
=
(
ContentProtection
)
obj
;
return
schemeUriId
.
equals
(
other
.
schemeUriId
)
&&
Util
.
areEqual
(
uuid
,
other
.
uuid
)
&&
Arrays
.
equals
(
data
,
other
.
data
);
}
@Override
public
int
hashCode
()
{
int
hashCode
=
1
;
hashCode
=
hashCode
*
37
+
schemeUriId
.
hashCode
();
if
(
uuid
!=
null
)
{
hashCode
=
hashCode
*
37
+
uuid
.
hashCode
();
}
if
(
data
!=
null
)
{
hashCode
=
hashCode
*
37
+
Arrays
.
hashCode
(
data
);
}
return
hashCode
;
}
}
}
library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java
View file @
fcc2138e
...
@@ -38,6 +38,8 @@ import java.io.IOException;
...
@@ -38,6 +38,8 @@ import java.io.IOException;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.text.ParseException
;
import
java.text.ParseException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.List
;
/**
/**
...
@@ -178,24 +180,22 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
...
@@ -178,24 +180,22 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
int
contentType
=
parseAdaptationSetTypeFromMimeType
(
mimeType
);
int
contentType
=
parseAdaptationSetTypeFromMimeType
(
mimeType
);
int
id
=
-
1
;
int
id
=
-
1
;
List
<
ContentProtection
>
contentProtections
=
null
;
ContentProtectionsBuilder
contentProtectionsBuilder
=
new
ContentProtectionsBuilder
()
;
List
<
Representation
>
representations
=
new
ArrayList
<
Representation
>();
List
<
Representation
>
representations
=
new
ArrayList
<
Representation
>();
do
{
do
{
xpp
.
next
();
xpp
.
next
();
if
(
isStartTag
(
xpp
,
"BaseURL"
))
{
if
(
isStartTag
(
xpp
,
"BaseURL"
))
{
baseUrl
=
parseBaseUrl
(
xpp
,
baseUrl
);
baseUrl
=
parseBaseUrl
(
xpp
,
baseUrl
);
}
else
if
(
isStartTag
(
xpp
,
"ContentProtection"
))
{
}
else
if
(
isStartTag
(
xpp
,
"ContentProtection"
))
{
if
(
contentProtections
==
null
)
{
contentProtectionsBuilder
.
addAdaptationSetProtection
(
parseContentProtection
(
xpp
));
contentProtections
=
new
ArrayList
<
ContentProtection
>();
}
contentProtections
.
add
(
parseContentProtection
(
xpp
));
}
else
if
(
isStartTag
(
xpp
,
"ContentComponent"
))
{
}
else
if
(
isStartTag
(
xpp
,
"ContentComponent"
))
{
id
=
Integer
.
parseInt
(
xpp
.
getAttributeValue
(
null
,
"id"
));
id
=
Integer
.
parseInt
(
xpp
.
getAttributeValue
(
null
,
"id"
));
contentType
=
checkAdaptationSetTypeConsistency
(
contentType
,
contentType
=
checkAdaptationSetTypeConsistency
(
contentType
,
parseAdaptationSetType
(
xpp
.
getAttributeValue
(
null
,
"contentType"
)));
parseAdaptationSetType
(
xpp
.
getAttributeValue
(
null
,
"contentType"
)));
}
else
if
(
isStartTag
(
xpp
,
"Representation"
))
{
}
else
if
(
isStartTag
(
xpp
,
"Representation"
))
{
Representation
representation
=
parseRepresentation
(
xpp
,
baseUrl
,
periodStartMs
,
Representation
representation
=
parseRepresentation
(
xpp
,
baseUrl
,
periodStartMs
,
periodDurationMs
,
mimeType
,
language
,
segmentBase
);
periodDurationMs
,
mimeType
,
language
,
segmentBase
,
contentProtectionsBuilder
);
contentProtectionsBuilder
.
endRepresentation
();
contentType
=
checkAdaptationSetTypeConsistency
(
contentType
,
contentType
=
checkAdaptationSetTypeConsistency
(
contentType
,
parseAdaptationSetTypeFromMimeType
(
representation
.
format
.
mimeType
));
parseAdaptationSetTypeFromMimeType
(
representation
.
format
.
mimeType
));
representations
.
add
(
representation
);
representations
.
add
(
representation
);
...
@@ -211,7 +211,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
...
@@ -211,7 +211,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
}
}
while
(!
isEndTag
(
xpp
,
"AdaptationSet"
));
}
while
(!
isEndTag
(
xpp
,
"AdaptationSet"
));
return
buildAdaptationSet
(
id
,
contentType
,
representations
,
contentProtections
);
return
buildAdaptationSet
(
id
,
contentType
,
representations
,
contentProtections
Builder
.
build
()
);
}
}
protected
AdaptationSet
buildAdaptationSet
(
int
id
,
int
contentType
,
protected
AdaptationSet
buildAdaptationSet
(
int
id
,
int
contentType
,
...
@@ -289,7 +289,8 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
...
@@ -289,7 +289,8 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
protected
Representation
parseRepresentation
(
XmlPullParser
xpp
,
String
baseUrl
,
protected
Representation
parseRepresentation
(
XmlPullParser
xpp
,
String
baseUrl
,
long
periodStartMs
,
long
periodDurationMs
,
String
mimeType
,
String
language
,
long
periodStartMs
,
long
periodDurationMs
,
String
mimeType
,
String
language
,
SegmentBase
segmentBase
)
throws
XmlPullParserException
,
IOException
{
SegmentBase
segmentBase
,
ContentProtectionsBuilder
contentProtectionsBuilder
)
throws
XmlPullParserException
,
IOException
{
String
id
=
xpp
.
getAttributeValue
(
null
,
"id"
);
String
id
=
xpp
.
getAttributeValue
(
null
,
"id"
);
int
bandwidth
=
parseInt
(
xpp
,
"bandwidth"
);
int
bandwidth
=
parseInt
(
xpp
,
"bandwidth"
);
int
audioSamplingRate
=
parseInt
(
xpp
,
"audioSamplingRate"
);
int
audioSamplingRate
=
parseInt
(
xpp
,
"audioSamplingRate"
);
...
@@ -312,6 +313,8 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
...
@@ -312,6 +313,8 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
else
if
(
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
}
else
if
(
isStartTag
(
xpp
,
"SegmentTemplate"
))
{
segmentBase
=
parseSegmentTemplate
(
xpp
,
baseUrl
,
(
SegmentTemplate
)
segmentBase
,
segmentBase
=
parseSegmentTemplate
(
xpp
,
baseUrl
,
(
SegmentTemplate
)
segmentBase
,
periodDurationMs
);
periodDurationMs
);
}
else
if
(
isStartTag
(
xpp
,
"ContentProtection"
))
{
contentProtectionsBuilder
.
addRepresentationProtection
(
parseContentProtection
(
xpp
));
}
}
}
while
(!
isEndTag
(
xpp
,
"Representation"
));
}
while
(!
isEndTag
(
xpp
,
"Representation"
));
...
@@ -577,4 +580,120 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
...
@@ -577,4 +580,120 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
return
value
==
null
?
defaultValue
:
value
;
return
value
==
null
?
defaultValue
:
value
;
}
}
/**
* Builds a list of {@link ContentProtection} elements for an {@link AdaptationSet}.
* <p>
* If child Representation elements contain ContentProtection elements, then it is required that
* they all define the same ones. If they do, the ContentProtection elements are bubbled up to the
* AdaptationSet. Child Representation elements defining different ContentProtection elements is
* considered an error.
*/
protected
static
final
class
ContentProtectionsBuilder
implements
Comparator
<
ContentProtection
>
{
private
ArrayList
<
ContentProtection
>
adaptationSetProtections
;
private
ArrayList
<
ContentProtection
>
representationProtections
;
private
ArrayList
<
ContentProtection
>
currentRepresentationProtections
;
private
boolean
representationProtectionsSet
;
/**
* Adds a {@link ContentProtection} found in the AdaptationSet element.
*
* @param contentProtection The {@link ContentProtection} to add.
*/
public
void
addAdaptationSetProtection
(
ContentProtection
contentProtection
)
{
if
(
adaptationSetProtections
==
null
)
{
adaptationSetProtections
=
new
ArrayList
<
ContentProtection
>();
}
maybeAddContentProtection
(
adaptationSetProtections
,
contentProtection
);
}
/**
* Adds a {@link ContentProtection} found in a child Representation element.
*
* @param contentProtection The {@link ContentProtection} to add.
*/
public
void
addRepresentationProtection
(
ContentProtection
contentProtection
)
{
if
(
currentRepresentationProtections
==
null
)
{
currentRepresentationProtections
=
new
ArrayList
<
ContentProtection
>();
}
maybeAddContentProtection
(
currentRepresentationProtections
,
contentProtection
);
}
/**
* Should be invoked after processing each child Representation element, in order to apply
* consistency checks.
*/
public
void
endRepresentation
()
{
if
(!
representationProtectionsSet
)
{
if
(
currentRepresentationProtections
!=
null
)
{
Collections
.
sort
(
currentRepresentationProtections
,
this
);
}
representationProtections
=
currentRepresentationProtections
;
representationProtectionsSet
=
true
;
}
else
{
// Assert that each Representation element defines the same ContentProtection elements.
if
(
currentRepresentationProtections
==
null
)
{
Assertions
.
checkState
(
representationProtections
==
null
);
}
else
{
Collections
.
sort
(
currentRepresentationProtections
,
this
);
Assertions
.
checkState
(
currentRepresentationProtections
.
equals
(
representationProtections
));
}
}
currentRepresentationProtections
=
null
;
}
/**
* Returns the final list of consistent {@link ContentProtection} elements.
*/
public
ArrayList
<
ContentProtection
>
build
()
{
if
(
adaptationSetProtections
==
null
)
{
return
representationProtections
;
}
else
if
(
representationProtections
==
null
)
{
return
adaptationSetProtections
;
}
else
{
// Bubble up ContentProtection elements found in the child Representation elements.
for
(
int
i
=
0
;
i
<
representationProtections
.
size
();
i
++)
{
maybeAddContentProtection
(
adaptationSetProtections
,
representationProtections
.
get
(
i
));
}
return
adaptationSetProtections
;
}
}
/**
* Checks a ContentProtection for consistency with the given list, adding it if necessary.
* <ul>
* <li>If the new ContentProtection matches another in the list, it's consistent and is not
* added to the list.
* <li>If the new ContentProtection has the same schemeUriId as another ContentProtection in the
* list, but its other attributes do not match, then it's inconsistent and an
* {@link IllegalStateException} is thrown.
* <li>Else the new ContentProtection has a unique schemeUriId, it's consistent and is added.
* </ul>
*
* @param contentProtections The list of ContentProtection elements currently known.
* @param contentProtection The ContentProtection to add.
*/
private
void
maybeAddContentProtection
(
List
<
ContentProtection
>
contentProtections
,
ContentProtection
contentProtection
)
{
if
(!
contentProtections
.
contains
(
contentProtection
))
{
for
(
int
i
=
0
;
i
<
contentProtections
.
size
();
i
++)
{
// If contains returned false (no complete match), but find a matching schemeUriId, then
// the MPD contains inconsistent ContentProtection data.
Assertions
.
checkState
(
!
contentProtections
.
get
(
i
).
schemeUriId
.
equals
(
contentProtection
.
schemeUriId
));
}
contentProtections
.
add
(
contentProtection
);
}
}
// Comparator implementation.
@Override
public
int
compare
(
ContentProtection
first
,
ContentProtection
second
)
{
return
first
.
schemeUriId
.
compareTo
(
second
.
schemeUriId
);
}
}
}
}
library/src/main/java/com/google/android/exoplayer/hls/HlsParserUtil.java
View file @
fcc2138e
...
@@ -23,9 +23,10 @@ import java.util.regex.Pattern;
...
@@ -23,9 +23,10 @@ import java.util.regex.Pattern;
/**
/**
* Utility methods for HLS manifest parsing.
* Utility methods for HLS manifest parsing.
*/
*/
/* package */
class
HlsParserUtil
{
/* package */
final
class
HlsParserUtil
{
private
static
final
String
BOOLEAN_YES
=
"YES"
;
private
static
final
String
BOOLEAN_YES
=
"YES"
;
private
static
final
String
BOOLEAN_NO
=
"NO"
;
private
HlsParserUtil
()
{}
private
HlsParserUtil
()
{}
...
@@ -56,7 +57,7 @@ import java.util.regex.Pattern;
...
@@ -56,7 +57,7 @@ import java.util.regex.Pattern;
return
null
;
return
null
;
}
}
public
static
boolean
parseOptionalBoolAttr
(
String
line
,
Pattern
pattern
)
{
public
static
boolean
parseOptionalBool
ean
Attr
(
String
line
,
Pattern
pattern
)
{
Matcher
matcher
=
pattern
.
matcher
(
line
);
Matcher
matcher
=
pattern
.
matcher
(
line
);
if
(
matcher
.
find
()
&&
matcher
.
groupCount
()
==
1
)
{
if
(
matcher
.
find
()
&&
matcher
.
groupCount
()
==
1
)
{
return
BOOLEAN_YES
.
equals
(
matcher
.
group
(
1
));
return
BOOLEAN_YES
.
equals
(
matcher
.
group
(
1
));
...
@@ -64,4 +65,8 @@ import java.util.regex.Pattern;
...
@@ -64,4 +65,8 @@ import java.util.regex.Pattern;
return
false
;
return
false
;
}
}
public
static
Pattern
compileBooleanAttrPattern
(
String
attrName
)
{
return
Pattern
.
compile
(
attrName
+
"=("
+
BOOLEAN_YES
+
"|"
+
BOOLEAN_NO
+
")"
);
}
}
}
library/src/main/java/com/google/android/exoplayer/hls/HlsPlaylistParser.java
View file @
fcc2138e
...
@@ -98,9 +98,9 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
...
@@ -98,9 +98,9 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
private
static
final
Pattern
NAME_ATTR_REGEX
=
private
static
final
Pattern
NAME_ATTR_REGEX
=
Pattern
.
compile
(
NAME_ATTR
+
"=\"(.+?)\""
);
Pattern
.
compile
(
NAME_ATTR
+
"=\"(.+?)\""
);
private
static
final
Pattern
AUTOSELECT_ATTR_REGEX
=
private
static
final
Pattern
AUTOSELECT_ATTR_REGEX
=
Pattern
.
compile
(
AUTOSELECT_ATTR
+
"=\"(.+?)\""
);
HlsParserUtil
.
compileBooleanAttrPattern
(
AUTOSELECT_ATTR
);
private
static
final
Pattern
DEFAULT_ATTR_REGEX
=
private
static
final
Pattern
DEFAULT_ATTR_REGEX
=
Pattern
.
compile
(
DEFAULT_ATTR
+
"=\"(.+?)\""
);
HlsParserUtil
.
compileBooleanAttrPattern
(
DEFAULT_ATTR
);
@Override
@Override
public
HlsPlaylist
parse
(
String
connectionUrl
,
InputStream
inputStream
)
public
HlsPlaylist
parse
(
String
connectionUrl
,
InputStream
inputStream
)
...
@@ -156,8 +156,8 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
...
@@ -156,8 +156,8 @@ public final class HlsPlaylistParser implements NetworkLoadable.Parser<HlsPlayli
String
name
=
HlsParserUtil
.
parseStringAttr
(
line
,
NAME_ATTR_REGEX
,
NAME_ATTR
);
String
name
=
HlsParserUtil
.
parseStringAttr
(
line
,
NAME_ATTR_REGEX
,
NAME_ATTR
);
String
uri
=
HlsParserUtil
.
parseStringAttr
(
line
,
URI_ATTR_REGEX
,
URI_ATTR
);
String
uri
=
HlsParserUtil
.
parseStringAttr
(
line
,
URI_ATTR_REGEX
,
URI_ATTR
);
String
language
=
HlsParserUtil
.
parseOptionalStringAttr
(
line
,
LANGUAGE_ATTR_REGEX
);
String
language
=
HlsParserUtil
.
parseOptionalStringAttr
(
line
,
LANGUAGE_ATTR_REGEX
);
boolean
isDefault
=
HlsParserUtil
.
parseOptionalBoolAttr
(
line
,
DEFAULT_ATTR_REGEX
);
boolean
isDefault
=
HlsParserUtil
.
parseOptionalBool
ean
Attr
(
line
,
DEFAULT_ATTR_REGEX
);
boolean
autoSelect
=
HlsParserUtil
.
parseOptionalBoolAttr
(
line
,
AUTOSELECT_ATTR_REGEX
);
boolean
autoSelect
=
HlsParserUtil
.
parseOptionalBool
ean
Attr
(
line
,
AUTOSELECT_ATTR_REGEX
);
subtitles
.
add
(
new
Subtitle
(
name
,
uri
,
language
,
isDefault
,
autoSelect
));
subtitles
.
add
(
new
Subtitle
(
name
,
uri
,
language
,
isDefault
,
autoSelect
));
}
else
{
}
else
{
// TODO: Support other types of media tag.
// TODO: Support other types of media tag.
...
...
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