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
02c7525f
authored
Aug 11, 2015
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Remove custom VTT logic.
parent
dbaeecc4
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
32 additions
and
131 deletions
library/src/androidTest/assets/webvtt/live_typical
library/src/androidTest/assets/webvtt/typical
library/src/androidTest/assets/webvtt/typical_with_identifiers
library/src/androidTest/assets/webvtt/typical_with_tags
library/src/androidTest/java/com/google/android/exoplayer/text/webvtt/WebvttParserTest.java
library/src/main/java/com/google/android/exoplayer/C.java
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleMediaChunk.java
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
library/src/main/java/com/google/android/exoplayer/text/webvtt/WebvttParser.java
library/src/androidTest/assets/webvtt/live_typical
View file @
02c7525f
EXO-HEADER=OFFSET:-5000000
WEBVTT
X-TIMESTAMP-MAP=LOCAL:00:00.000,MPEGTS:450000
00:00.000 --> 00:01.234
This is the first subtitle.
...
...
library/src/androidTest/assets/webvtt/typical
View file @
02c7525f
WEBVTT # This comment is allowed
X-TIMESTAMP-MAP=LOCAL:00:00.000,MPEGTS:450000
00:00.000 --> 00:01.234
This is the first subtitle.
...
...
library/src/androidTest/assets/webvtt/typical_with_identifiers
View file @
02c7525f
WEBVTT
X-TIMESTAMP-MAP=LOCAL:00:00.000,MPEGTS:450000
1
00:00.000 --> 00:01.234
...
...
library/src/androidTest/assets/webvtt/typical_with_tags
View file @
02c7525f
WEBVTT
X-TIMESTAMP-MAP=LOCAL:00:00.000,MPEGTS:450000
00:00.000 --> 00:01.234
This is the <i>first</i> subtitle.
...
...
library/src/androidTest/java/com/google/android/exoplayer/text/webvtt/WebvttParserTest.java
View file @
02c7525f
...
...
@@ -53,21 +53,20 @@ public class WebvttParserTest extends InstrumentationTestCase {
WebvttSubtitle
subtitle
=
parser
.
parse
(
inputStream
,
C
.
UTF8_NAME
,
0
);
// test start time and event count
long
startTimeUs
=
5000000
;
assertEquals
(
startTimeUs
,
subtitle
.
getStartTime
());
assertEquals
(
0
,
subtitle
.
getStartTime
());
assertEquals
(
4
,
subtitle
.
getEventTimeCount
());
// test first cue
assertEquals
(
startTimeUs
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
0
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
"This is the first subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
0
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
1234000
,
subtitle
.
getEventTime
(
1
));
assertEquals
(
1234000
,
subtitle
.
getEventTime
(
1
));
// test second cue
assertEquals
(
startTimeUs
+
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
"This is the second subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
2
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
3456000
,
subtitle
.
getEventTime
(
3
));
assertEquals
(
3456000
,
subtitle
.
getEventTime
(
3
));
}
public
void
testParseTypicalWithIdsWebvttFile
()
throws
IOException
{
...
...
@@ -78,21 +77,20 @@ public class WebvttParserTest extends InstrumentationTestCase {
WebvttSubtitle
subtitle
=
parser
.
parse
(
inputStream
,
C
.
UTF8_NAME
,
0
);
// test start time and event count
long
startTimeUs
=
5000000
;
assertEquals
(
startTimeUs
,
subtitle
.
getStartTime
());
assertEquals
(
0
,
subtitle
.
getStartTime
());
assertEquals
(
4
,
subtitle
.
getEventTimeCount
());
// test first cue
assertEquals
(
startTimeUs
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
0
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
"This is the first subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
0
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
1234000
,
subtitle
.
getEventTime
(
1
));
assertEquals
(
1234000
,
subtitle
.
getEventTime
(
1
));
// test second cue
assertEquals
(
startTimeUs
+
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
"This is the second subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
2
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
3456000
,
subtitle
.
getEventTime
(
3
));
assertEquals
(
3456000
,
subtitle
.
getEventTime
(
3
));
}
public
void
testParseTypicalWithTagsWebvttFile
()
throws
IOException
{
...
...
@@ -103,33 +101,32 @@ public class WebvttParserTest extends InstrumentationTestCase {
WebvttSubtitle
subtitle
=
parser
.
parse
(
inputStream
,
C
.
UTF8_NAME
,
0
);
// test start time and event count
long
startTimeUs
=
5000000
;
assertEquals
(
startTimeUs
,
subtitle
.
getStartTime
());
assertEquals
(
0
,
subtitle
.
getStartTime
());
assertEquals
(
8
,
subtitle
.
getEventTimeCount
());
// test first cue
assertEquals
(
startTimeUs
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
0
,
subtitle
.
getEventTime
(
0
));
assertEquals
(
"This is the first subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
0
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
1234000
,
subtitle
.
getEventTime
(
1
));
assertEquals
(
1234000
,
subtitle
.
getEventTime
(
1
));
// test second cue
assertEquals
(
startTimeUs
+
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
2345000
,
subtitle
.
getEventTime
(
2
));
assertEquals
(
"This is the second subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
2
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
3456000
,
subtitle
.
getEventTime
(
3
));
assertEquals
(
3456000
,
subtitle
.
getEventTime
(
3
));
// test third cue
assertEquals
(
startTimeUs
+
4000000
,
subtitle
.
getEventTime
(
4
));
assertEquals
(
4000000
,
subtitle
.
getEventTime
(
4
));
assertEquals
(
"This is the third subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
4
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
5000000
,
subtitle
.
getEventTime
(
5
));
assertEquals
(
5000000
,
subtitle
.
getEventTime
(
5
));
// test fourth cue
assertEquals
(
startTimeUs
+
6000000
,
subtitle
.
getEventTime
(
6
));
assertEquals
(
6000000
,
subtitle
.
getEventTime
(
6
));
assertEquals
(
"This is the <fourth> &subtitle."
,
subtitle
.
getCues
(
subtitle
.
getEventTime
(
6
)).
get
(
0
).
text
.
toString
());
assertEquals
(
startTimeUs
+
7000000
,
subtitle
.
getEventTime
(
7
));
assertEquals
(
7000000
,
subtitle
.
getEventTime
(
7
));
}
public
void
testParseLiveTypicalWebvttFile
()
throws
IOException
{
...
...
library/src/main/java/com/google/android/exoplayer/C.java
View file @
02c7525f
...
...
@@ -90,18 +90,6 @@ public final class C {
*/
public
static
final
int
RESULT_END_OF_INPUT
=
-
1
;
/**
* A prefix for custom ExoPlayer WebVTT headers.
*/
public
static
final
String
WEBVTT_EXO_HEADER
=
"EXO-HEADER"
;
/**
* An element of a custom ExoPlayer WebVTT header. An {@code WEBVTT_OFFSET + value} element can
* be added to a custom ExoPlayer WebVTT header to specify an offset time (in microseconds) that
* should be added to the embedded MPEGTS value.
*/
public
static
final
String
WEBVTT_EXO_HEADER_OFFSET
=
"OFFSET:"
;
private
C
()
{}
}
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java
View file @
02c7525f
...
...
@@ -109,7 +109,7 @@ public final class SingleSampleChunkSource implements ChunkSource {
private
SingleSampleMediaChunk
initChunk
()
{
return
new
SingleSampleMediaChunk
(
dataSource
,
dataSpec
,
Chunk
.
TRIGGER_UNSPECIFIED
,
format
,
0
,
durationUs
,
0
,
true
,
mediaFormat
,
null
,
null
);
durationUs
,
0
,
true
,
mediaFormat
,
null
);
}
}
library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleMediaChunk.java
View file @
02c7525f
...
...
@@ -20,7 +20,6 @@ import com.google.android.exoplayer.MediaFormat;
import
com.google.android.exoplayer.drm.DrmInitData
;
import
com.google.android.exoplayer.upstream.DataSource
;
import
com.google.android.exoplayer.upstream.DataSpec
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
com.google.android.exoplayer.util.Util
;
import
java.io.IOException
;
...
...
@@ -32,9 +31,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
private
final
MediaFormat
sampleFormat
;
private
final
DrmInitData
sampleDrmInitData
;
private
final
byte
[]
headerData
;
private
boolean
writtenHeader
;
private
volatile
int
bytesLoaded
;
private
volatile
boolean
loadCanceled
;
...
...
@@ -51,18 +47,14 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
* @param sampleFormat The format of the sample.
* @param sampleDrmInitData The {@link DrmInitData} for the sample. Null if the sample is not drm
* protected.
* @param headerData Custom header data for the sample. May be null. If set, the header data is
* prepended to the sample data. It is not reflected in the values returned by
* {@link #bytesLoaded()}.
*/
public
SingleSampleMediaChunk
(
DataSource
dataSource
,
DataSpec
dataSpec
,
int
trigger
,
Format
format
,
long
startTimeUs
,
long
endTimeUs
,
int
chunkIndex
,
boolean
isLastChunk
,
MediaFormat
sampleFormat
,
DrmInitData
sampleDrmInitData
,
byte
[]
headerData
)
{
MediaFormat
sampleFormat
,
DrmInitData
sampleDrmInitData
)
{
super
(
dataSource
,
dataSpec
,
trigger
,
format
,
startTimeUs
,
endTimeUs
,
chunkIndex
,
isLastChunk
,
true
);
this
.
sampleFormat
=
sampleFormat
;
this
.
sampleDrmInitData
=
sampleDrmInitData
;
this
.
headerData
=
headerData
;
}
@Override
...
...
@@ -95,13 +87,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
@SuppressWarnings
(
"NonAtomicVolatileUpdate"
)
@Override
public
void
load
()
throws
IOException
,
InterruptedException
{
if
(!
writtenHeader
)
{
if
(
headerData
!=
null
)
{
getOutput
().
sampleData
(
new
ParsableByteArray
(
headerData
),
headerData
.
length
);
}
writtenHeader
=
true
;
}
DataSpec
loadDataSpec
=
Util
.
getRemainderDataSpec
(
dataSpec
,
bytesLoaded
);
try
{
// Create and open the input.
...
...
@@ -113,9 +98,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
result
=
getOutput
().
sampleData
(
dataSource
,
Integer
.
MAX_VALUE
,
true
);
}
int
sampleSize
=
bytesLoaded
;
if
(
headerData
!=
null
)
{
sampleSize
+=
headerData
.
length
;
}
getOutput
().
sampleMetadata
(
startTimeUs
,
C
.
SAMPLE_FLAG_SYNC
,
sampleSize
,
0
,
null
);
}
finally
{
dataSource
.
close
();
...
...
library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java
View file @
02c7525f
...
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer
.
dash
;
import
com.google.android.exoplayer.BehindLiveWindowException
;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.TimeRange
;
import
com.google.android.exoplayer.TrackInfo
;
...
...
@@ -104,7 +103,6 @@ public class DashChunkSource implements ChunkSource {
private
final
FormatEvaluator
formatEvaluator
;
private
final
Evaluation
evaluation
;
private
final
Clock
systemClock
;
private
final
StringBuilder
headerBuilder
;
private
final
long
liveEdgeLatencyUs
;
private
final
long
elapsedRealtimeOffsetUs
;
private
final
int
maxWidth
;
...
...
@@ -258,7 +256,6 @@ public class DashChunkSource implements ChunkSource {
this
.
eventHandler
=
eventHandler
;
this
.
eventListener
=
eventListener
;
this
.
evaluation
=
new
Evaluation
();
this
.
headerBuilder
=
new
StringBuilder
();
this
.
seekRangeValues
=
new
long
[
2
];
drmInitData
=
getDrmInitData
(
currentManifest
,
adaptationSetIndex
);
...
...
@@ -645,19 +642,9 @@ public class DashChunkSource implements ChunkSource {
long
sampleOffsetUs
=
representation
.
periodStartMs
*
1000
-
representation
.
presentationTimeOffsetUs
;
if
(
representation
.
format
.
mimeType
.
equals
(
MimeTypes
.
TEXT_VTT
))
{
if
(
representationHolder
.
vttHeaderOffsetUs
!=
sampleOffsetUs
)
{
// Update the VTT header.
headerBuilder
.
setLength
(
0
);
headerBuilder
.
append
(
C
.
WEBVTT_EXO_HEADER
).
append
(
"="
)
.
append
(
C
.
WEBVTT_EXO_HEADER_OFFSET
).
append
(
sampleOffsetUs
)
.
append
(
"\n"
);
representationHolder
.
vttHeader
=
headerBuilder
.
toString
().
getBytes
();
representationHolder
.
vttHeaderOffsetUs
=
sampleOffsetUs
;
}
return
new
SingleSampleMediaChunk
(
dataSource
,
dataSpec
,
Chunk
.
TRIGGER_INITIAL
,
representation
.
format
,
startTimeUs
,
endTimeUs
,
absoluteSegmentNum
,
isLastSegment
,
MediaFormat
.
createTextFormat
(
MimeTypes
.
TEXT_VTT
,
representation
.
format
.
language
),
null
,
representationHolder
.
vttHeader
);
MediaFormat
.
createTextFormat
(
MimeTypes
.
TEXT_VTT
,
representation
.
format
.
language
),
null
);
}
else
{
return
new
ContainerMediaChunk
(
dataSource
,
dataSpec
,
trigger
,
representation
.
format
,
startTimeUs
,
endTimeUs
,
absoluteSegmentNum
,
isLastSegment
,
sampleOffsetUs
,
...
...
@@ -741,8 +728,6 @@ public class DashChunkSource implements ChunkSource {
public
MediaFormat
format
;
public
int
segmentNumShift
;
public
long
vttHeaderOffsetUs
;
public
byte
[]
vttHeader
;
public
RepresentationHolder
(
Representation
representation
,
ChunkExtractorWrapper
extractorWrapper
)
{
...
...
library/src/main/java/com/google/android/exoplayer/text/webvtt/WebvttParser.java
View file @
02c7525f
...
...
@@ -38,12 +38,10 @@ import java.util.regex.Pattern;
* <p>
* @see <a href="http://dev.w3.org/html5/webvtt">WebVTT specification</a>
*/
public
class
WebvttParser
implements
SubtitleParser
{
public
final
class
WebvttParser
implements
SubtitleParser
{
private
static
final
String
TAG
=
"WebvttParser"
;
private
static
final
long
SAMPLING_RATE
=
90
;
private
static
final
String
WEBVTT_FILE_HEADER_STRING
=
"^\uFEFF?WEBVTT((\\u0020|\u0009).*)?$"
;
private
static
final
Pattern
WEBVTT_FILE_HEADER
=
Pattern
.
compile
(
WEBVTT_FILE_HEADER_STRING
);
...
...
@@ -62,10 +60,6 @@ public class WebvttParser implements SubtitleParser {
private
static
final
String
WEBVTT_CUE_SETTING_STRING
=
"\\S*:\\S*"
;
private
static
final
Pattern
WEBVTT_CUE_SETTING
=
Pattern
.
compile
(
WEBVTT_CUE_SETTING_STRING
);
private
static
final
Pattern
MEDIA_TIMESTAMP_OFFSET
=
Pattern
.
compile
(
C
.
WEBVTT_EXO_HEADER_OFFSET
+
"\\-?\\d+"
);
private
static
final
Pattern
MEDIA_TIMESTAMP
=
Pattern
.
compile
(
"MPEGTS:\\d+"
);
private
static
final
String
NON_NUMERIC_STRING
=
".*[^0-9].*"
;
private
final
StringBuilder
textBuilder
;
...
...
@@ -94,33 +88,13 @@ public class WebvttParser implements SubtitleParser {
public
final
WebvttSubtitle
parse
(
InputStream
inputStream
,
String
inputEncoding
,
long
startTimeUs
)
throws
IOException
{
ArrayList
<
WebvttCue
>
subtitles
=
new
ArrayList
<>();
long
mediaTimestampUs
=
startTimeUs
;
long
mediaTimestampOffsetUs
=
0
;
BufferedReader
webvttData
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
,
C
.
UTF8_NAME
));
String
line
;
// file should start with "WEBVTT"
on the first line or "EXO-HEADER"
// file should start with "WEBVTT"
line
=
webvttData
.
readLine
();
if
(
line
==
null
)
{
throw
new
ParserException
(
"Expected WEBVTT or EXO-HEADER. Got null"
);
}
if
(
line
.
startsWith
(
C
.
WEBVTT_EXO_HEADER
))
{
// parse the timestamp offset, if present
Matcher
matcher
=
MEDIA_TIMESTAMP_OFFSET
.
matcher
(
line
);
if
(
matcher
.
find
())
{
mediaTimestampOffsetUs
=
Long
.
parseLong
(
matcher
.
group
().
substring
(
7
));
}
// read the next line, which should now be WEBVTT
line
=
webvttData
.
readLine
();
if
(
line
==
null
)
{
throw
new
ParserException
(
"Expected WEBVTT. Got null"
);
}
}
if
(!
WEBVTT_FILE_HEADER
.
matcher
(
line
).
matches
())
{
if
(
line
==
null
||
!
WEBVTT_FILE_HEADER
.
matcher
(
line
).
matches
())
{
throw
new
ParserException
(
"Expected WEBVTT. Got "
+
line
);
}
...
...
@@ -135,21 +109,11 @@ public class WebvttParser implements SubtitleParser {
break
;
}
Matcher
matcher
=
WEBVTT_METADATA_HEADER
.
matcher
(
line
);
if
(!
matcher
.
find
())
{
handleNoncompliantLine
(
line
);
}
if
(
line
.
startsWith
(
"X-TIMESTAMP-MAP"
))
{
// parse the media timestamp
Matcher
timestampMatcher
=
MEDIA_TIMESTAMP
.
matcher
(
line
);
if
(!
timestampMatcher
.
find
())
{
throw
new
ParserException
(
"X-TIMESTAMP-MAP doesn't contain media timestamp: "
+
line
);
}
else
{
mediaTimestampUs
=
(
Long
.
parseLong
(
timestampMatcher
.
group
().
substring
(
7
))
*
1000
)
/
SAMPLING_RATE
+
mediaTimestampOffsetUs
;
if
(
strictParsing
)
{
Matcher
matcher
=
WEBVTT_METADATA_HEADER
.
matcher
(
line
);
if
(!
matcher
.
find
())
{
throw
new
ParserException
(
"Unexpected line: "
+
line
);
}
mediaTimestampUs
=
getAdjustedStartTime
(
mediaTimestampUs
);
}
}
...
...
@@ -178,7 +142,7 @@ public class WebvttParser implements SubtitleParser {
if
(!
matcher
.
find
())
{
throw
new
ParserException
(
"Expected cue start time: "
+
line
);
}
else
{
startTime
=
parseTimestampUs
(
matcher
.
group
())
+
mediaTimestamp
Us
;
startTime
=
parseTimestampUs
(
matcher
.
group
())
+
startTime
Us
;
}
// parse end timestamp
...
...
@@ -187,7 +151,7 @@ public class WebvttParser implements SubtitleParser {
throw
new
ParserException
(
"Expected cue end time: "
+
line
);
}
else
{
endTimeString
=
matcher
.
group
();
endTime
=
parseTimestampUs
(
endTimeString
)
+
mediaTimestamp
Us
;
endTime
=
parseTimestampUs
(
endTimeString
)
+
startTime
Us
;
}
// parse the (optional) cue setting list
...
...
@@ -249,7 +213,7 @@ public class WebvttParser implements SubtitleParser {
subtitles
.
add
(
cue
);
}
return
new
WebvttSubtitle
(
subtitles
,
mediaTimestamp
Us
);
return
new
WebvttSubtitle
(
subtitles
,
startTime
Us
);
}
@Override
...
...
@@ -257,16 +221,6 @@ public class WebvttParser implements SubtitleParser {
return
MimeTypes
.
TEXT_VTT
.
equals
(
mimeType
);
}
protected
long
getAdjustedStartTime
(
long
startTimeUs
)
{
return
startTimeUs
;
}
protected
void
handleNoncompliantLine
(
String
line
)
throws
ParserException
{
if
(
strictParsing
)
{
throw
new
ParserException
(
"Unexpected line: "
+
line
);
}
}
private
static
int
parseIntPercentage
(
String
s
)
throws
NumberFormatException
{
if
(!
s
.
endsWith
(
"%"
))
{
throw
new
NumberFormatException
(
s
+
" doesn't end with '%'"
);
...
...
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