mirror of
https://github.com/samsonjs/media.git
synced 2026-03-31 10:25:48 +00:00
CEA608: Limiting duplicated command checks to immediate frames
Reported in https://github.com/google/ExoPlayer/issues/3860 For failing examples see the github link above. [Problem] We drop matching control codes even if they are not received on consecutive frames. The specification says "(4) If the first transmission of a control code pair passes parity, it is acted upon within one video frame. If the NEXT frame contains a perfect repeat of the same pair, the redundant code is ignored." Keyword is the NEXT. The frames must arrive immediately after each other. See https://www.law.cornell.edu/cfr/text/47/79.101 [Solution] Set an additional flag when any data is processed. Control code duplication checks should be limited only for the first control byte pairs processed after any control code. [Test] Sarnoff tests have equivalent CEA708 and CEA608 Streams.
This commit is contained in:
parent
e0c6f538af
commit
fff602358f
1 changed files with 9 additions and 13 deletions
|
|
@ -292,7 +292,6 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
protected void decode(SubtitleInputBuffer inputBuffer) {
|
||||
ccData.reset(inputBuffer.data.array(), inputBuffer.data.limit());
|
||||
boolean captionDataProcessed = false;
|
||||
boolean isRepeatableControl = false;
|
||||
while (ccData.bytesLeft() >= packetLength) {
|
||||
byte ccHeader = packetLength == 2 ? CC_IMPLICIT_DATA_HEADER
|
||||
: (byte) ccData.readUnsignedByte();
|
||||
|
|
@ -337,6 +336,9 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
// If we've reached this point then there is data to process; flag that work has been done.
|
||||
captionDataProcessed = true;
|
||||
|
||||
boolean repeatedControlPossible = repeatableControlSet;
|
||||
repeatableControlSet = false;
|
||||
|
||||
if (!ODD_PARITY_BYTE_TABLE[ccByte1] || !ODD_PARITY_BYTE_TABLE[ccByte2]) {
|
||||
// The data is invalid.
|
||||
resetCueBuilders();
|
||||
|
|
@ -372,7 +374,7 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
// Control character.
|
||||
// ccData1 - 0|0|0|X|X|X|X|X
|
||||
if ((ccData1 & 0xE0) == 0x00) {
|
||||
isRepeatableControl = handleCtrl(ccData1, ccData2);
|
||||
handleCtrl(ccData1, ccData2, repeatedControlPossible);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -384,30 +386,26 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
}
|
||||
|
||||
if (captionDataProcessed) {
|
||||
if (!isRepeatableControl) {
|
||||
repeatableControlSet = false;
|
||||
}
|
||||
if (captionMode == CC_MODE_ROLL_UP || captionMode == CC_MODE_PAINT_ON) {
|
||||
cues = getDisplayCues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleCtrl(byte cc1, byte cc2) {
|
||||
private void handleCtrl(byte cc1, byte cc2, boolean repeatedControlPossible) {
|
||||
boolean isRepeatableControl = isRepeatable(cc1);
|
||||
|
||||
// Most control commands are sent twice in succession to ensure they are received properly.
|
||||
// We don't want to process duplicate commands, so if we see the same repeatable command twice
|
||||
// in a row, ignore the second one.
|
||||
if (isRepeatableControl) {
|
||||
if (repeatableControlSet
|
||||
if (repeatedControlPossible
|
||||
&& repeatableControlCc1 == cc1
|
||||
&& repeatableControlCc2 == cc2) {
|
||||
// This is a duplicate. Clear the repeatable control flag and return.
|
||||
repeatableControlSet = false;
|
||||
return true;
|
||||
// This is a duplicate. Repeatable control flag should be already cleared, let's return.
|
||||
return;
|
||||
} else {
|
||||
// This is a repeatable command, but we haven't see it yet, so set the repeatable control
|
||||
// This is a repeatable command, but we haven't seen it yet, so set the repeatable control
|
||||
// flag (to ensure we ignore the next one should it be a duplicate) and continue processing
|
||||
// the command.
|
||||
repeatableControlSet = true;
|
||||
|
|
@ -425,8 +423,6 @@ public final class Cea608Decoder extends CeaDecoder {
|
|||
} else if (isMiscCode(cc1, cc2)) {
|
||||
handleMiscCode(cc2);
|
||||
}
|
||||
|
||||
return isRepeatableControl;
|
||||
}
|
||||
|
||||
private void handleMidrowCtrl(byte cc2) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue