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
1344b36d
authored
Dec 08, 2014
by
ojw28
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #194 from google/dev
dev -> dev-hls
parents
0a888a0d
c4b2a012
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
93 additions
and
35 deletions
demo/src/main/java/com/google/android/exoplayer/demo/full/player/DashRendererBuilder.java
demo/src/main/java/com/google/android/exoplayer/demo/full/player/SmoothStreamingRendererBuilder.java
library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
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/drm/StreamingDrmSessionManager.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java
demo/src/main/java/com/google/android/exoplayer/demo/full/player/DashRendererBuilder.java
View file @
1344b36d
...
...
@@ -279,8 +279,8 @@ public class DashRendererBuilder implements RendererBuilder,
public
static
Pair
<
DrmSessionManager
,
Boolean
>
getDrmSessionManagerData
(
DemoPlayer
player
,
MediaDrmCallback
drmCallback
)
throws
UnsupportedSchemeException
{
StreamingDrmSessionManager
streamingDrmSessionManager
=
new
StreamingDrmSessionManager
(
DemoUtil
.
WIDEVINE_UUID
,
player
.
getPlaybackLooper
(),
drmCallback
,
player
.
getMainHandler
()
,
player
);
DemoUtil
.
WIDEVINE_UUID
,
player
.
getPlaybackLooper
(),
drmCallback
,
null
,
player
.
getMainHandler
(),
player
);
return
Pair
.
create
((
DrmSessionManager
)
streamingDrmSessionManager
,
getWidevineSecurityLevel
(
streamingDrmSessionManager
)
==
SECURITY_LEVEL_1
);
}
...
...
demo/src/main/java/com/google/android/exoplayer/demo/full/player/SmoothStreamingRendererBuilder.java
View file @
1344b36d
...
...
@@ -252,7 +252,7 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
public
static
DrmSessionManager
getDrmSessionManager
(
UUID
uuid
,
DemoPlayer
player
,
MediaDrmCallback
drmCallback
)
throws
UnsupportedSchemeException
{
return
new
StreamingDrmSessionManager
(
uuid
,
player
.
getPlaybackLooper
(),
drmCallback
,
return
new
StreamingDrmSessionManager
(
uuid
,
player
.
getPlaybackLooper
(),
drmCallback
,
null
,
player
.
getMainHandler
(),
player
);
}
...
...
library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java
View file @
1344b36d
...
...
@@ -41,6 +41,17 @@ public final class Mp4MediaChunk extends MediaChunk {
private
Map
<
UUID
,
byte
[]>
psshInfo
;
/**
* @deprecated Use the other constructor, passing null as {@code psshInfo}.
*/
@Deprecated
public
Mp4MediaChunk
(
DataSource
dataSource
,
DataSpec
dataSpec
,
Format
format
,
int
trigger
,
long
startTimeUs
,
long
endTimeUs
,
int
nextChunkIndex
,
Extractor
extractor
,
boolean
maybeSelfContained
,
long
sampleOffsetUs
)
{
this
(
dataSource
,
dataSpec
,
format
,
trigger
,
startTimeUs
,
endTimeUs
,
nextChunkIndex
,
extractor
,
null
,
maybeSelfContained
,
sampleOffsetUs
);
}
/**
* @param dataSource A {@link DataSource} for loading the data.
* @param dataSpec Defines the data to be loaded.
* @param format The format of the stream to which this chunk belongs.
...
...
@@ -49,6 +60,8 @@ public final class Mp4MediaChunk extends MediaChunk {
* @param endTimeUs The end time of the media contained by the chunk, in microseconds.
* @param nextChunkIndex The index of the next chunk, or -1 if this is the last chunk.
* @param extractor The extractor that will be used to extract the samples.
* @param psshInfo Pssh data. May be null if pssh data is present within the stream, meaning it
* can be obtained directly from {@code extractor}, or if no pssh data is required.
* @param maybeSelfContained Set to true if this chunk might be self contained, meaning it might
* contain a moov atom defining the media format of the chunk. This parameter can always be
* safely set to true. Setting to false where the chunk is known to not be self contained may
...
...
@@ -56,12 +69,13 @@ public final class Mp4MediaChunk extends MediaChunk {
* @param sampleOffsetUs An offset to subtract from the sample timestamps parsed by the extractor.
*/
public
Mp4MediaChunk
(
DataSource
dataSource
,
DataSpec
dataSpec
,
Format
format
,
int
trigger
,
long
startTimeUs
,
long
endTimeUs
,
int
nextChunkIndex
,
Extractor
extractor
,
boolean
maybeSelfContained
,
long
sampleOffsetUs
)
{
int
trigger
,
long
startTimeUs
,
long
endTimeUs
,
int
nextChunkIndex
,
Extractor
extractor
,
Map
<
UUID
,
byte
[]>
psshInfo
,
boolean
maybeSelfContained
,
long
sampleOffsetUs
)
{
super
(
dataSource
,
dataSpec
,
format
,
trigger
,
startTimeUs
,
endTimeUs
,
nextChunkIndex
);
this
.
extractor
=
extractor
;
this
.
maybeSelfContained
=
maybeSelfContained
;
this
.
sampleOffsetUs
=
sampleOffsetUs
;
this
.
psshInfo
=
psshInfo
;
}
@Override
...
...
@@ -97,7 +111,10 @@ public final class Mp4MediaChunk extends MediaChunk {
}
if
(
prepared
)
{
mediaFormat
=
extractor
.
getFormat
();
psshInfo
=
extractor
.
getPsshInfo
();
Map
<
UUID
,
byte
[]>
extractorPsshInfo
=
extractor
.
getPsshInfo
();
if
(
extractorPsshInfo
!=
null
)
{
psshInfo
=
extractorPsshInfo
;
}
}
}
return
prepared
;
...
...
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
View file @
1344b36d
...
...
@@ -31,6 +31,7 @@ import com.google.android.exoplayer.chunk.MediaChunk;
import
com.google.android.exoplayer.chunk.Mp4MediaChunk
;
import
com.google.android.exoplayer.chunk.SingleSampleMediaChunk
;
import
com.google.android.exoplayer.dash.mpd.AdaptationSet
;
import
com.google.android.exoplayer.dash.mpd.ContentProtection
;
import
com.google.android.exoplayer.dash.mpd.MediaPresentationDescription
;
import
com.google.android.exoplayer.dash.mpd.Period
;
import
com.google.android.exoplayer.dash.mpd.RangedUri
;
...
...
@@ -53,6 +54,8 @@ import java.util.Arrays;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.UUID
;
/**
* An {@link ChunkSource} for DASH streams.
...
...
@@ -92,6 +95,7 @@ public class DashChunkSource implements ChunkSource {
private
final
ManifestFetcher
<
MediaPresentationDescription
>
manifestFetcher
;
private
final
int
adaptationSetIndex
;
private
final
int
[]
representationIndices
;
private
final
Map
<
UUID
,
byte
[]>
psshInfo
;
private
MediaPresentationDescription
currentManifest
;
private
boolean
finishedCurrentManifest
;
...
...
@@ -180,6 +184,7 @@ public class DashChunkSource implements ChunkSource {
this
.
evaluation
=
new
Evaluation
();
this
.
headerBuilder
=
new
StringBuilder
();
psshInfo
=
getPsshInfo
(
currentManifest
,
adaptationSetIndex
);
Representation
[]
representations
=
getFilteredRepresentations
(
currentManifest
,
adaptationSetIndex
,
representationIndices
);
long
periodDurationUs
=
(
representations
[
0
].
periodDurationMs
==
TrackRenderer
.
UNKNOWN_TIME_US
)
...
...
@@ -438,7 +443,7 @@ public class DashChunkSource implements ChunkSource {
startTimeUs
,
endTimeUs
,
nextAbsoluteSegmentNum
,
null
,
representationHolder
.
vttHeader
);
}
else
{
return
new
Mp4MediaChunk
(
dataSource
,
dataSpec
,
representation
.
format
,
trigger
,
startTimeUs
,
endTimeUs
,
nextAbsoluteSegmentNum
,
representationHolder
.
extractor
,
false
,
endTimeUs
,
nextAbsoluteSegmentNum
,
representationHolder
.
extractor
,
psshInfo
,
false
,
presentationTimeOffsetUs
);
}
}
...
...
@@ -463,8 +468,8 @@ public class DashChunkSource implements ChunkSource {
private
static
Representation
[]
getFilteredRepresentations
(
MediaPresentationDescription
manifest
,
int
adaptationSetIndex
,
int
[]
representationIndices
)
{
List
<
Representation
>
representations
=
manifest
.
periods
.
get
(
0
).
adaptationSets
.
get
(
adaptationSetIndex
)
.
representations
;
AdaptationSet
adaptationSet
=
manifest
.
periods
.
get
(
0
).
adaptationSets
.
get
(
adaptationSetIndex
);
List
<
Representation
>
representations
=
adaptationSet
.
representations
;
if
(
representationIndices
==
null
)
{
Representation
[]
filteredRepresentations
=
new
Representation
[
representations
.
size
()];
representations
.
toArray
(
filteredRepresentations
);
...
...
@@ -478,6 +483,22 @@ public class DashChunkSource implements ChunkSource {
}
}
private
static
Map
<
UUID
,
byte
[]>
getPsshInfo
(
MediaPresentationDescription
manifest
,
int
adaptationSetIndex
)
{
AdaptationSet
adaptationSet
=
manifest
.
periods
.
get
(
0
).
adaptationSets
.
get
(
adaptationSetIndex
);
if
(
adaptationSet
.
contentProtections
.
isEmpty
())
{
return
null
;
}
else
{
Map
<
UUID
,
byte
[]>
psshInfo
=
new
HashMap
<
UUID
,
byte
[]>();
for
(
ContentProtection
contentProtection
:
adaptationSet
.
contentProtections
)
{
if
(
contentProtection
.
uuid
!=
null
&&
contentProtection
.
data
!=
null
)
{
psshInfo
.
put
(
contentProtection
.
uuid
,
contentProtection
.
data
);
}
}
return
psshInfo
.
isEmpty
()
?
null
:
psshInfo
;
}
}
private
static
MediaPresentationDescription
buildManifest
(
List
<
Representation
>
representations
)
{
Representation
firstRepresentation
=
representations
.
get
(
0
);
AdaptationSet
adaptationSet
=
new
AdaptationSet
(
0
,
AdaptationSet
.
TYPE_UNKNOWN
,
representations
);
...
...
library/src/main/java/com/google/android/exoplayer/dash/mpd/ContentProtection.java
View file @
1344b36d
...
...
@@ -15,6 +15,8 @@
*/
package
com
.
google
.
android
.
exoplayer
.
dash
.
mpd
;
import
java.util.UUID
;
/**
* Represents a ContentProtection tag in an AdaptationSet.
*/
...
...
@@ -26,10 +28,24 @@ public class ContentProtection {
public
final
String
schemeUriId
;
/**
* The UUID of the protection scheme. May be null.
*/
public
final
UUID
uuid
;
/**
* Protection scheme specific data. May be null.
*/
public
final
byte
[]
data
;
/**
* @param schemeUriId Identifies the content protection scheme.
* @param uuid The UUID of the protection scheme, if known. May be null.
* @param data Protection scheme specific initialization data. May be null.
*/
public
ContentProtection
(
String
schemeUriId
)
{
public
ContentProtection
(
String
schemeUriId
,
UUID
uuid
,
byte
[]
data
)
{
this
.
schemeUriId
=
schemeUriId
;
this
.
uuid
=
uuid
;
this
.
data
=
data
;
}
}
library/src/main/java/com/google/android/exoplayer/dash/mpd/MediaPresentationDescriptionParser.java
View file @
1344b36d
...
...
@@ -257,7 +257,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
protected
ContentProtection
buildContentProtection
(
String
schemeIdUri
)
{
return
new
ContentProtection
(
schemeIdUri
);
return
new
ContentProtection
(
schemeIdUri
,
null
,
null
);
}
/**
...
...
library/src/main/java/com/google/android/exoplayer/drm/StreamingDrmSessionManager.java
View file @
1344b36d
...
...
@@ -30,6 +30,7 @@ import android.os.HandlerThread;
import
android.os.Looper
;
import
android.os.Message
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.UUID
;
...
...
@@ -61,6 +62,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
private
final
Handler
eventHandler
;
private
final
EventListener
eventListener
;
private
final
MediaDrm
mediaDrm
;
private
final
HashMap
<
String
,
String
>
optionalKeyRequestParameters
;
/* package */
final
MediaDrmHandler
mediaDrmHandler
;
/* package */
final
MediaDrmCallback
callback
;
...
...
@@ -80,19 +82,32 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
private
byte
[]
sessionId
;
/**
* @deprecated Use the other constructor, passing null as {@code optionalKeyRequestParameters}.
*/
@Deprecated
public
StreamingDrmSessionManager
(
UUID
uuid
,
Looper
playbackLooper
,
MediaDrmCallback
callback
,
Handler
eventHandler
,
EventListener
eventListener
)
throws
UnsupportedSchemeException
{
this
(
uuid
,
playbackLooper
,
callback
,
null
,
eventHandler
,
eventListener
);
}
/**
* @param uuid The UUID of the drm scheme.
* @param playbackLooper The looper associated with the media playback thread. Should usually be
* obtained using {@link com.google.android.exoplayer.ExoPlayer#getPlaybackLooper()}.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedSchemeException If the specified DRM scheme is not supported.
*/
public
StreamingDrmSessionManager
(
UUID
uuid
,
Looper
playbackLooper
,
MediaDrmCallback
callback
,
Handler
eventHandler
,
EventListener
eventListener
)
throws
UnsupportedSchemeException
{
HashMap
<
String
,
String
>
optionalKeyRequestParameters
,
Handler
eventHandler
,
EventListener
eventListener
)
throws
UnsupportedSchemeException
{
this
.
uuid
=
uuid
;
this
.
callback
=
callback
;
this
.
optionalKeyRequestParameters
=
optionalKeyRequestParameters
;
this
.
eventHandler
=
eventHandler
;
this
.
eventListener
=
eventListener
;
mediaDrm
=
new
MediaDrm
(
uuid
);
...
...
@@ -250,7 +265,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
KeyRequest
keyRequest
;
try
{
keyRequest
=
mediaDrm
.
getKeyRequest
(
sessionId
,
schemePsshData
,
mimeType
,
MediaDrm
.
KEY_TYPE_STREAMING
,
null
);
MediaDrm
.
KEY_TYPE_STREAMING
,
optionalKeyRequestParameters
);
postRequestHandler
.
obtainMessage
(
MSG_KEYS
,
keyRequest
).
sendToTarget
();
}
catch
(
NotProvisionedException
e
)
{
onKeysError
(
e
);
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
View file @
1344b36d
...
...
@@ -189,20 +189,6 @@ public final class FragmentedMp4Extractor implements Extractor {
this
.
track
=
track
;
}
/**
* Sideloads pssh information into the extractor, so that it can be read through
* {@link #getPsshInfo()}.
*
* @param uuid The UUID of the scheme for which information is being sideloaded.
* @param data The corresponding data.
*/
public
void
putPsshInfo
(
UUID
uuid
,
byte
[]
data
)
{
// TODO: This is for SmoothStreaming. Consider using something other than
// FragmentedMp4Extractor.getPsshInfo to obtain the pssh data for that use case, so that we can
// remove this method.
psshData
.
put
(
uuid
,
data
);
}
@Override
public
Map
<
UUID
,
byte
[]>
getPsshInfo
()
{
return
psshData
.
isEmpty
()
?
null
:
psshData
;
...
...
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
View file @
1344b36d
...
...
@@ -48,6 +48,8 @@ import java.io.IOException;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.UUID
;
/**
* An {@link ChunkSource} for SmoothStreaming.
...
...
@@ -69,6 +71,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
private
final
int
maxHeight
;
private
final
SparseArray
<
FragmentedMp4Extractor
>
extractors
;
private
final
Map
<
UUID
,
byte
[]>
psshInfo
;
private
final
SmoothStreamingFormat
[]
formats
;
private
SmoothStreamingManifest
currentManifest
;
...
...
@@ -140,6 +143,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
byte
[]
keyId
=
getKeyId
(
protectionElement
.
data
);
trackEncryptionBoxes
=
new
TrackEncryptionBox
[
1
];
trackEncryptionBoxes
[
0
]
=
new
TrackEncryptionBox
(
true
,
INITIALIZATION_VECTOR_SIZE
,
keyId
);
psshInfo
=
Collections
.
singletonMap
(
protectionElement
.
uuid
,
protectionElement
.
data
);
}
else
{
psshInfo
=
null
;
}
int
trackCount
=
trackIndices
!=
null
?
trackIndices
.
length
:
streamElement
.
tracks
.
length
;
...
...
@@ -163,9 +169,6 @@ public class SmoothStreamingChunkSource implements ChunkSource {
FragmentedMp4Extractor
.
WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
);
extractor
.
setTrack
(
new
Track
(
trackIndex
,
trackType
,
streamElement
.
timescale
,
mediaFormat
,
trackEncryptionBoxes
));
if
(
protectionElement
!=
null
)
{
extractor
.
putPsshInfo
(
protectionElement
.
uuid
,
protectionElement
.
data
);
}
extractors
.
put
(
trackIndex
,
extractor
);
}
this
.
maxHeight
=
maxHeight
;
...
...
@@ -296,8 +299,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
Uri
uri
=
streamElement
.
buildRequestUri
(
selectedFormat
.
trackIndex
,
chunkIndex
);
Chunk
mediaChunk
=
newMediaChunk
(
selectedFormat
,
uri
,
null
,
extractors
.
get
(
Integer
.
parseInt
(
selectedFormat
.
id
)),
dataSource
,
currentAbsoluteChunkIndex
,
isLastChunk
,
chunkStartTimeUs
,
nextChunkStartTimeUs
,
0
);
extractors
.
get
(
Integer
.
parseInt
(
selectedFormat
.
id
)),
psshInfo
,
dataSource
,
currentAbsoluteChunkIndex
,
isLastChunk
,
chunkStartTimeUs
,
nextChunkStartTimeUs
,
0
);
out
.
chunk
=
mediaChunk
;
}
...
...
@@ -361,7 +364,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
}
private
static
MediaChunk
newMediaChunk
(
Format
formatInfo
,
Uri
uri
,
String
cacheKey
,
Extractor
extractor
,
DataSource
dataSource
,
int
chunkIndex
,
Extractor
extractor
,
Map
<
UUID
,
byte
[]>
psshInfo
,
DataSource
dataSource
,
int
chunkIndex
,
boolean
isLast
,
long
chunkStartTimeUs
,
long
nextChunkStartTimeUs
,
int
trigger
)
{
int
nextChunkIndex
=
isLast
?
-
1
:
chunkIndex
+
1
;
long
nextStartTimeUs
=
isLast
?
-
1
:
nextChunkStartTimeUs
;
...
...
@@ -370,7 +373,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
// In SmoothStreaming each chunk contains sample timestamps relative to the start of the chunk.
// To convert them the absolute timestamps, we need to set sampleOffsetUs to -chunkStartTimeUs.
return
new
Mp4MediaChunk
(
dataSource
,
dataSpec
,
formatInfo
,
trigger
,
chunkStartTimeUs
,
nextStartTimeUs
,
nextChunkIndex
,
extractor
,
false
,
-
chunkStartTimeUs
);
nextStartTimeUs
,
nextChunkIndex
,
extractor
,
psshInfo
,
false
,
-
chunkStartTimeUs
);
}
private
static
byte
[]
getKeyId
(
byte
[]
initData
)
{
...
...
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingManifest.java
View file @
1344b36d
...
...
@@ -274,7 +274,7 @@ public class SmoothStreamingManifest {
String
chunkUrl
=
chunkTemplate
.
replace
(
URL_PLACEHOLDER_BITRATE
,
Integer
.
toString
(
tracks
[
track
].
bitrate
))
.
replace
(
URL_PLACEHOLDER_START_TIME
,
Long
.
toString
(
chunkStartTimes
.
get
(
chunkIndex
)));
return
baseUri
.
buildUpon
().
appendEncodedPath
(
chunkUrl
).
build
(
);
return
Util
.
getMergedUri
(
baseUri
,
chunkUrl
);
}
}
...
...
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