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
0ead2af2
authored
Jan 21, 2021
by
Arnold Szabo
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add support for SSA (V4+) PrimaryColour style
parent
c40d1c66
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
75 additions
and
5 deletions
demos/main/src/main/assets/media.exolist.json
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java
library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java
library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java
demos/main/src/main/assets/media.exolist.json
View file @
0ead2af2
...
@@ -507,6 +507,13 @@
...
@@ -507,6 +507,13 @@
"subtitle_language"
:
"en"
"subtitle_language"
:
"en"
},
},
{
{
"name"
:
"SubStation Alpha colors"
,
"uri"
:
"https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/video-avc-baseline-480.mp4"
,
"subtitle_uri"
:
"https://drive.google.com/uc?export=download&id=13EdW4Qru-vQerUlwS_Ht5Cely_Tn0tQe"
,
"subtitle_mime_type"
:
"text/x-ssa"
,
"subtitle_language"
:
"en"
},
{
"name"
:
"MPEG-4 Timed Text"
,
"name"
:
"MPEG-4 Timed Text"
,
"uri"
:
"https://storage.googleapis.com/exoplayer-test-media-1/mp4/dizzy-with-tx3g.mp4"
"uri"
:
"https://storage.googleapis.com/exoplayer-test-media-1/mp4/dizzy-with-tx3g.mp4"
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
View file @
0ead2af2
...
@@ -19,6 +19,8 @@ import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_FRACTION;
...
@@ -19,6 +19,8 @@ import static com.google.android.exoplayer2.text.Cue.LINE_TYPE_FRACTION;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
android.text.Layout
;
import
android.text.Layout
;
import
android.text.SpannableString
;
import
android.text.style.ForegroundColorSpan
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Cue
;
...
@@ -301,8 +303,17 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
...
@@ -301,8 +303,17 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
SsaStyle
.
Overrides
styleOverrides
,
SsaStyle
.
Overrides
styleOverrides
,
float
screenWidth
,
float
screenWidth
,
float
screenHeight
)
{
float
screenHeight
)
{
Cue
.
Builder
cue
=
new
Cue
.
Builder
().
setText
(
text
);
SpannableString
spannableText
=
new
SpannableString
(
text
);
Cue
.
Builder
cue
=
new
Cue
.
Builder
().
setText
(
spannableText
);
// Apply primary color.
if
(
style
!=
null
)
{
if
(
style
.
primaryColor
!=
SsaStyle
.
SSA_COLOR_UNKNOWN
)
{
spannableText
.
setSpan
(
new
ForegroundColorSpan
(
style
.
primaryColor
),
0
,
spannableText
.
length
(),
SpannableString
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
// Apply alignment.
@SsaStyle
.
SsaAlignment
int
alignment
;
@SsaStyle
.
SsaAlignment
int
alignment
;
if
(
styleOverrides
.
alignment
!=
SsaStyle
.
SSA_ALIGNMENT_UNKNOWN
)
{
if
(
styleOverrides
.
alignment
!=
SsaStyle
.
SSA_ALIGNMENT_UNKNOWN
)
{
alignment
=
styleOverrides
.
alignment
;
alignment
=
styleOverrides
.
alignment
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java
View file @
0ead2af2
...
@@ -21,10 +21,12 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
...
@@ -21,10 +21,12 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import
android.graphics.PointF
;
import
android.graphics.PointF
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
androidx.annotation.ColorInt
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ColorParser
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.Documented
;
...
@@ -83,12 +85,16 @@ import java.util.regex.Pattern;
...
@@ -83,12 +85,16 @@ import java.util.regex.Pattern;
public
static
final
int
SSA_ALIGNMENT_TOP_CENTER
=
8
;
public
static
final
int
SSA_ALIGNMENT_TOP_CENTER
=
8
;
public
static
final
int
SSA_ALIGNMENT_TOP_RIGHT
=
9
;
public
static
final
int
SSA_ALIGNMENT_TOP_RIGHT
=
9
;
public
static
final
int
SSA_COLOR_UNKNOWN
=
-
1
;
public
final
String
name
;
public
final
String
name
;
@SsaAlignment
public
final
int
alignment
;
@SsaAlignment
public
final
int
alignment
;
@ColorInt
public
int
primaryColor
;
private
SsaStyle
(
String
name
,
@SsaAlignment
int
alignment
)
{
private
SsaStyle
(
String
name
,
@SsaAlignment
int
alignment
,
@ColorInt
int
primaryColor
)
{
this
.
name
=
name
;
this
.
name
=
name
;
this
.
alignment
=
alignment
;
this
.
alignment
=
alignment
;
this
.
primaryColor
=
primaryColor
;
}
}
@Nullable
@Nullable
...
@@ -105,7 +111,9 @@ import java.util.regex.Pattern;
...
@@ -105,7 +111,9 @@ import java.util.regex.Pattern;
}
}
try
{
try
{
return
new
SsaStyle
(
return
new
SsaStyle
(
styleValues
[
format
.
nameIndex
].
trim
(),
parseAlignment
(
styleValues
[
format
.
alignmentIndex
]));
styleValues
[
format
.
nameIndex
].
trim
(),
parseAlignment
(
styleValues
[
format
.
alignmentIndex
]),
parsePrimaryColor
(
styleValues
[
format
.
primaryColorIndex
]));
}
catch
(
RuntimeException
e
)
{
}
catch
(
RuntimeException
e
)
{
Log
.
w
(
TAG
,
"Skipping malformed 'Style:' line: '"
+
styleLine
+
"'"
,
e
);
Log
.
w
(
TAG
,
"Skipping malformed 'Style:' line: '"
+
styleLine
+
"'"
,
e
);
return
null
;
return
null
;
...
@@ -144,6 +152,16 @@ import java.util.regex.Pattern;
...
@@ -144,6 +152,16 @@ import java.util.regex.Pattern;
}
}
}
}
@ColorInt
private
static
int
parsePrimaryColor
(
String
primaryColorStr
)
{
try
{
return
ColorParser
.
parseSsaColor
(
primaryColorStr
);
}
catch
(
IllegalArgumentException
ex
)
{
Log
.
w
(
TAG
,
"Failed parsing color value: "
+
primaryColorStr
);
}
return
SSA_COLOR_UNKNOWN
;
}
/**
/**
* Represents a {@code Format:} line from the {@code [V4+ Styles]} section
* Represents a {@code Format:} line from the {@code [V4+ Styles]} section
*
*
...
@@ -154,11 +172,13 @@ import java.util.regex.Pattern;
...
@@ -154,11 +172,13 @@ import java.util.regex.Pattern;
public
final
int
nameIndex
;
public
final
int
nameIndex
;
public
final
int
alignmentIndex
;
public
final
int
alignmentIndex
;
public
final
int
primaryColorIndex
;
public
final
int
length
;
public
final
int
length
;
private
Format
(
int
nameIndex
,
int
alignmentIndex
,
int
length
)
{
private
Format
(
int
nameIndex
,
int
alignmentIndex
,
int
primaryColorIndex
,
int
length
)
{
this
.
nameIndex
=
nameIndex
;
this
.
nameIndex
=
nameIndex
;
this
.
alignmentIndex
=
alignmentIndex
;
this
.
alignmentIndex
=
alignmentIndex
;
this
.
primaryColorIndex
=
primaryColorIndex
;
this
.
length
=
length
;
this
.
length
=
length
;
}
}
...
@@ -171,6 +191,7 @@ import java.util.regex.Pattern;
...
@@ -171,6 +191,7 @@ import java.util.regex.Pattern;
public
static
Format
fromFormatLine
(
String
styleFormatLine
)
{
public
static
Format
fromFormatLine
(
String
styleFormatLine
)
{
int
nameIndex
=
C
.
INDEX_UNSET
;
int
nameIndex
=
C
.
INDEX_UNSET
;
int
alignmentIndex
=
C
.
INDEX_UNSET
;
int
alignmentIndex
=
C
.
INDEX_UNSET
;
int
primaryColorIndex
=
C
.
INDEX_UNSET
;
String
[]
keys
=
String
[]
keys
=
TextUtils
.
split
(
styleFormatLine
.
substring
(
SsaDecoder
.
FORMAT_LINE_PREFIX
.
length
()),
","
);
TextUtils
.
split
(
styleFormatLine
.
substring
(
SsaDecoder
.
FORMAT_LINE_PREFIX
.
length
()),
","
);
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
...
@@ -181,9 +202,14 @@ import java.util.regex.Pattern;
...
@@ -181,9 +202,14 @@ import java.util.regex.Pattern;
case
"alignment"
:
case
"alignment"
:
alignmentIndex
=
i
;
alignmentIndex
=
i
;
break
;
break
;
case
"primarycolour"
:
primaryColorIndex
=
i
;
break
;
}
}
}
}
return
nameIndex
!=
C
.
INDEX_UNSET
?
new
Format
(
nameIndex
,
alignmentIndex
,
keys
.
length
)
:
null
;
return
nameIndex
!=
C
.
INDEX_UNSET
?
new
Format
(
nameIndex
,
alignmentIndex
,
primaryColorIndex
,
keys
.
length
)
:
null
;
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/ColorParser.java
View file @
0ead2af2
...
@@ -67,6 +67,27 @@ public final class ColorParser {
...
@@ -67,6 +67,27 @@ public final class ColorParser {
return
parseColorInternal
(
colorExpression
,
true
);
return
parseColorInternal
(
colorExpression
,
true
);
}
}
/**
* Parses a SSA V4+ color expression.
*
* @param colorExpression The color expression.
* @return The parsed ARGB color.
*/
@ColorInt
public
static
int
parseSsaColor
(
String
colorExpression
)
{
// SSA V4+ color format is &HAABBGGRR.
if
(
colorExpression
.
length
()
!=
10
||
!
"&H"
.
equals
(
colorExpression
.
substring
(
0
,
2
)))
{
throw
new
IllegalArgumentException
();
}
// Convert &HAABBGGRR to #RRGGBBAA.
String
rgba
=
new
StringBuilder
()
.
append
(
colorExpression
.
substring
(
2
))
.
append
(
"#"
)
.
reverse
()
.
toString
();
return
parseColorInternal
(
rgba
,
true
);
}
@ColorInt
@ColorInt
private
static
int
parseColorInternal
(
String
colorExpression
,
boolean
alphaHasFloatFormat
)
{
private
static
int
parseColorInternal
(
String
colorExpression
,
boolean
alphaHasFloatFormat
)
{
Assertions
.
checkArgument
(!
TextUtils
.
isEmpty
(
colorExpression
));
Assertions
.
checkArgument
(!
TextUtils
.
isEmpty
(
colorExpression
));
...
...
library/core/src/test/java/com/google/android/exoplayer2/util/ColorParserTest.java
View file @
0ead2af2
...
@@ -18,8 +18,10 @@ package com.google.android.exoplayer2.util;
...
@@ -18,8 +18,10 @@ package com.google.android.exoplayer2.util;
import
static
android
.
graphics
.
Color
.
BLACK
;
import
static
android
.
graphics
.
Color
.
BLACK
;
import
static
android
.
graphics
.
Color
.
RED
;
import
static
android
.
graphics
.
Color
.
RED
;
import
static
android
.
graphics
.
Color
.
WHITE
;
import
static
android
.
graphics
.
Color
.
WHITE
;
import
static
android
.
graphics
.
Color
.
YELLOW
;
import
static
android
.
graphics
.
Color
.
argb
;
import
static
android
.
graphics
.
Color
.
argb
;
import
static
android
.
graphics
.
Color
.
parseColor
;
import
static
android
.
graphics
.
Color
.
parseColor
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
ColorParser
.
parseSsaColor
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
ColorParser
.
parseTtmlColor
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
ColorParser
.
parseTtmlColor
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
...
@@ -64,6 +66,9 @@ public final class ColorParserTest {
...
@@ -64,6 +66,9 @@ public final class ColorParserTest {
// Hex colors in ColorParser are RGBA, where-as {@link Color#parseColor} takes ARGB.
// Hex colors in ColorParser are RGBA, where-as {@link Color#parseColor} takes ARGB.
assertThat
(
parseTtmlColor
(
"#FFFFFF00"
)).
isEqualTo
(
parseColor
(
"#00FFFFFF"
));
assertThat
(
parseTtmlColor
(
"#FFFFFF00"
)).
isEqualTo
(
parseColor
(
"#00FFFFFF"
));
assertThat
(
parseTtmlColor
(
"#12345678"
)).
isEqualTo
(
parseColor
(
"#78123456"
));
assertThat
(
parseTtmlColor
(
"#12345678"
)).
isEqualTo
(
parseColor
(
"#78123456"
));
// SSA colors are in &HAABBGGRR format.
assertThat
(
parseSsaColor
(
"&HFF0000FF"
)).
isEqualTo
(
RED
);
assertThat
(
parseSsaColor
(
"&HFF00FFFF"
)).
isEqualTo
(
YELLOW
);
}
}
@Test
@Test
...
...
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