Skip to content

Commit 1705ecc

Browse files
authored
[SCC reader] Ensure a caption exists when receiving a BS or TOx code
#468 #467
1 parent b7df763 commit 1705ecc

File tree

3 files changed

+36
-21
lines changed

3 files changed

+36
-21
lines changed

src/main/python/ttconv/scc/context.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,12 @@ def new_buffered_caption(self):
103103
"""Resets buffered caption"""
104104
self.buffered_caption = SccCaptionParagraph(self.safe_area_x_offset, self.safe_area_y_offset, SccCaptionStyle.PopOn)
105105

106-
def get_caption_to_process(self) -> Optional[SccCaptionParagraph]:
106+
def get_caption_to_process(self, time_code: SmpteTimeCode) -> Optional[SccCaptionParagraph]:
107107
"""Returns the caption currently being processed"""
108108
if self.current_style in (SccCaptionStyle.PaintOn, SccCaptionStyle.RollUp):
109109
# If the Paint-On or Roll-Up style is activated, write directly on active caption
110+
if not self.has_active_caption():
111+
self.new_active_caption(time_code, self.current_style)
110112
return self.active_caption
111113
if self.current_style is SccCaptionStyle.PopOn:
112114
# For Pop-On style, write first on a buffered caption
@@ -159,11 +161,12 @@ def push_active_caption_to_model(self, time_code: SmpteTimeCode, clear_active_ca
159161
if not previous_caption.is_empty():
160162
self.div.push_child(previous_caption.to_paragraph(self.div.get_doc()))
161163

162-
def backspace(self):
164+
def backspace(self, time_code: SmpteTimeCode):
163165
"""Move the cursors in a column to the left"""
164-
self.get_caption_to_process().get_current_text().backspace()
165-
(row, indent) = self.get_caption_to_process().get_cursor()
166-
self.get_caption_to_process().set_cursor_at(row, max(indent - 1, 0))
166+
caption = self.get_caption_to_process(time_code)
167+
caption.get_current_text().backspace()
168+
(row, indent) = caption.get_cursor()
169+
caption.set_cursor_at(row, max(indent - 1, 0))
167170

168171
def paint_on_active_caption(self, time_code: SmpteTimeCode):
169172
"""Initialize active caption for paint-on style"""
@@ -200,11 +203,10 @@ def process_preamble_address_code(self, pac: SccPreambleAddressCode, time_code:
200203

201204
self.paint_on_active_caption(time_code)
202205

203-
if self.active_caption.get_caption_style() is SccCaptionStyle.PaintOn:
204-
# Clear target row on Paint-On style
205-
target_row = self.active_caption.get_lines().get(pac_row)
206-
if target_row is not None:
207-
target_row.clear()
206+
# Clear target row on Paint-On style
207+
target_row = self.active_caption.get_lines().get(pac_row)
208+
if target_row is not None:
209+
target_row.clear()
208210

209211
self.active_caption.set_cursor_at(pac_row, pac_indent)
210212

@@ -245,7 +247,7 @@ def process_preamble_address_code(self, pac: SccPreambleAddressCode, time_code:
245247
def process_mid_row_code(self, mid_row_code: SccMidRowCode, time_code: SmpteTimeCode):
246248
"""Processes SCC Mid-Row Code to map it to the model"""
247249

248-
processed_caption = self.get_caption_to_process()
250+
processed_caption = self.get_caption_to_process(time_code)
249251

250252
color = mid_row_code.get_color()
251253
font_style = mid_row_code.get_font_style()
@@ -295,10 +297,10 @@ def process_mid_row_code(self, mid_row_code: SccMidRowCode, time_code: SmpteTime
295297
and processed_caption.get_caption_style() is SccCaptionStyle.PaintOn:
296298
processed_caption.get_current_text().set_begin(time_code)
297299

298-
def process_attribute_code(self, attribute_code: SccAttributeCode):
300+
def process_attribute_code(self, attribute_code: SccAttributeCode, time_code: SmpteTimeCode):
299301
"""Processes SCC Attribute Code to map it to the model"""
300302

301-
processed_caption = self.get_caption_to_process()
303+
processed_caption = self.get_caption_to_process(time_code)
302304

303305
if processed_caption is None:
304306
LOGGER.warning("No current SCC caption nor content initialized")
@@ -375,13 +377,13 @@ def process_control_code(self, control_code: SccControlCode, time_code: SmpteTim
375377
self.new_buffered_caption()
376378

377379
elif control_code is SccControlCode.TO1:
378-
self.get_caption_to_process().indent_cursor(1)
380+
self.get_caption_to_process(time_code).indent_cursor(1)
379381

380382
elif control_code is SccControlCode.TO2:
381-
self.get_caption_to_process().indent_cursor(2)
383+
self.get_caption_to_process(time_code).indent_cursor(2)
382384

383385
elif control_code is SccControlCode.TO3:
384-
self.get_caption_to_process().indent_cursor(3)
386+
self.get_caption_to_process(time_code).indent_cursor(3)
385387

386388
elif control_code is SccControlCode.CR:
387389
# Roll the displayed caption up one row (Roll-Up)
@@ -421,7 +423,7 @@ def process_control_code(self, control_code: SccControlCode, time_code: SmpteTim
421423
# Backspace
422424
# When a Backspace is received, the cursor moves to the left one column position erasing
423425
# the character or Mid-Row Code occupying that location, unless the cursor is in Column 1
424-
self.backspace()
426+
self.backspace(time_code)
425427

426428
def process_text(self, word: str, time_code: SmpteTimeCode):
427429
"""Processes SCC text words"""

src/main/python/ttconv/scc/line.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def process(self, context: SccContext) -> SmpteTimeCode:
150150

151151
elif isinstance(scc_code, SccAttributeCode):
152152
debug += scc_code.debug(scc_word.value)
153-
context.process_attribute_code(scc_code)
153+
context.process_attribute_code(scc_code, self.time_code)
154154
context.previous_word_type = type(scc_code)
155155

156156
elif isinstance(scc_code, SccMidRowCode):
@@ -170,7 +170,7 @@ def process(self, context: SccContext) -> SmpteTimeCode:
170170
context.previous_word_type = type(scc_code)
171171

172172
elif isinstance(scc_code, SccExtendedCharacter):
173-
context.backspace()
173+
context.backspace(self.time_code)
174174

175175
word = scc_code.get_unicode_value()
176176
debug += word

src/test/python/test_scc_reader.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,13 +1271,26 @@ def test_scc_with_negative_cursor(self):
12711271
self.check_caption(p_list[0], "caption1", "00:00:01:16", "00:00:02:00", "Scary! Eeech!")
12721272
self.assertEqual(region_1, p_list[0].get_region())
12731273

1274+
def test_scc_content_starting_with_tab(self):
1275+
scc_content = """Scenarist_SCC V1.0
1276+
00:42:41;20 942C 9429 97A2 5BF7
1277+
"""
1278+
print(to_disassembly(scc_content))
1279+
self.assertIsNotNone(to_model(scc_content))
1280+
1281+
def test_scc_content_starting_with_bs(self):
1282+
scc_content = """Scenarist_SCC V1.0
1283+
00:42:41;20 942C 9429 94A1 5BF7
1284+
"""
1285+
self.assertIsNotNone(to_model(scc_content))
1286+
12741287
def test_scc_content_starting_with_backspace(self):
12751288
scc_content = """Scenarist_SCC V1.0
1276-
10:01:44;17 94AE 9420 9470 9723 946E 80C1 92B0 20ec 6120 e6e9 6e20 64e5 7320 616e 6edc e573 2031 38b0 b02c 942C 8080 8080 942F
1289+
10:01:44;17 94AE 9420 9470 9723 946E 94A1 92B0 20ec 6120 e6e9 6e20 64e5 7320 616e 6edc e573 2031 38b0 b02c 942C 8080 8080 942F
12771290
"""
12781291

12791292
expected_scc_disassembly = """\
1280-
10:01:44;17 {ENM}{RCL}{1500}{TO3}{15WhI}{??}À la fin des années 1800,{EDM}{}{}{EOC}
1293+
10:01:44;17 {ENM}{RCL}{1500}{TO3}{15WhI}{BS}À la fin des années 1800,{EDM}{}{}{EOC}
12811294
"""
12821295

12831296
scc_disassembly = to_disassembly(scc_content)

0 commit comments

Comments
 (0)