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
43e6e161
authored
Aug 24, 2016
by
Rik Heijdens
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Implemented PAC and Midrow code handling for EIA-608 captions
parent
f6fdcee9
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
292 additions
and
42 deletions
library/src/main/java/com/google/android/exoplayer2/text/eia608/Eia608Decoder.java
library/src/main/java/com/google/android/exoplayer2/text/eia608/Eia608Subtitle.java
library/src/main/java/com/google/android/exoplayer2/text/eia608/Eia608Decoder.java
View file @
43e6e161
...
@@ -15,14 +15,27 @@
...
@@ -15,14 +15,27 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
text
.
eia608
;
package
com
.
google
.
android
.
exoplayer2
.
text
.
eia608
;
import
android.text.TextUtils
;
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.SubtitleDecoder
;
import
com.google.android.exoplayer2.text.SubtitleDecoder
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.text.SubtitleInputBuffer
;
import
com.google.android.exoplayer2.text.SubtitleInputBuffer
;
import
com.google.android.exoplayer2.text.SubtitleOutputBuffer
;
import
com.google.android.exoplayer2.text.SubtitleOutputBuffer
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
android.graphics.Color
;
import
android.graphics.Typeface
;
import
android.text.Layout
;
import
android.text.SpannableStringBuilder
;
import
android.text.Spanned
;
import
android.text.style.BackgroundColorSpan
;
import
android.text.style.CharacterStyle
;
import
android.text.style.ForegroundColorSpan
;
import
android.text.style.StyleSpan
;
import
android.text.style.UnderlineSpan
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.TreeSet
;
import
java.util.TreeSet
;
...
@@ -86,6 +99,12 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -86,6 +99,12 @@ public final class Eia608Decoder implements SubtitleDecoder {
private
static
final
byte
CTRL_CARRIAGE_RETURN
=
0x2D
;
private
static
final
byte
CTRL_CARRIAGE_RETURN
=
0x2D
;
private
static
final
byte
CTRL_ERASE_NON_DISPLAYED_MEMORY
=
0x2E
;
private
static
final
byte
CTRL_ERASE_NON_DISPLAYED_MEMORY
=
0x2E
;
private
static
final
byte
CTRL_TAB_OFFSET_CHAN_1
=
0x17
;
private
static
final
byte
CTRL_TAB_OFFSET_CHAN_2
=
0x1F
;
private
static
final
byte
CTRL_TAB_OFFSET_1
=
0x21
;
private
static
final
byte
CTRL_TAB_OFFSET_2
=
0x22
;
private
static
final
byte
CTRL_TAB_OFFSET_3
=
0x23
;
private
static
final
byte
CTRL_BACKSPACE
=
0x21
;
private
static
final
byte
CTRL_BACKSPACE
=
0x21
;
private
static
final
byte
CTRL_MISC_CHAN_1
=
0x14
;
private
static
final
byte
CTRL_MISC_CHAN_1
=
0x14
;
...
@@ -159,13 +178,66 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -159,13 +178,66 @@ public final class Eia608Decoder implements SubtitleDecoder {
0xC5
,
0xE5
,
0xD8
,
0xF8
,
0x250C
,
0x2510
,
0x2514
,
0x2518
0xC5
,
0xE5
,
0xD8
,
0xF8
,
0x250C
,
0x2510
,
0x2514
,
0x2518
};
};
// Maps EIA-608 PAC row numbers to WebVTT cue line settings.
// Adapted from: https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#x1-preamble-address-code-pac
private
static
final
float
[]
CUE_LINE_MAP
=
new
float
[]
{
10.00f
,
// Row 1
15.33f
,
20.66f
,
26.00f
,
31.33f
,
36.66f
,
42.00f
,
47.33f
,
52.66f
,
58.00f
,
63.33f
,
68.66f
,
74.00f
,
79.33f
,
84.66f
// Row 15
};
// Maps EIA-608 PAC indents to WebVTT cue position values.
// Adapted from: https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#x1-preamble-address-code-pac
// Note that these cue position values may not give the intended result, unless the font size is set
// to allow for a maximum of 32 (or 41) characters per line.
private
static
final
float
[]
INDENT_MAP
=
new
float
[]
{
10.0f
,
// Indent 0/Column 1
20.0f
,
// Indent 4/Column 5
30.0f
,
// Indent 8/Column 9
40.0f
,
// Indent 12/Column 13
50.0f
,
// Indent 16/Column 17
60.0f
,
// Indent 20/Column 21
70.0f
,
// Indent 24/Column 25
80.0f
,
// Indent 28/Column 29
};
private
static
final
int
[]
COLOR_MAP
=
new
int
[]
{
Color
.
WHITE
,
Color
.
GREEN
,
Color
.
BLUE
,
Color
.
CYAN
,
Color
.
RED
,
Color
.
YELLOW
,
Color
.
MAGENTA
,
Color
.
BLACK
// Only used by Mid Row style changes, for PAC an value of 0x7 means italics.
};
// Transparency is defined in the two left most bytes of an integer.
private
static
final
int
TRANSPARENCY_MASK
=
0x80FFFFFF
;
private
static
final
int
STYLE_ITALIC
=
Typeface
.
ITALIC
;
private
static
final
float
DEFAULT_CUE_LINE
=
CUE_LINE_MAP
[
10
];
// Row 11
private
static
final
float
DEFAULT_INDENT
=
INDENT_MAP
[
0
];
// Indent 0
private
final
LinkedList
<
SubtitleInputBuffer
>
availableInputBuffers
;
private
final
LinkedList
<
SubtitleInputBuffer
>
availableInputBuffers
;
private
final
LinkedList
<
SubtitleOutputBuffer
>
availableOutputBuffers
;
private
final
LinkedList
<
SubtitleOutputBuffer
>
availableOutputBuffers
;
private
final
TreeSet
<
SubtitleInputBuffer
>
queuedInputBuffers
;
private
final
TreeSet
<
SubtitleInputBuffer
>
queuedInputBuffers
;
private
final
ParsableByteArray
ccData
;
private
final
ParsableByteArray
ccData
;
private
final
StringBuilder
captionStringBuilder
;
private
final
S
pannableS
tringBuilder
captionStringBuilder
;
private
long
playbackPositionUs
;
private
long
playbackPositionUs
;
...
@@ -173,9 +245,12 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -173,9 +245,12 @@ public final class Eia608Decoder implements SubtitleDecoder {
private
int
captionMode
;
private
int
captionMode
;
private
int
captionRowCount
;
private
int
captionRowCount
;
private
String
captionString
;
private
String
lastCaptionString
;
private
LinkedList
<
Cue
>
cues
;
private
HashMap
<
Integer
,
CharacterStyle
>
captionStyles
;
float
cueIndent
;
float
cueLine
;
int
tabOffset
;
private
boolean
repeatableControlSet
;
private
boolean
repeatableControlSet
;
private
byte
repeatableControlCc1
;
private
byte
repeatableControlCc1
;
...
@@ -194,10 +269,14 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -194,10 +269,14 @@ public final class Eia608Decoder implements SubtitleDecoder {
ccData
=
new
ParsableByteArray
();
ccData
=
new
ParsableByteArray
();
captionStringBuilder
=
new
StringBuilder
();
captionStringBuilder
=
new
SpannableStringBuilder
();
captionStyles
=
new
HashMap
<>();
setCaptionMode
(
CC_MODE_UNKNOWN
);
setCaptionMode
(
CC_MODE_UNKNOWN
);
captionRowCount
=
DEFAULT_CAPTIONS_ROW_COUNT
;
captionRowCount
=
DEFAULT_CAPTIONS_ROW_COUNT
;
cueIndent
=
DEFAULT_INDENT
;
cueLine
=
DEFAULT_CUE_LINE
;
tabOffset
=
0
;
}
}
@Override
@Override
...
@@ -253,11 +332,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -253,11 +332,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
decode
(
inputBuffer
);
decode
(
inputBuffer
);
// check if we have any caption updates to report
// check if we have any caption updates to report
if
(!
TextUtils
.
equals
(
captionString
,
lastCaptionString
))
{
if
(!
cues
.
isEmpty
())
{
lastCaptionString
=
captionString
;
if
(!
inputBuffer
.
isDecodeOnly
())
{
if
(!
inputBuffer
.
isDecodeOnly
())
{
SubtitleOutputBuffer
outputBuffer
=
availableOutputBuffers
.
pollFirst
();
SubtitleOutputBuffer
outputBuffer
=
availableOutputBuffers
.
pollFirst
();
outputBuffer
.
setContent
(
inputBuffer
.
timeUs
,
new
Eia608Subtitle
(
captionString
),
0
);
outputBuffer
.
setContent
(
inputBuffer
.
timeUs
,
new
Eia608Subtitle
(
cues
),
0
);
cues
=
new
LinkedList
<>();
releaseInputBuffer
(
inputBuffer
);
releaseInputBuffer
(
inputBuffer
);
return
outputBuffer
;
return
outputBuffer
;
}
}
...
@@ -284,9 +363,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -284,9 +363,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
setCaptionMode
(
CC_MODE_UNKNOWN
);
setCaptionMode
(
CC_MODE_UNKNOWN
);
captionRowCount
=
DEFAULT_CAPTIONS_ROW_COUNT
;
captionRowCount
=
DEFAULT_CAPTIONS_ROW_COUNT
;
playbackPositionUs
=
0
;
playbackPositionUs
=
0
;
captionStringBuilder
.
setLength
(
0
);
flushCaptionBuilder
();
captionString
=
null
;
cues
=
new
LinkedList
<>();
lastCaptionString
=
null
;
cueIndent
=
DEFAULT_INDENT
;
cueLine
=
DEFAULT_CUE_LINE
;
tabOffset
=
0
;
repeatableControlSet
=
false
;
repeatableControlSet
=
false
;
repeatableControlCc1
=
0
;
repeatableControlCc1
=
0
;
repeatableControlCc2
=
0
;
repeatableControlCc2
=
0
;
...
@@ -342,6 +423,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -342,6 +423,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
continue
;
continue
;
}
}
// Mid row changes.
if
((
ccData1
==
0x11
||
ccData1
==
0x19
)
&&
ccData2
>=
0x20
&&
ccData2
<=
0x2F
)
{
handleMidrowCode
(
ccData1
,
ccData2
);
}
// Control character.
// Control character.
if
(
ccData1
<
0x20
)
{
if
(
ccData1
<
0x20
)
{
isRepeatableControl
=
handleCtrl
(
ccData1
,
ccData2
);
isRepeatableControl
=
handleCtrl
(
ccData1
,
ccData2
);
...
@@ -360,7 +446,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -360,7 +446,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
repeatableControlSet
=
false
;
repeatableControlSet
=
false
;
}
}
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_PAINT_ON
)
{
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_PAINT_ON
)
{
captionString
=
getDisplayCaption
();
buildCue
();
}
}
}
}
}
}
...
@@ -380,8 +466,9 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -380,8 +466,9 @@ public final class Eia608Decoder implements SubtitleDecoder {
if
(
isMiscCode
(
cc1
,
cc2
))
{
if
(
isMiscCode
(
cc1
,
cc2
))
{
handleMiscCode
(
cc2
);
handleMiscCode
(
cc2
);
}
else
if
(
isPreambleAddressCode
(
cc1
,
cc2
))
{
}
else
if
(
isPreambleAddressCode
(
cc1
,
cc2
))
{
// TODO: Add better handling of this with specific positioning.
handlePreambleCode
(
cc1
,
cc2
);
maybeAppendNewline
();
}
else
if
(
isTabOffset
(
cc1
,
cc2
))
{
handleTabOffset
(
cc2
);
}
}
return
isRepeatableControl
;
return
isRepeatableControl
;
}
}
...
@@ -414,32 +501,197 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -414,32 +501,197 @@ public final class Eia608Decoder implements SubtitleDecoder {
switch
(
cc2
)
{
switch
(
cc2
)
{
case
CTRL_ERASE_DISPLAYED_MEMORY:
case
CTRL_ERASE_DISPLAYED_MEMORY:
captionString
=
null
;
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_PAINT_ON
)
{
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_PAINT_ON
)
{
captionStringBuilder
.
setLength
(
0
);
flushCaptionBuilder
(
);
}
}
return
;
return
;
case
CTRL_ERASE_NON_DISPLAYED_MEMORY:
case
CTRL_ERASE_NON_DISPLAYED_MEMORY:
captionStringBuilder
.
setLength
(
0
);
flushCaptionBuilder
(
);
return
;
return
;
case
CTRL_END_OF_CAPTION:
case
CTRL_END_OF_CAPTION:
captionString
=
getDisplayCaption
();
buildCue
();
captionStringBuilder
.
setLength
(
0
);
flushCaptionBuilder
(
);
return
;
return
;
case
CTRL_CARRIAGE_RETURN:
case
CTRL_CARRIAGE_RETURN:
maybeAppendNewline
();
maybeAppendNewline
();
return
;
return
;
case
CTRL_BACKSPACE:
case
CTRL_BACKSPACE:
if
(
captionStringBuilder
.
length
()
>
0
)
{
backspace
();
captionStringBuilder
.
setLength
(
captionStringBuilder
.
length
()
-
1
);
}
return
;
return
;
}
}
}
}
private
void
handlePreambleCode
(
byte
cc1
,
byte
cc2
)
{
// For PAC layout see: https://en.wikipedia.org/wiki/EIA-608#Control_commands
applySpan
();
// Apply any spans.
// Parse the "next row down" flag.
boolean
nextRowDown
=
(
cc2
&
0x20
)
!=
0
;
if
(
nextRowDown
)
{
// TODO: We should create a new cue instead, this may cause issues when
// the new line receives it's own PAC which we ignore currently.
// As a result of that the new line will be positioned directly below the
// previous line.
maybeAppendNewline
();
}
// Go through the bits, starting with the last bit - the underline flag:
boolean
underline
=
(
cc2
&
0x1
)
!=
0
;
if
(
underline
)
{
captionStyles
.
put
(
getSpanStartIndex
(),
new
UnderlineSpan
());
}
// Next, parse the attribute bits:
int
attribute
=
cc2
>>
1
&
0xF
;
if
(
attribute
>=
0x0
&&
attribute
<
0x7
)
{
// Attribute is a foreground color
captionStyles
.
put
(
getSpanStartIndex
(),
new
ForegroundColorSpan
(
COLOR_MAP
[
attribute
]));
}
else
if
(
attribute
==
0x7
)
{
// Attribute is "italics"
captionStyles
.
put
(
getSpanStartIndex
(),
new
StyleSpan
(
STYLE_ITALIC
));
}
else
if
(
attribute
>=
0x8
&&
attribute
<=
0xF
)
{
// Attribute is an indent
if
(
cueIndent
==
DEFAULT_INDENT
)
{
// Only update the indent, if it's the default indent.
// This is not conform the spec, but otherwise indentations may be off
// because we don't create a new cue when we see the nextRowDown flag.
cueIndent
=
INDENT_MAP
[
attribute
&
0x7
];
}
}
// Parse the row bits
int
row
=
cc1
&
0x7
;
if
(
row
>=
0x4
)
{
// Extended Preamble Code
row
=
row
&
0x3
;
switch
(
row
)
{
case
0x0
:
// Row 14 or 15
cueLine
=
CUE_LINE_MAP
[
13
];
break
;
case
0x1
:
// Row 5 or 6
cueLine
=
CUE_LINE_MAP
[
4
];
break
;
case
0x2
:
// Row 7 or 8
cueLine
=
CUE_LINE_MAP
[
7
];
break
;
case
0x3
:
// Row 9 or 10
cueLine
=
CUE_LINE_MAP
[
8
];
break
;
}
}
else
{
// Regular Preamble Code
switch
(
row
)
{
case
0x0
:
// Row 11 (Default)
cueLine
=
CUE_LINE_MAP
[
10
];
break
;
case
0x1
:
// Row 1 (Top)
cueLine
=
CUE_LINE_MAP
[
0
];
break
;
case
0x2
:
// Row 4 (Top)
cueLine
=
CUE_LINE_MAP
[
3
];
break
;
case
0x3
:
// Row 12 or 13 (Bottom)
cueLine
=
CUE_LINE_MAP
[
11
];
break
;
}
}
}
private
void
handleMidrowCode
(
byte
cc1
,
byte
cc2
)
{
boolean
transparentOrUnderline
=
(
cc2
&
0x1
)
!=
0
;
int
attribute
=
cc2
>>
1
&
0xF
;
if
((
cc1
&
0x1
)
!=
0
)
{
// Background Color
captionStyles
.
put
(
getSpanStartIndex
(),
new
BackgroundColorSpan
(
transparentOrUnderline
?
COLOR_MAP
[
attribute
]
&
TRANSPARENCY_MASK
:
COLOR_MAP
[
attribute
]));
}
else
{
// Foreground color
captionStyles
.
put
(
getSpanStartIndex
(),
new
ForegroundColorSpan
(
COLOR_MAP
[
attribute
]));
if
(
transparentOrUnderline
)
{
// Text should be underlined
captionStyles
.
put
(
getSpanStartIndex
(),
new
UnderlineSpan
());
}
}
}
private
void
handleTabOffset
(
byte
cc2
)
{
// Formula for tab offset handling adapted from:
// https://dvcs.w3.org/hg/text-tracks/raw-file/default/608toVTT/608toVTT.html#x1-preamble-address-code-pac
// We're ignoring any tab offsets that do not occur at the beginning of a new cue.
// This is not conform the spec, but works in most cases.
if
(
captionStringBuilder
.
length
()
==
0
)
{
switch
(
cc2
)
{
case
CTRL_TAB_OFFSET_1:
tabOffset
++;
break
;
case
CTRL_TAB_OFFSET_2:
tabOffset
+=
2
;
break
;
case
CTRL_TAB_OFFSET_3:
tabOffset
+=
3
;
break
;
}
}
}
private
int
getSpanStartIndex
()
{
return
captionStringBuilder
.
length
()
>
0
?
captionStringBuilder
.
length
()
-
1
:
0
;
}
/**
* Applies a Span to the SpannableStringBuilder.
*/
private
void
applySpan
()
{
// Check if we have to do anything.
if
(
captionStyles
.
size
()
==
0
)
{
return
;
}
for
(
Integer
startIndex
:
captionStyles
.
keySet
())
{
CharacterStyle
captionStyle
=
captionStyles
.
get
(
startIndex
);
captionStringBuilder
.
setSpan
(
captionStyle
,
startIndex
,
captionStringBuilder
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
captionStyles
.
remove
(
startIndex
);
}
}
/**
* Builds a cue from whatever is in the SpannableStringBuilder now.
*/
private
void
buildCue
()
{
applySpan
();
// Apply Spans
CharSequence
captionString
=
getDisplayCaption
();
if
(
captionString
!=
null
)
{
cueIndent
=
tabOffset
*
2.5f
+
cueIndent
;
tabOffset
=
0
;
Cue
cue
=
new
Cue
(
captionString
,
Layout
.
Alignment
.
ALIGN_NORMAL
,
cueLine
/
100
,
Cue
.
LINE_TYPE_FRACTION
,
Cue
.
ANCHOR_TYPE_START
,
cueIndent
/
100
,
Cue
.
TYPE_UNSET
,
Cue
.
DIMEN_UNSET
);
cues
.
add
(
cue
);
if
(
captionMode
==
CC_MODE_POP_ON
)
{
captionStringBuilder
.
clear
();
captionStringBuilder
.
clearSpans
();
cueLine
=
DEFAULT_CUE_LINE
;
}
cueIndent
=
DEFAULT_INDENT
;
}
}
private
void
flushCaptionBuilder
()
{
captionStringBuilder
.
clear
();
captionStringBuilder
.
clearSpans
();
}
private
void
backspace
()
{
private
void
backspace
()
{
if
(
captionStringBuilder
.
length
()
>
0
)
{
if
(
captionStringBuilder
.
length
()
>
0
)
{
captionStringBuilder
.
setLength
(
captionStringBuilder
.
length
()
-
1
);
captionStringBuilder
.
replace
(
captionStringBuilder
.
length
()
-
1
,
captionStringBuilder
.
length
(),
""
);
}
}
}
}
...
@@ -450,7 +702,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -450,7 +702,7 @@ public final class Eia608Decoder implements SubtitleDecoder {
}
}
}
}
private
String
getDisplayCaption
()
{
private
CharSequence
getDisplayCaption
()
{
int
buildLength
=
captionStringBuilder
.
length
();
int
buildLength
=
captionStringBuilder
.
length
();
if
(
buildLength
==
0
)
{
if
(
buildLength
==
0
)
{
return
null
;
return
null
;
...
@@ -463,19 +715,19 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -463,19 +715,19 @@ public final class Eia608Decoder implements SubtitleDecoder {
int
endIndex
=
endsWithNewline
?
buildLength
-
1
:
buildLength
;
int
endIndex
=
endsWithNewline
?
buildLength
-
1
:
buildLength
;
if
(
captionMode
!=
CC_MODE_ROLL_UP
)
{
if
(
captionMode
!=
CC_MODE_ROLL_UP
)
{
return
captionStringBuilder
.
sub
string
(
0
,
endIndex
);
return
captionStringBuilder
.
sub
Sequence
(
0
,
endIndex
);
}
}
int
startIndex
=
0
;
int
startIndex
=
0
;
int
searchBackwardFromIndex
=
endIndex
;
int
searchBackwardFromIndex
=
endIndex
;
for
(
int
i
=
0
;
i
<
captionRowCount
&&
searchBackwardFromIndex
!=
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
captionRowCount
&&
searchBackwardFromIndex
!=
-
1
;
i
++)
{
searchBackwardFromIndex
=
captionStringBuilder
.
lastIndexOf
(
"\n"
,
searchBackwardFromIndex
-
1
);
searchBackwardFromIndex
=
captionStringBuilder
.
toString
().
lastIndexOf
(
"\n"
,
searchBackwardFromIndex
-
1
);
}
}
if
(
searchBackwardFromIndex
!=
-
1
)
{
if
(
searchBackwardFromIndex
!=
-
1
)
{
startIndex
=
searchBackwardFromIndex
+
1
;
startIndex
=
searchBackwardFromIndex
+
1
;
}
}
captionStringBuilder
.
delete
(
0
,
startIndex
);
captionStringBuilder
.
delete
(
0
,
startIndex
);
return
captionStringBuilder
.
sub
string
(
0
,
endIndex
-
startIndex
);
return
captionStringBuilder
.
sub
Sequence
(
0
,
endIndex
-
startIndex
);
}
}
private
void
setCaptionMode
(
int
captionMode
)
{
private
void
setCaptionMode
(
int
captionMode
)
{
...
@@ -485,10 +737,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -485,10 +737,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
this
.
captionMode
=
captionMode
;
this
.
captionMode
=
captionMode
;
// Clear the working memory.
// Clear the working memory.
captionStringBuilder
.
setLength
(
0
);
captionStringBuilder
.
clear
();
captionStringBuilder
.
clearSpans
();
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_UNKNOWN
)
{
if
(
captionMode
==
CC_MODE_ROLL_UP
||
captionMode
==
CC_MODE_UNKNOWN
)
{
// When switching to roll-up or unknown, we also need to clear the caption.
// When switching to roll-up or unknown, we also need to clear the caption.
c
aptionString
=
null
;
c
ues
=
new
LinkedList
<>()
;
}
}
}
}
...
@@ -525,6 +778,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
...
@@ -525,6 +778,11 @@ public final class Eia608Decoder implements SubtitleDecoder {
return
cc1
>=
0x10
&&
cc1
<=
0x1F
;
return
cc1
>=
0x10
&&
cc1
<=
0x1F
;
}
}
private
static
boolean
isTabOffset
(
byte
cc1
,
byte
cc2
)
{
return
(
cc1
==
CTRL_TAB_OFFSET_CHAN_1
||
cc1
==
CTRL_TAB_OFFSET_CHAN_2
)
&&
(
cc2
>=
0x21
&&
cc2
<=
0x23
);
}
/**
/**
* Inspects an sei message to determine whether it contains EIA-608.
* Inspects an sei message to determine whether it contains EIA-608.
* <p>
* <p>
...
...
library/src/main/java/com/google/android/exoplayer2/text/eia608/Eia608Subtitle.java
View file @
43e6e161
...
@@ -15,10 +15,9 @@
...
@@ -15,10 +15,9 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
text
.
eia608
;
package
com
.
google
.
android
.
exoplayer2
.
text
.
eia608
;
import
android.text.TextUtils
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Subtitle
;
import
com.google.android.exoplayer2.text.Subtitle
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
/**
/**
...
@@ -26,13 +25,10 @@ import java.util.List;
...
@@ -26,13 +25,10 @@ import java.util.List;
*/
*/
/* package */
final
class
Eia608Subtitle
implements
Subtitle
{
/* package */
final
class
Eia608Subtitle
implements
Subtitle
{
private
final
String
text
;
private
final
List
<
Cue
>
cues
;
/**
public
Eia608Subtitle
(
List
<
Cue
>
cues
)
{
* @param text The subtitle text.
this
.
cues
=
cues
;
*/
public
Eia608Subtitle
(
String
text
)
{
this
.
text
=
text
;
}
}
@Override
@Override
...
@@ -52,11 +48,7 @@ import java.util.List;
...
@@ -52,11 +48,7 @@ import java.util.List;
@Override
@Override
public
List
<
Cue
>
getCues
(
long
timeUs
)
{
public
List
<
Cue
>
getCues
(
long
timeUs
)
{
if
(
TextUtils
.
isEmpty
(
text
))
{
return
cues
;
return
Collections
.
emptyList
();
}
else
{
return
Collections
.
singletonList
(
new
Cue
(
text
));
}
}
}
}
}
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