1 // Copyright 2019 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 
5 #include <v4l2_codec2/common/Fourcc.h>
6 
7 #include <linux/videodev2.h>
8 
9 #include <utils/Log.h>
10 
11 namespace android {
12 
Fourcc(Fourcc::Value fourcc)13 Fourcc::Fourcc(Fourcc::Value fourcc) : mValue(fourcc) {}
14 Fourcc::~Fourcc() = default;
15 Fourcc& Fourcc::operator=(const Fourcc& other) = default;
16 
17 // static
fromUint32(uint32_t fourcc)18 std::optional<Fourcc> Fourcc::fromUint32(uint32_t fourcc) {
19     switch (fourcc) {
20     case AR24:
21     case AB24:
22     case XR24:
23     case XB24:
24     case RGB4:
25     case YU12:
26     case YV12:
27     case YM12:
28     case YM21:
29     case YUYV:
30     case NV12:
31     case NV21:
32     case NM12:
33     case NM21:
34     case YM16:
35     case MT21:
36     case MM21:
37         return Fourcc(static_cast<Value>(fourcc));
38     }
39     ALOGE("Unmapped fourcc: %s", fourccToString(fourcc).c_str());
40     return std::nullopt;
41 }
42 
43 // static
fromVideoPixelFormat(VideoPixelFormat pixelFormat,bool singlePlanar)44 std::optional<Fourcc> Fourcc::fromVideoPixelFormat(VideoPixelFormat pixelFormat,
45                                                    bool singlePlanar) {
46     if (singlePlanar) {
47         switch (pixelFormat) {
48         case VideoPixelFormat::ARGB:
49             return Fourcc(AR24);
50         case VideoPixelFormat::ABGR:
51             return Fourcc(AB24);
52         case VideoPixelFormat::XRGB:
53             return Fourcc(XR24);
54         case VideoPixelFormat::XBGR:
55             return Fourcc(XB24);
56         case VideoPixelFormat::BGRA:
57             return Fourcc(RGB4);
58         case VideoPixelFormat::I420:
59             return Fourcc(YU12);
60         case VideoPixelFormat::YV12:
61             return Fourcc(YV12);
62         case VideoPixelFormat::YUY2:
63             return Fourcc(YUYV);
64         case VideoPixelFormat::NV12:
65             return Fourcc(NV12);
66         case VideoPixelFormat::NV21:
67             return Fourcc(NV21);
68         case VideoPixelFormat::I422:
69         case VideoPixelFormat::I420A:
70         case VideoPixelFormat::I444:
71         case VideoPixelFormat::RGB24:
72         case VideoPixelFormat::MJPEG:
73         case VideoPixelFormat::YUV420P9:
74         case VideoPixelFormat::YUV420P10:
75         case VideoPixelFormat::YUV422P9:
76         case VideoPixelFormat::YUV422P10:
77         case VideoPixelFormat::YUV444P9:
78         case VideoPixelFormat::YUV444P10:
79         case VideoPixelFormat::YUV420P12:
80         case VideoPixelFormat::YUV422P12:
81         case VideoPixelFormat::YUV444P12:
82         case VideoPixelFormat::Y16:
83         case VideoPixelFormat::P016LE:
84         case VideoPixelFormat::XR30:
85         case VideoPixelFormat::XB30:
86         case VideoPixelFormat::UNKNOWN:
87             break;
88         }
89     } else {
90         switch (pixelFormat) {
91         case VideoPixelFormat::I420:
92             return Fourcc(YM12);
93         case VideoPixelFormat::YV12:
94             return Fourcc(YM21);
95         case VideoPixelFormat::NV12:
96             return Fourcc(NM12);
97         case VideoPixelFormat::I422:
98             return Fourcc(YM16);
99         case VideoPixelFormat::NV21:
100             return Fourcc(NM21);
101         case VideoPixelFormat::I420A:
102         case VideoPixelFormat::I444:
103         case VideoPixelFormat::YUY2:
104         case VideoPixelFormat::ARGB:
105         case VideoPixelFormat::XRGB:
106         case VideoPixelFormat::RGB24:
107         case VideoPixelFormat::MJPEG:
108         case VideoPixelFormat::YUV420P9:
109         case VideoPixelFormat::YUV420P10:
110         case VideoPixelFormat::YUV422P9:
111         case VideoPixelFormat::YUV422P10:
112         case VideoPixelFormat::YUV444P9:
113         case VideoPixelFormat::YUV444P10:
114         case VideoPixelFormat::YUV420P12:
115         case VideoPixelFormat::YUV422P12:
116         case VideoPixelFormat::YUV444P12:
117         case VideoPixelFormat::Y16:
118         case VideoPixelFormat::ABGR:
119         case VideoPixelFormat::XBGR:
120         case VideoPixelFormat::P016LE:
121         case VideoPixelFormat::XR30:
122         case VideoPixelFormat::XB30:
123         case VideoPixelFormat::BGRA:
124         case VideoPixelFormat::UNKNOWN:
125             break;
126         }
127     }
128     ALOGE("Unmapped %s for %s", videoPixelFormatToString(pixelFormat).c_str(),
129           singlePlanar ? "single-planar" : "multi-planar");
130     return std::nullopt;
131 }
132 
toVideoPixelFormat() const133 VideoPixelFormat Fourcc::toVideoPixelFormat() const {
134     switch (mValue) {
135     case AR24:
136         return VideoPixelFormat::ARGB;
137     case AB24:
138         return VideoPixelFormat::ABGR;
139     case XR24:
140         return VideoPixelFormat::XRGB;
141     case XB24:
142         return VideoPixelFormat::XBGR;
143     case RGB4:
144         return VideoPixelFormat::BGRA;
145     case YU12:
146     case YM12:
147         return VideoPixelFormat::I420;
148     case YV12:
149     case YM21:
150         return VideoPixelFormat::YV12;
151     case YUYV:
152         return VideoPixelFormat::YUY2;
153     case NV12:
154     case NM12:
155         return VideoPixelFormat::NV12;
156     case NV21:
157     case NM21:
158         return VideoPixelFormat::NV21;
159     case YM16:
160         return VideoPixelFormat::I422;
161     // V4L2_PIX_FMT_MT21C is only used for MT8173 hardware video decoder output
162     // and should be converted by MT8173 image processor for compositor to
163     // render. Since it is an intermediate format for video decoder,
164     // VideoPixelFormat shall not have its mapping. However, we need to create a
165     // VideoFrameLayout for the format to process the intermediate frame. Hence
166     // we map V4L2_PIX_FMT_MT21C to PIXEL_FORMAT_NV12 as their layout are the
167     // same.
168     case MT21:
169     // V4L2_PIX_FMT_MM21 is used for MT8183 hardware video decoder. It is
170     // similar to V4L2_PIX_FMT_MT21C but is not compressed ; thus it can also
171     // be mapped to PIXEL_FORMAT_NV12.
172     case MM21:
173         return VideoPixelFormat::NV12;
174     }
175 
176     ALOGE("Unmapped Fourcc: %s", toString().c_str());
177     return VideoPixelFormat::UNKNOWN;
178 }
179 
180 // static
fromV4L2PixFmt(uint32_t v4l2PixFmt)181 std::optional<Fourcc> Fourcc::fromV4L2PixFmt(uint32_t v4l2PixFmt) {
182     // We can do that because we adopt the same internal definition of Fourcc as
183     // V4L2.
184     return fromUint32(v4l2PixFmt);
185 }
186 
toV4L2PixFmt() const187 uint32_t Fourcc::toV4L2PixFmt() const {
188     // Note that we can do that because we adopt the same internal definition of
189     // Fourcc as V4L2.
190     return static_cast<uint32_t>(mValue);
191 }
192 
toSinglePlanar() const193 std::optional<Fourcc> Fourcc::toSinglePlanar() const {
194     switch (mValue) {
195     case AR24:
196     case AB24:
197     case XR24:
198     case XB24:
199     case RGB4:
200     case YU12:
201     case YV12:
202     case YUYV:
203     case NV12:
204     case NV21:
205         return Fourcc(mValue);
206     case YM12:
207         return Fourcc(YU12);
208     case YM21:
209         return Fourcc(YV12);
210     case NM12:
211         return Fourcc(NV12);
212     case NM21:
213         return Fourcc(NV21);
214     case YM16:
215     case MT21:
216     case MM21:
217         return std::nullopt;
218     }
219 }
220 
operator !=(const Fourcc & lhs,const Fourcc & rhs)221 bool operator!=(const Fourcc& lhs, const Fourcc& rhs) {
222     return !(lhs == rhs);
223 }
224 
isMultiPlanar() const225 bool Fourcc::isMultiPlanar() const {
226     switch (mValue) {
227     case AR24:
228     case AB24:
229     case XR24:
230     case XB24:
231     case RGB4:
232     case YU12:
233     case YV12:
234     case YUYV:
235     case NV12:
236     case NV21:
237         return false;
238     case YM12:
239     case YM21:
240     case NM12:
241     case NM21:
242     case YM16:
243     case MT21:
244     case MM21:
245         return true;
246     }
247 }
248 
toString() const249 std::string Fourcc::toString() const {
250     return fourccToString(static_cast<uint32_t>(mValue));
251 }
252 
253 static_assert(Fourcc::AR24 == V4L2_PIX_FMT_ABGR32, "Mismatch Fourcc");
254 #ifdef V4L2_PIX_FMT_RGBA32
255 // V4L2_PIX_FMT_RGBA32 is defined since v5.2
256 static_assert(Fourcc::AB24 == V4L2_PIX_FMT_RGBA32, "Mismatch Fourcc");
257 #endif  // V4L2_PIX_FMT_RGBA32
258 static_assert(Fourcc::XR24 == V4L2_PIX_FMT_XBGR32, "Mismatch Fourcc");
259 #ifdef V4L2_PIX_FMT_RGBX32
260 // V4L2_PIX_FMT_RGBX32 is defined since v5.2
261 static_assert(Fourcc::XB24 == V4L2_PIX_FMT_RGBX32, "Mismatch Fourcc");
262 #endif  // V4L2_PIX_FMT_RGBX32
263 static_assert(Fourcc::RGB4 == V4L2_PIX_FMT_RGB32, "Mismatch Fourcc");
264 static_assert(Fourcc::YU12 == V4L2_PIX_FMT_YUV420, "Mismatch Fourcc");
265 static_assert(Fourcc::YV12 == V4L2_PIX_FMT_YVU420, "Mismatch Fourcc");
266 static_assert(Fourcc::YM12 == V4L2_PIX_FMT_YUV420M, "Mismatch Fourcc");
267 static_assert(Fourcc::YM21 == V4L2_PIX_FMT_YVU420M, "Mismatch Fourcc");
268 static_assert(Fourcc::YUYV == V4L2_PIX_FMT_YUYV, "Mismatch Fourcc");
269 static_assert(Fourcc::NV12 == V4L2_PIX_FMT_NV12, "Mismatch Fourcc");
270 static_assert(Fourcc::NV21 == V4L2_PIX_FMT_NV21, "Mismatch Fourcc");
271 static_assert(Fourcc::NM12 == V4L2_PIX_FMT_NV12M, "Mismatch Fourcc");
272 static_assert(Fourcc::NM21 == V4L2_PIX_FMT_NV21M, "Mismatch Fourcc");
273 static_assert(Fourcc::YM16 == V4L2_PIX_FMT_YUV422M, "Mismatch Fourcc");
274 static_assert(Fourcc::MT21 == V4L2_PIX_FMT_MT21C, "Mismatch Fourcc");
275 #ifdef V4L2_PIX_FMT_MM21
276 // V4L2_PIX_FMT_MM21 is not yet upstreamed.
277 static_assert(Fourcc::MM21 == V4L2_PIX_FMT_MM21, "Mismatch Fourcc");
278 #endif  // V4L2_PIX_FMT_MM21
279 
280 }  // namespace android
281