Esempio n. 1
0
    def cell_resolution(self):

        cr = model.CellResolutionType(rows=10, columns=20)

        self.assertEqual(cr.columns, 20)

        self.assertEqual(cr.rows, 10)

        with self.assertRaises(ValueError):
            cr = model.CellResolutionType(rows=0, columns=20)
Esempio n. 2
0
    def test_copy_to(self):
        src = model.ContentDocument()

        src.set_display_aspect_ratio(Fraction(16, 9))
        src.set_active_area(model.ActiveAreaType(0.1, 0.15, 0.8, 0.7))
        src.set_px_resolution(model.PixelResolutionType(height=480, width=640))
        src.set_lang("fr")
        src.set_cell_resolution(model.CellResolutionType(rows=10, columns=20))

        src.put_initial_value(styles.StyleProperties.Color,
                              styles.ColorType((12, 23, 43, 56)))

        dest = model.ContentDocument()

        src.copy_to(dest)

        self.assertEqual(dest.get_display_aspect_ratio(),
                         src.get_display_aspect_ratio())
        self.assertEqual(dest.get_active_area(), src.get_active_area())
        self.assertEqual(dest.get_px_resolution(), src.get_px_resolution())
        self.assertEqual(dest.get_lang(), src.get_lang())
        self.assertEqual(dest.get_cell_resolution(), src.get_cell_resolution())

        self.assertSequenceEqual(list(dest.iter_initial_values()),
                                 list(src.iter_initial_values()))
Esempio n. 3
0
  def extract(ttml_element) -> model.CellResolutionType:

    cr = ttml_element.attrib.get(CellResolutionAttribute.qn)

    if cr is not None:

      m = CellResolutionAttribute._CELL_RESOLUTION_RE.match(cr)

      if m is not None:

        return model.CellResolutionType(int(m.group(1)), int(m.group(2)))

      LOGGER.error("ttp:cellResolution invalid syntax")

    # default value in TTML

    return model.CellResolutionType(rows=15, columns=32)
Esempio n. 4
0
  def test_init(self):
    d = model.ContentDocument()

    self.assertIsNone(d.get_body())
    
    self.assertEqual(d.get_px_resolution(), model.PixelResolutionType(width=1920, height=1080))

    self.assertEqual(len(d.iter_initial_values()), 0)

    self.assertEqual(len(d.iter_regions()), 0)

    self.assertEqual(d.get_cell_resolution(), model.CellResolutionType(rows=15, columns=32))
Esempio n. 5
0
    def from_model(model_doc: model.ContentDocument) -> et.Element:

        tt_element = et.Element(TTElement.qn)

        imsc_attr.XMLLangAttribute.set(tt_element, model_doc.get_lang())

        if model_doc.get_cell_resolution() != model.CellResolutionType(
                rows=15, columns=32):
            imsc_attr.CellResolutionAttribute.set(
                tt_element, model_doc.get_cell_resolution())

        has_px = False

        all_elements = list(model_doc.iter_regions())

        if model_doc.get_body() is not None:
            all_elements.extend(model_doc.get_body().dfs_iterator())

        for element in all_elements:
            for model_style_prop in element.iter_styles():
                if StyleProperties.BY_MODEL_PROP[model_style_prop].has_px(
                        element.get_style(model_style_prop)):
                    has_px = True
                    break
            if has_px:
                break

        if model_doc.get_px_resolution() is not None and has_px:
            imsc_attr.ExtentAttribute.set(tt_element,
                                          model_doc.get_px_resolution())

        if model_doc.get_active_area() is not None:
            imsc_attr.ActiveAreaAttribute.set(tt_element,
                                              model_doc.get_active_area())

        # Write the <head> section first
        head_element = HeadElement.from_model(model_doc)

        if head_element is not None:
            tt_element.append(head_element)

        model_body = model_doc.get_body()

        if model_body is not None:

            body_element = BodyElement.from_model(model_body)

            if body_element is not None:
                tt_element.append(body_element)

        return tt_element
Esempio n. 6
0
  def from_model(
    model_doc: model.ContentDocument,
    frame_rate: typing.Optional[Fraction],
    time_expression_syntax: imsc_attr.TimeExpressionSyntaxEnum,
    progress_callback: typing.Callable[[numbers.Real], typing.NoReturn]
  ) -> et.Element:
    '''Converts the data model to an IMSC document contained in an ElementTree Element'''

    ctx = TTMLElement.WritingContext(frame_rate, time_expression_syntax)

    tt_element = et.Element(TTElement.qn)

    imsc_attr.XMLLangAttribute.set(tt_element, model_doc.get_lang())
    
    if model_doc.get_cell_resolution() != model.CellResolutionType(rows=15, columns=32):
      imsc_attr.CellResolutionAttribute.set(tt_element, model_doc.get_cell_resolution())

    has_px = False

    all_elements = list(model_doc.iter_regions())

    if model_doc.get_body() is not None:
      all_elements.extend(model_doc.get_body().dfs_iterator())

    for element in all_elements:
      for model_style_prop in element.iter_styles():
        if StyleProperties.BY_MODEL_PROP[model_style_prop].has_px(element.get_style(model_style_prop)):
          has_px = True
          break
      for animation_step in element.iter_animation_steps():
        if StyleProperties.BY_MODEL_PROP[animation_step.style_property].has_px(animation_step.value):
          has_px = True
          break      
      if has_px:
        break

    if model_doc.get_px_resolution() is not None and has_px:
      imsc_attr.ExtentAttribute.set(tt_element, model_doc.get_px_resolution())

    if model_doc.get_active_area() is not None:
      imsc_attr.ActiveAreaAttribute.set(tt_element, model_doc.get_active_area())

    if model_doc.get_display_aspect_ratio() is not None:
      imsc_attr.DisplayAspectRatioAttribute.set(tt_element, model_doc.get_display_aspect_ratio())

    if frame_rate is not None:
      imsc_attr.FrameRateAttribute.set(tt_element, frame_rate)

    # Write the <head> section first
    head_element = HeadElement.from_model(ctx, model_doc)

    progress_callback(0.5)

    if head_element is not None:
      tt_element.append(head_element)

    model_body = model_doc.get_body()

    if model_body is not None:

      body_element = BodyElement.from_model(ctx, model_body)

      if body_element is not None:
        tt_element.append(body_element)

    progress_callback(1.0)

    return tt_element
Esempio n. 7
0
    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