Skip to content

Commit

Permalink
Merge pull request #942 from datdoantelus:CC_708_parser_fix
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 596836615
  • Loading branch information
copybara-github committed Jan 9, 2024
2 parents c6b5100 + 0b482ef commit 6f82491
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 16 deletions.
4 changes: 4 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
that contained Binder objects` error when using
`DefaultExtractorsFactory.setTextTrackTranscodingEnabled`
([#836](https://github.com/androidx/media/issues/836)).
* CEA-708: Ignore `rowLock` value. The CEA-708-E S-2023 spec states that
`rowLock` and `columnLock` should both be assumed to be true, regardless
of the values present in the stream (`columnLock` support is not
implemented, so it's effectively assumed to always be false).
* Metadata:
* Fix bug where `MediaMetadata` was only populated from Vorbis comments
with upper-case keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,8 +786,11 @@ private void handleDefineWindow(int window) {
// first byte
captionChannelPacketData.skipBits(2); // null padding
boolean visible = captionChannelPacketData.readBit();
boolean rowLock = captionChannelPacketData.readBit();
boolean columnLock = captionChannelPacketData.readBit();

// ANSI/CTA-708-E S-2023 spec (Section 8.4.7) indicates that rowLock and columnLock values in
// the media should be ignored and assumed to be true.
captionChannelPacketData.skipBits(2);

int priority = captionChannelPacketData.readBits(3);
// second byte
boolean relativePositioning = captionChannelPacketData.readBit();
Expand All @@ -799,22 +802,20 @@ private void handleDefineWindow(int window) {
int rowCount = captionChannelPacketData.readBits(4);
// fifth byte
captionChannelPacketData.skipBits(2); // null padding
int columnCount = captionChannelPacketData.readBits(6);
// TODO: Add support for column count.
captionChannelPacketData.skipBits(6); // column count
// sixth byte
captionChannelPacketData.skipBits(2); // null padding
int windowStyle = captionChannelPacketData.readBits(3);
int penStyle = captionChannelPacketData.readBits(3);

cueInfoBuilder.defineWindow(
visible,
rowLock,
columnLock,
priority,
relativePositioning,
verticalAnchor,
horizontalAnchor,
rowCount,
columnCount,
anchorId,
windowStyle,
penStyle);
Expand Down Expand Up @@ -975,7 +976,6 @@ private static final class CueInfoBuilder {
private int horizontalAnchor;
private int anchorId;
private int rowCount;
private boolean rowLock;
private int justification;
private int windowStyleId;
private int penStyleId;
Expand Down Expand Up @@ -1011,7 +1011,6 @@ public void reset() {
horizontalAnchor = 0;
anchorId = 0;
rowCount = MAXIMUM_ROW_COUNT;
rowLock = true;
justification = JUSTIFICATION_LEFT;
windowStyleId = 0;
penStyleId = 0;
Expand Down Expand Up @@ -1045,20 +1044,16 @@ public boolean isVisible() {

public void defineWindow(
boolean visible,
boolean rowLock,
boolean columnLock,
int priority,
boolean relativePositioning,
int verticalAnchor,
int horizontalAnchor,
int rowCount,
int columnCount,
int anchorId,
int windowStyleId,
int penStyleId) {
this.defined = true;
this.visible = visible;
this.rowLock = rowLock;
this.priority = priority;
this.relativePositioning = relativePositioning;
this.verticalAnchor = verticalAnchor;
Expand All @@ -1070,14 +1065,12 @@ public void defineWindow(
this.rowCount = rowCount + 1;

// Trim any rolled up captions that are no longer valid, if applicable.
while ((rowLock && (rolledUpCaptions.size() >= this.rowCount))
while ((rolledUpCaptions.size() >= this.rowCount)
|| (rolledUpCaptions.size() >= MAXIMUM_ROW_COUNT)) {
rolledUpCaptions.remove(0);
}
}

// TODO: Add support for column lock and count.

if (windowStyleId != 0 && this.windowStyleId != windowStyleId) {
this.windowStyleId = windowStyleId;
// windowStyleId is 1-based.
Expand Down Expand Up @@ -1239,7 +1232,7 @@ public void append(char text) {
backgroundColorStartPosition = 0;
}

while ((rowLock && (rolledUpCaptions.size() >= rowCount))
while ((rolledUpCaptions.size() >= rowCount)
|| (rolledUpCaptions.size() >= MAXIMUM_ROW_COUNT)) {
rolledUpCaptions.remove(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,40 @@ public void singleServiceAndWindowDefinition_respectsOffsetAndLimit() throws Exc
.isEqualTo("test subtitle");
}

@Test
public void singleServiceAndWindowDefinition_ignoreRowLock() throws Exception {
Cea708Parser cea708Parser =
new Cea708Parser(
/* accessibilityChannel= */ Format.NO_VALUE, /* initializationData= */ null);
byte[] windowDefinition =
TestUtil.createByteArray(
0x98, // DF0 command (define window 0)
0b0010_0000, // visible=true, row lock and column lock disabled, priority=0
0xF0 | 50, // relative positioning, anchor vertical
50, // anchor horizontal
1, // anchor point = 0, row count = 1
30, // column count = 30
0b0000_1001); // window style = 1, pen style = 1
byte[] setCurrentWindow = TestUtil.createByteArray(0x80); // CW0 (set current window to 0)
byte[] subtitleData =
encodePacketIntoBytePairs(
createPacket(
/* sequenceNumber= */ 0,
createServiceBlock(
Bytes.concat(
windowDefinition,
setCurrentWindow,
"row1\r\nrow2\r\nrow3\r\nrow4".getBytes(Charsets.UTF_8)))));

List<CuesWithTiming> result = new ArrayList<>();
cea708Parser.parse(subtitleData, SubtitleParser.OutputOptions.allCues(), result::add);

// Row count is 1 (which means 2 rows should be kept). Row lock is disabled in the media,
// but this is ignored and the result is still truncated to only the last two rows.
assertThat(Iterables.getOnlyElement(Iterables.getOnlyElement(result).cues).text.toString())
.isEqualTo("row3\nrow4");
}

/** See section 4.4.1 of the CEA-708-B spec. */
private static byte[] encodePacketIntoBytePairs(byte[] packet) {
checkState(packet.length % 2 == 0);
Expand Down

0 comments on commit 6f82491

Please sign in to comment.