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
a8c0a1bd
authored
May 09, 2022
by
Ian Baker
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #10150 from egor-n:dev-v2-8435-outlinecolour
PiperOrigin-RevId: 444787307
parents
c25a3af0
2bd348ef
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
130 additions
and
6 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java
library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java
testdata/src/test/assets/media/ssa/style_outline_color
testdata/src/test/assets/media/ssa/style_colors → testdata/src/test/assets/media/ssa/style_primary_color
library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java
View file @
a8c0a1bd
...
@@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
...
@@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull;
import
android.graphics.Typeface
;
import
android.graphics.Typeface
;
import
android.text.Layout
;
import
android.text.Layout
;
import
android.text.SpannableString
;
import
android.text.SpannableString
;
import
android.text.style.BackgroundColorSpan
;
import
android.text.style.ForegroundColorSpan
;
import
android.text.style.ForegroundColorSpan
;
import
android.text.style.StrikethroughSpan
;
import
android.text.style.StrikethroughSpan
;
import
android.text.style.StyleSpan
;
import
android.text.style.StyleSpan
;
...
@@ -319,6 +320,13 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
...
@@ -319,6 +320,13 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
/* end= */
spannableText
.
length
(),
/* end= */
spannableText
.
length
(),
SpannableString
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
SpannableString
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
if
(
style
.
borderStyle
==
SsaStyle
.
SSA_BORDER_STYLE_BOX
&&
style
.
outlineColor
!=
null
)
{
spannableText
.
setSpan
(
new
BackgroundColorSpan
(
style
.
outlineColor
),
/* start= */
0
,
/* end= */
spannableText
.
length
(),
SpannableString
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
}
if
(
style
.
fontSize
!=
Cue
.
DIMEN_UNSET
&&
screenHeight
!=
Cue
.
DIMEN_UNSET
)
{
if
(
style
.
fontSize
!=
Cue
.
DIMEN_UNSET
&&
screenHeight
!=
Cue
.
DIMEN_UNSET
)
{
cue
.
setTextSize
(
cue
.
setTextSize
(
style
.
fontSize
/
screenHeight
,
Cue
.
TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING
);
style
.
fontSize
/
screenHeight
,
Cue
.
TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING
);
...
...
library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java
View file @
a8c0a1bd
...
@@ -92,32 +92,64 @@ import java.util.regex.Pattern;
...
@@ -92,32 +92,64 @@ 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
;
/**
* The SSA/ASS BorderStyle.
*
* <p>Allowed values:
*
* <ul>
* <li>{@link #SSA_BORDER_STYLE_UNKNOWN}
* <li>{@link #SSA_BORDER_STYLE_OUTLINE}
* <li>{@link #SSA_BORDER_STYLE_BOX}
* </ul>
*/
@Target
(
TYPE_USE
)
@IntDef
({
SSA_BORDER_STYLE_UNKNOWN
,
SSA_BORDER_STYLE_OUTLINE
,
SSA_BORDER_STYLE_BOX
,
})
@Documented
@Retention
(
SOURCE
)
public
@interface
SsaBorderStyle
{}
// The numbering follows the ASS (v4+) spec.
public
static
final
int
SSA_BORDER_STYLE_UNKNOWN
=
-
1
;
public
static
final
int
SSA_BORDER_STYLE_OUTLINE
=
1
;
public
static
final
int
SSA_BORDER_STYLE_BOX
=
3
;
public
final
String
name
;
public
final
String
name
;
public
final
@SsaAlignment
int
alignment
;
public
final
@SsaAlignment
int
alignment
;
@Nullable
@ColorInt
public
final
Integer
primaryColor
;
@Nullable
@ColorInt
public
final
Integer
primaryColor
;
@Nullable
@ColorInt
public
final
Integer
outlineColor
;
public
final
float
fontSize
;
public
final
float
fontSize
;
public
final
boolean
bold
;
public
final
boolean
bold
;
public
final
boolean
italic
;
public
final
boolean
italic
;
public
final
boolean
underline
;
public
final
boolean
underline
;
public
final
boolean
strikeout
;
public
final
boolean
strikeout
;
public
final
@SsaBorderStyle
int
borderStyle
;
private
SsaStyle
(
private
SsaStyle
(
String
name
,
String
name
,
@SsaAlignment
int
alignment
,
@SsaAlignment
int
alignment
,
@Nullable
@ColorInt
Integer
primaryColor
,
@Nullable
@ColorInt
Integer
primaryColor
,
@Nullable
@ColorInt
Integer
outlineColor
,
float
fontSize
,
float
fontSize
,
boolean
bold
,
boolean
bold
,
boolean
italic
,
boolean
italic
,
boolean
underline
,
boolean
underline
,
boolean
strikeout
)
{
boolean
strikeout
,
@SsaBorderStyle
int
borderStyle
)
{
this
.
name
=
name
;
this
.
name
=
name
;
this
.
alignment
=
alignment
;
this
.
alignment
=
alignment
;
this
.
primaryColor
=
primaryColor
;
this
.
primaryColor
=
primaryColor
;
this
.
outlineColor
=
outlineColor
;
this
.
fontSize
=
fontSize
;
this
.
fontSize
=
fontSize
;
this
.
bold
=
bold
;
this
.
bold
=
bold
;
this
.
italic
=
italic
;
this
.
italic
=
italic
;
this
.
underline
=
underline
;
this
.
underline
=
underline
;
this
.
strikeout
=
strikeout
;
this
.
strikeout
=
strikeout
;
this
.
borderStyle
=
borderStyle
;
}
}
@Nullable
@Nullable
...
@@ -141,6 +173,9 @@ import java.util.regex.Pattern;
...
@@ -141,6 +173,9 @@ import java.util.regex.Pattern;
format
.
primaryColorIndex
!=
C
.
INDEX_UNSET
format
.
primaryColorIndex
!=
C
.
INDEX_UNSET
?
parseColor
(
styleValues
[
format
.
primaryColorIndex
].
trim
())
?
parseColor
(
styleValues
[
format
.
primaryColorIndex
].
trim
())
:
null
,
:
null
,
format
.
outlineColorIndex
!=
C
.
INDEX_UNSET
?
parseColor
(
styleValues
[
format
.
outlineColorIndex
].
trim
())
:
null
,
format
.
fontSizeIndex
!=
C
.
INDEX_UNSET
format
.
fontSizeIndex
!=
C
.
INDEX_UNSET
?
parseFontSize
(
styleValues
[
format
.
fontSizeIndex
].
trim
())
?
parseFontSize
(
styleValues
[
format
.
fontSizeIndex
].
trim
())
:
Cue
.
DIMEN_UNSET
,
:
Cue
.
DIMEN_UNSET
,
...
@@ -151,7 +186,10 @@ import java.util.regex.Pattern;
...
@@ -151,7 +186,10 @@ import java.util.regex.Pattern;
format
.
underlineIndex
!=
C
.
INDEX_UNSET
format
.
underlineIndex
!=
C
.
INDEX_UNSET
&&
parseBooleanValue
(
styleValues
[
format
.
underlineIndex
].
trim
()),
&&
parseBooleanValue
(
styleValues
[
format
.
underlineIndex
].
trim
()),
format
.
strikeoutIndex
!=
C
.
INDEX_UNSET
format
.
strikeoutIndex
!=
C
.
INDEX_UNSET
&&
parseBooleanValue
(
styleValues
[
format
.
strikeoutIndex
].
trim
()));
&&
parseBooleanValue
(
styleValues
[
format
.
strikeoutIndex
].
trim
()),
format
.
borderStyleIndex
!=
C
.
INDEX_UNSET
?
parseBorderStyle
(
styleValues
[
format
.
borderStyleIndex
].
trim
())
:
SSA_BORDER_STYLE_UNKNOWN
);
}
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
;
...
@@ -189,6 +227,30 @@ import java.util.regex.Pattern;
...
@@ -189,6 +227,30 @@ import java.util.regex.Pattern;
}
}
}
}
private
static
@SsaBorderStyle
int
parseBorderStyle
(
String
borderStyleStr
)
{
try
{
@SsaBorderStyle
int
borderStyle
=
Integer
.
parseInt
(
borderStyleStr
.
trim
());
if
(
isValidBorderStyle
(
borderStyle
))
{
return
borderStyle
;
}
}
catch
(
NumberFormatException
e
)
{
// Swallow the exception and return UNKNOWN below.
}
Log
.
w
(
TAG
,
"Ignoring unknown BorderStyle: "
+
borderStyleStr
);
return
SSA_BORDER_STYLE_UNKNOWN
;
}
private
static
boolean
isValidBorderStyle
(
@SsaBorderStyle
int
alignment
)
{
switch
(
alignment
)
{
case
SSA_BORDER_STYLE_OUTLINE:
case
SSA_BORDER_STYLE_BOX:
return
true
;
case
SSA_BORDER_STYLE_UNKNOWN:
default
:
return
false
;
}
}
/**
/**
* Parses a SSA V4+ color expression.
* Parses a SSA V4+ color expression.
*
*
...
@@ -257,31 +319,37 @@ import java.util.regex.Pattern;
...
@@ -257,31 +319,37 @@ 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
primaryColorIndex
;
public
final
int
outlineColorIndex
;
public
final
int
fontSizeIndex
;
public
final
int
fontSizeIndex
;
public
final
int
boldIndex
;
public
final
int
boldIndex
;
public
final
int
italicIndex
;
public
final
int
italicIndex
;
public
final
int
underlineIndex
;
public
final
int
underlineIndex
;
public
final
int
strikeoutIndex
;
public
final
int
strikeoutIndex
;
public
final
int
borderStyleIndex
;
public
final
int
length
;
public
final
int
length
;
private
Format
(
private
Format
(
int
nameIndex
,
int
nameIndex
,
int
alignmentIndex
,
int
alignmentIndex
,
int
primaryColorIndex
,
int
primaryColorIndex
,
int
outlineColorIndex
,
int
fontSizeIndex
,
int
fontSizeIndex
,
int
boldIndex
,
int
boldIndex
,
int
italicIndex
,
int
italicIndex
,
int
underlineIndex
,
int
underlineIndex
,
int
strikeoutIndex
,
int
strikeoutIndex
,
int
borderStyleIndex
,
int
length
)
{
int
length
)
{
this
.
nameIndex
=
nameIndex
;
this
.
nameIndex
=
nameIndex
;
this
.
alignmentIndex
=
alignmentIndex
;
this
.
alignmentIndex
=
alignmentIndex
;
this
.
primaryColorIndex
=
primaryColorIndex
;
this
.
primaryColorIndex
=
primaryColorIndex
;
this
.
outlineColorIndex
=
outlineColorIndex
;
this
.
fontSizeIndex
=
fontSizeIndex
;
this
.
fontSizeIndex
=
fontSizeIndex
;
this
.
boldIndex
=
boldIndex
;
this
.
boldIndex
=
boldIndex
;
this
.
italicIndex
=
italicIndex
;
this
.
italicIndex
=
italicIndex
;
this
.
underlineIndex
=
underlineIndex
;
this
.
underlineIndex
=
underlineIndex
;
this
.
strikeoutIndex
=
strikeoutIndex
;
this
.
strikeoutIndex
=
strikeoutIndex
;
this
.
borderStyleIndex
=
borderStyleIndex
;
this
.
length
=
length
;
this
.
length
=
length
;
}
}
...
@@ -295,11 +363,13 @@ import java.util.regex.Pattern;
...
@@ -295,11 +363,13 @@ import java.util.regex.Pattern;
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
;
int
primaryColorIndex
=
C
.
INDEX_UNSET
;
int
outlineColorIndex
=
C
.
INDEX_UNSET
;
int
fontSizeIndex
=
C
.
INDEX_UNSET
;
int
fontSizeIndex
=
C
.
INDEX_UNSET
;
int
boldIndex
=
C
.
INDEX_UNSET
;
int
boldIndex
=
C
.
INDEX_UNSET
;
int
italicIndex
=
C
.
INDEX_UNSET
;
int
italicIndex
=
C
.
INDEX_UNSET
;
int
underlineIndex
=
C
.
INDEX_UNSET
;
int
underlineIndex
=
C
.
INDEX_UNSET
;
int
strikeoutIndex
=
C
.
INDEX_UNSET
;
int
strikeoutIndex
=
C
.
INDEX_UNSET
;
int
borderStyleIndex
=
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
++)
{
...
@@ -313,6 +383,9 @@ import java.util.regex.Pattern;
...
@@ -313,6 +383,9 @@ import java.util.regex.Pattern;
case
"primarycolour"
:
case
"primarycolour"
:
primaryColorIndex
=
i
;
primaryColorIndex
=
i
;
break
;
break
;
case
"outlinecolour"
:
outlineColorIndex
=
i
;
break
;
case
"fontsize"
:
case
"fontsize"
:
fontSizeIndex
=
i
;
fontSizeIndex
=
i
;
break
;
break
;
...
@@ -328,6 +401,9 @@ import java.util.regex.Pattern;
...
@@ -328,6 +401,9 @@ import java.util.regex.Pattern;
case
"strikeout"
:
case
"strikeout"
:
strikeoutIndex
=
i
;
strikeoutIndex
=
i
;
break
;
break
;
case
"borderstyle"
:
borderStyleIndex
=
i
;
break
;
}
}
}
}
return
nameIndex
!=
C
.
INDEX_UNSET
return
nameIndex
!=
C
.
INDEX_UNSET
...
@@ -335,11 +411,13 @@ import java.util.regex.Pattern;
...
@@ -335,11 +411,13 @@ import java.util.regex.Pattern;
nameIndex
,
nameIndex
,
alignmentIndex
,
alignmentIndex
,
primaryColorIndex
,
primaryColorIndex
,
outlineColorIndex
,
fontSizeIndex
,
fontSizeIndex
,
boldIndex
,
boldIndex
,
italicIndex
,
italicIndex
,
underlineIndex
,
underlineIndex
,
strikeoutIndex
,
strikeoutIndex
,
borderStyleIndex
,
keys
.
length
)
keys
.
length
)
:
null
;
:
null
;
}
}
...
...
library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java
View file @
a8c0a1bd
...
@@ -48,7 +48,8 @@ public final class SsaDecoderTest {
...
@@ -48,7 +48,8 @@ public final class SsaDecoderTest {
private
static
final
String
INVALID_TIMECODES
=
"media/ssa/invalid_timecodes"
;
private
static
final
String
INVALID_TIMECODES
=
"media/ssa/invalid_timecodes"
;
private
static
final
String
INVALID_POSITIONS
=
"media/ssa/invalid_positioning"
;
private
static
final
String
INVALID_POSITIONS
=
"media/ssa/invalid_positioning"
;
private
static
final
String
POSITIONS_WITHOUT_PLAYRES
=
"media/ssa/positioning_without_playres"
;
private
static
final
String
POSITIONS_WITHOUT_PLAYRES
=
"media/ssa/positioning_without_playres"
;
private
static
final
String
STYLE_COLORS
=
"media/ssa/style_colors"
;
private
static
final
String
STYLE_PRIMARY_COLOR
=
"media/ssa/style_primary_color"
;
private
static
final
String
STYLE_OUTLINE_COLOR
=
"media/ssa/style_outline_color"
;
private
static
final
String
STYLE_FONT_SIZE
=
"media/ssa/style_font_size"
;
private
static
final
String
STYLE_FONT_SIZE
=
"media/ssa/style_font_size"
;
private
static
final
String
STYLE_BOLD_ITALIC
=
"media/ssa/style_bold_italic"
;
private
static
final
String
STYLE_BOLD_ITALIC
=
"media/ssa/style_bold_italic"
;
private
static
final
String
STYLE_UNDERLINE
=
"media/ssa/style_underline"
;
private
static
final
String
STYLE_UNDERLINE
=
"media/ssa/style_underline"
;
...
@@ -297,9 +298,10 @@ public final class SsaDecoderTest {
...
@@ -297,9 +298,10 @@ public final class SsaDecoderTest {
}
}
@Test
@Test
public
void
decode
Colors
()
throws
IOException
{
public
void
decode
PrimaryColor
()
throws
IOException
{
SsaDecoder
decoder
=
new
SsaDecoder
();
SsaDecoder
decoder
=
new
SsaDecoder
();
byte
[]
bytes
=
TestUtil
.
getByteArray
(
ApplicationProvider
.
getApplicationContext
(),
STYLE_COLORS
);
byte
[]
bytes
=
TestUtil
.
getByteArray
(
ApplicationProvider
.
getApplicationContext
(),
STYLE_PRIMARY_COLOR
);
Subtitle
subtitle
=
decoder
.
decode
(
bytes
,
bytes
.
length
,
false
);
Subtitle
subtitle
=
decoder
.
decode
(
bytes
,
bytes
.
length
,
false
);
assertThat
(
subtitle
.
getEventTimeCount
()).
isEqualTo
(
14
);
assertThat
(
subtitle
.
getEventTimeCount
()).
isEqualTo
(
14
);
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
...
@@ -345,6 +347,26 @@ public final class SsaDecoderTest {
...
@@ -345,6 +347,26 @@ public final class SsaDecoderTest {
}
}
@Test
@Test
public
void
decodeOutlineColor
()
throws
IOException
{
SsaDecoder
decoder
=
new
SsaDecoder
();
byte
[]
bytes
=
TestUtil
.
getByteArray
(
ApplicationProvider
.
getApplicationContext
(),
STYLE_OUTLINE_COLOR
);
Subtitle
subtitle
=
decoder
.
decode
(
bytes
,
bytes
.
length
,
false
);
assertThat
(
subtitle
.
getEventTimeCount
()).
isEqualTo
(
4
);
Spanned
firstCueText
=
(
Spanned
)
Iterables
.
getOnlyElement
(
subtitle
.
getCues
(
subtitle
.
getEventTime
(
0
))).
text
;
SpannedSubject
.
assertThat
(
firstCueText
)
.
hasBackgroundColorSpanBetween
(
0
,
firstCueText
.
length
())
.
withColor
(
Color
.
BLUE
);
// OutlineColour should be treated as background only when BorderStyle=3
Spanned
secondCueText
=
(
Spanned
)
Iterables
.
getOnlyElement
(
subtitle
.
getCues
(
subtitle
.
getEventTime
(
2
))).
text
;
SpannedSubject
.
assertThat
(
secondCueText
)
.
hasNoBackgroundColorSpanBetween
(
0
,
secondCueText
.
length
());
}
@Test
public
void
decodeFontSize
()
throws
IOException
{
public
void
decodeFontSize
()
throws
IOException
{
SsaDecoder
decoder
=
new
SsaDecoder
();
SsaDecoder
decoder
=
new
SsaDecoder
();
byte
[]
bytes
=
byte
[]
bytes
=
...
...
testdata/src/test/assets/media/ssa/style_outline_color
0 → 100644
View file @
a8c0a1bd
[Script Info]
Title: OutlineColour settings
Script Type: V4.00+
PlayResX: 1280
PlayResY: 720
[V4+ Styles]
Format: Name ,OutlineColour,BorderStyle
Style: OutlineColourStyleBlue ,&H00FF0000 ,3
Style: OutlineColourStyleIgnored ,&H00FF0000 ,1
[Events]
Format: Start ,End ,Style ,Text
Dialogue: 0:00:01.00,0:00:02.00,OutlineColourStyleBlue ,Line with BLUE (&H00FF0000) outline.
Dialogue: 0:00:03.00,0:00:04.00,OutlineColourStyleIgnored ,Line with ignored outline because BorderStyle is not 3.
testdata/src/test/assets/media/ssa/style_
colors
→
testdata/src/test/assets/media/ssa/style_
primary_color
View file @
a8c0a1bd
[Script Info]
[Script Info]
Title:
Coloring
Title:
PrimaryColour settings
Script Type: V4.00+
Script Type: V4.00+
PlayResX: 1280
PlayResX: 1280
PlayResY: 720
PlayResY: 720
...
...
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