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
925a907c
authored
May 09, 2022
by
Ian Baker
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #9967 from jruesga:cea708-handle-multiple-service-blocks
PiperOrigin-RevId: 444816821
parents
a5adc8d7
42301243
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
144 additions
and
132 deletions
library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java
library/extractor/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Decoder.java
View file @
925a907c
...
...
@@ -143,7 +143,7 @@ public final class Cea708Decoder extends CeaDecoder {
private
static
final
int
CHARACTER_UPPER_LEFT_BORDER
=
0x7F
;
private
final
ParsableByteArray
ccData
;
private
final
ParsableBitArray
serviceBlockPacket
;
private
final
ParsableBitArray
captionChannelPacketData
;
private
int
previousSequenceNumber
;
// TODO: Use isWideAspectRatio in decoding.
@SuppressWarnings
({
"unused"
,
"FieldCanBeLocal"
})
...
...
@@ -161,7 +161,7 @@ public final class Cea708Decoder extends CeaDecoder {
public
Cea708Decoder
(
int
accessibilityChannel
,
@Nullable
List
<
byte
[]>
initializationData
)
{
ccData
=
new
ParsableByteArray
();
serviceBlockPacket
=
new
ParsableBitArray
();
captionChannelPacketData
=
new
ParsableBitArray
();
previousSequenceNumber
=
C
.
INDEX_UNSET
;
selectedServiceNumber
=
accessibilityChannel
==
Format
.
NO_VALUE
?
1
:
accessibilityChannel
;
isWideAspectRatio
=
...
...
@@ -297,71 +297,83 @@ public final class Cea708Decoder extends CeaDecoder {
// we have received.
}
serviceBlockPacket
.
reset
(
currentDtvCcPacket
.
packetData
,
currentDtvCcPacket
.
currentIndex
);
int
serviceNumber
=
serviceBlockPacket
.
readBits
(
3
);
int
blockSize
=
serviceBlockPacket
.
readBits
(
5
);
if
(
serviceNumber
==
7
)
{
// extended service numbers
serviceBlockPacket
.
skipBits
(
2
);
serviceNumber
=
serviceBlockPacket
.
readBits
(
6
);
if
(
serviceNumber
<
7
)
{
Log
.
w
(
TAG
,
"Invalid extended service number: "
+
serviceNumber
);
}
}
// Ignore packets in which blockSize is 0
if
(
blockSize
==
0
)
{
if
(
serviceNumber
!=
0
)
{
Log
.
w
(
TAG
,
"serviceNumber is non-zero ("
+
serviceNumber
+
") when blockSize is 0"
);
}
return
;
}
if
(
serviceNumber
!=
selectedServiceNumber
)
{
return
;
}
// The cues should be updated if we receive a C0 ETX command, any C1 command, or if after
// processing the service block any text has been added to the buffer. See CEA-708-B Section
// 8.10.4 for more details.
boolean
cuesNeedUpdate
=
false
;
int
blockEndBitPosition
=
serviceBlockPacket
.
getPosition
()
+
(
blockSize
*
8
);
while
(
serviceBlockPacket
.
bitsLeft
()
>
0
&&
serviceBlockPacket
.
getPosition
()
<
blockEndBitPosition
)
{
int
command
=
serviceBlockPacket
.
readBits
(
8
);
if
(
command
!=
COMMAND_EXT1
)
{
if
(
command
<=
GROUP_C0_END
)
{
handleC0Command
(
command
);
// If the C0 command was an ETX command, the cues are updated in handleC0Command
.
}
else
if
(
command
<=
GROUP_G0_END
)
{
handleG0Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_C1_END
)
{
handleC1Command
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_G1_END
)
{
handleG1Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
{
Log
.
w
(
TAG
,
"Invalid
base command: "
+
command
);
// Streams with multiple embedded CC tracks (different language tracks) can be delivered
// in the same frame packet, so captionChannelPacketData can contain service blocks with
// different service numbers.
//
// We iterate over the full buffer until we find a null service block or until the buffer is
// exhausted. On each iteration we process a single service block. If the block has a service
// number different to the currently selected service, then we skip it and continue with the
// next service block
.
captionChannelPacketData
.
reset
(
currentDtvCcPacket
.
packetData
,
currentDtvCcPacket
.
currentIndex
);
while
(
captionChannelPacketData
.
bitsLeft
()
>
0
)
{
// Parse the Standard Service Block Header (see CEA-708B 6.2.1)
int
serviceNumber
=
captionChannelPacketData
.
readBits
(
3
);
int
blockSize
=
captionChannelPacketData
.
readBits
(
5
);
if
(
serviceNumber
==
7
)
{
// Parse the Extended Service Block Header (see CEA-708B 6.2.2)
captionChannelPacketData
.
skipBits
(
2
);
serviceNumber
=
captionChannelPacketData
.
readBits
(
6
)
;
if
(
serviceNumber
<
7
)
{
Log
.
w
(
TAG
,
"Invalid
extended service number: "
+
serviceNumber
);
}
}
else
{
// Read the extended command
command
=
serviceBlockPacket
.
readBits
(
8
);
if
(
command
<=
GROUP_C2_END
)
{
handleC2Command
(
command
);
}
else
if
(
command
<=
GROUP_G2_END
)
{
handleG2Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_C3_END
)
{
handleC3Command
(
command
);
}
else
if
(
command
<=
GROUP_G3_END
)
{
handleG3Character
(
command
);
cuesNeedUpdate
=
true
;
}
// Ignore packets with the Null Service Block Header (see CEA-708B 6.2.3)
if
(
blockSize
==
0
)
{
if
(
serviceNumber
!=
0
)
{
Log
.
w
(
TAG
,
"serviceNumber is non-zero ("
+
serviceNumber
+
") when blockSize is 0"
);
}
break
;
}
if
(
serviceNumber
!=
selectedServiceNumber
)
{
captionChannelPacketData
.
skipBytes
(
blockSize
);
continue
;
}
// Process only the information for the current service block (there could be
// more data in the buffer, but it is not part of the current service block).
int
endBlockPosition
=
captionChannelPacketData
.
getPosition
()
+
(
blockSize
*
8
);
while
(
captionChannelPacketData
.
getPosition
()
<
endBlockPosition
)
{
int
command
=
captionChannelPacketData
.
readBits
(
8
);
if
(
command
!=
COMMAND_EXT1
)
{
if
(
command
<=
GROUP_C0_END
)
{
handleC0Command
(
command
);
// If the C0 command was an ETX command, the cues are updated in handleC0Command.
}
else
if
(
command
<=
GROUP_G0_END
)
{
handleG0Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_C1_END
)
{
handleC1Command
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_G1_END
)
{
handleG1Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
{
Log
.
w
(
TAG
,
"Invalid base command: "
+
command
);
}
}
else
{
Log
.
w
(
TAG
,
"Invalid extended command: "
+
command
);
// Read the extended command
command
=
captionChannelPacketData
.
readBits
(
8
);
if
(
command
<=
GROUP_C2_END
)
{
handleC2Command
(
command
);
}
else
if
(
command
<=
GROUP_G2_END
)
{
handleG2Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
if
(
command
<=
GROUP_C3_END
)
{
handleC3Command
(
command
);
}
else
if
(
command
<=
GROUP_G3_END
)
{
handleG3Character
(
command
);
cuesNeedUpdate
=
true
;
}
else
{
Log
.
w
(
TAG
,
"Invalid extended command: "
+
command
);
}
}
}
}
...
...
@@ -394,10 +406,10 @@ public final class Cea708Decoder extends CeaDecoder {
default
:
if
(
command
>=
COMMAND_EXT1_START
&&
command
<=
COMMAND_EXT1_END
)
{
Log
.
w
(
TAG
,
"Currently unsupported COMMAND_EXT1 Command: "
+
command
);
serviceBlockPacket
.
skipBits
(
8
);
captionChannelPacketData
.
skipBits
(
8
);
}
else
if
(
command
>=
COMMAND_P16_START
&&
command
<=
COMMAND_P16_END
)
{
Log
.
w
(
TAG
,
"Currently unsupported COMMAND_P16 Command: "
+
command
);
serviceBlockPacket
.
skipBits
(
16
);
captionChannelPacketData
.
skipBits
(
16
);
}
else
{
Log
.
w
(
TAG
,
"Invalid C0 command: "
+
command
);
}
...
...
@@ -423,28 +435,28 @@ public final class Cea708Decoder extends CeaDecoder {
break
;
case
COMMAND_CLW:
for
(
int
i
=
1
;
i
<=
NUM_WINDOWS
;
i
++)
{
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
cueInfoBuilders
[
NUM_WINDOWS
-
i
].
clear
();
}
}
break
;
case
COMMAND_DSW:
for
(
int
i
=
1
;
i
<=
NUM_WINDOWS
;
i
++)
{
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
cueInfoBuilders
[
NUM_WINDOWS
-
i
].
setVisibility
(
true
);
}
}
break
;
case
COMMAND_HDW:
for
(
int
i
=
1
;
i
<=
NUM_WINDOWS
;
i
++)
{
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
cueInfoBuilders
[
NUM_WINDOWS
-
i
].
setVisibility
(
false
);
}
}
break
;
case
COMMAND_TGW:
for
(
int
i
=
1
;
i
<=
NUM_WINDOWS
;
i
++)
{
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
CueInfoBuilder
cueInfoBuilder
=
cueInfoBuilders
[
NUM_WINDOWS
-
i
];
cueInfoBuilder
.
setVisibility
(!
cueInfoBuilder
.
isVisible
());
}
...
...
@@ -452,14 +464,14 @@ public final class Cea708Decoder extends CeaDecoder {
break
;
case
COMMAND_DLW:
for
(
int
i
=
1
;
i
<=
NUM_WINDOWS
;
i
++)
{
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
cueInfoBuilders
[
NUM_WINDOWS
-
i
].
reset
();
}
}
break
;
case
COMMAND_DLY:
// TODO: Add support for delay commands.
serviceBlockPacket
.
skipBits
(
8
);
captionChannelPacketData
.
skipBits
(
8
);
break
;
case
COMMAND_DLC:
// TODO: Add support for delay commands.
...
...
@@ -470,7 +482,7 @@ public final class Cea708Decoder extends CeaDecoder {
case
COMMAND_SPA:
if
(!
currentCueInfoBuilder
.
isDefined
())
{
// ignore this command if the current window/cue isn't defined
serviceBlockPacket
.
skipBits
(
16
);
captionChannelPacketData
.
skipBits
(
16
);
}
else
{
handleSetPenAttributes
();
}
...
...
@@ -478,7 +490,7 @@ public final class Cea708Decoder extends CeaDecoder {
case
COMMAND_SPC:
if
(!
currentCueInfoBuilder
.
isDefined
())
{
// ignore this command if the current window/cue isn't defined
serviceBlockPacket
.
skipBits
(
24
);
captionChannelPacketData
.
skipBits
(
24
);
}
else
{
handleSetPenColor
();
}
...
...
@@ -486,7 +498,7 @@ public final class Cea708Decoder extends CeaDecoder {
case
COMMAND_SPL:
if
(!
currentCueInfoBuilder
.
isDefined
())
{
// ignore this command if the current window/cue isn't defined
serviceBlockPacket
.
skipBits
(
16
);
captionChannelPacketData
.
skipBits
(
16
);
}
else
{
handleSetPenLocation
();
}
...
...
@@ -494,7 +506,7 @@ public final class Cea708Decoder extends CeaDecoder {
case
COMMAND_SWA:
if
(!
currentCueInfoBuilder
.
isDefined
())
{
// ignore this command if the current window/cue isn't defined
serviceBlockPacket
.
skipBits
(
32
);
captionChannelPacketData
.
skipBits
(
32
);
}
else
{
handleSetWindowAttributes
();
}
...
...
@@ -525,27 +537,27 @@ public final class Cea708Decoder extends CeaDecoder {
if
(
command
<=
0x07
)
{
// Do nothing.
}
else
if
(
command
<=
0x0F
)
{
serviceBlockPacket
.
skipBits
(
8
);
captionChannelPacketData
.
skipBits
(
8
);
}
else
if
(
command
<=
0x17
)
{
serviceBlockPacket
.
skipBits
(
16
);
captionChannelPacketData
.
skipBits
(
16
);
}
else
if
(
command
<=
0x1F
)
{
serviceBlockPacket
.
skipBits
(
24
);
captionChannelPacketData
.
skipBits
(
24
);
}
}
private
void
handleC3Command
(
int
command
)
{
// C3 Table doesn't contain any commands in CEA-708-B, but we do need to skip bytes
if
(
command
<=
0x87
)
{
serviceBlockPacket
.
skipBits
(
32
);
captionChannelPacketData
.
skipBits
(
32
);
}
else
if
(
command
<=
0x8F
)
{
serviceBlockPacket
.
skipBits
(
40
);
captionChannelPacketData
.
skipBits
(
40
);
}
else
if
(
command
<=
0x9F
)
{
// 90-9F are variable length codes; the first byte defines the header with the first
// 2 bits specifying the type and the last 6 bits specifying the remaining length of the
// command in bytes
serviceBlockPacket
.
skipBits
(
2
);
int
length
=
serviceBlockPacket
.
readBits
(
6
);
serviceBlockPacket
.
skipBits
(
8
*
length
);
captionChannelPacketData
.
skipBits
(
2
);
int
length
=
captionChannelPacketData
.
readBits
(
6
);
captionChannelPacketData
.
skipBits
(
8
*
length
);
}
}
...
...
@@ -661,14 +673,14 @@ public final class Cea708Decoder extends CeaDecoder {
private
void
handleSetPenAttributes
()
{
// the SetPenAttributes command contains 2 bytes of data
// first byte
int
textTag
=
serviceBlockPacket
.
readBits
(
4
);
int
offset
=
serviceBlockPacket
.
readBits
(
2
);
int
penSize
=
serviceBlockPacket
.
readBits
(
2
);
int
textTag
=
captionChannelPacketData
.
readBits
(
4
);
int
offset
=
captionChannelPacketData
.
readBits
(
2
);
int
penSize
=
captionChannelPacketData
.
readBits
(
2
);
// second byte
boolean
italicsToggle
=
serviceBlockPacket
.
readBit
();
boolean
underlineToggle
=
serviceBlockPacket
.
readBit
();
int
edgeType
=
serviceBlockPacket
.
readBits
(
3
);
int
fontStyle
=
serviceBlockPacket
.
readBits
(
3
);
boolean
italicsToggle
=
captionChannelPacketData
.
readBit
();
boolean
underlineToggle
=
captionChannelPacketData
.
readBit
();
int
edgeType
=
captionChannelPacketData
.
readBits
(
3
);
int
fontStyle
=
captionChannelPacketData
.
readBits
(
3
);
currentCueInfoBuilder
.
setPenAttributes
(
textTag
,
offset
,
penSize
,
italicsToggle
,
underlineToggle
,
edgeType
,
fontStyle
);
...
...
@@ -677,24 +689,24 @@ public final class Cea708Decoder extends CeaDecoder {
private
void
handleSetPenColor
()
{
// the SetPenColor command contains 3 bytes of data
// first byte
int
foregroundO
=
serviceBlockPacket
.
readBits
(
2
);
int
foregroundR
=
serviceBlockPacket
.
readBits
(
2
);
int
foregroundG
=
serviceBlockPacket
.
readBits
(
2
);
int
foregroundB
=
serviceBlockPacket
.
readBits
(
2
);
int
foregroundO
=
captionChannelPacketData
.
readBits
(
2
);
int
foregroundR
=
captionChannelPacketData
.
readBits
(
2
);
int
foregroundG
=
captionChannelPacketData
.
readBits
(
2
);
int
foregroundB
=
captionChannelPacketData
.
readBits
(
2
);
int
foregroundColor
=
CueInfoBuilder
.
getArgbColorFromCeaColor
(
foregroundR
,
foregroundG
,
foregroundB
,
foregroundO
);
// second byte
int
backgroundO
=
serviceBlockPacket
.
readBits
(
2
);
int
backgroundR
=
serviceBlockPacket
.
readBits
(
2
);
int
backgroundG
=
serviceBlockPacket
.
readBits
(
2
);
int
backgroundB
=
serviceBlockPacket
.
readBits
(
2
);
int
backgroundO
=
captionChannelPacketData
.
readBits
(
2
);
int
backgroundR
=
captionChannelPacketData
.
readBits
(
2
);
int
backgroundG
=
captionChannelPacketData
.
readBits
(
2
);
int
backgroundB
=
captionChannelPacketData
.
readBits
(
2
);
int
backgroundColor
=
CueInfoBuilder
.
getArgbColorFromCeaColor
(
backgroundR
,
backgroundG
,
backgroundB
,
backgroundO
);
// third byte
serviceBlockPacket
.
skipBits
(
2
);
// null padding
int
edgeR
=
serviceBlockPacket
.
readBits
(
2
);
int
edgeG
=
serviceBlockPacket
.
readBits
(
2
);
int
edgeB
=
serviceBlockPacket
.
readBits
(
2
);
captionChannelPacketData
.
skipBits
(
2
);
// null padding
int
edgeR
=
captionChannelPacketData
.
readBits
(
2
);
int
edgeG
=
captionChannelPacketData
.
readBits
(
2
);
int
edgeB
=
captionChannelPacketData
.
readBits
(
2
);
int
edgeColor
=
CueInfoBuilder
.
getArgbColorFromCeaColor
(
edgeR
,
edgeG
,
edgeB
);
currentCueInfoBuilder
.
setPenColor
(
foregroundColor
,
backgroundColor
,
edgeColor
);
...
...
@@ -703,11 +715,11 @@ public final class Cea708Decoder extends CeaDecoder {
private
void
handleSetPenLocation
()
{
// the SetPenLocation command contains 2 bytes of data
// first byte
serviceBlockPacket
.
skipBits
(
4
);
int
row
=
serviceBlockPacket
.
readBits
(
4
);
captionChannelPacketData
.
skipBits
(
4
);
int
row
=
captionChannelPacketData
.
readBits
(
4
);
// second byte
serviceBlockPacket
.
skipBits
(
2
);
int
column
=
serviceBlockPacket
.
readBits
(
6
);
captionChannelPacketData
.
skipBits
(
2
);
int
column
=
captionChannelPacketData
.
readBits
(
6
);
currentCueInfoBuilder
.
setPenLocation
(
row
,
column
);
}
...
...
@@ -715,28 +727,28 @@ public final class Cea708Decoder extends CeaDecoder {
private
void
handleSetWindowAttributes
()
{
// the SetWindowAttributes command contains 4 bytes of data
// first byte
int
fillO
=
serviceBlockPacket
.
readBits
(
2
);
int
fillR
=
serviceBlockPacket
.
readBits
(
2
);
int
fillG
=
serviceBlockPacket
.
readBits
(
2
);
int
fillB
=
serviceBlockPacket
.
readBits
(
2
);
int
fillO
=
captionChannelPacketData
.
readBits
(
2
);
int
fillR
=
captionChannelPacketData
.
readBits
(
2
);
int
fillG
=
captionChannelPacketData
.
readBits
(
2
);
int
fillB
=
captionChannelPacketData
.
readBits
(
2
);
int
fillColor
=
CueInfoBuilder
.
getArgbColorFromCeaColor
(
fillR
,
fillG
,
fillB
,
fillO
);
// second byte
int
borderType
=
serviceBlockPacket
.
readBits
(
2
);
// only the lower 2 bits of borderType
int
borderR
=
serviceBlockPacket
.
readBits
(
2
);
int
borderG
=
serviceBlockPacket
.
readBits
(
2
);
int
borderB
=
serviceBlockPacket
.
readBits
(
2
);
int
borderType
=
captionChannelPacketData
.
readBits
(
2
);
// only the lower 2 bits of borderType
int
borderR
=
captionChannelPacketData
.
readBits
(
2
);
int
borderG
=
captionChannelPacketData
.
readBits
(
2
);
int
borderB
=
captionChannelPacketData
.
readBits
(
2
);
int
borderColor
=
CueInfoBuilder
.
getArgbColorFromCeaColor
(
borderR
,
borderG
,
borderB
);
// third byte
if
(
serviceBlockPacket
.
readBit
())
{
if
(
captionChannelPacketData
.
readBit
())
{
borderType
|=
0x04
;
// set the top bit of the 3-bit borderType
}
boolean
wordWrapToggle
=
serviceBlockPacket
.
readBit
();
int
printDirection
=
serviceBlockPacket
.
readBits
(
2
);
int
scrollDirection
=
serviceBlockPacket
.
readBits
(
2
);
int
justification
=
serviceBlockPacket
.
readBits
(
2
);
boolean
wordWrapToggle
=
captionChannelPacketData
.
readBit
();
int
printDirection
=
captionChannelPacketData
.
readBits
(
2
);
int
scrollDirection
=
captionChannelPacketData
.
readBits
(
2
);
int
justification
=
captionChannelPacketData
.
readBits
(
2
);
// fourth byte
// Note that we don't intend to support display effects
serviceBlockPacket
.
skipBits
(
8
);
// effectSpeed(4), effectDirection(2), displayEffect(2)
captionChannelPacketData
.
skipBits
(
8
);
// effectSpeed(4), effectDirection(2), displayEffect(2)
currentCueInfoBuilder
.
setWindowAttributes
(
fillColor
,
...
...
@@ -753,26 +765,26 @@ public final class Cea708Decoder extends CeaDecoder {
// the DefineWindow command contains 6 bytes of data
// first byte
serviceBlockPacket
.
skipBits
(
2
);
// null padding
boolean
visible
=
serviceBlockPacket
.
readBit
();
boolean
rowLock
=
serviceBlockPacket
.
readBit
();
boolean
columnLock
=
serviceBlockPacket
.
readBit
();
int
priority
=
serviceBlockPacket
.
readBits
(
3
);
captionChannelPacketData
.
skipBits
(
2
);
// null padding
boolean
visible
=
captionChannelPacketData
.
readBit
();
boolean
rowLock
=
captionChannelPacketData
.
readBit
();
boolean
columnLock
=
captionChannelPacketData
.
readBit
();
int
priority
=
captionChannelPacketData
.
readBits
(
3
);
// second byte
boolean
relativePositioning
=
serviceBlockPacket
.
readBit
();
int
verticalAnchor
=
serviceBlockPacket
.
readBits
(
7
);
boolean
relativePositioning
=
captionChannelPacketData
.
readBit
();
int
verticalAnchor
=
captionChannelPacketData
.
readBits
(
7
);
// third byte
int
horizontalAnchor
=
serviceBlockPacket
.
readBits
(
8
);
int
horizontalAnchor
=
captionChannelPacketData
.
readBits
(
8
);
// fourth byte
int
anchorId
=
serviceBlockPacket
.
readBits
(
4
);
int
rowCount
=
serviceBlockPacket
.
readBits
(
4
);
int
anchorId
=
captionChannelPacketData
.
readBits
(
4
);
int
rowCount
=
captionChannelPacketData
.
readBits
(
4
);
// fifth byte
serviceBlockPacket
.
skipBits
(
2
);
// null padding
int
columnCount
=
serviceBlockPacket
.
readBits
(
6
);
captionChannelPacketData
.
skipBits
(
2
);
// null padding
int
columnCount
=
captionChannelPacketData
.
readBits
(
6
);
// sixth byte
serviceBlockPacket
.
skipBits
(
2
);
// null padding
int
windowStyle
=
serviceBlockPacket
.
readBits
(
3
);
int
penStyle
=
serviceBlockPacket
.
readBits
(
3
);
captionChannelPacketData
.
skipBits
(
2
);
// null padding
int
windowStyle
=
captionChannelPacketData
.
readBits
(
3
);
int
penStyle
=
captionChannelPacketData
.
readBits
(
3
);
cueInfoBuilder
.
defineWindow
(
visible
,
...
...
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