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
f4d3079b
authored
Oct 01, 2014
by
ojw28
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #63 from google/dev
Update dev-l
parents
e99aaa4d
8c665e3d
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
162 additions
and
32 deletions
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java
library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
library/src/main/java/com/google/android/exoplayer/text/webvtt/WebvttSubtitle.java
library/src/main/java/com/google/android/exoplayer/upstream/DataSpec.java
library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java
View file @
f4d3079b
...
@@ -45,6 +45,8 @@ public interface ChunkSource {
...
@@ -45,6 +45,8 @@ public interface ChunkSource {
* the supplied {@link MediaFormat}. Other implementations do nothing.
* the supplied {@link MediaFormat}. Other implementations do nothing.
* <p>
* <p>
* Only called when the source is enabled.
* Only called when the source is enabled.
*
* @param out The {@link MediaFormat} on which the maximum video dimensions should be set.
*/
*/
void
getMaxVideoDimensions
(
MediaFormat
out
);
void
getMaxVideoDimensions
(
MediaFormat
out
);
...
...
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java
0 → 100644
View file @
f4d3079b
/*
* 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
.
chunk
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.TrackInfo
;
import
com.google.android.exoplayer.upstream.DataSource
;
import
com.google.android.exoplayer.upstream.DataSpec
;
import
java.io.IOException
;
import
java.util.List
;
/**
* A chunk source that provides a single chunk containing a single sample.
* <p>
* An example use case for this implementation is to act as the source for loading out-of-band
* subtitles, where subtitles for the entire video are delivered as a single file.
*/
public
class
SingleSampleChunkSource
implements
ChunkSource
{
private
final
DataSource
dataSource
;
private
final
DataSpec
dataSpec
;
private
final
Format
format
;
private
final
long
durationUs
;
private
final
MediaFormat
mediaFormat
;
private
final
TrackInfo
trackInfo
;
/**
* @param dataSource A {@link DataSource} suitable for loading the sample data.
* @param dataSpec Defines the location of the sample.
* @param format The format of the sample.
* @param durationUs The duration of the sample in microseconds.
* @param mediaFormat The sample media format. May be null.
*/
public
SingleSampleChunkSource
(
DataSource
dataSource
,
DataSpec
dataSpec
,
Format
format
,
long
durationUs
,
MediaFormat
mediaFormat
)
{
this
.
dataSource
=
dataSource
;
this
.
dataSpec
=
dataSpec
;
this
.
format
=
format
;
this
.
durationUs
=
durationUs
;
this
.
mediaFormat
=
mediaFormat
;
trackInfo
=
new
TrackInfo
(
format
.
mimeType
,
durationUs
);
}
@Override
public
TrackInfo
getTrackInfo
()
{
return
trackInfo
;
}
@Override
public
void
getMaxVideoDimensions
(
MediaFormat
out
)
{
// Do nothing.
}
@Override
public
void
enable
()
{
// Do nothing.
}
@Override
public
void
continueBuffering
(
long
playbackPositionUs
)
{
// Do nothing.
}
@Override
public
void
getChunkOperation
(
List
<?
extends
MediaChunk
>
queue
,
long
seekPositionUs
,
long
playbackPositionUs
,
ChunkOperationHolder
out
)
{
if
(!
queue
.
isEmpty
())
{
// We've already provided the single sample.
return
;
}
out
.
chunk
=
initChunk
();
}
@Override
public
void
disable
(
List
<?
extends
MediaChunk
>
queue
)
{
// Do nothing.
}
@Override
public
IOException
getError
()
{
return
null
;
}
@Override
public
void
onChunkLoadError
(
Chunk
chunk
,
Exception
e
)
{
// Do nothing.
}
private
SingleSampleMediaChunk
initChunk
()
{
return
new
SingleSampleMediaChunk
(
dataSource
,
dataSpec
,
format
,
0
,
0
,
durationUs
,
-
1
,
mediaFormat
);
}
}
library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
View file @
f4d3079b
...
@@ -20,20 +20,18 @@ import com.google.android.exoplayer.MediaFormatHolder;
...
@@ -20,20 +20,18 @@ import com.google.android.exoplayer.MediaFormatHolder;
import
com.google.android.exoplayer.SampleHolder
;
import
com.google.android.exoplayer.SampleHolder
;
import
com.google.android.exoplayer.SampleSource
;
import
com.google.android.exoplayer.SampleSource
;
import
com.google.android.exoplayer.TrackRenderer
;
import
com.google.android.exoplayer.TrackRenderer
;
import
com.google.android.exoplayer.dash.mpd.AdaptationSet
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.VerboseLogUtil
;
import
com.google.android.exoplayer.util.VerboseLogUtil
;
import
android.annotation.TargetApi
;
import
android.annotation.TargetApi
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.Handler.Callback
;
import
android.os.Handler.Callback
;
import
android.os.HandlerThread
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.os.Message
;
import
android.os.Message
;
import
android.util.Log
;
import
android.util.Log
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
/**
/**
* A {@link TrackRenderer} for textual subtitles. The actual rendering of each line of text to a
* A {@link TrackRenderer} for textual subtitles. The actual rendering of each line of text to a
...
@@ -63,7 +61,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -63,7 +61,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
private
final
Handler
textRendererHandler
;
private
final
Handler
textRendererHandler
;
private
final
TextRenderer
textRenderer
;
private
final
TextRenderer
textRenderer
;
private
final
SampleSource
source
;
private
final
SampleSource
source
;
private
final
SampleHolder
sampleHolder
;
private
final
MediaFormatHolder
formatHolder
;
private
final
MediaFormatHolder
formatHolder
;
private
final
SubtitleParser
subtitleParser
;
private
final
SubtitleParser
subtitleParser
;
...
@@ -73,6 +70,8 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -73,6 +70,8 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
private
boolean
inputStreamEnded
;
private
boolean
inputStreamEnded
;
private
Subtitle
subtitle
;
private
Subtitle
subtitle
;
private
SubtitleParserHelper
parserHelper
;
private
HandlerThread
parserThread
;
private
int
nextSubtitleEventIndex
;
private
int
nextSubtitleEventIndex
;
private
boolean
textRendererNeedsUpdate
;
private
boolean
textRendererNeedsUpdate
;
...
@@ -94,7 +93,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -94,7 +93,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
this
.
textRendererHandler
=
textRendererLooper
==
null
?
null
:
new
Handler
(
textRendererLooper
,
this
.
textRendererHandler
=
textRendererLooper
==
null
?
null
:
new
Handler
(
textRendererLooper
,
this
);
this
);
formatHolder
=
new
MediaFormatHolder
();
formatHolder
=
new
MediaFormatHolder
();
sampleHolder
=
new
SampleHolder
(
true
);
}
}
@Override
@Override
...
@@ -119,6 +117,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -119,6 +117,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
@Override
@Override
protected
void
onEnabled
(
long
timeUs
,
boolean
joining
)
{
protected
void
onEnabled
(
long
timeUs
,
boolean
joining
)
{
source
.
enable
(
trackIndex
,
timeUs
);
source
.
enable
(
trackIndex
,
timeUs
);
parserThread
=
new
HandlerThread
(
"textParser"
);
parserThread
.
start
();
parserHelper
=
new
SubtitleParserHelper
(
parserThread
.
getLooper
(),
subtitleParser
);
seekToInternal
(
timeUs
);
seekToInternal
(
timeUs
);
}
}
...
@@ -136,7 +137,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -136,7 +137,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
||
subtitle
.
getLastEventTime
()
<=
timeUs
))
{
||
subtitle
.
getLastEventTime
()
<=
timeUs
))
{
subtitle
=
null
;
subtitle
=
null
;
}
}
resetSampleData
();
parserHelper
.
flush
();
clearTextRenderer
();
clearTextRenderer
();
syncNextEventIndex
(
timeUs
);
syncNextEventIndex
(
timeUs
);
textRendererNeedsUpdate
=
subtitle
!=
null
;
textRendererNeedsUpdate
=
subtitle
!=
null
;
...
@@ -152,9 +153,27 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -152,9 +153,27 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
currentPositionUs
=
timeUs
;
currentPositionUs
=
timeUs
;
// We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we advance
if
(
parserHelper
.
isParsing
())
{
// to the next event.
return
;
if
(
subtitle
!=
null
)
{
}
Subtitle
dequeuedSubtitle
=
null
;
if
(
subtitle
==
null
)
{
try
{
dequeuedSubtitle
=
parserHelper
.
getAndClearResult
();
}
catch
(
IOException
e
)
{
throw
new
ExoPlaybackException
(
e
);
}
}
if
(
subtitle
==
null
&&
dequeuedSubtitle
!=
null
)
{
// We've dequeued a new subtitle. Sync the event index and update the subtitle.
subtitle
=
dequeuedSubtitle
;
syncNextEventIndex
(
timeUs
);
textRendererNeedsUpdate
=
true
;
}
else
if
(
subtitle
!=
null
)
{
// We're iterating through the events in a subtitle. Set textRendererNeedsUpdate if we
// advance to the next event.
long
nextEventTimeUs
=
getNextEventTime
();
long
nextEventTimeUs
=
getNextEventTime
();
while
(
nextEventTimeUs
<=
timeUs
)
{
while
(
nextEventTimeUs
<=
timeUs
)
{
nextSubtitleEventIndex
++;
nextSubtitleEventIndex
++;
...
@@ -170,26 +189,16 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -170,26 +189,16 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
// We don't have a subtitle. Try and read the next one from the source, and if we succeed then
// We don't have a subtitle. Try and read the next one from the source, and if we succeed then
// sync and set textRendererNeedsUpdate.
// sync and set textRendererNeedsUpdate.
if
(
subtitle
==
null
)
{
if
(
subtitle
==
null
)
{
boolean
resetSampleHolder
=
false
;
try
{
try
{
SampleHolder
sampleHolder
=
parserHelper
.
getSampleHolder
();
int
result
=
source
.
readData
(
trackIndex
,
timeUs
,
formatHolder
,
sampleHolder
,
false
);
int
result
=
source
.
readData
(
trackIndex
,
timeUs
,
formatHolder
,
sampleHolder
,
false
);
if
(
result
==
SampleSource
.
SAMPLE_READ
)
{
if
(
result
==
SampleSource
.
SAMPLE_READ
)
{
resetSampleHolder
=
true
;
parserHelper
.
startParseOperation
();
InputStream
subtitleInputStream
=
new
ByteArrayInputStream
(
sampleHolder
.
data
.
array
(),
0
,
sampleHolder
.
size
);
subtitle
=
subtitleParser
.
parse
(
subtitleInputStream
,
null
,
sampleHolder
.
timeUs
);
syncNextEventIndex
(
timeUs
);
textRendererNeedsUpdate
=
true
;
}
else
if
(
result
==
SampleSource
.
END_OF_STREAM
)
{
}
else
if
(
result
==
SampleSource
.
END_OF_STREAM
)
{
inputStreamEnded
=
true
;
inputStreamEnded
=
true
;
}
}
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
resetSampleHolder
=
true
;
throw
new
ExoPlaybackException
(
e
);
throw
new
ExoPlaybackException
(
e
);
}
finally
{
if
(
resetSampleHolder
)
{
resetSampleData
();
}
}
}
}
}
...
@@ -208,7 +217,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -208,7 +217,9 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
protected
void
onDisabled
()
{
protected
void
onDisabled
()
{
source
.
disable
(
trackIndex
);
source
.
disable
(
trackIndex
);
subtitle
=
null
;
subtitle
=
null
;
resetSampleData
();
parserThread
.
quit
();
parserThread
=
null
;
parserHelper
=
null
;
clearTextRenderer
();
clearTextRenderer
();
}
}
...
@@ -255,12 +266,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -255,12 +266,6 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
:
(
subtitle
.
getEventTime
(
nextSubtitleEventIndex
));
:
(
subtitle
.
getEventTime
(
nextSubtitleEventIndex
));
}
}
private
void
resetSampleData
()
{
if
(
sampleHolder
.
data
!=
null
)
{
sampleHolder
.
data
.
position
(
0
);
}
}
private
void
updateTextRenderer
(
long
timeUs
)
{
private
void
updateTextRenderer
(
long
timeUs
)
{
String
text
=
subtitle
.
getText
(
timeUs
);
String
text
=
subtitle
.
getText
(
timeUs
);
log
(
"updateTextRenderer; text=: "
+
text
);
log
(
"updateTextRenderer; text=: "
+
text
);
...
@@ -296,7 +301,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
...
@@ -296,7 +301,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
private
void
log
(
String
logMessage
)
{
private
void
log
(
String
logMessage
)
{
if
(
VerboseLogUtil
.
isTagEnabled
(
TAG
))
{
if
(
VerboseLogUtil
.
isTagEnabled
(
TAG
))
{
Log
.
v
(
TAG
,
"type="
+
AdaptationSet
.
TYPE_TEXT
+
", "
+
logMessage
);
Log
.
v
(
TAG
,
logMessage
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer/text/webvtt/WebvttSubtitle.java
View file @
f4d3079b
...
@@ -79,15 +79,21 @@ public class WebvttSubtitle implements Subtitle {
...
@@ -79,15 +79,21 @@ public class WebvttSubtitle implements Subtitle {
@Override
@Override
public
String
getText
(
long
timeUs
)
{
public
String
getText
(
long
timeUs
)
{
StringBuilder
s
ubtitleS
tringBuilder
=
new
StringBuilder
();
StringBuilder
stringBuilder
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
cueTimesUs
.
length
;
i
+=
2
)
{
for
(
int
i
=
0
;
i
<
cueTimesUs
.
length
;
i
+=
2
)
{
if
((
cueTimesUs
[
i
]
<=
timeUs
)
&&
(
timeUs
<
cueTimesUs
[
i
+
1
]))
{
if
((
cueTimesUs
[
i
]
<=
timeUs
)
&&
(
timeUs
<
cueTimesUs
[
i
+
1
]))
{
s
ubtitleS
tringBuilder
.
append
(
cueText
[
i
/
2
]);
stringBuilder
.
append
(
cueText
[
i
/
2
]);
}
}
}
}
return
(
subtitleStringBuilder
.
length
()
>
0
)
?
subtitleStringBuilder
.
toString
()
:
null
;
int
stringLength
=
stringBuilder
.
length
();
if
(
stringLength
>
0
&&
stringBuilder
.
charAt
(
stringLength
-
1
)
==
'\n'
)
{
// Adjust the length to remove the trailing newline character.
stringLength
-=
1
;
}
return
stringLength
==
0
?
null
:
stringBuilder
.
substring
(
0
,
stringLength
);
}
}
}
}
library/src/main/java/com/google/android/exoplayer/upstream/DataSpec.java
View file @
f4d3079b
...
@@ -54,6 +54,15 @@ public final class DataSpec {
...
@@ -54,6 +54,15 @@ public final class DataSpec {
public
final
String
key
;
public
final
String
key
;
/**
/**
* Construct a {@link DataSpec} for the given uri and with {@link #key} set to null.
*
* @param uri {@link #uri}.
*/
public
DataSpec
(
Uri
uri
)
{
this
(
uri
,
0
,
C
.
LENGTH_UNBOUNDED
,
null
);
}
/**
* Construct a {@link DataSpec} for which {@link #uriIsFullStream} is true.
* Construct a {@link DataSpec} for which {@link #uriIsFullStream} is true.
*
*
* @param uri {@link #uri}.
* @param uri {@link #uri}.
...
...
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