Merge #5140: Cea608 - Check parity and valid bits

Imported from GitHub PR https://github.com/google/ExoPlayer/pull/5140

https://github.com/google/ExoPlayer/pull/5086 moved onto the right branch.
Merge 8822e188d24c1d9b3ed101918763b16e46c8debc into 0c385a854d

PiperOrigin-RevId: 222633340
This commit is contained in:
Oliver Woodman 2018-11-23 17:46:26 +00:00
parent 0c385a854d
commit e2e1c459c8

View file

@ -46,7 +46,6 @@ public final class Cea608Decoder extends CeaDecoder {
private static final int NTSC_CC_FIELD_1 = 0x00;
private static final int NTSC_CC_FIELD_2 = 0x01;
private static final int CC_VALID_608_ID = 0x04;
private static final int CC_MODE_UNKNOWN = 0;
private static final int CC_MODE_ROLL_UP = 1;
@ -179,6 +178,41 @@ public final class Cea608Decoder extends CeaDecoder {
0xC5, 0xE5, 0xD8, 0xF8, 0x250C, 0x2510, 0x2514, 0x2518
};
private static final boolean[] ODD_PARITY_BYTE_TABLE = {
false, true, true, false, true, false, false, true, // 0
true, false, false, true, false, true, true, false, // 8
true, false, false, true, false, true, true, false, // 16
false, true, true, false, true, false, false, true, // 24
true, false, false, true, false, true, true, false, // 32
false, true, true, false, true, false, false, true, // 40
false, true, true, false, true, false, false, true, // 48
true, false, false, true, false, true, true, false, // 56
true, false, false, true, false, true, true, false, // 64
false, true, true, false, true, false, false, true, // 72
false, true, true, false, true, false, false, true, // 80
true, false, false, true, false, true, true, false, // 88
false, true, true, false, true, false, false, true, // 96
true, false, false, true, false, true, true, false, // 104
true, false, false, true, false, true, true, false, // 112
false, true, true, false, true, false, false, true, // 120
true, false, false, true, false, true, true, false, // 128
false, true, true, false, true, false, false, true, // 136
false, true, true, false, true, false, false, true, // 144
true, false, false, true, false, true, true, false, // 152
false, true, true, false, true, false, false, true, // 160
true, false, false, true, false, true, true, false, // 168
true, false, false, true, false, true, true, false, // 176
false, true, true, false, true, false, false, true, // 184
false, true, true, false, true, false, false, true, // 192
true, false, false, true, false, true, true, false, // 200
true, false, false, true, false, true, true, false, // 208
false, true, true, false, true, false, false, true, // 216
true, false, false, true, false, true, true, false, // 224
false, true, true, false, true, false, false, true, // 232
false, true, true, false, true, false, false, true, // 240
true, false, false, true, false, true, true, false, // 248
};
private final ParsableByteArray ccData;
private final int packetLength;
private final int selectedField;
@ -191,6 +225,7 @@ public final class Cea608Decoder extends CeaDecoder {
private int captionMode;
private int captionRowCount;
private boolean captionValid;
private boolean repeatableControlSet;
private byte repeatableControlCc1;
private byte repeatableControlCc2;
@ -229,6 +264,7 @@ public final class Cea608Decoder extends CeaDecoder {
setCaptionMode(CC_MODE_UNKNOWN);
setCaptionRowCount(DEFAULT_CAPTIONS_ROW_COUNT);
resetCueBuilders();
captionValid = false;
repeatableControlSet = false;
repeatableControlCc1 = 0;
repeatableControlCc2 = 0;
@ -259,31 +295,54 @@ public final class Cea608Decoder extends CeaDecoder {
while (ccData.bytesLeft() >= packetLength) {
byte ccDataHeader = packetLength == 2 ? CC_IMPLICIT_DATA_HEADER
: (byte) ccData.readUnsignedByte();
byte ccData1 = (byte) (ccData.readUnsignedByte() & 0x7F); // strip the parity bit
byte ccData2 = (byte) (ccData.readUnsignedByte() & 0x7F); // strip the parity bit
// Only examine valid CEA-608 packets
// TODO: We're currently ignoring the top 5 marker bits, which should all be 1s according
// to the CEA-608 specification. We need to determine if the data should be handled
// differently when that is not the case.
if ((ccDataHeader & (CC_VALID_FLAG | CC_TYPE_FLAG)) != CC_VALID_608_ID) {
if ((ccDataHeader & CC_TYPE_FLAG) != 0) {
// Do not process anything that is not part of the 608 byte stream.
continue;
}
// Only examine packets within the selected field
if ((selectedField == 1 && (ccDataHeader & CC_FIELD_FLAG) != NTSC_CC_FIELD_1)
|| (selectedField == 2 && (ccDataHeader & CC_FIELD_FLAG) != NTSC_CC_FIELD_2)) {
// Do not process packets not within the selected field.
continue;
}
// Ignore empty captions.
int ccByte1 = ccData.readUnsignedByte();
int ccByte2 = ccData.readUnsignedByte();
// Strip the parity bit from each byte to get CC data.
byte ccData1 = (byte) (ccByte1 & 0x7F);
byte ccData2 = (byte) (ccByte2 & 0x7F);
if (ccData1 == 0 && ccData2 == 0) {
// Ignore empty captions.
continue;
}
if ((ccDataHeader & CC_VALID_FLAG) != CC_VALID_FLAG) {
if (captionValid) {
// The encoder has flipped the validity bit to indicate closed captions are being turned.
resetCueBuilders();
captionValid = false;
captionDataProcessed = true;
}
continue;
}
// If we've reached this point then there is data to process; flag that work has been done.
captionDataProcessed = true;
if (!ODD_PARITY_BYTE_TABLE[ccByte1] || !ODD_PARITY_BYTE_TABLE[ccByte2]) {
// The data is invalid.
resetCueBuilders();
continue;
}
// Special North American character set.
// ccData1 - 0|0|0|1|C|0|0|1
// ccData2 - 0|0|1|1|X|X|X|X