Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore rowLock and columnLock values as specified by ANSI/CTA-708-E S… #942

Merged
merged 5 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -783,8 +783,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 @@ -796,22 +799,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 @@ -972,7 +973,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 @@ -1008,7 +1008,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 @@ -1042,20 +1041,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 @@ -1067,14 +1062,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 @@ -1236,7 +1229,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 @@ -42,6 +42,7 @@ public class Cea708ParserTest {
private static final byte CHANNEL_PACKET_DATA = 0x6;
private static final byte CHANNEL_PACKET_END = 0x2;


@Test
public void singleServiceAndWindowDefinition() throws Exception {
Cea708Parser cea708Parser =
Expand Down Expand Up @@ -115,6 +116,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