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
9d4e1773
authored
Dec 12, 2014
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Support DASH Live TTML subtitles.
Also add missing file.
parent
bb024fda
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
93 additions
and
21 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
demo/src/main/java/com/google/android/exoplayer/demo/full/player/UnsupportedDrmException.java
library/src/main/java/com/google/android/exoplayer/MediaFormat.java
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
library/src/main/java/com/google/android/exoplayer/parser/mp4/Track.java
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
demo/src/main/java/com/google/android/exoplayer/demo/full/player/DashRendererBuilder.java
View file @
9d4e1773
...
...
@@ -41,6 +41,7 @@ import com.google.android.exoplayer.drm.DrmSessionManager;
import
com.google.android.exoplayer.drm.MediaDrmCallback
;
import
com.google.android.exoplayer.drm.StreamingDrmSessionManager
;
import
com.google.android.exoplayer.text.TextTrackRenderer
;
import
com.google.android.exoplayer.text.ttml.TtmlParser
;
import
com.google.android.exoplayer.text.webvtt.WebvttParser
;
import
com.google.android.exoplayer.upstream.BufferPool
;
import
com.google.android.exoplayer.upstream.DataSource
;
...
...
@@ -274,8 +275,8 @@ public class DashRendererBuilder implements RendererBuilder,
SampleSource
textSampleSource
=
new
ChunkSampleSource
(
textChunkSource
,
loadControl
,
TEXT_BUFFER_SEGMENTS
*
BUFFER_SEGMENT_SIZE
,
true
,
mainHandler
,
player
,
DemoPlayer
.
TYPE_TEXT
);
textRenderer
=
new
TextTrackRenderer
(
textSampleSource
,
new
WebvttParser
(),
player
,
mainHandler
.
getLoop
er
());
textRenderer
=
new
TextTrackRenderer
(
textSampleSource
,
player
,
mainHandler
.
getLooper
()
,
new
TtmlParser
(),
new
WebvttPars
er
());
}
// Invoke the callback.
...
...
demo/src/main/java/com/google/android/exoplayer/demo/full/player/SmoothStreamingRendererBuilder.java
View file @
9d4e1773
...
...
@@ -233,8 +233,8 @@ public class SmoothStreamingRendererBuilder implements RendererBuilder,
ChunkSampleSource
ttmlSampleSource
=
new
ChunkSampleSource
(
textChunkSource
,
loadControl
,
TEXT_BUFFER_SEGMENTS
*
BUFFER_SEGMENT_SIZE
,
true
,
mainHandler
,
player
,
DemoPlayer
.
TYPE_TEXT
);
textRenderer
=
new
TextTrackRenderer
(
ttmlSampleSource
,
new
TtmlParser
(),
player
,
mainHandler
.
getLoop
er
());
textRenderer
=
new
TextTrackRenderer
(
ttmlSampleSource
,
player
,
mainHandler
.
getLooper
()
,
new
TtmlPars
er
());
}
// Invoke the callback.
...
...
demo/src/main/java/com/google/android/exoplayer/demo/full/player/UnsupportedDrmException.java
0 → 100644
View file @
9d4e1773
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
demo
.
full
.
player
;
/**
* Exception thrown when the required level of DRM is not supported.
*/
public
final
class
UnsupportedDrmException
extends
Exception
{
public
static
final
int
REASON_NO_DRM
=
0
;
public
static
final
int
REASON_UNSUPPORTED_SCHEME
=
1
;
public
static
final
int
REASON_UNKNOWN
=
2
;
public
final
int
reason
;
public
UnsupportedDrmException
(
int
reason
)
{
this
.
reason
=
reason
;
}
public
UnsupportedDrmException
(
int
reason
,
Exception
cause
)
{
super
(
cause
);
this
.
reason
=
reason
;
}
}
library/src/main/java/com/google/android/exoplayer/MediaFormat.java
View file @
9d4e1773
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer
;
import
com.google.android.exoplayer.util.MimeTypes
;
import
com.google.android.exoplayer.util.Util
;
import
android.annotation.SuppressLint
;
...
...
@@ -86,6 +87,15 @@ public class MediaFormat {
sampleRate
,
bitrate
,
initializationData
);
}
public
static
MediaFormat
createTtmlFormat
()
{
return
createFormatForMimeType
(
MimeTypes
.
APPLICATION_TTML
);
}
public
static
MediaFormat
createFormatForMimeType
(
String
mimeType
)
{
return
new
MediaFormat
(
mimeType
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
);
}
@TargetApi
(
16
)
private
MediaFormat
(
android
.
media
.
MediaFormat
format
)
{
this
.
frameworkMediaFormat
=
format
;
...
...
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java
View file @
9d4e1773
...
...
@@ -272,16 +272,23 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
downstreamPositionUs
=
positionUs
;
chunkSource
.
continueBuffering
(
positionUs
);
updateLoadControl
();
boolean
haveSamples
=
false
;
if
(
isPendingReset
()
||
mediaChunks
.
isEmpty
())
{
return
false
;
// No sample available.
}
else
if
(
mediaChunks
.
getFirst
().
sampleAvailable
())
{
// There's a sample available to be read from the current chunk.
return
true
;
haveSamples
=
true
;
}
else
{
// It may be the case that the current chunk has been fully read but not yet discarded and
// that the next chunk has an available sample. Return true if so, otherwise false.
return
mediaChunks
.
size
()
>
1
&&
mediaChunks
.
get
(
1
).
sampleAvailable
();
haveSamples
=
mediaChunks
.
size
()
>
1
&&
mediaChunks
.
get
(
1
).
sampleAvailable
();
}
if
(!
haveSamples
)
{
maybeThrowLoadableException
();
}
return
haveSamples
;
}
@Override
...
...
@@ -380,7 +387,8 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback {
}
private
void
maybeThrowLoadableException
()
throws
IOException
{
if
(
currentLoadableException
!=
null
&&
currentLoadableExceptionCount
>
minLoadableRetryCount
)
{
if
(
currentLoadableException
!=
null
&&
(
currentLoadableExceptionFatal
||
currentLoadableExceptionCount
>
minLoadableRetryCount
))
{
throw
currentLoadableException
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/Atom.java
View file @
9d4e1773
...
...
@@ -58,6 +58,7 @@ import java.util.ArrayList;
public
static
final
int
TYPE_uuid
=
0x75756964
;
public
static
final
int
TYPE_senc
=
0x73656E63
;
public
static
final
int
TYPE_pasp
=
0x70617370
;
public
static
final
int
TYPE_TTML
=
0x54544D4C
;
public
final
int
type
;
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java
View file @
9d4e1773
...
...
@@ -428,7 +428,8 @@ public final class FragmentedMp4Extractor implements Extractor {
private
static
Track
parseTrak
(
ContainerAtom
trak
)
{
ContainerAtom
mdia
=
trak
.
getContainerAtomOfType
(
Atom
.
TYPE_mdia
);
int
trackType
=
parseHdlr
(
mdia
.
getLeafAtomOfType
(
Atom
.
TYPE_hdlr
).
data
);
Assertions
.
checkState
(
trackType
==
Track
.
TYPE_AUDIO
||
trackType
==
Track
.
TYPE_VIDEO
);
Assertions
.
checkState
(
trackType
==
Track
.
TYPE_AUDIO
||
trackType
==
Track
.
TYPE_VIDEO
||
trackType
==
Track
.
TYPE_TEXT
);
Pair
<
Integer
,
Long
>
header
=
parseTkhd
(
trak
.
getLeafAtomOfType
(
Atom
.
TYPE_tkhd
).
data
);
int
id
=
header
.
first
;
...
...
@@ -528,6 +529,8 @@ public final class FragmentedMp4Extractor implements Extractor {
parseAudioSampleEntry
(
stsd
,
childAtomType
,
childStartPosition
,
childAtomSize
);
mediaFormat
=
audioSampleEntry
.
first
;
trackEncryptionBoxes
[
i
]
=
audioSampleEntry
.
second
;
}
else
if
(
childAtomType
==
Atom
.
TYPE_TTML
)
{
mediaFormat
=
MediaFormat
.
createTtmlFormat
();
}
stsd
.
setPosition
(
childStartPosition
+
childAtomSize
);
}
...
...
library/src/main/java/com/google/android/exoplayer/parser/mp4/Track.java
View file @
9d4e1773
...
...
@@ -31,6 +31,10 @@ public final class Track {
*/
public
static
final
int
TYPE_AUDIO
=
0x736F756E
;
/**
* Type of a text track.
*/
public
static
final
int
TYPE_TEXT
=
0x74657874
;
/**
* Type of a hint track.
*/
public
static
final
int
TYPE_HINT
=
0x68696E74
;
...
...
library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java
View file @
9d4e1773
...
...
@@ -358,8 +358,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
MediaFormat
format
=
MediaFormat
.
createAudioFormat
(
mimeType
,
-
1
,
trackElement
.
numChannels
,
trackElement
.
sampleRate
,
csd
);
return
format
;
}
else
if
(
streamElement
.
type
==
StreamElement
.
TYPE_TEXT
)
{
return
MediaFormat
.
createFormatForMimeType
(
streamElement
.
tracks
[
trackIndex
].
mimeType
);
}
// TODO: Do subtitles need a format? MediaFormat supports KEY_LANGUAGE.
return
null
;
}
...
...
library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
View file @
9d4e1773
...
...
@@ -58,8 +58,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
private
final
TextRenderer
textRenderer
;
private
final
SampleSource
source
;
private
final
MediaFormatHolder
formatHolder
;
private
final
SubtitleParser
subtitleParser
;
private
final
SubtitleParser
[]
subtitleParsers
;
private
int
parserIndex
;
private
int
trackIndex
;
private
long
currentPositionUs
;
...
...
@@ -73,21 +74,22 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
/**
* @param source A source from which samples containing subtitle data can be read.
* @param subtitleParser A subtitle parser that will parse Subtitle objects from the source.
* @param textRenderer The text renderer.
* @param textRendererLooper The looper associated with the thread on which textRenderer should be
* invoked. If the renderer makes use of standard Android UI components, then this should
* normally be the looper associated with the applications' main thread, which can be
* obtained using {@link android.app.Activity#getMainLooper()}. Null may be passed if the
* renderer should be invoked directly on the player's internal rendering thread.
* @param subtitleParsers An array of available subtitle parsers. Where multiple parsers are able
* to render a subtitle, the one with the lowest index will be preferred.
*/
public
TextTrackRenderer
(
SampleSource
source
,
SubtitleParser
subtitlePars
er
,
TextRenderer
textRenderer
,
Looper
textRendererLooper
)
{
public
TextTrackRenderer
(
SampleSource
source
,
TextRenderer
textRender
er
,
Looper
textRendererLooper
,
SubtitleParser
...
subtitleParsers
)
{
this
.
source
=
Assertions
.
checkNotNull
(
source
);
this
.
subtitleParser
=
Assertions
.
checkNotNull
(
subtitleParser
);
this
.
textRenderer
=
Assertions
.
checkNotNull
(
textRenderer
);
this
.
textRendererHandler
=
textRendererLooper
==
null
?
null
:
new
Handler
(
textRendererLooper
,
this
);
this
.
textRendererHandler
=
textRendererLooper
==
null
?
null
:
new
Handler
(
textRendererLooper
,
this
);
this
.
subtitleParsers
=
Assertions
.
checkNotNull
(
subtitleParsers
);
formatHolder
=
new
MediaFormatHolder
();
}
...
...
@@ -101,12 +103,15 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
}
catch
(
IOException
e
)
{
throw
new
ExoPlaybackException
(
e
);
}
for
(
int
i
=
0
;
i
<
source
.
getTrackCount
();
i
++)
{
if
(
subtitleParser
.
canParse
(
source
.
getTrackInfo
(
i
).
mimeType
))
{
trackIndex
=
i
;
for
(
int
i
=
0
;
i
<
subtitleParsers
.
length
;
i
++)
{
for
(
int
j
=
0
;
j
<
source
.
getTrackCount
();
j
++)
{
if
(
subtitleParsers
[
i
].
canParse
(
source
.
getTrackInfo
(
j
).
mimeType
))
{
parserIndex
=
i
;
trackIndex
=
j
;
return
TrackRenderer
.
STATE_PREPARED
;
}
}
}
return
TrackRenderer
.
STATE_IGNORE
;
}
...
...
@@ -115,7 +120,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
source
.
enable
(
trackIndex
,
positionUs
);
parserThread
=
new
HandlerThread
(
"textParser"
);
parserThread
.
start
();
parserHelper
=
new
SubtitleParserHelper
(
parserThread
.
getLooper
(),
subtitleParser
);
parserHelper
=
new
SubtitleParserHelper
(
parserThread
.
getLooper
(),
subtitleParser
s
[
parserIndex
]
);
seekToInternal
(
positionUs
);
}
...
...
@@ -189,6 +194,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
int
result
=
source
.
readData
(
trackIndex
,
positionUs
,
formatHolder
,
sampleHolder
,
false
);
if
(
result
==
SampleSource
.
SAMPLE_READ
)
{
parserHelper
.
startParseOperation
();
textRendererNeedsUpdate
=
false
;
}
else
if
(
result
==
SampleSource
.
END_OF_STREAM
)
{
inputStreamEnded
=
true
;
}
...
...
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