1 /* Webcamoid, webcam capture application.
2 * Copyright (C) 2016 Gonzalo Exequiel Pedone
3 *
4 * Webcamoid is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Webcamoid is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Webcamoid. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Web-Site: http://webcamoid.github.io/
18 */
19
20 #include <QDataStream>
21 #include <QDebug>
22 #include <QMetaEnum>
23 #include <QSize>
24 #include <QVector>
25
26 #include "akvideocaps.h"
27 #include "akfrac.h"
28 #include "akcaps.h"
29
30 class VideoFormat
31 {
32 public:
33 AkVideoCaps::PixelFormat format;
34 int bpp;
35 quint32 fourCC;
36 QVector<int> planes;
37 QVector<int> planes_div;
38
formats()39 static inline const QVector<VideoFormat> &formats()
40 {
41 static const QVector<VideoFormat> videoFormats = {
42 {AkVideoCaps::Format_none , 0, AK_FOURCC_NULL , {} , {} },
43 {AkVideoCaps::Format_rgb444be , 12, AkFourCCS("\xcBGR") , {16} , {1} },
44 {AkVideoCaps::Format_rgb444le , 12, AkFourCCS("RGB\xc") , {16} , {1} },
45 {AkVideoCaps::Format_argb444be , 16, AK_FOURCC_NULL , {16} , {1} },
46 {AkVideoCaps::Format_argb444le , 16, AK_FOURCC_NULL , {16} , {1} },
47 {AkVideoCaps::Format_rgb555be , 15, AkFourCCS("\xfBGR") , {16} , {1} },
48 {AkVideoCaps::Format_rgb555le , 15, AkFourCCS("RGB\xf") , {16} , {1} },
49 {AkVideoCaps::Format_argb555be , 16, AK_FOURCC_NULL , {16} , {1} },
50 {AkVideoCaps::Format_argb555le , 16, AK_FOURCC_NULL , {16} , {1} },
51 {AkVideoCaps::Format_rgb565be , 16, AkFourCCS("\x10""BGR") , {16} , {1} },
52 {AkVideoCaps::Format_rgb565le , 16, AkFourCCS("RGB\x10") , {16} , {1} },
53 {AkVideoCaps::Format_rgb0 , 24, AkFourCCS("RGB\x0") , {32} , {1} },
54 {AkVideoCaps::Format_rgb24 , 24, AkFourCCS("RGB\x18") , {24} , {1} },
55 {AkVideoCaps::Format_rgb48be , 48, AkFourCCS("0RGB") , {48} , {1} },
56 {AkVideoCaps::Format_rgb48le , 48, AkFourCCS("RGB0") , {48} , {1} },
57 {AkVideoCaps::Format_bgr444be , 12, AkFourCCS("\xcRGB") , {16} , {1} },
58 {AkVideoCaps::Format_bgr444le , 12, AkFourCCS("BGR\xc") , {16} , {1} },
59 {AkVideoCaps::Format_bgr555be , 15, AkFourCCS("\xfRGB") , {16} , {1} },
60 {AkVideoCaps::Format_bgr555le , 15, AkFourCCS("BGR\xf") , {16} , {1} },
61 {AkVideoCaps::Format_bgr565be , 16, AkFourCCS("\x10RGB") , {16} , {1} },
62 {AkVideoCaps::Format_bgr565le , 16, AkFourCCS("BGR\x10") , {16} , {1} },
63 {AkVideoCaps::Format_rgb666 , 18, AK_FOURCC_NULL , {24} , {1} },
64 {AkVideoCaps::Format_argb1665 , 18, AK_FOURCC_NULL , {24} , {1} },
65 {AkVideoCaps::Format_argb1666 , 19, AK_FOURCC_NULL , {24} , {1} },
66 {AkVideoCaps::Format_bgr666 , 18, AK_FOURCC_NULL , {24} , {1} },
67 {AkVideoCaps::Format_argb6666 , 24, AK_FOURCC_NULL , {24} , {1} },
68 {AkVideoCaps::Format_abgr6666 , 24, AK_FOURCC_NULL , {24} , {1} },
69 {AkVideoCaps::Format_0bgr , 32, AkFourCCS("\x0BGR") , {32} , {1} },
70 {AkVideoCaps::Format_0rgb , 32, AkFourCCS("\x0RGB") , {32} , {1} },
71 {AkVideoCaps::Format_abgr , 32, AkFourCCS("ABGR") , {32} , {1} },
72 {AkVideoCaps::Format_argb , 32, AkFourCCS("ARGB") , {32} , {1} },
73 {AkVideoCaps::Format_bgr0 , 32, AkFourCCS("BGR\x0") , {32} , {1} },
74 {AkVideoCaps::Format_bgr24 , 32, AkFourCCS("BGR\x18") , {24} , {1} },
75 {AkVideoCaps::Format_bgr48be , 48, AkFourCCS("0BGR") , {48} , {1} },
76 {AkVideoCaps::Format_bgr48le , 48, AkFourCCS("BGR0") , {48} , {1} },
77 {AkVideoCaps::Format_rgba , 32, AkFourCCS("RGBA") , {32} , {1} },
78 {AkVideoCaps::Format_rgba64be , 64, AkFourCCS("\x40RBA") , {64} , {1} },
79 {AkVideoCaps::Format_rgba64le , 64, AkFourCCS("RBA\x40") , {64} , {1} },
80 {AkVideoCaps::Format_bgra , 32, AkFourCCS("BGRA") , {32} , {1} },
81 {AkVideoCaps::Format_bgra64be , 64, AkFourCCS("\x40""BRA") , {64} , {1} },
82 {AkVideoCaps::Format_bgra64le , 64, AkFourCCS("BRA\x40") , {64} , {1} },
83 {AkVideoCaps::Format_argb1887 , 24, AK_FOURCC_NULL , {24} , {1} },
84 {AkVideoCaps::Format_bgra1888 , 25, AK_FOURCC_NULL , {32} , {1} },
85 {AkVideoCaps::Format_monob , 1, AkFourCCS("B0W1") , { 1} , {1} },
86 {AkVideoCaps::Format_monow , 1, AkFourCCS("B1W0") , { 1} , {1} },
87 {AkVideoCaps::Format_rgb4 , 4, AkFourCCS("RGB\x4") , { 4} , {1} },
88 {AkVideoCaps::Format_rgb4_byte , 4, AkFourCCS("B4BY") , { 8} , {1} },
89 {AkVideoCaps::Format_rgb8 , 8, AkFourCCS("RGB\x8") , { 8} , {1} },
90 {AkVideoCaps::Format_bgr4 , 4, AkFourCCS("BGR\x4") , { 4} , {1} },
91 {AkVideoCaps::Format_bgr4_byte , 4, AkFourCCS("R4BY") , { 8} , {1} },
92 {AkVideoCaps::Format_bgr8 , 8, AkFourCCS("BGR\x8") , { 8} , {1} },
93 {AkVideoCaps::Format_gray2 , 2, AK_FOURCC_NULL , { 8} , {1} },
94 {AkVideoCaps::Format_gray4 , 4, AK_FOURCC_NULL , { 8} , {1} },
95 {AkVideoCaps::Format_gray24 , 24, AK_FOURCC_NULL , {32} , {1} },
96 {AkVideoCaps::Format_gray32 , 32, AK_FOURCC_NULL , {32} , {1} },
97 {AkVideoCaps::Format_gray , 8, AkFourCCS("Y800") , { 8} , {1} },
98 {AkVideoCaps::Format_gray9be , 9, AkFourCCS("\x9\x01Y") , {16} , {1} },
99 {AkVideoCaps::Format_gray9le , 9, AkFourCCS("Y1\x0\x9") , {16} , {1} },
100 {AkVideoCaps::Format_gray10be , 10, AkFourCCS("\xa\x01Y") , {16} , {1} },
101 {AkVideoCaps::Format_gray10le , 10, AkFourCCS("Y1\x0\xa") , {16} , {1} },
102 {AkVideoCaps::Format_gray12be , 12, AkFourCCS("\xc\x01Y") , {16} , {1} },
103 {AkVideoCaps::Format_gray12le , 12, AkFourCCS("Y1\x0\xc") , {16} , {1} },
104 {AkVideoCaps::Format_gray14be , 14, AkFourCCS("\xe\x01Y") , {16} , {1} },
105 {AkVideoCaps::Format_gray14le , 14, AkFourCCS("Y1\x0\xe") , {16} , {1} },
106 {AkVideoCaps::Format_gray16be , 16, AkFourCCS("\x10\x01Y") , {16} , {1} },
107 {AkVideoCaps::Format_gray16le , 16, AkFourCCS("Y1\x0\x10") , {16} , {1} },
108 {AkVideoCaps::Format_grayf32be , 32, AK_FOURCC_NULL , {32} , {1} },
109 {AkVideoCaps::Format_grayf32le , 32, AK_FOURCC_NULL , {32} , {1} },
110 {AkVideoCaps::Format_bayer_bggr8 , 8, AkFourCCS("\xba""BG\x8") , { 8} , {1} },
111 {AkVideoCaps::Format_bayer_gbrg8 , 8, AkFourCCS("\xbaGB\x8") , { 8} , {1} },
112 {AkVideoCaps::Format_bayer_grbg8 , 8, AkFourCCS("\xbaGR\x8") , { 8} , {1} },
113 {AkVideoCaps::Format_bayer_rggb8 , 8, AkFourCCS("\xbaRG\x8") , { 8} , {1} },
114 {AkVideoCaps::Format_bayer_bggr16be, 16, AkFourCCS("\x10GB\xba") , {16} , {1} },
115 {AkVideoCaps::Format_bayer_bggr16le, 16, AkFourCCS("\xba""BG\x10"), {16} , {1} },
116 {AkVideoCaps::Format_bayer_gbrg16be, 16, AkFourCCS("\x10""BG\xba"), {16} , {1} },
117 {AkVideoCaps::Format_bayer_gbrg16le, 16, AkFourCCS("\xbaGB\x10") , {16} , {1} },
118 {AkVideoCaps::Format_bayer_grbg16be, 16, AkFourCCS("\x10RG\xba") , {16} , {1} },
119 {AkVideoCaps::Format_bayer_grbg16le, 16, AkFourCCS("\xbaGR\x10") , {16} , {1} },
120 {AkVideoCaps::Format_bayer_rggb16be, 16, AkFourCCS("\x10GR\xba") , {16} , {1} },
121 {AkVideoCaps::Format_bayer_rggb16le, 16, AkFourCCS("\xbaRG\x10") , {16} , {1} },
122 {AkVideoCaps::Format_ayuv64be , 64, AK_FOURCC_NULL , {64} , {1} },
123 {AkVideoCaps::Format_ayuv64le , 64, AK_FOURCC_NULL , {64} , {1} },
124 {AkVideoCaps::Format_uyvy422 , 16, AkFourCCS("UYVY") , {16} , {1} },
125 {AkVideoCaps::Format_vyuy422 , 16, AK_FOURCC_NULL , {16} , {1} },
126 {AkVideoCaps::Format_uyyvyy411 , 12, AkFourCCS("Y411") , {12} , {1} },
127 {AkVideoCaps::Format_ya16be , 32, AK_FOURCC_NULL , {32} , {1} },
128 {AkVideoCaps::Format_ya16le , 32, AK_FOURCC_NULL , {32} , {1} },
129 {AkVideoCaps::Format_ya8 , 16, AkFourCCS("Y2\x0\x8") , {16} , {1} },
130 {AkVideoCaps::Format_yuyv422 , 16, AkFourCCS("YUY2") , {16} , {1} },
131 {AkVideoCaps::Format_yvyu422 , 16, AkFourCCS("YVYU") , {16} , {1} },
132 {AkVideoCaps::Format_xyz12be , 36, AkFourCCS("\x24ZYX") , {48} , {1} },
133 {AkVideoCaps::Format_xyz12le , 36, AkFourCCS("XYZ\x24") , {48} , {1} },
134 {AkVideoCaps::Format_nv12 , 12, AkFourCCS("NV12") , { 8, 8} , {1, 2} },
135 {AkVideoCaps::Format_nv16 , 16, AK_FOURCC_NULL , { 8, 8} , {1, 1} },
136 {AkVideoCaps::Format_nv20be , 20, AK_FOURCC_NULL , {16, 16} , {1, 1} },
137 {AkVideoCaps::Format_nv20le , 20, AK_FOURCC_NULL , {16, 16} , {1, 1} },
138 {AkVideoCaps::Format_nv21 , 12, AkFourCCS("NV21") , { 8, 8} , {1, 2} },
139 {AkVideoCaps::Format_p010be , 15, AK_FOURCC_NULL , {16, 16} , {1, 2} },
140 {AkVideoCaps::Format_p010le , 15, AK_FOURCC_NULL , {16, 16} , {1, 2} },
141 {AkVideoCaps::Format_p016be , 24, AK_FOURCC_NULL , {16, 16} , {1, 2} },
142 {AkVideoCaps::Format_p016le , 24, AK_FOURCC_NULL , {16, 16} , {1, 2} },
143 {AkVideoCaps::Format_yuv410p , 9, AkFourCCS("YUV9") , { 8, 2, 2} , {1, 4, 4} },
144 {AkVideoCaps::Format_yuv411p , 12, AkFourCCS("Y41B") , { 8, 2, 2} , {1, 1, 1} },
145 {AkVideoCaps::Format_yuv420p , 12, AkFourCCS("I420") , { 8, 4, 4} , {1, 2, 2} },
146 {AkVideoCaps::Format_yvu420p , 12, AK_FOURCC_NULL , { 8, 4, 4} , {1, 2, 2} },
147 {AkVideoCaps::Format_yuv422p , 16, AkFourCCS("Y42B") , { 8, 4, 4} , {1, 1, 1} },
148 {AkVideoCaps::Format_yuv440p , 16, AkFourCCS("440P") , { 8, 8, 8} , {1, 2, 2} },
149 {AkVideoCaps::Format_yuv444p , 24, AkFourCCS("444P") , { 8, 8, 8} , {1, 1, 1} },
150 {AkVideoCaps::Format_yuvj411p , 12, AK_FOURCC_NULL , { 8, 2, 2} , {1, 1, 1} },
151 {AkVideoCaps::Format_yuvj420p , 12, AkFourCCS("I420") , { 8, 4, 4} , {1, 2, 2} },
152 {AkVideoCaps::Format_yuvj422p , 16, AkFourCCS("Y42B") , { 8, 4, 4} , {1, 1, 1} },
153 {AkVideoCaps::Format_yuvj440p , 16, AkFourCCS("440P") , { 8, 8, 8} , {1, 2, 2} },
154 {AkVideoCaps::Format_yuvj444p , 24, AkFourCCS("444P") , { 8, 8, 8} , {1, 1, 1} },
155 {AkVideoCaps::Format_yuv420p9be , 13, AkFourCCS("\x9\xb3Y") , {16, 8, 8} , {1, 2, 2} },
156 {AkVideoCaps::Format_yuv420p9le , 13, AkFourCCS("Y3\xb\x9") , {16, 8, 8} , {1, 2, 2} },
157 {AkVideoCaps::Format_yuv420p10be , 15, AkFourCCS("\xa\xb3Y") , {16, 8, 8} , {1, 2, 2} },
158 {AkVideoCaps::Format_yuv420p10le , 15, AkFourCCS("Y3\xb\xa") , {16, 8, 8} , {1, 2, 2} },
159 {AkVideoCaps::Format_yuv420p12be , 18, AkFourCCS("\xc\xb3Y") , {16, 8, 8} , {1, 2, 2} },
160 {AkVideoCaps::Format_yuv420p12le , 18, AkFourCCS("Y3\xb\xc") , {16, 8, 8} , {1, 2, 2} },
161 {AkVideoCaps::Format_yuv420p14be , 21, AkFourCCS("\xe\xb3Y") , {16, 8, 8} , {1, 2, 2} },
162 {AkVideoCaps::Format_yuv420p14le , 21, AkFourCCS("Y3\xb\xe") , {16, 8, 8} , {1, 2, 2} },
163 {AkVideoCaps::Format_yuv420p16be , 24, AkFourCCS("\x10\xb3Y") , {16, 8, 8} , {1, 2, 2} },
164 {AkVideoCaps::Format_yuv420p16le , 24, AkFourCCS("Y3\xb\x10") , {16, 8, 8} , {1, 2, 2} },
165 {AkVideoCaps::Format_yuv422p9be , 18, AkFourCCS("\x9\xa3Y") , {16, 8, 8} , {1, 1, 1} },
166 {AkVideoCaps::Format_yuv422p9le , 18, AkFourCCS("Y3\xa\x9") , {16, 8, 8} , {1, 1, 1} },
167 {AkVideoCaps::Format_yuv422p10be , 20, AkFourCCS("\xa\xa3Y") , {16, 8, 8} , {1, 1, 1} },
168 {AkVideoCaps::Format_yuv422p10le , 20, AkFourCCS("Y3\xa\xa") , {16, 8, 8} , {1, 1, 1} },
169 {AkVideoCaps::Format_yuv422p12be , 24, AkFourCCS("\xc\xa3Y") , {16, 8, 8} , {1, 1, 1} },
170 {AkVideoCaps::Format_yuv422p12le , 24, AkFourCCS("Y3\xa\xc") , {16, 8, 8} , {1, 1, 1} },
171 {AkVideoCaps::Format_yuv422p14be , 28, AkFourCCS("\xe\xa3Y") , {16, 8, 8} , {1, 1, 1} },
172 {AkVideoCaps::Format_yuv422p14le , 28, AkFourCCS("Y3\xa\xe") , {16, 8, 8} , {1, 1, 1} },
173 {AkVideoCaps::Format_yuv422p16be , 32, AkFourCCS("\x10\xa3Y") , {16, 8, 8} , {1, 1, 1} },
174 {AkVideoCaps::Format_yuv422p16le , 32, AkFourCCS("Y3\xa\x10") , {16, 8, 8} , {1, 1, 1} },
175 {AkVideoCaps::Format_yuv440p10be , 20, AK_FOURCC_NULL , {16, 16, 16} , {1, 2, 2} },
176 {AkVideoCaps::Format_yuv440p10le , 20, AK_FOURCC_NULL , {16, 16, 16} , {1, 2, 2} },
177 {AkVideoCaps::Format_yuv440p12be , 24, AK_FOURCC_NULL , {16, 16, 16} , {1, 2, 2} },
178 {AkVideoCaps::Format_yuv440p12le , 24, AK_FOURCC_NULL , {16, 16, 16} , {1, 2, 2} },
179 {AkVideoCaps::Format_yuv444p9be , 27, AkFourCCS("\x9\x03Y") , {16, 16, 16} , {1, 1, 1} },
180 {AkVideoCaps::Format_yuv444p9le , 27, AkFourCCS("Y3\x0\x9") , {16, 16, 16} , {1, 1, 1} },
181 {AkVideoCaps::Format_yuv444p10be , 30, AkFourCCS("\xa\x03Y") , {16, 16, 16} , {1, 1, 1} },
182 {AkVideoCaps::Format_yuv444p10le , 30, AkFourCCS("Y3\x0\xa") , {16, 16, 16} , {1, 1, 1} },
183 {AkVideoCaps::Format_yuv444p12be , 36, AkFourCCS("\xc\x03Y") , {16, 16, 16} , {1, 1, 1} },
184 {AkVideoCaps::Format_yuv444p12le , 36, AkFourCCS("Y3\x0\xc") , {16, 16, 16} , {1, 1, 1} },
185 {AkVideoCaps::Format_yuv444p14be , 42, AkFourCCS("\xe\x03Y") , {16, 16, 16} , {1, 1, 1} },
186 {AkVideoCaps::Format_yuv444p14le , 42, AkFourCCS("Y3\x0\xe") , {16, 16, 16} , {1, 1, 1} },
187 {AkVideoCaps::Format_yuv444p16be , 48, AkFourCCS("\x10\x03Y") , {16, 16, 16} , {1, 1, 1} },
188 {AkVideoCaps::Format_yuv444p16le , 48, AkFourCCS("Y3\x0\x10") , {16, 16, 16} , {1, 1, 1} },
189 {AkVideoCaps::Format_yuva420p , 20, AkFourCCS("Y4\xb\x8") , { 8, 4, 4, 8}, {1, 2, 2, 1}},
190 {AkVideoCaps::Format_yuva422p , 24, AkFourCCS("Y4\xa\x8") , { 8, 4, 4, 8}, {1, 1, 1, 1}},
191 {AkVideoCaps::Format_yuv444 , 24, AK_FOURCC_NULL , {24} , {1} },
192 {AkVideoCaps::Format_yuva444p , 32, AkFourCCS("Y4\x0\x8") , { 8, 8, 8, 8}, {1, 1, 1, 1}},
193 {AkVideoCaps::Format_yuva420p9be , 22, AkFourCCS("\x9\xb4Y") , {16, 8, 8, 16}, {1, 2, 2, 1}},
194 {AkVideoCaps::Format_yuva420p9le , 22, AkFourCCS("Y4\xb\x9") , {16, 8, 8, 16}, {1, 2, 2, 1}},
195 {AkVideoCaps::Format_yuva420p10be , 25, AkFourCCS("\xa\xb4Y") , {16, 8, 8, 16}, {1, 2, 2, 1}},
196 {AkVideoCaps::Format_yuva420p10le , 25, AkFourCCS("Y4\xb\xa") , {16, 8, 8, 16}, {1, 2, 2, 1}},
197 {AkVideoCaps::Format_yuva420p16be , 40, AkFourCCS("\x10\xb4Y") , {16, 8, 8, 16}, {1, 2, 2, 1}},
198 {AkVideoCaps::Format_yuva420p16le , 40, AkFourCCS("Y4\xb\x10") , {16, 8, 8, 16}, {1, 2, 2, 1}},
199 {AkVideoCaps::Format_yuva422p9be , 27, AkFourCCS("\x9\xa4Y") , {16, 8, 8, 16}, {1, 1, 1, 1}},
200 {AkVideoCaps::Format_yuva422p9le , 27, AkFourCCS("Y4\xa\x9") , {16, 8, 8, 16}, {1, 1, 1, 1}},
201 {AkVideoCaps::Format_yuva422p10be , 30, AkFourCCS("\xa\xa4Y") , {16, 8, 8, 16}, {1, 1, 1, 1}},
202 {AkVideoCaps::Format_yuva422p10le , 30, AkFourCCS("Y4\xa\xa") , {16, 8, 8, 16}, {1, 1, 1, 1}},
203 {AkVideoCaps::Format_yuva422p16be , 48, AkFourCCS("\x10\xa4Y") , {16, 8, 8, 16}, {1, 1, 1, 1}},
204 {AkVideoCaps::Format_yuva422p16le , 48, AkFourCCS("Y4\xa\x10") , {16, 8, 8, 16}, {1, 1, 1, 1}},
205 {AkVideoCaps::Format_yuva444p9be , 36, AkFourCCS("\x9\x04Y") , {16, 16, 16, 16}, {1, 1, 1, 1}},
206 {AkVideoCaps::Format_yuva444p9le , 36, AkFourCCS("Y4\x0\x9") , {16, 16, 16, 16}, {1, 1, 1, 1}},
207 {AkVideoCaps::Format_yuva444p10be , 40, AkFourCCS("\xa\x04Y") , {16, 16, 16, 16}, {1, 1, 1, 1}},
208 {AkVideoCaps::Format_yuva444p10le , 40, AkFourCCS("Y4\x0\xa") , {16, 16, 16, 16}, {1, 1, 1, 1}},
209 {AkVideoCaps::Format_yuva444p16be , 64, AkFourCCS("\x10\x04Y") , {16, 16, 16, 16}, {1, 1, 1, 1}},
210 {AkVideoCaps::Format_yuva444p16le , 64, AkFourCCS("Y4\x0\x10") , {16, 16, 16, 16}, {1, 1, 1, 1}},
211 {AkVideoCaps::Format_gbrp , 24, AkFourCCS("G3\x0\x8") , { 8, 8, 8} , {1, 1, 1} },
212 {AkVideoCaps::Format_gbrp9be , 27, AkFourCCS("\x9\x03G") , {16, 16, 16} , {1, 1, 1} },
213 {AkVideoCaps::Format_gbrp9le , 27, AkFourCCS("G3\x0\x9") , {16, 16, 16} , {1, 1, 1} },
214 {AkVideoCaps::Format_gbrp10be , 30, AkFourCCS("\xa\x03G") , {16, 16, 16} , {1, 1, 1} },
215 {AkVideoCaps::Format_gbrp10le , 30, AkFourCCS("G3\x0\xa") , {16, 16, 16} , {1, 1, 1} },
216 {AkVideoCaps::Format_gbrp12be , 36, AkFourCCS("\xc\x03G") , {16, 16, 16} , {1, 1, 1} },
217 {AkVideoCaps::Format_gbrp12le , 36, AkFourCCS("G3\x0\xc") , {16, 16, 16} , {1, 1, 1} },
218 {AkVideoCaps::Format_gbrp14be , 42, AkFourCCS("\xe\x03G") , {16, 16, 16} , {1, 1, 1} },
219 {AkVideoCaps::Format_gbrp14le , 42, AkFourCCS("G3\x0\xe") , {16, 16, 16} , {1, 1, 1} },
220 {AkVideoCaps::Format_gbrp16be , 48, AkFourCCS("\x10\x03G") , {16, 16, 16} , {1, 1, 1} },
221 {AkVideoCaps::Format_gbrp16le , 48, AkFourCCS("G3\x0\x10") , {16, 16, 16} , {1, 1, 1} },
222 {AkVideoCaps::Format_gbrpf32be , 96, AK_FOURCC_NULL , {32, 32, 32} , {1, 1, 1} },
223 {AkVideoCaps::Format_gbrpf32le , 96, AK_FOURCC_NULL , {32, 32, 32} , {1, 1, 1} },
224 {AkVideoCaps::Format_rgbp , 24, AK_FOURCC_NULL , { 8, 8, 8} , {1, 1, 1} },
225 {AkVideoCaps::Format_rgbap , 32, AK_FOURCC_NULL , { 8, 8, 8, 8}, {1, 1, 1, 1}},
226 {AkVideoCaps::Format_gbrap , 32, AkFourCCS("G4\x0\x8") , { 8, 8, 8, 8}, {1, 1, 1, 1}},
227 {AkVideoCaps::Format_gbrap10be , 40, AkFourCCS("\xa\x04G") , {16, 16, 16, 16}, {1, 1, 1, 1}},
228 {AkVideoCaps::Format_gbrap10le , 40, AkFourCCS("G4\x0\xa") , {16, 16, 16, 16}, {1, 1, 1, 1}},
229 {AkVideoCaps::Format_gbrap12be , 48, AkFourCCS("\xc\x04G") , {16, 16, 16, 16}, {1, 1, 1, 1}},
230 {AkVideoCaps::Format_gbrap12le , 48, AkFourCCS("G4\x0\xc") , {16, 16, 16, 16}, {1, 1, 1, 1}},
231 {AkVideoCaps::Format_gbrap16be , 64, AkFourCCS("\x10\x04G") , {16, 16, 16, 16}, {1, 1, 1, 1}},
232 {AkVideoCaps::Format_gbrap16le , 64, AkFourCCS("G4\x0\x10") , {16, 16, 16, 16}, {1, 1, 1, 1}},
233 {AkVideoCaps::Format_gbrapf32be , 128, AK_FOURCC_NULL , {32, 32, 32, 32}, {1, 1, 1, 1}},
234 {AkVideoCaps::Format_gbrapf32le , 128, AK_FOURCC_NULL , {32, 32, 32, 32}, {1, 1, 1, 1}},
235 };
236
237 return videoFormats;
238 }
239
byFormat(AkVideoCaps::PixelFormat format)240 static inline const VideoFormat *byFormat(AkVideoCaps::PixelFormat format)
241 {
242 for (auto &format_: formats())
243 if (format_.format == format)
244 return &format_;
245
246 return &formats().front();
247 }
248
byBpp(int bpp)249 static inline const VideoFormat *byBpp(int bpp)
250 {
251 for (auto &format: formats())
252 if (format.bpp == bpp)
253 return &format;
254
255 return &formats().front();
256 }
257
byFourCC(quint32 fourCC)258 static inline const VideoFormat *byFourCC(quint32 fourCC)
259 {
260 for (auto &format: formats())
261 if (format.fourCC == fourCC)
262 return &format;
263
264 return &formats().front();
265 }
266
267 template<typename T>
alignUp(const T & value,const T & align)268 static inline T alignUp(const T &value, const T &align)
269 {
270 return (value + align - 1) & ~(align - 1);
271 }
272 };
273
274 class AkVideoCapsPrivate
275 {
276 public:
277 AkVideoCaps::PixelFormat m_format {AkVideoCaps::Format_none};
278 int m_width {0};
279 int m_height {0};
280 int m_align {1};
281 AkFrac m_fps;
282 const QVector<int> *m_planes_div;
283 QVector<size_t> m_bypl;
284 QVector<size_t> m_offset;
285
286 void updateParams();
287 };
288
AkVideoCaps(QObject * parent)289 AkVideoCaps::AkVideoCaps(QObject *parent):
290 QObject(parent)
291 {
292 this->d = new AkVideoCapsPrivate();
293 }
294
AkVideoCaps(AkVideoCaps::PixelFormat format,int width,int height,const AkFrac & fps,int align)295 AkVideoCaps::AkVideoCaps(AkVideoCaps::PixelFormat format,
296 int width,
297 int height,
298 const AkFrac &fps,
299 int align)
300 {
301 this->d = new AkVideoCapsPrivate();
302 this->d->m_format = format;
303 this->d->m_width = width;
304 this->d->m_height = height;
305 this->d->m_fps = fps;
306 this->d->m_align = align;
307 this->d->updateParams();
308 }
309
AkVideoCaps(AkVideoCaps::PixelFormat format,const QSize & size,const AkFrac & fps,int align)310 AkVideoCaps::AkVideoCaps(AkVideoCaps::PixelFormat format,
311 const QSize &size,
312 const AkFrac &fps,
313 int align)
314 {
315 AkVideoCaps(format, size.width(), size.height(), fps, align);
316 }
317
318
AkVideoCaps(const AkCaps & caps)319 AkVideoCaps::AkVideoCaps(const AkCaps &caps)
320 {
321 this->d = new AkVideoCapsPrivate();
322
323 if (caps.mimeType() == "video/x-raw")
324 this->update(caps);
325 }
326
AkVideoCaps(const AkVideoCaps & other)327 AkVideoCaps::AkVideoCaps(const AkVideoCaps &other):
328 QObject()
329 {
330 this->d = new AkVideoCapsPrivate();
331 this->d->m_format = other.d->m_format;
332 this->d->m_width = other.d->m_width;
333 this->d->m_height = other.d->m_height;
334 this->d->m_fps = other.d->m_fps;
335 this->d->m_align = other.d->m_align;
336 this->d->m_planes_div = other.d->m_planes_div;
337 this->d->m_bypl = other.d->m_bypl;
338 this->d->m_offset = other.d->m_offset;
339 auto properties = other.dynamicPropertyNames();
340
341 for (auto &property: properties)
342 this->setProperty(property, other.property(property));
343 }
344
~AkVideoCaps()345 AkVideoCaps::~AkVideoCaps()
346 {
347 delete this->d;
348 }
349
operator =(const AkVideoCaps & other)350 AkVideoCaps &AkVideoCaps::operator =(const AkVideoCaps &other)
351 {
352 if (this != &other) {
353 this->d->m_format = other.d->m_format;
354 this->d->m_width = other.d->m_width;
355 this->d->m_height = other.d->m_height;
356 this->d->m_fps = other.d->m_fps;
357 this->d->m_align = other.d->m_align;
358 this->d->m_planes_div = other.d->m_planes_div;
359 this->d->m_bypl = other.d->m_bypl;
360 this->d->m_offset = other.d->m_offset;
361
362 this->clear();
363 auto properties = other.dynamicPropertyNames();
364
365 for (auto &property: properties)
366 this->setProperty(property, other.property(property));
367
368 this->d->updateParams();
369 }
370
371 return *this;
372 }
373
operator =(const AkCaps & caps)374 AkVideoCaps &AkVideoCaps::operator =(const AkCaps &caps)
375 {
376 if (caps.mimeType() == "video/x-raw") {
377 this->update(caps);
378 } else {
379 this->d->m_format = AkVideoCaps::Format_none;
380 this->d->m_width = 0;
381 this->d->m_height = 0;
382 this->d->m_fps = AkFrac();
383 this->d->m_align = 1;
384 }
385
386 return *this;
387 }
388
operator ==(const AkVideoCaps & other) const389 bool AkVideoCaps::operator ==(const AkVideoCaps &other) const
390 {
391 if (this->dynamicPropertyNames() != other.dynamicPropertyNames())
392 return false;
393
394 for (auto &property: this->dynamicPropertyNames())
395 if (this->property(property) != other.property(property))
396 return false;
397
398 return this->d->m_format == other.d->m_format
399 && this->d->m_width == other.d->m_width
400 && this->d->m_height == other.d->m_height
401 && this->d->m_fps == other.d->m_fps
402 && this->d->m_align == other.d->m_align;
403 }
404
operator !=(const AkVideoCaps & other) const405 bool AkVideoCaps::operator !=(const AkVideoCaps &other) const
406 {
407 return !(*this == other);
408 }
409
operator AkCaps() const410 AkVideoCaps::operator AkCaps() const
411 {
412 AkCaps caps("video/x-raw");
413 caps.setProperty("format", this->d->m_format);
414 caps.setProperty("width" , this->d->m_width);
415 caps.setProperty("height", this->d->m_height);
416 caps.setProperty("fps" , QVariant::fromValue(this->d->m_fps));
417 caps.setProperty("align" , this->d->m_align);
418
419 return caps;
420 }
421
operator bool() const422 AkVideoCaps::operator bool() const
423 {
424 return this->pictureSize() > 0;
425 }
426
format() const427 AkVideoCaps::PixelFormat AkVideoCaps::format() const
428 {
429 return this->d->m_format;
430 }
431
fourCC() const432 quint32 AkVideoCaps::fourCC() const
433 {
434 return AkVideoCaps::fourCC(this->d->m_format);
435 }
436
bpp() const437 int AkVideoCaps::bpp() const
438 {
439 return VideoFormat::byFormat(this->d->m_format)->bpp;
440 }
441
size() const442 QSize AkVideoCaps::size() const
443 {
444 return {this->d->m_width, this->d->m_height};
445 }
446
width() const447 int AkVideoCaps::width() const
448 {
449 return this->d->m_width;
450 }
451
height() const452 int AkVideoCaps::height() const
453 {
454 return this->d->m_height;
455 }
456
fps() const457 AkFrac AkVideoCaps::fps() const
458 {
459 return this->d->m_fps;
460 }
461
fps()462 AkFrac &AkVideoCaps::fps()
463 {
464 return this->d->m_fps;
465 }
466
align() const467 int AkVideoCaps::align() const
468 {
469 return this->d->m_align;
470 }
471
pictureSize() const472 size_t AkVideoCaps::pictureSize() const
473 {
474 auto vf = VideoFormat::byFormat(this->d->m_format);
475
476 if (!vf)
477 return 0;
478
479 size_t size = 0;
480
481 for (int i = 0; i < vf->planes.size(); i++)
482 size += this->planeSize(i);
483
484 return size;
485 }
486
fromMap(const QVariantMap & caps)487 AkVideoCaps AkVideoCaps::fromMap(const QVariantMap &caps)
488 {
489 AkVideoCaps videoCaps;
490
491 if (!caps.contains("mimeType") || caps["mimeType"] != "video/x-raw")
492 return videoCaps;
493
494 for (auto it = caps.begin(); it != caps.end(); it++) {
495 auto value = it.value();
496
497 if (it.key() == "mimeType")
498 continue;
499
500 videoCaps.setProperty(it.key().toStdString().c_str(), value);
501 }
502
503 return videoCaps;
504 }
505
toMap() const506 QVariantMap AkVideoCaps::toMap() const
507 {
508 QVariantMap map {
509 {"mimeType", "video/x-raw" },
510 {"format" , this->d->m_format },
511 {"width" , this->d->m_width },
512 {"height" , this->d->m_height },
513 {"fps" , QVariant::fromValue(this->d->m_fps)},
514 {"align" , this->d->m_align },
515 };
516
517 for (auto &property: this->dynamicPropertyNames()) {
518 auto key = QString::fromUtf8(property.constData());
519 map[key] = this->property(property);
520 }
521
522 return map;
523 }
524
update(const AkCaps & caps)525 AkVideoCaps &AkVideoCaps::update(const AkCaps &caps)
526 {
527 if (caps.mimeType() != "video/x-raw")
528 return *this;
529
530 this->clear();
531
532 for (auto &property: caps.dynamicPropertyNames()) {
533 int i = this->metaObject()->indexOfProperty(property);
534
535 if (this->metaObject()->property(i).isWritable())
536 this->setProperty(property, caps.property(property));
537 }
538
539 this->d->updateParams();
540
541 return *this;
542 }
543
planeOffset(int plane) const544 size_t AkVideoCaps::planeOffset(int plane) const
545 {
546 return this->d->m_offset[plane];
547 }
548
lineOffset(int plane,int y) const549 size_t AkVideoCaps::lineOffset(int plane, int y) const
550 {
551 y /= (*this->d->m_planes_div)[plane];
552
553 return this->planeOffset(plane) + this->bytesPerLine(plane) * size_t(y);
554 }
555
bytesPerLine(int plane) const556 size_t AkVideoCaps::bytesPerLine(int plane) const
557 {
558 return this->d->m_bypl.value(plane, 0);
559 }
560
planes() const561 int AkVideoCaps::planes() const
562 {
563 auto vf = VideoFormat::byFormat(this->d->m_format);
564
565 return vf? vf->planes.size(): 0;
566 }
567
planeSize(int plane) const568 size_t AkVideoCaps::planeSize(int plane) const
569 {
570 auto bypl = this->bytesPerLine(plane);
571
572 if (bypl < 1)
573 return 0;
574
575 auto vf = VideoFormat::byFormat(this->d->m_format);
576
577 return bypl
578 * size_t(this->d->m_height)
579 / size_t(vf->planes_div[plane]);
580 }
581
bitsPerPixel(AkVideoCaps::PixelFormat pixelFormat)582 int AkVideoCaps::bitsPerPixel(AkVideoCaps::PixelFormat pixelFormat)
583 {
584 return VideoFormat::byFormat(pixelFormat)->bpp;
585 }
586
bitsPerPixel(const QString & pixelFormat)587 int AkVideoCaps::bitsPerPixel(const QString &pixelFormat)
588 {
589 return AkVideoCaps::bitsPerPixel(AkVideoCaps::pixelFormatFromString(pixelFormat));
590 }
591
pixelFormatToString(AkVideoCaps::PixelFormat pixelFormat)592 QString AkVideoCaps::pixelFormatToString(AkVideoCaps::PixelFormat pixelFormat)
593 {
594 AkVideoCaps caps;
595 int formatIndex = caps.metaObject()->indexOfEnumerator("PixelFormat");
596 QMetaEnum formatEnum = caps.metaObject()->enumerator(formatIndex);
597 QString format(formatEnum.valueToKey(pixelFormat));
598 format.remove("Format_");
599
600 return format;
601 }
602
pixelFormatFromString(const QString & pixelFormat)603 AkVideoCaps::PixelFormat AkVideoCaps::pixelFormatFromString(const QString &pixelFormat)
604 {
605 AkVideoCaps caps;
606 QString format = "Format_" + pixelFormat;
607 int enumIndex = caps.metaObject()->indexOfEnumerator("PixelFormat");
608 QMetaEnum enumType = caps.metaObject()->enumerator(enumIndex);
609 int enumValue = enumType.keyToValue(format.toStdString().c_str());
610
611 return static_cast<PixelFormat>(enumValue);
612 }
613
fourCC(AkVideoCaps::PixelFormat pixelFormat)614 quint32 AkVideoCaps::fourCC(AkVideoCaps::PixelFormat pixelFormat)
615 {
616 return VideoFormat::byFormat(pixelFormat)->fourCC;
617 }
618
fourCC(const QString & pixelFormat)619 quint32 AkVideoCaps::fourCC(const QString &pixelFormat)
620 {
621 return AkVideoCaps::fourCC(AkVideoCaps::pixelFormatFromString(pixelFormat));
622 }
623
setFormat(AkVideoCaps::PixelFormat format)624 void AkVideoCaps::setFormat(AkVideoCaps::PixelFormat format)
625 {
626 if (this->d->m_format == format)
627 return;
628
629 this->d->m_format = format;
630 this->d->updateParams();
631 emit this->formatChanged(format);
632 }
633
setSize(const QSize & size)634 void AkVideoCaps::setSize(const QSize &size)
635 {
636 QSize curSize(this->d->m_width, this->d->m_height);
637
638 if (curSize == size)
639 return;
640
641 this->d->m_width = size.width();
642 this->d->m_height = size.height();
643 this->d->updateParams();
644 emit this->widthChanged(size.width());
645 emit this->heightChanged(size.height());
646 emit sizeChanged(size);
647 }
648
setWidth(int width)649 void AkVideoCaps::setWidth(int width)
650 {
651 if (this->d->m_width == width)
652 return;
653
654 this->d->m_width = width;
655 this->d->updateParams();
656 emit this->widthChanged(width);
657 }
658
setHeight(int height)659 void AkVideoCaps::setHeight(int height)
660 {
661 if (this->d->m_height == height)
662 return;
663
664 this->d->m_height = height;
665 this->d->updateParams();
666 emit this->heightChanged(height);
667 }
668
setFps(const AkFrac & fps)669 void AkVideoCaps::setFps(const AkFrac &fps)
670 {
671 if (this->d->m_fps == fps)
672 return;
673
674 this->d->m_fps = fps;
675 emit this->fpsChanged(fps);
676 }
677
setAlign(int align)678 void AkVideoCaps::setAlign(int align)
679 {
680 if (this->d->m_align == align)
681 return;
682
683 this->d->m_align = align;
684 this->d->updateParams();
685 emit this->alignChanged(align);
686 }
687
resetFormat()688 void AkVideoCaps::resetFormat()
689 {
690 this->setFormat(AkVideoCaps::Format_none);
691 }
692
resetSize()693 void AkVideoCaps::resetSize()
694 {
695 this->setSize(QSize());
696 }
697
resetWidth()698 void AkVideoCaps::resetWidth()
699 {
700 this->setWidth(0);
701 }
702
resetHeight()703 void AkVideoCaps::resetHeight()
704 {
705 this->setHeight(0);
706 }
707
resetFps()708 void AkVideoCaps::resetFps()
709 {
710 this->setFps(AkFrac());
711 }
712
resetAlign()713 void AkVideoCaps::resetAlign()
714 {
715 this->setAlign(1);
716 }
717
clear()718 void AkVideoCaps::clear()
719 {
720 for (auto &property: this->dynamicPropertyNames())
721 this->setProperty(property.constData(), {});
722 }
723
updateParams()724 void AkVideoCapsPrivate::updateParams()
725 {
726 auto vf = VideoFormat::byFormat(this->m_format);
727
728 if (!vf) {
729 this->m_planes_div = nullptr;
730 this->m_offset.clear();
731 this->m_bypl.clear();
732
733 return;
734 }
735
736 this->m_planes_div = &vf->planes_div;
737 this->m_offset.clear();
738 this->m_bypl.clear();
739 size_t offset = 0;
740
741 for (int i = 0; i < vf->planes_div.size(); i++) {
742 this->m_offset << offset;
743 auto bypl = VideoFormat::alignUp(size_t(vf->planes[i]
744 * this->m_width
745 / 8),
746 size_t(this->m_align));
747 this->m_bypl << bypl;
748 offset += bypl * size_t(this->m_height) / size_t(vf->planes_div[i]);
749 }
750 }
751
operator <<(QDebug debug,const AkVideoCaps & caps)752 QDebug operator <<(QDebug debug, const AkVideoCaps &caps)
753 {
754 debug.nospace() << "AkVideoCaps("
755 << "format="
756 << caps.format()
757 << ",width="
758 << caps.width()
759 << ",height="
760 << caps.height()
761 << ",fps="
762 << caps.fps()
763 << ",align="
764 << caps.align();
765
766 QStringList properties;
767
768 for (auto &property: caps.dynamicPropertyNames())
769 properties << QString::fromUtf8(property.constData());
770
771 properties.sort();
772
773 for (auto &property: properties)
774 debug.nospace() << ","
775 << property.toStdString().c_str()
776 << "="
777 << caps.property(property.toStdString().c_str());
778
779 debug.nospace() << ")";
780
781 return debug.space();
782 }
783
operator <<(QDebug debug,AkVideoCaps::PixelFormat format)784 QDebug operator <<(QDebug debug, AkVideoCaps::PixelFormat format)
785 {
786 debug.nospace() << AkVideoCaps::pixelFormatToString(format).toStdString().c_str();
787
788 return debug.space();
789 }
790
operator >>(QDataStream & istream,AkVideoCaps & caps)791 QDataStream &operator >>(QDataStream &istream, AkVideoCaps &caps)
792 {
793 int nProperties;
794 istream >> nProperties;
795
796 for (int i = 0; i < nProperties; i++) {
797 QByteArray key;
798 QVariant value;
799 istream >> key;
800 istream >> value;
801
802 caps.setProperty(key.toStdString().c_str(), value);
803 }
804
805 return istream;
806 }
807
operator <<(QDataStream & ostream,const AkVideoCaps & caps)808 QDataStream &operator <<(QDataStream &ostream, const AkVideoCaps &caps)
809 {
810 QVariantMap staticProperties {
811 {"format", caps.format() },
812 {"width" , caps.width() },
813 {"height", caps.height() },
814 {"fps" , QVariant::fromValue(caps.fps())},
815 {"align" , caps.align() },
816 };
817
818 int nProperties =
819 staticProperties.size() + caps.dynamicPropertyNames().size();
820 ostream << nProperties;
821
822 for (auto &key: caps.dynamicPropertyNames()) {
823 ostream << key;
824 ostream << caps.property(key);
825 }
826
827 return ostream;
828 }
829
830 #include "moc_akvideocaps.cpp"
831