From 44cb8a2ed8bd5d24d90e8c2213351eef2f22841e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Tyczy=C5=84ski?= Date: Wed, 10 Jan 2024 16:17:10 +0100 Subject: [PATCH] fix: fix handling of multiple CC tracks (#6076) Due to issue around channel calculation, shaka was never using CC4 track and data from there were landing in CC2 track. --- lib/cea/cea608_memory.js | 2 +- lib/cea/cea_decoder.js | 2 +- test/cea/cea_decoder_unit.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/cea/cea608_memory.js b/lib/cea/cea608_memory.js index 12ae686ab0..1bf125d403 100644 --- a/lib/cea/cea608_memory.js +++ b/lib/cea/cea608_memory.js @@ -79,7 +79,7 @@ shaka.cea.Cea608Memory = class { * @return {?shaka.extern.ICaptionDecoder.ClosedCaption} */ forceEmit(startTime, endTime) { - const stream = `CC${(this.fieldNum_<< 1) | this.channelNum_ +1}`; + const stream = `CC${((this.fieldNum_<< 1) | this.channelNum_) + 1}`; const topLevelCue = new shaka.text.Cue( startTime, endTime, /* payload= */ ''); topLevelCue.lineInterpretation = diff --git a/lib/cea/cea_decoder.js b/lib/cea/cea_decoder.js index 4e0a4ef6ee..dc4bbe6749 100644 --- a/lib/cea/cea_decoder.js +++ b/lib/cea/cea_decoder.js @@ -283,7 +283,7 @@ shaka.cea.CeaDecoder = class { // Get the correct stream for this caption packet (CC1, ..., CC4) const selectedChannel = fieldNum ? this.currentField2Channel_ : this.currentField1Channel_; - const selectedMode = `CC${(fieldNum << 1) | selectedChannel + 1}`; + const selectedMode = `CC${((fieldNum << 1) | selectedChannel) + 1}`; const selectedStream = this.cea608ModeToStream_.get(selectedMode); // Check for bad frames (bad pairs). This can be two 0xff, two 0x00, or any diff --git a/test/cea/cea_decoder_unit.js b/test/cea/cea_decoder_unit.js index 4eeeff88f8..dd0a22971e 100644 --- a/test/cea/cea_decoder_unit.js +++ b/test/cea/cea_decoder_unit.js @@ -44,6 +44,42 @@ describe('CeaDecoder', () => { decoder.clear(); }); + it('painton captions on CC4', () => { + const controlCount = 0x03; + const captionData = 0xc0 | controlCount; + const paintonCaptionCC4Packet = new Uint8Array([ + ...atscCaptionInitBytes, captionData, /* padding= */ 0xff, + 0xfd, 0x9d, 0x29, // Paint-on mode (RDC control code). + 0xfd, 0xf4, 0xe5, // t, e + 0xfd, 0x73, 0xf4, // s, t + ]); + + const startTimeCaption1 = 1; + const startTimeCaption2 = 2; + const expectedText = 'test'; + + const topLevelCue = new shaka.text.Cue(startTimeCaption1, + startTimeCaption2, ''); + topLevelCue.line = 10; + topLevelCue.lineInterpretation = + shaka.text.Cue.lineInterpretation.PERCENTAGE; + topLevelCue.nestedCues = [ + CeaUtils.createDefaultCue( + startTimeCaption1, startTimeCaption2, expectedText), + ]; + + const expectedCaptions = [{ + stream: 'CC4', + cue: topLevelCue, + }]; + + decoder.extract(paintonCaptionCC4Packet, startTimeCaption1); + decoder.extract(eraseDisplayedMemory, startTimeCaption2); + const captions = decoder.decode(); + + expect(captions).toEqual(expectedCaptions); + }); + it('green and underlined popon caption data on CC3', () => { const controlCount = 0x08; const captionData = 0xc0 | controlCount;