1# -*- coding: utf-8 -*-
2
3from __future__ import absolute_import
4
5from .base import Type
6from .isobmff import IsoBmff
7
8
9class Mp4(IsoBmff):
10    """
11    Implements the MP4 video type matcher.
12    """
13    MIME = 'video/mp4'
14    EXTENSION = 'mp4'
15
16    def __init__(self):
17        super(Mp4, self).__init__(
18            mime=Mp4.MIME,
19            extension=Mp4.EXTENSION
20        )
21
22    def match(self, buf):
23        if not self._is_isobmff(buf):
24            return False
25
26        major_brand, minor_version, compatible_brands = self._get_ftyp(buf)
27        return major_brand in ['mp41', 'mp42', 'isom']
28
29
30class M4v(Type):
31    """
32    Implements the M4V video type matcher.
33    """
34    MIME = 'video/x-m4v'
35    EXTENSION = 'm4v'
36
37    def __init__(self):
38        super(M4v, self).__init__(
39            mime=M4v.MIME,
40            extension=M4v.EXTENSION
41        )
42
43    def match(self, buf):
44        return (len(buf) > 10 and
45                buf[0] == 0x0 and buf[1] == 0x0 and
46                buf[2] == 0x0 and buf[3] == 0x1C and
47                buf[4] == 0x66 and buf[5] == 0x74 and
48                buf[6] == 0x79 and buf[7] == 0x70 and
49                buf[8] == 0x4D and buf[9] == 0x34 and
50                buf[10] == 0x56)
51
52
53class Mkv(Type):
54    """
55    Implements the MKV video type matcher.
56    """
57    MIME = 'video/x-matroska'
58    EXTENSION = 'mkv'
59
60    def __init__(self):
61        super(Mkv, self).__init__(
62            mime=Mkv.MIME,
63            extension=Mkv.EXTENSION
64        )
65
66    def match(self, buf):
67        return ((len(buf) > 15 and
68                buf[0] == 0x1A and buf[1] == 0x45 and
69                buf[2] == 0xDF and buf[3] == 0xA3 and
70                buf[4] == 0x93 and buf[5] == 0x42 and
71                buf[6] == 0x82 and buf[7] == 0x88 and
72                buf[8] == 0x6D and buf[9] == 0x61 and
73                buf[10] == 0x74 and buf[11] == 0x72 and
74                buf[12] == 0x6F and buf[13] == 0x73 and
75                buf[14] == 0x6B and buf[15] == 0x61) or
76                (len(buf) > 38 and
77                    buf[31] == 0x6D and buf[32] == 0x61 and
78                    buf[33] == 0x74 and buf[34] == 0x72 and
79                    buf[35] == 0x6f and buf[36] == 0x73 and
80                    buf[37] == 0x6B and buf[38] == 0x61))
81
82
83class Webm(Type):
84    """
85    Implements the WebM video type matcher.
86    """
87    MIME = 'video/webm'
88    EXTENSION = 'webm'
89
90    def __init__(self):
91        super(Webm, self).__init__(
92            mime=Webm.MIME,
93            extension=Webm.EXTENSION
94        )
95
96    def match(self, buf):
97        return (len(buf) > 3 and
98                buf[0] == 0x1A and
99                buf[1] == 0x45 and
100                buf[2] == 0xDF and
101                buf[3] == 0xA3)
102
103
104class Mov(IsoBmff):
105    """
106    Implements the MOV video type matcher.
107    """
108    MIME = 'video/quicktime'
109    EXTENSION = 'mov'
110
111    def __init__(self):
112        super(Mov, self).__init__(
113            mime=Mov.MIME,
114            extension=Mov.EXTENSION
115        )
116
117    def match(self, buf):
118        if not self._is_isobmff(buf):
119            return False
120
121        major_brand, minor_version, compatible_brands = self._get_ftyp(buf)
122        return major_brand == 'qt  '
123
124
125class Avi(Type):
126    """
127    Implements the AVI video type matcher.
128    """
129    MIME = 'video/x-msvideo'
130    EXTENSION = 'avi'
131
132    def __init__(self):
133        super(Avi, self).__init__(
134            mime=Avi.MIME,
135            extension=Avi.EXTENSION
136        )
137
138    def match(self, buf):
139        return (len(buf) > 10 and
140                buf[0] == 0x52 and
141                buf[1] == 0x49 and
142                buf[2] == 0x46 and
143                buf[3] == 0x46 and
144                buf[8] == 0x41 and
145                buf[9] == 0x56 and
146                buf[10] == 0x49)
147
148
149class Wmv(Type):
150    """
151    Implements the WMV video type matcher.
152    """
153    MIME = 'video/x-ms-wmv'
154    EXTENSION = 'wmv'
155
156    def __init__(self):
157        super(Wmv, self).__init__(
158            mime=Wmv.MIME,
159            extension=Wmv.EXTENSION
160        )
161
162    def match(self, buf):
163        return (len(buf) > 9 and
164                buf[0] == 0x30 and
165                buf[1] == 0x26 and
166                buf[2] == 0xB2 and
167                buf[3] == 0x75 and
168                buf[4] == 0x8E and
169                buf[5] == 0x66 and
170                buf[6] == 0xCF and
171                buf[7] == 0x11 and
172                buf[8] == 0xA6 and
173                buf[9] == 0xD9)
174
175
176class Flv(Type):
177    """
178    Implements the FLV video type matcher.
179    """
180    MIME = 'video/x-flv'
181    EXTENSION = 'flv'
182
183    def __init__(self):
184        super(Flv, self).__init__(
185            mime=Flv.MIME,
186            extension=Flv.EXTENSION
187        )
188
189    def match(self, buf):
190        return (len(buf) > 3 and
191                buf[0] == 0x46 and
192                buf[1] == 0x4C and
193                buf[2] == 0x56 and
194                buf[3] == 0x01)
195
196
197class Mpeg(Type):
198    """
199    Implements the MPEG video type matcher.
200    """
201    MIME = 'video/mpeg'
202    EXTENSION = 'mpg'
203
204    def __init__(self):
205        super(Mpeg, self).__init__(
206            mime=Mpeg.MIME,
207            extension=Mpeg.EXTENSION
208        )
209
210    def match(self, buf):
211        return (len(buf) > 3 and
212                buf[0] == 0x0 and
213                buf[1] == 0x0 and
214                buf[2] == 0x1 and
215                buf[3] >= 0xb0 and
216                buf[3] <= 0xbf)
217