def test_parse_drop_frame_time_code(self): time_code = SmpteTimeCode.parse("01:02:03;04", FPS_29_97) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual(Fraction(111582, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("01:02:03;04", str(time_code)) time_code = SmpteTimeCode.parse("01;02;03;04", FPS_29_97) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual(Fraction(111582, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("01:02:03;04", str(time_code)) time_code = SmpteTimeCode.parse("01:02:03;04", FPS_30) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual(Fraction(111582, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("01:02:03;04", str(time_code)) time_code = SmpteTimeCode.parse("01:02:03.04", FPS_29_97) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual(Fraction(111582, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("01:02:03;04", str(time_code)) time_code = SmpteTimeCode.parse("01.02.03.04", FPS_29_97) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual(Fraction(111582, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("01:02:03;04", str(time_code))
def test_to_paragraph(self): caption_paragraph = SccCaptionParagraph() doc = ContentDocument() self.assertRaisesRegex(TypeError, "Element id must be a valid xml:id string", caption_paragraph.to_paragraph, doc) caption_paragraph.set_id("test-id") origin = caption_paragraph.get_origin() self.assertEqual(0, origin.x.value) self.assertEqual(0, origin.y.value) extent = caption_paragraph.get_extent() self.assertEqual(0, extent.width.value) self.assertEqual(0, extent.height.value) paragraph = caption_paragraph.to_paragraph(doc) self.assertEqual("test-id", paragraph.get_id()) self.assertEqual(doc, paragraph.get_doc()) self.assertIsNone(paragraph.get_begin()) self.assertIsNone(paragraph.get_end()) children = list(paragraph) self.assertEqual(0, len(children)) caption_paragraph.set_begin(SmpteTimeCode.parse("00:01:02:03", FPS_30)) caption_paragraph.set_end(SmpteTimeCode.parse("00:02:03:04", FPS_30)) caption_paragraph.set_cursor_at(0) caption_paragraph.new_caption_text() caption_paragraph.append_text("Hello") caption_paragraph.set_cursor_at(1) caption_paragraph.new_caption_text() caption_paragraph.append_text("World") paragraph = caption_paragraph.to_paragraph(doc) self.assertEqual("test-id", paragraph.get_id()) self.assertEqual(doc, paragraph.get_doc()) self.assertEqual(Fraction(1863, 30), paragraph.get_begin()) self.assertEqual(Fraction(3694, 30), paragraph.get_end()) children = list(paragraph) self.assertEqual(3, len(children)) self.assertIsInstance(children[0], Span) self.assertEqual("Hello", list(children[0])[0].get_text()) self.assertIsInstance(children[1], Br) self.assertIsInstance(children[2], Span) self.assertEqual("World", list(children[2])[0].get_text())
def test_irt_requirement_0062_002_modified(self): '''Testing Time Code Out with value media 25 frames upper bound''' with open("src/test/resources/stl/irt/requirement-0062-002_modified.stl", "rb") as f: doc = ttconv.stl.reader.to_model(f) p = doc.get_body().first_child().first_child() self.assertEqual(p.get_end(), SmpteTimeCode.parse("23:59:59:24",FPS_25).to_temporal_offset())
def test_irt_requirement_0061_001(self): '''Testing Time Code In with value media 25 frames lowerbounds''' with open("src/test/resources/stl/irt/requirement-0061-001.stl", "rb") as f: doc = ttconv.stl.reader.to_model(f) p = doc.get_body().first_child().first_child() self.assertEqual(p.get_begin(), SmpteTimeCode.parse("00:00:00:00",FPS_25).to_temporal_offset())
def test_scc_line_from_str_with_paint_on_style(self): line_str = "01:03:27:29 9429 9429 94f2 94f2 c845 d92c 2054 c845 5245 ae80" scc_line = SccLine.from_str(line_str) self.assertEqual(10, len(scc_line.scc_words)) self.assertEqual( SmpteTimeCode(1, 3, 27, 29, FPS_30).to_temporal_offset(), scc_line.time_code.to_temporal_offset()) self.assertEqual("01:03:27:29 {RDC}{RDC}{1504}{1504}HEY, THERE.", scc_line.to_disassembly()) self.assertEqual(SccCaptionStyle.PaintOn, scc_line.get_style())
def test_scc_line_from_str_with_roll_up_style(self): line_str = "01:03:27:29 9425 9425 94ad 94ad 94c8 94c8 c845 d92c 2054 c845 5245 ae80" scc_line = SccLine.from_str(line_str) self.assertEqual(12, len(scc_line.scc_words)) self.assertEqual( SmpteTimeCode(1, 3, 27, 29, FPS_30).to_temporal_offset(), scc_line.time_code.to_temporal_offset()) self.assertEqual("01:03:27:29 {RU2}{RU2}{CR}{CR}{14R}{14R}HEY, THERE.", scc_line.to_disassembly()) self.assertEqual(SccCaptionStyle.RollUp, scc_line.get_style())
def test_scc_line_from_str_with_unknown_style(self): line_str = "01:03:27:29 " scc_line = SccLine.from_str(line_str) self.assertEqual(0, len(scc_line.scc_words)) self.assertEqual( SmpteTimeCode(1, 3, 27, 29, FPS_30).to_temporal_offset(), scc_line.time_code.to_temporal_offset()) self.assertEqual("01:03:27:29 ", scc_line.to_disassembly()) self.assertEqual(SccCaptionStyle.Unknown, scc_line.get_style()) line_str = "01:03:27:29 9024 c845 d92c 2054 c845 5245 ae80 9f9f" scc_line = SccLine.from_str(line_str) self.assertEqual(8, len(scc_line.scc_words)) self.assertEqual( SmpteTimeCode(1, 3, 27, 29, FPS_30).to_temporal_offset(), scc_line.time_code.to_temporal_offset()) self.assertEqual("01:03:27:29 {BBl}HEY, THERE.{??}", scc_line.to_disassembly()) self.assertEqual(SccCaptionStyle.Unknown, scc_line.get_style())
def test_scc_line_from_str_with_pop_on_style(self): line_str = "01:03:27:29 94ae 94ae 9420 9420 94f2 94f2 c845 d92c 2054 c845 5245 ae80 942c 942c 8080 8080 942f 942f" scc_line = SccLine.from_str(line_str) self.assertEqual(18, len(scc_line.scc_words)) self.assertEqual( SmpteTimeCode(1, 3, 27, 29, FPS_30).to_temporal_offset(), scc_line.time_code.to_temporal_offset()) self.assertEqual( "01:03:27:29 {ENM}{ENM}{RCL}{RCL}{1504}{1504}HEY, THERE.{EDM}{EDM}{}{}{EOC}{EOC}", scc_line.to_disassembly()) self.assertEqual(SccCaptionStyle.PopOn, scc_line.get_style())
def test_from_frames(self): time_code = SmpteTimeCode.from_frames(111694, FPS_30) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_30, time_code.get_frame_rate()) self.assertFalse(time_code.is_drop_frame()) self.assertEqual(111694, time_code.to_frames()) self.assertEqual("01:02:03:04", str(time_code)) time_code = SmpteTimeCode.from_frames(111582, FPS_29_97) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(111582, time_code.to_frames()) self.assertEqual("01:02:03;04", str(time_code))
def test_parse_non_drop_frame_time_code(self): time_code = SmpteTimeCode.parse("01:02:03:04", FPS_30) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(3, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_30, time_code.get_frame_rate()) self.assertFalse(time_code.is_drop_frame()) self.assertEqual(111694, time_code.to_frames()) self.assertAlmostEqual(3723.133, time_code.to_seconds(), delta=0.001) self.assertEqual("01:02:03:04", str(time_code))
def check_caption(self, paragraph: P, caption_id: str, begin: str, end: Optional[str], *children): self.assertEqual(caption_id, paragraph.get_id()) self.assertEqual( SmpteTimeCode.parse(begin, FPS_30).to_temporal_offset(), paragraph.get_begin()) if end is not None: self.assertEqual( SmpteTimeCode.parse(end, FPS_30).to_temporal_offset(), paragraph.get_end()) p_children = list(paragraph) self.assertEqual(len(children), len(p_children)) for (index, child) in enumerate(p_children): expected_child = children[index] if isinstance(expected_child, str): texts = list(child) self.assertEqual(expected_child, texts[0].get_text()) else: self.assertEqual(expected_child, Br)
def test_add_frames(self): time_code = SmpteTimeCode.parse("01:02:03:04", FPS_30) time_code.add_frames(30) self.assertEqual(1, time_code.get_hours()) self.assertEqual(2, time_code.get_minutes()) self.assertEqual(4, time_code.get_seconds()) self.assertEqual(4, time_code.get_frames()) self.assertEqual(FPS_30, time_code.get_frame_rate()) self.assertFalse(time_code.is_drop_frame()) self.assertEqual(111724, time_code.to_frames()) self.assertEqual(Fraction(111724, 30), time_code.to_temporal_offset()) self.assertEqual("01:02:04:04", str(time_code)) time_code = SmpteTimeCode.parse("00:00:59;29", FPS_29_97) time_code.add_frames() self.assertEqual(0, time_code.get_hours()) self.assertEqual(1, time_code.get_minutes()) self.assertEqual(0, time_code.get_seconds()) self.assertEqual(2, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(1_800, time_code.to_frames()) self.assertEqual(Fraction(1800, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("00:01:00;02", str(time_code)) time_code = SmpteTimeCode.parse("00:19:59;29", FPS_29_97) time_code.add_frames() self.assertEqual(0, time_code.get_hours()) self.assertEqual(20, time_code.get_minutes()) self.assertEqual(0, time_code.get_seconds()) self.assertEqual(0, time_code.get_frames()) self.assertEqual(FPS_29_97, time_code.get_frame_rate()) self.assertTrue(time_code.is_drop_frame()) self.assertEqual(35_964, time_code.to_frames()) self.assertEqual(Fraction(35964, Fraction(30000, 1001)), time_code.to_temporal_offset()) self.assertEqual("00:20:00;00", str(time_code))
def from_str(line: str) -> Optional[SccLine]: """Creates a SCC line instance from the specified string""" if not line: return None regex = re.compile(SCC_LINE_PATTERN) match = regex.match(line) if match is None: return None time_code = match.group(1) time_offset = SmpteTimeCode.parse(time_code, FPS_30) hex_words = line.split('\t')[1].split(' ') scc_words = [SccWord.from_str(hex_word) for hex_word in hex_words if hex_word] return SccLine(time_offset, scc_words)
def test_time_code_frames_conversion(self): time_code = SmpteTimeCode.from_frames(1795, FPS_30) self.assertEqual("00:00:59:25", str(time_code)) self.assertEqual(1795, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1796, FPS_30) self.assertEqual("00:00:59:26", str(time_code)) self.assertEqual(1796, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1797, FPS_30) self.assertEqual("00:00:59:27", str(time_code)) self.assertEqual(1797, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1798, FPS_30) self.assertEqual("00:00:59:28", str(time_code)) self.assertEqual(1798, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1799, FPS_30) self.assertEqual("00:00:59:29", str(time_code)) self.assertEqual(1799, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1800, FPS_30) self.assertEqual("00:01:00:00", str(time_code)) self.assertEqual(1800, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1801, FPS_30) self.assertEqual("00:01:00:01", str(time_code)) self.assertEqual(1801, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1802, FPS_30) self.assertEqual("00:01:00:02", str(time_code)) self.assertEqual(1802, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1803, FPS_30) self.assertEqual("00:01:00:03", str(time_code)) self.assertEqual(1803, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1804, FPS_30) self.assertEqual("00:01:00:04", str(time_code)) self.assertEqual(1804, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1805, FPS_30) self.assertEqual("00:01:00:05", str(time_code)) self.assertEqual(1805, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17977, FPS_30) self.assertEqual("00:09:59:07", str(time_code)) self.assertEqual(17977, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17978, FPS_30) self.assertEqual("00:09:59:08", str(time_code)) self.assertEqual(17978, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17979, FPS_30) self.assertEqual("00:09:59:09", str(time_code)) self.assertEqual(17979, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17980, FPS_30) self.assertEqual("00:09:59:10", str(time_code)) self.assertEqual(17980, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17981, FPS_30) self.assertEqual("00:09:59:11", str(time_code)) self.assertEqual(17981, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17982, FPS_30) self.assertEqual("00:09:59:12", str(time_code)) self.assertEqual(17982, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17983, FPS_30) self.assertEqual("00:09:59:13", str(time_code)) self.assertEqual(17983, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17984, FPS_30) self.assertEqual("00:09:59:14", str(time_code)) self.assertEqual(17984, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17985, FPS_30) self.assertEqual("00:09:59:15", str(time_code)) self.assertEqual(17985, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17986, FPS_30) self.assertEqual("00:09:59:16", str(time_code)) self.assertEqual(17986, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17987, FPS_30) self.assertEqual("00:09:59:17", str(time_code)) self.assertEqual(17987, time_code.to_frames())
def __init__(self, gsi_block: bytes, disable_fill_line_gap: bool = False, disable_line_padding: bool = False, start_tc: typing.Optional[str] = None, font_stack: typing.Tuple[typing.Union[ str, styles.GenericFontFamilyType]] = None, max_row_count: typing.Optional[typing.Union[int, str]] = None): self.gsi = _GSIBlock._make( struct.unpack( '3s8sc2s2s32s32s32s32s32s32s16s6s6s2s5s5s3s2s2s1s8s8s1s1s3s32s32s32s75x576s', gsi_block)) self.doc = model.ContentDocument() self.doc.set_cell_resolution( model.CellResolutionType( columns=round(100 * DEFAULT_TELETEXT_COLS / (100 - 2 * DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT)), rows=round(100 * DEFAULT_TELETEXT_ROWS / (100 - 2 * DEFAULT_VERTICAL_SAFE_MARGIN_PCT)))) self.doc.set_active_area( model.ActiveAreaType( left_offset=DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT / 100, top_offset=DEFAULT_VERTICAL_SAFE_MARGIN_PCT / 100, width=1 - 2 * DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT / 100, height=1 - 2 * DEFAULT_VERTICAL_SAFE_MARGIN_PCT / 100)) self.body = model.Body(self.doc) if not disable_fill_line_gap: self.body.set_style(styles.StyleProperties.FillLineGap, True) if not disable_line_padding: self.body.set_style( styles.StyleProperties.LinePadding, styles.LengthType(LINE_PADDING_LENGTH_C, styles.LengthType.Units.c)) if font_stack is not None: self.body.set_style(styles.StyleProperties.FontFamily, font_stack) else: self.body.set_style(styles.StyleProperties.FontFamily, DEFAULT_FONT_STACK) self.doc.set_body(self.body) self.sgn_to_div_map = {} self.last_sn = None self.is_in_extension = False self.tti_tf = None self.fps = _DFC_FRACTION_MAP.get(self.gsi.DFC) if self.fps is None: LOGGER.error("Unknown GSI DFC value %s, defaulting to 25 fps", self.gsi.DFC) self.fps = Fraction(25) else: LOGGER.debug("GSI DFC: %s", self.gsi.DFC) self.cct = self.gsi.CCT LOGGER.debug("GSI CCT: %s", self.gsi.CCT) try: self.tti_count = int(self.gsi.TNB) LOGGER.debug("GSI TNB: %s", self.gsi.TNB) except ValueError: LOGGER.error("Invalid TNB field value: %s", self.gsi.TNB) self.tti_count = sys.maxsize self.language = _LC_BCP47_MAP.get(self.gsi.LC) if self.language is None: LOGGER.warning( "Unknown LC value: %s, defaulting to 'unspecified''", self.gsi.LC) self.language = "" else: LOGGER.debug("GSI LC: %s", self.gsi.LC) self.doc.set_lang(self.language) if start_tc is None: self.start_offset = 0 elif start_tc == "TCP": try: self.start_offset = SmpteTimeCode( int(self.gsi.TCP[0:2]), int(self.gsi.TCP[2:4]), int(self.gsi.TCP[4:6]), int(self.gsi.TCP[6:8]), self.get_fps()).to_temporal_offset() LOGGER.debug("GSI TCP: %s", self.gsi.TCP) except ValueError: LOGGER.error("Invalid TCP value: %s", self.gsi.tcp) self.start_offset = 0 else: try: self.start_offset = SmpteTimeCode.parse( start_tc, self.get_fps()).to_temporal_offset() except ValueError: LOGGER.error("Invalid start_tc value") raise if max_row_count is None or self.is_teletext(): self.max_row_count = DEFAULT_TELETEXT_ROWS elif isinstance(max_row_count, str) and max_row_count == "MNR": try: self.max_row_count = int(self.gsi.MNR) LOGGER.debug("GSI MNR: %s", self.gsi.MNR) except ValueError: LOGGER.error("Invalid MNR value: %s", self.gsi.MNR) self.start_offset = DEFAULT_TELETEXT_ROWS else: self.max_row_count = max_row_count # p_element for use across cumulative subtitles self.cur_p_element = None
def process_tti_block(self, tti_block: bytes): """Processes a single TTI block """ if tti_block is None: raise ValueError("tti_block should not be None") tti = _TTIBlock._make(struct.unpack('<BHBBBBBBBBBBBBB112s', tti_block)) LOGGER.debug("Subtitle SN: %s", tti.SN) LOGGER.debug(" EBN: %s", tti.EBN) LOGGER.debug(" CS: %s", tti.CS) LOGGER.debug(" SGN: %s", tti.SGN) LOGGER.debug(" JC: %s", tti.JC) LOGGER.debug(" VP: %s", tti.VP) if 0xEF < tti.EBN < 0xFF: # skip user data and reserved blocks return if not self.is_in_extension: self.tti_tf = b'' self.tti_tf += tti.TF.strip(b'\x8f') is_double_height_characters = tf.has_double_height_char(self.tti_tf) # continue accumulating if we have an extension block if tti.EBN != 0xFF: self.is_in_extension = True return self.is_in_extension = False # apply program offset try: tci = SmpteTimeCode(tti.TCIh, tti.TCIm, tti.TCIs, tti.TCIf, self.get_fps()) tco = SmpteTimeCode(tti.TCOh, tti.TCOm, tti.TCOs, tti.TCOf, self.get_fps()) except ValueError: LOGGER.error("Invalid TTI timecode") return begin_time = tci.to_temporal_offset() - self.start_offset if begin_time < 0: LOGGER.debug( "Skipping subtitle because TCI is less than start time") return LOGGER.debug(" Time in: %s", tci) end_time = tco.to_temporal_offset() - self.start_offset if end_time < begin_time: LOGGER.error("Subtitle TCO is less than TCI") return LOGGER.debug(" Time out: %s", tco) # create a new subtitle if SN changes and we are not in cumulative mode if tti.SN is not self.last_sn and tti.CS in (0x00, 0x01): self.last_sn = tti.SN # find the div to which the subtitle belongs, based on SGN div_element = self.sgn_to_div_map.get(tti.SGN) # create the div if it does not exist if div_element is None: div_element = model.Div(self.doc) self.body.push_child(div_element) self.sgn_to_div_map[tti.SGN] = div_element # create the p that will hold the subtitle self.cur_p_element = model.P(self.doc) if tti.JC == 0x01: self.cur_p_element.set_style(styles.StyleProperties.TextAlign, styles.TextAlignType.start) elif tti.JC == 0x03: self.cur_p_element.set_style(styles.StyleProperties.TextAlign, styles.TextAlignType.end) else: self.cur_p_element.set_style(styles.StyleProperties.TextAlign, styles.TextAlignType.center) self.cur_p_element.set_style( styles.StyleProperties.LineHeight, styles.LengthType(DEFAULT_LINE_HEIGHT_PCT, styles.LengthType.Units.pct)) if self.is_teletext() and not is_double_height_characters: font_size = DEFAULT_SINGLE_HEIGHT_FONT_SIZE_PCT else: font_size = DEFAULT_DOUBLE_HEIGHT_FONT_SIZE_PCT self.cur_p_element.set_style( styles.StyleProperties.FontSize, styles.LengthType(font_size, styles.LengthType.Units.pct)) safe_area_height = round(100 - DEFAULT_VERTICAL_SAFE_MARGIN_PCT * 2) safe_area_width = round(100 - DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT * 2) # assume that VP < max number of rows/2 means bottom-aligned and otherwise top-aligned # probably should offer an option to override this if tti.VP < self.get_max_row_count() // 2: # top-aligned large region r_y = DEFAULT_VERTICAL_SAFE_MARGIN_PCT + ( (tti.VP - 1) / self.get_max_row_count()) * safe_area_height r_height = 100 - DEFAULT_VERTICAL_SAFE_MARGIN_PCT - r_y region = _get_region_from_model( self.doc, round(DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT), r_y, safe_area_width, r_height, styles.DisplayAlignType.before) else: line_count = tf.line_count(self.tti_tf, is_double_height_characters) vp = tti.VP line_height = 2 if is_double_height_characters else 1 r_y = DEFAULT_VERTICAL_SAFE_MARGIN_PCT r_height = ((vp + line_count * line_height - 1) / self.get_max_row_count()) * safe_area_height region = _get_region_from_model( self.doc, round(DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT), r_y, safe_area_width, r_height, styles.DisplayAlignType.after) self.cur_p_element.set_region(region) div_element.push_child(self.cur_p_element) if tti.CS in (0x01, 0x02, 0x03): # create a nested span if we are in cumulative mode sub_element = model.Span(self.doc) self.cur_p_element.push_child(sub_element) else: sub_element = self.cur_p_element sub_element.set_begin(begin_time) sub_element.set_end(end_time) LOGGER.debug(" TF: %s", self.tti_tf) tf.to_model(sub_element, self.is_teletext(), self.get_cct(), self.tti_tf) if tti.CS in (0x01, 0x02): sub_element.push_child(model.Br(self.doc))
def test_drop_frame_time_code_frames_conversion(self): time_code = SmpteTimeCode.from_frames(1795, FPS_29_97) self.assertEqual("00:00:59;25", str(time_code)) self.assertEqual(1795, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1796, FPS_29_97) self.assertEqual("00:00:59;26", str(time_code)) self.assertEqual(1796, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1797, FPS_29_97) self.assertEqual("00:00:59;27", str(time_code)) self.assertEqual(1797, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1798, FPS_29_97) self.assertEqual("00:00:59;28", str(time_code)) self.assertEqual(1798, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1799, FPS_29_97) self.assertEqual("00:00:59;29", str(time_code)) self.assertEqual(1799, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1800, FPS_29_97) self.assertEqual("00:01:00;02", str(time_code)) self.assertEqual(1800, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1801, FPS_29_97) self.assertEqual("00:01:00;03", str(time_code)) self.assertEqual(1801, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1802, FPS_29_97) self.assertEqual("00:01:00;04", str(time_code)) self.assertEqual(1802, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1803, FPS_29_97) self.assertEqual("00:01:00;05", str(time_code)) self.assertEqual(1803, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1804, FPS_29_97) self.assertEqual("00:01:00;06", str(time_code)) self.assertEqual(1804, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(1805, FPS_29_97) self.assertEqual("00:01:00;07", str(time_code)) self.assertEqual(1805, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17977, FPS_29_97) self.assertEqual("00:09:59;25", str(time_code)) self.assertEqual(17977, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17978, FPS_29_97) self.assertEqual("00:09:59;26", str(time_code)) self.assertEqual(17978, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17979, FPS_29_97) self.assertEqual("00:09:59;27", str(time_code)) self.assertEqual(17979, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17980, FPS_29_97) self.assertEqual("00:09:59;28", str(time_code)) self.assertEqual(17980, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17981, FPS_29_97) self.assertEqual("00:09:59;29", str(time_code)) self.assertEqual(17981, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17982, FPS_29_97) self.assertEqual("00:10:00;00", str(time_code)) self.assertEqual(17982, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17983, FPS_29_97) self.assertEqual("00:10:00;01", str(time_code)) self.assertEqual(17983, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17984, FPS_29_97) self.assertEqual("00:10:00;02", str(time_code)) self.assertEqual(17984, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17985, FPS_29_97) self.assertEqual("00:10:00;03", str(time_code)) self.assertEqual(17985, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17986, FPS_29_97) self.assertEqual("00:10:00;04", str(time_code)) self.assertEqual(17986, time_code.to_frames()) time_code = SmpteTimeCode.from_frames(17987, FPS_29_97) self.assertEqual("00:10:00;05", str(time_code)) self.assertEqual(17987, time_code.to_frames())
def test_drop_frame_time_code_seconds_conversion(self): time_code = SmpteTimeCode.from_frames(1795, FPS_29_97) self.assertEqual("00:00:59;25", str(time_code)) self.assertAlmostEqual(59.893, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1796, FPS_29_97) self.assertEqual("00:00:59;26", str(time_code)) self.assertAlmostEqual(59.926, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1797, FPS_29_97) self.assertEqual("00:00:59;27", str(time_code)) self.assertAlmostEqual(59.959, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1798, FPS_29_97) self.assertEqual("00:00:59;28", str(time_code)) self.assertAlmostEqual(59.993, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1799, FPS_29_97) self.assertEqual("00:00:59;29", str(time_code)) self.assertAlmostEqual(60.026, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1800, FPS_29_97) self.assertEqual("00:01:00;02", str(time_code)) self.assertAlmostEqual(60.06, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1801, FPS_29_97) self.assertEqual("00:01:00;03", str(time_code)) self.assertAlmostEqual(60.093, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1802, FPS_29_97) self.assertEqual("00:01:00;04", str(time_code)) self.assertAlmostEqual(60.126, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1803, FPS_29_97) self.assertEqual("00:01:00;05", str(time_code)) self.assertAlmostEqual(60.160, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1804, FPS_29_97) self.assertEqual("00:01:00;06", str(time_code)) self.assertAlmostEqual(60.193, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1805, FPS_29_97) self.assertEqual("00:01:00;07", str(time_code)) self.assertAlmostEqual(60.226, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17977, FPS_29_97) self.assertEqual("00:09:59;25", str(time_code)) self.assertAlmostEqual(599.832, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17978, FPS_29_97) self.assertEqual("00:09:59;26", str(time_code)) self.assertAlmostEqual(599.865, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17979, FPS_29_97) self.assertEqual("00:09:59;27", str(time_code)) self.assertAlmostEqual(599.899, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17980, FPS_29_97) self.assertEqual("00:09:59;28", str(time_code)) self.assertAlmostEqual(599.932, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17981, FPS_29_97) self.assertEqual("00:09:59;29", str(time_code)) self.assertAlmostEqual(599.966, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17982, FPS_29_97) self.assertEqual("00:10:00;00", str(time_code)) self.assertAlmostEqual(599.999, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17983, FPS_29_97) self.assertEqual("00:10:00;01", str(time_code)) self.assertAlmostEqual(600.032, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17984, FPS_29_97) self.assertEqual("00:10:00;02", str(time_code)) self.assertAlmostEqual(600.066, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17985, FPS_29_97) self.assertEqual("00:10:00;03", str(time_code)) self.assertAlmostEqual(600.099, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17986, FPS_29_97) self.assertEqual("00:10:00;04", str(time_code)) self.assertAlmostEqual(600.132, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17987, FPS_29_97) self.assertEqual("00:10:00;05", str(time_code)) self.assertAlmostEqual(600.166, time_code.to_seconds(), delta=0.001)
def test_time_code_seconds_conversion(self): time_code = SmpteTimeCode.from_frames(1795, FPS_30) self.assertEqual("00:00:59:25", str(time_code)) self.assertAlmostEqual(59.833, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1796, FPS_30) self.assertEqual("00:00:59:26", str(time_code)) self.assertAlmostEqual(59.866, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1797, FPS_30) self.assertEqual("00:00:59:27", str(time_code)) self.assertAlmostEqual(59.9, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1798, FPS_30) self.assertEqual("00:00:59:28", str(time_code)) self.assertAlmostEqual(59.933, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1799, FPS_30) self.assertEqual("00:00:59:29", str(time_code)) self.assertAlmostEqual(59.966, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1800, FPS_30) self.assertEqual("00:01:00:00", str(time_code)) self.assertAlmostEqual(60.0, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1801, FPS_30) self.assertEqual("00:01:00:01", str(time_code)) self.assertAlmostEqual(60.033, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1802, FPS_30) self.assertEqual("00:01:00:02", str(time_code)) self.assertAlmostEqual(60.066, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1803, FPS_30) self.assertEqual("00:01:00:03", str(time_code)) self.assertAlmostEqual(60.1, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1804, FPS_30) self.assertEqual("00:01:00:04", str(time_code)) self.assertAlmostEqual(60.133, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(1805, FPS_30) self.assertEqual("00:01:00:05", str(time_code)) self.assertAlmostEqual(60.166, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17977, FPS_30) self.assertEqual("00:09:59:07", str(time_code)) self.assertAlmostEqual(599.233, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17978, FPS_30) self.assertEqual("00:09:59:08", str(time_code)) self.assertAlmostEqual(599.266, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17979, FPS_30) self.assertEqual("00:09:59:09", str(time_code)) self.assertAlmostEqual(599.3, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17980, FPS_30) self.assertEqual("00:09:59:10", str(time_code)) self.assertAlmostEqual(599.333, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17981, FPS_30) self.assertEqual("00:09:59:11", str(time_code)) self.assertAlmostEqual(599.366, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17982, FPS_30) self.assertEqual("00:09:59:12", str(time_code)) self.assertAlmostEqual(599.4, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17983, FPS_30) self.assertEqual("00:09:59:13", str(time_code)) self.assertAlmostEqual(599.433, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17984, FPS_30) self.assertEqual("00:09:59:14", str(time_code)) self.assertAlmostEqual(599.466, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17985, FPS_30) self.assertEqual("00:09:59:15", str(time_code)) self.assertAlmostEqual(599.5, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17986, FPS_30) self.assertEqual("00:09:59:16", str(time_code)) self.assertAlmostEqual(599.533, time_code.to_seconds(), delta=0.001) time_code = SmpteTimeCode.from_frames(17987, FPS_30) self.assertEqual("00:09:59:17", str(time_code)) self.assertAlmostEqual(599.566, time_code.to_seconds(), delta=0.001)