summaryrefslogtreecommitdiffhomepage
path: root/libs/knowit/properties/video.py
blob: 60c5b8264a894e36102ea34d3b504e4853fafd55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import re
import typing
from decimal import Decimal

from knowit.core import Configurable
from knowit.core import Property
from knowit.utils import round_decimal


class VideoCodec(Configurable[str]):
    """Video Codec handler."""

    @classmethod
    def _extract_key(cls, value) -> str:
        key = value.upper().split('/')[-1]
        if key.startswith('V_'):
            key = key[2:]

        return key.split(' ')[-1]


class VideoDimensions(Property[int]):
    """Dimensions property."""

    def __init__(self, *args: str, dimension='width' or 'height', **kwargs):
        """Initialize the object."""
        super().__init__(*args, **kwargs)
        self.dimension = dimension

    dimensions_re = re.compile(r'(?P<width>\d+)x(?P<height>\d+)')

    def handle(self, value, context) -> typing.Optional[int]:
        """Handle ratio."""
        match = self.dimensions_re.match(value)
        if match:
            match_dict = match.groupdict()
            try:
                value = match_dict[self.dimension]
            except KeyError:
                pass
            else:
                return int(value)

        self.report(value, context)
        return None


class VideoEncoder(Configurable):
    """Video Encoder property."""


class VideoHdrFormat(Configurable):
    """Video HDR Format property."""


class VideoProfile(Configurable[str]):
    """Video Profile property."""

    @classmethod
    def _extract_key(cls, value) -> str:
        return value.upper().split('@')[0]


class VideoProfileLevel(Configurable[str]):
    """Video Profile Level property."""

    @classmethod
    def _extract_key(cls, value) -> typing.Union[str, bool]:
        values = str(value).upper().split('@')
        if len(values) > 1:
            value = values[1]
            return value

        # There's no level, so don't warn or report it
        return False


class VideoProfileTier(Configurable[str]):
    """Video Profile Tier property."""

    @classmethod
    def _extract_key(cls, value) -> typing.Union[str, bool]:
        values = str(value).upper().split('@')
        if len(values) > 2:
            return values[2]

        # There's no tier, so don't warn or report it
        return False


class Ratio(Property[Decimal]):
    """Ratio property."""

    def __init__(self, *args: str, unit=None, **kwargs):
        """Initialize the object."""
        super().__init__(*args, **kwargs)
        self.unit = unit

    ratio_re = re.compile(r'(?P<width>\d+)[:/](?P<height>\d+)')

    def handle(self, value, context) -> typing.Optional[Decimal]:
        """Handle ratio."""
        match = self.ratio_re.match(value)
        if match:
            width, height = match.groups()
            if (width, height) == ('0', '1'):  # identity
                return Decimal('1.0')

            if height:
                result = round_decimal(Decimal(width) / Decimal(height), min_digits=1, max_digits=3)
                if self.unit:
                    result *= self.unit

                return result

        self.report(value, context)
        return None


class ScanType(Configurable[str]):
    """Scan Type property."""