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
0391e73a
authored
Oct 30, 2019
by
Arnold Szabo
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Adding support for overlapping subtitles
parent
57916774
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
55 additions
and
35 deletions
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
View file @
0391e73a
...
...
@@ -24,7 +24,6 @@ import com.google.android.exoplayer2.text.SimpleSubtitleDecoder;
import
com.google.android.exoplayer2.text.Subtitle
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.LongArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
...
...
@@ -82,19 +81,15 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
@Override
protected
Subtitle
decode
(
byte
[]
bytes
,
int
length
,
boolean
reset
)
{
ArrayList
<
Cue
>
cues
=
new
ArrayList
<>();
L
ongArray
cueTimesUs
=
new
LongArray
();
ArrayList
<
List
<
Cue
>
>
cues
=
new
ArrayList
<>();
L
ist
<
Long
>
cueTimesUs
=
new
ArrayList
<>
();
ParsableByteArray
data
=
new
ParsableByteArray
(
bytes
,
length
);
if
(!
haveInitializationData
)
{
parseHeader
(
data
);
}
parseEventBody
(
data
,
cues
,
cueTimesUs
);
Cue
[]
cuesArray
=
new
Cue
[
cues
.
size
()];
cues
.
toArray
(
cuesArray
);
long
[]
cueTimesUsArray
=
cueTimesUs
.
toArray
();
return
new
SsaSubtitle
(
cuesArray
,
cueTimesUsArray
);
return
new
SsaSubtitle
(
cues
,
cueTimesUs
);
}
/**
...
...
@@ -126,7 +121,7 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
* @param cues A list to which parsed cues will be added.
* @param cueTimesUs An array to which parsed cue timestamps will be added.
*/
private
void
parseEventBody
(
ParsableByteArray
data
,
List
<
Cue
>
cues
,
LongArray
cueTimesUs
)
{
private
void
parseEventBody
(
ParsableByteArray
data
,
List
<
List
<
Cue
>>
cues
,
List
<
Long
>
cueTimesUs
)
{
String
currentLine
;
while
((
currentLine
=
data
.
readLine
())
!=
null
)
{
if
(!
haveInitializationData
&&
currentLine
.
startsWith
(
FORMAT_LINE_PREFIX
))
{
...
...
@@ -180,7 +175,7 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
* @param cues A list to which parsed cues will be added.
* @param cueTimesUs An array to which parsed cue timestamps will be added.
*/
private
void
parseDialogueLine
(
String
dialogueLine
,
List
<
Cue
>
cues
,
LongArray
cueTimesUs
)
{
private
void
parseDialogueLine
(
String
dialogueLine
,
List
<
List
<
Cue
>>
cues
,
List
<
Long
>
cueTimesUs
)
{
if
(
formatKeyCount
==
0
)
{
Log
.
w
(
TAG
,
"Skipping dialogue line before complete format: "
+
dialogueLine
);
return
;
...
...
@@ -222,7 +217,7 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
cue
=
new
Cue
(
text
,
/* textAlignment */
null
,
1
-
position
.
second
/
playResY
,
position
.
second
/
playResY
,
Cue
.
LINE_TYPE_FRACTION
,
Cue
.
ANCHOR_TYPE_START
,
position
.
first
/
playResX
,
...
...
@@ -232,12 +227,44 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
cue
=
new
Cue
(
text
);
}
cues
.
add
(
cue
);
cueTimesUs
.
add
(
startTimeUs
);
int
startTimeIndex
=
insertToCueTimes
(
cueTimesUs
,
startTimeUs
);
List
<
Cue
>
startCueList
=
new
ArrayList
<>();
if
(
startTimeIndex
!=
0
)
{
startCueList
.
addAll
(
cues
.
get
(
startTimeIndex
-
1
));
}
cues
.
add
(
startTimeIndex
,
startCueList
);
if
(
endTimeUs
!=
C
.
TIME_UNSET
)
{
cues
.
add
(
Cue
.
EMPTY
);
cueTimesUs
.
add
(
endTimeUs
);
int
endTimeIndex
=
insertToCueTimes
(
cueTimesUs
,
endTimeUs
);
List
<
Cue
>
endList
=
new
ArrayList
<>(
cues
.
get
(
endTimeIndex
-
1
));
cues
.
add
(
endTimeIndex
,
endList
);
int
i
=
startTimeIndex
;
do
{
cues
.
get
(
i
).
add
(
cue
);
i
++;
}
while
(
i
!=
endTimeIndex
);
}
}
/**
* Insert the given cue time into the given array keeping the array sorted.
*
* @param cueTimes The array with sorted cue times
* @param timeUs The cue time to be inserted
* @return The index where the cue time was inserted
*/
private
static
int
insertToCueTimes
(
List
<
Long
>
cueTimes
,
long
timeUs
)
{
for
(
int
i
=
cueTimes
.
size
()
-
1
;
i
>=
0
;
i
--)
{
if
(
cueTimes
.
get
(
i
)
<=
timeUs
)
{
cueTimes
.
add
(
i
+
1
,
timeUs
);
return
i
+
1
;
}
}
cueTimes
.
add
(
0
,
timeUs
);
return
0
;
}
/**
...
...
@@ -246,7 +273,7 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
* @param timeString The string to parse.
* @return The parsed timestamp in microseconds.
*/
p
ublic
static
long
parseTimecodeUs
(
String
timeString
)
{
p
rivate
static
long
parseTimecodeUs
(
String
timeString
)
{
Matcher
matcher
=
SSA_TIMECODE_PATTERN
.
matcher
(
timeString
);
if
(!
matcher
.
matches
())
{
return
C
.
TIME_UNSET
;
...
...
@@ -258,21 +285,15 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
return
timestampUs
;
}
/**
* Parses an SSA position attribute.
*
* @param line The string to parse.
* @return The parsed position in a pair (x,y).
*/
@Nullable
public
static
Pair
<
Float
,
Float
>
parsePosition
(
String
line
)
{
public
static
Pair
<
Float
,
Float
>
parsePosition
(
String
line
){
Matcher
matcher
=
SSA_POSITION_PATTERN
.
matcher
(
line
);
if
(!
matcher
.
find
())
{
if
(!
matcher
.
find
())
{
return
null
;
}
float
x
=
Float
.
parseFloat
(
matcher
.
group
(
1
));
float
y
=
Float
.
parseFloat
(
matcher
.
group
(
3
));
return
new
Pair
<>(
x
,
y
);
return
new
Pair
<>(
x
,
y
);
}
}
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaSubtitle.java
View file @
0391e73a
...
...
@@ -28,14 +28,14 @@ import java.util.List;
*/
/* package */
final
class
SsaSubtitle
implements
Subtitle
{
private
final
Cue
[]
cues
;
private
final
long
[]
cueTimesUs
;
private
final
List
<
List
<
Cue
>>
cues
;
private
final
List
<
Long
>
cueTimesUs
;
/**
* @param cues The cues in the subtitle.
* @param cueTimesUs The cue times, in microseconds.
*/
public
SsaSubtitle
(
Cue
[]
cues
,
long
[]
cueTimesUs
)
{
public
SsaSubtitle
(
List
<
List
<
Cue
>>
cues
,
List
<
Long
>
cueTimesUs
)
{
this
.
cues
=
cues
;
this
.
cueTimesUs
=
cueTimesUs
;
}
...
...
@@ -43,30 +43,29 @@ import java.util.List;
@Override
public
int
getNextEventTimeIndex
(
long
timeUs
)
{
int
index
=
Util
.
binarySearchCeil
(
cueTimesUs
,
timeUs
,
false
,
false
);
return
index
<
cueTimesUs
.
length
?
index
:
C
.
INDEX_UNSET
;
return
index
<
cueTimesUs
.
size
()
?
index
:
C
.
INDEX_UNSET
;
}
@Override
public
int
getEventTimeCount
()
{
return
cueTimesUs
.
length
;
return
cueTimesUs
.
size
()
;
}
@Override
public
long
getEventTime
(
int
index
)
{
Assertions
.
checkArgument
(
index
>=
0
);
Assertions
.
checkArgument
(
index
<
cueTimesUs
.
length
);
return
cueTimesUs
[
index
]
;
Assertions
.
checkArgument
(
index
<
cueTimesUs
.
size
()
);
return
cueTimesUs
.
get
(
index
)
;
}
@Override
public
List
<
Cue
>
getCues
(
long
timeUs
)
{
int
index
=
Util
.
binarySearchFloor
(
cueTimesUs
,
timeUs
,
true
,
false
);
if
(
index
==
-
1
||
cues
[
index
]
==
Cue
.
EMPTY
)
{
if
(
index
==
-
1
||
cues
.
get
(
index
).
isEmpty
()
)
{
// timeUs is earlier than the start of the first cue, or we have an empty cue.
return
Collections
.
emptyList
();
}
else
{
return
Collections
.
singletonList
(
cues
[
index
]
);
return
cues
.
get
(
index
);
}
}
}
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