xref: /aosp_15_r20/external/v4l2_codec2/common/VideoPixelFormat.cpp (revision 0ec5a0ec62797f775085659156625e7f1bdb369f)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 // Note: ported from Chromium commit head: 3b7ce92816e2
5 // Note: only necessary functions are ported from video_types.cc
6 
7 #include <v4l2_codec2/common/VideoPixelFormat.h>
8 
9 #include <base/bits.h>
10 #include <utils/Log.h>
11 
12 namespace android {
13 
14 namespace {
15 
16 enum {
17     kMaxPlanes = 4,
18     kYPlane = 0,
19     kARGBPlane = kYPlane,
20     kUPlane = 1,
21     kUVPlane = kUPlane,
22     kVPlane = 2,
23     kAPlane = 3,
24 };
25 }
26 
videoPixelFormatToString(VideoPixelFormat format)27 std::string videoPixelFormatToString(VideoPixelFormat format) {
28     switch (format) {
29     case VideoPixelFormat::I420:
30         return "I420";
31     case VideoPixelFormat::YV12:
32         return "YV12";
33     case VideoPixelFormat::I422:
34         return "I422";
35     case VideoPixelFormat::I420A:
36         return "I420A";
37     case VideoPixelFormat::I444:
38         return "I444";
39     case VideoPixelFormat::NV12:
40         return "NV12";
41     case VideoPixelFormat::NV21:
42         return "NV21";
43     case VideoPixelFormat::YUY2:
44         return "YUY2";
45     case VideoPixelFormat::ARGB:
46         return "ARGB";
47     case VideoPixelFormat::XRGB:
48         return "XRGB";
49     case VideoPixelFormat::RGB24:
50         return "RGB24";
51     case VideoPixelFormat::MJPEG:
52         return "MJPEG";
53     case VideoPixelFormat::YUV420P9:
54         return "YUV420P9";
55     case VideoPixelFormat::YUV420P10:
56         return "YUV420P10";
57     case VideoPixelFormat::YUV422P9:
58         return "YUV422P9";
59     case VideoPixelFormat::YUV422P10:
60         return "YUV422P10";
61     case VideoPixelFormat::YUV444P9:
62         return "YUV444P9";
63     case VideoPixelFormat::YUV444P10:
64         return "YUV444P10";
65     case VideoPixelFormat::YUV420P12:
66         return "YUV420P12";
67     case VideoPixelFormat::YUV422P12:
68         return "YUV422P12";
69     case VideoPixelFormat::YUV444P12:
70         return "YUV444P12";
71     case VideoPixelFormat::Y16:
72         return "Y16";
73     case VideoPixelFormat::ABGR:
74         return "ABGR";
75     case VideoPixelFormat::XBGR:
76         return "XBGR";
77     case VideoPixelFormat::P016LE:
78         return "P016LE";
79     case VideoPixelFormat::XR30:
80         return "XR30";
81     case VideoPixelFormat::XB30:
82         return "XB30";
83     case VideoPixelFormat::BGRA:
84         return "BGRA";
85     case VideoPixelFormat::RGBA:
86         return "BGRA";
87     case VideoPixelFormat::UNKNOWN:
88         return "UNKNOWN";
89     }
90 }
91 
fourccToString(uint32_t fourcc)92 std::string fourccToString(uint32_t fourcc) {
93     std::string result = "0000";
94     for (size_t i = 0; i < 4; ++i, fourcc >>= 8) {
95         const char c = static_cast<char>(fourcc & 0xFF);
96         if (c <= 0x1f || c >= 0x7f) {
97             return (std::stringstream("0x") << std::hex << fourcc).str();
98         }
99         result[i] = c;
100     }
101     return result;
102 }
103 
bitDepth(VideoPixelFormat format)104 size_t bitDepth(VideoPixelFormat format) {
105     switch (format) {
106     case VideoPixelFormat::I420:
107     case VideoPixelFormat::YV12:
108     case VideoPixelFormat::I422:
109     case VideoPixelFormat::I420A:
110     case VideoPixelFormat::I444:
111     case VideoPixelFormat::NV12:
112     case VideoPixelFormat::NV21:
113     case VideoPixelFormat::YUY2:
114     case VideoPixelFormat::ARGB:
115     case VideoPixelFormat::XRGB:
116     case VideoPixelFormat::RGB24:
117     case VideoPixelFormat::MJPEG:
118     case VideoPixelFormat::ABGR:
119     case VideoPixelFormat::XBGR:
120     case VideoPixelFormat::BGRA:
121     case VideoPixelFormat::RGBA:
122         return 8;
123     case VideoPixelFormat::YUV420P9:
124     case VideoPixelFormat::YUV422P9:
125     case VideoPixelFormat::YUV444P9:
126         return 9;
127     case VideoPixelFormat::YUV420P10:
128     case VideoPixelFormat::YUV422P10:
129     case VideoPixelFormat::YUV444P10:
130     case VideoPixelFormat::XR30:
131     case VideoPixelFormat::XB30:
132         return 10;
133     case VideoPixelFormat::YUV420P12:
134     case VideoPixelFormat::YUV422P12:
135     case VideoPixelFormat::YUV444P12:
136         return 12;
137     case VideoPixelFormat::Y16:
138     case VideoPixelFormat::P016LE:
139         return 16;
140     case VideoPixelFormat::UNKNOWN:
141         ALOGE("Invalid pixel format");
142         return 0;
143     }
144 }
145 
146 // If it is required to allocate aligned to multiple-of-two size overall for the
147 // frame of pixel |format|.
RequiresEvenSizeAllocation(VideoPixelFormat format)148 static bool RequiresEvenSizeAllocation(VideoPixelFormat format) {
149     switch (format) {
150     case VideoPixelFormat::ARGB:
151     case VideoPixelFormat::XRGB:
152     case VideoPixelFormat::RGB24:
153     case VideoPixelFormat::Y16:
154     case VideoPixelFormat::ABGR:
155     case VideoPixelFormat::XBGR:
156     case VideoPixelFormat::XR30:
157     case VideoPixelFormat::XB30:
158     case VideoPixelFormat::BGRA:
159     case VideoPixelFormat::RGBA:
160         return false;
161     case VideoPixelFormat::NV12:
162     case VideoPixelFormat::NV21:
163     case VideoPixelFormat::I420:
164     case VideoPixelFormat::MJPEG:
165     case VideoPixelFormat::YUY2:
166     case VideoPixelFormat::YV12:
167     case VideoPixelFormat::I422:
168     case VideoPixelFormat::I444:
169     case VideoPixelFormat::YUV420P9:
170     case VideoPixelFormat::YUV422P9:
171     case VideoPixelFormat::YUV444P9:
172     case VideoPixelFormat::YUV420P10:
173     case VideoPixelFormat::YUV422P10:
174     case VideoPixelFormat::YUV444P10:
175     case VideoPixelFormat::YUV420P12:
176     case VideoPixelFormat::YUV422P12:
177     case VideoPixelFormat::YUV444P12:
178     case VideoPixelFormat::I420A:
179     case VideoPixelFormat::P016LE:
180         return true;
181     case VideoPixelFormat::UNKNOWN:
182         ALOGE("Invalid pixel format");
183         return false;
184     }
185 }
186 
numPlanes(VideoPixelFormat format)187 size_t numPlanes(VideoPixelFormat format) {
188     switch (format) {
189     case VideoPixelFormat::YUY2:
190     case VideoPixelFormat::ARGB:
191     case VideoPixelFormat::BGRA:
192     case VideoPixelFormat::RGBA:
193     case VideoPixelFormat::XRGB:
194     case VideoPixelFormat::RGB24:
195     case VideoPixelFormat::MJPEG:
196     case VideoPixelFormat::Y16:
197     case VideoPixelFormat::ABGR:
198     case VideoPixelFormat::XBGR:
199     case VideoPixelFormat::XR30:
200     case VideoPixelFormat::XB30:
201         return 1;
202     case VideoPixelFormat::NV12:
203     case VideoPixelFormat::NV21:
204     case VideoPixelFormat::P016LE:
205         return 2;
206     case VideoPixelFormat::I420:
207     case VideoPixelFormat::YV12:
208     case VideoPixelFormat::I422:
209     case VideoPixelFormat::I444:
210     case VideoPixelFormat::YUV420P9:
211     case VideoPixelFormat::YUV422P9:
212     case VideoPixelFormat::YUV444P9:
213     case VideoPixelFormat::YUV420P10:
214     case VideoPixelFormat::YUV422P10:
215     case VideoPixelFormat::YUV444P10:
216     case VideoPixelFormat::YUV420P12:
217     case VideoPixelFormat::YUV422P12:
218     case VideoPixelFormat::YUV444P12:
219         return 3;
220     case VideoPixelFormat::I420A:
221         return 4;
222     case VideoPixelFormat::UNKNOWN:
223         // Note: VideoPixelFormat::UNKNOWN is used for end-of-stream frame.
224         return 0;
225     }
226 }
227 
allocationSize(VideoPixelFormat format,const android::ui::Size & coded_size)228 size_t allocationSize(VideoPixelFormat format, const android::ui::Size& coded_size) {
229     size_t total = 0;
230     for (size_t i = 0; i < numPlanes(format); ++i) {
231         android::ui::Size plane_size = planeSize(format, i, coded_size);
232         total += (plane_size.width * plane_size.height);
233     }
234 
235     return total;
236 }
237 
planeSize(VideoPixelFormat format,size_t plane,const android::ui::Size & coded_size)238 android::ui::Size planeSize(VideoPixelFormat format, size_t plane,
239                             const android::ui::Size& coded_size) {
240     ALOG_ASSERT(isValidPlane(plane, format));
241 
242     int width = coded_size.width;
243     int height = coded_size.height;
244     if (RequiresEvenSizeAllocation(format)) {
245         // Align to multiple-of-two size overall. This ensures that non-subsampled
246         // planes can be addressed by pixel with the same scaling as the subsampled
247         // planes.
248         width = base::bits::Align(width, 2);
249         height = base::bits::Align(height, 2);
250     }
251 
252     const android::ui::Size subsample = SampleSize(format, plane);
253     ALOG_ASSERT(width % subsample.width == 0);
254     ALOG_ASSERT(height % subsample.height == 0);
255     return android::ui::Size(bytesPerElement(format, plane) * width / subsample.width,
256                              height / subsample.height);
257 }
258 
planeHorizontalBitsPerPixel(VideoPixelFormat format,size_t plane)259 int planeHorizontalBitsPerPixel(VideoPixelFormat format, size_t plane) {
260     ALOG_ASSERT(isValidPlane(plane, format));
261     const int bitsPerElement = 8 * bytesPerElement(format, plane);
262     const int horizPixelsPerElement = SampleSize(format, plane).width;
263     ALOG_ASSERT(bitsPerElement % horizPixelsPerElement == 0);
264     return bitsPerElement / horizPixelsPerElement;
265 }
266 
planeBitsPerPixel(VideoPixelFormat format,size_t plane)267 int planeBitsPerPixel(VideoPixelFormat format, size_t plane) {
268     ALOG_ASSERT(isValidPlane(plane, format));
269     return planeHorizontalBitsPerPixel(format, plane) / SampleSize(format, plane).height;
270 }
271 
bytesPerElement(VideoPixelFormat format,size_t plane)272 int bytesPerElement(VideoPixelFormat format, size_t plane) {
273     ALOG_ASSERT(isValidPlane(format, plane));
274     switch (format) {
275     case VideoPixelFormat::ARGB:
276     case VideoPixelFormat::BGRA:
277     case VideoPixelFormat::RGBA:
278     case VideoPixelFormat::XRGB:
279     case VideoPixelFormat::ABGR:
280     case VideoPixelFormat::XBGR:
281     case VideoPixelFormat::XR30:
282     case VideoPixelFormat::XB30:
283         return 4;
284     case VideoPixelFormat::RGB24:
285         return 3;
286     case VideoPixelFormat::Y16:
287     case VideoPixelFormat::YUY2:
288     case VideoPixelFormat::YUV420P9:
289     case VideoPixelFormat::YUV422P9:
290     case VideoPixelFormat::YUV444P9:
291     case VideoPixelFormat::YUV420P10:
292     case VideoPixelFormat::YUV422P10:
293     case VideoPixelFormat::YUV444P10:
294     case VideoPixelFormat::YUV420P12:
295     case VideoPixelFormat::YUV422P12:
296     case VideoPixelFormat::YUV444P12:
297     case VideoPixelFormat::P016LE:
298         return 2;
299     case VideoPixelFormat::NV12:
300     case VideoPixelFormat::NV21: {
301         static const int bytes_per_element[] = {1, 2};
302         ALOG_ASSERT(plane < base::size(bytes_per_element));
303         return bytes_per_element[plane];
304     }
305     case VideoPixelFormat::YV12:
306     case VideoPixelFormat::I420:
307     case VideoPixelFormat::I422:
308     case VideoPixelFormat::I420A:
309     case VideoPixelFormat::I444:
310         return 1;
311     case VideoPixelFormat::MJPEG:
312         return 0;
313     case VideoPixelFormat::UNKNOWN:
314         ALOGE("Invalid pixel format");
315         return 0;
316     }
317 }
318 
isValidPlane(VideoPixelFormat format,size_t plane)319 bool isValidPlane(VideoPixelFormat format, size_t plane) {
320     ALOG_ASSERT(numPlanes(format) <= static_cast<size_t>(kMaxPlanes));
321     return plane < numPlanes(format);
322 }
323 
SampleSize(VideoPixelFormat format,size_t plane)324 android::ui::Size SampleSize(VideoPixelFormat format, size_t plane) {
325     ALOG_ASSERT(isValidPlane(format, plane));
326 
327     switch (plane) {
328     case kYPlane:  // and kARGBPlane:
329     case kAPlane:
330         return android::ui::Size(1, 1);
331 
332     case kUPlane:  // and kUVPlane:
333     case kVPlane:
334         switch (format) {
335         case VideoPixelFormat::I444:
336         case VideoPixelFormat::YUV444P9:
337         case VideoPixelFormat::YUV444P10:
338         case VideoPixelFormat::YUV444P12:
339         case VideoPixelFormat::Y16:
340             return android::ui::Size(1, 1);
341 
342         case VideoPixelFormat::I422:
343         case VideoPixelFormat::YUV422P9:
344         case VideoPixelFormat::YUV422P10:
345         case VideoPixelFormat::YUV422P12:
346             return android::ui::Size(2, 1);
347 
348         case VideoPixelFormat::YV12:
349         case VideoPixelFormat::I420:
350         case VideoPixelFormat::I420A:
351         case VideoPixelFormat::NV12:
352         case VideoPixelFormat::NV21:
353         case VideoPixelFormat::YUV420P9:
354         case VideoPixelFormat::YUV420P10:
355         case VideoPixelFormat::YUV420P12:
356         case VideoPixelFormat::P016LE:
357             return android::ui::Size(2, 2);
358 
359         case VideoPixelFormat::UNKNOWN:
360         case VideoPixelFormat::YUY2:
361         case VideoPixelFormat::ARGB:
362         case VideoPixelFormat::XRGB:
363         case VideoPixelFormat::RGB24:
364         case VideoPixelFormat::MJPEG:
365         case VideoPixelFormat::ABGR:
366         case VideoPixelFormat::XBGR:
367         case VideoPixelFormat::XR30:
368         case VideoPixelFormat::XB30:
369         case VideoPixelFormat::BGRA:
370         case VideoPixelFormat::RGBA:
371             ALOGE("Invalid pixel format");
372         }
373     }
374 
375     return android::ui::Size();
376 }
377 
378 }  // namespace android
379