| // Copyright 2019 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "media/gpu/chromeos/fourcc.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/notreached.h" | 
 | #include "media/gpu/macros.h" | 
 |  | 
 | #if BUILDFLAG(USE_V4L2_CODEC) | 
 | #include <linux/videodev2.h> | 
 | #endif  // BUILDFLAG(USE_V4L2_CODEC) | 
 |  | 
 | #if BUILDFLAG(USE_VAAPI) | 
 | #include <va/va.h> | 
 | #endif  // BUILDFLAG(USE_VAAPI) | 
 |  | 
 | namespace media { | 
 |  | 
 | Fourcc::Fourcc(Fourcc::Value fourcc) : value_(fourcc) {} | 
 | Fourcc::~Fourcc() = default; | 
 | Fourcc& Fourcc::operator=(const Fourcc& other) = default; | 
 |  | 
 | // static | 
 | absl::optional<Fourcc> Fourcc::FromUint32(uint32_t fourcc) { | 
 |   switch (fourcc) { | 
 |     case AR24: | 
 |     case AB24: | 
 |     case XR24: | 
 |     case XB24: | 
 |     case RGB4: | 
 |     case YU12: | 
 |     case YV12: | 
 |     case YM12: | 
 |     case YM21: | 
 |     case YUYV: | 
 |     case NV12: | 
 |     case NV21: | 
 |     case NM12: | 
 |     case NM21: | 
 |     case YU16: | 
 |     case YM16: | 
 |     case MT21: | 
 |     case MM21: | 
 |     case P010: | 
 |       return Fourcc(static_cast<Value>(fourcc)); | 
 |   } | 
 |   DVLOGF(3) << "Unmapped fourcc: " << FourccToString(fourcc); | 
 |   return absl::nullopt; | 
 | } | 
 |  | 
 | // static | 
 | absl::optional<Fourcc> Fourcc::FromVideoPixelFormat( | 
 |     VideoPixelFormat pixel_format, | 
 |     bool single_planar) { | 
 |   if (single_planar) { | 
 |     switch (pixel_format) { | 
 |       case PIXEL_FORMAT_ARGB: | 
 |         return Fourcc(AR24); | 
 |       case PIXEL_FORMAT_ABGR: | 
 |         return Fourcc(AB24); | 
 |       case PIXEL_FORMAT_XRGB: | 
 |         return Fourcc(XR24); | 
 |       case PIXEL_FORMAT_XBGR: | 
 |         return Fourcc(XB24); | 
 |       case PIXEL_FORMAT_BGRA: | 
 |         return Fourcc(RGB4); | 
 |       case PIXEL_FORMAT_I420: | 
 |         return Fourcc(YU12); | 
 |       case PIXEL_FORMAT_YV12: | 
 |         return Fourcc(YV12); | 
 |       case PIXEL_FORMAT_YUY2: | 
 |         return Fourcc(YUYV); | 
 |       case PIXEL_FORMAT_NV12: | 
 |         return Fourcc(NV12); | 
 |       case PIXEL_FORMAT_NV21: | 
 |         return Fourcc(NV21); | 
 |       case PIXEL_FORMAT_I422: | 
 |         return Fourcc(YU16); | 
 |       case PIXEL_FORMAT_P016LE: | 
 |         return Fourcc(P010); | 
 |       case PIXEL_FORMAT_UYVY: | 
 |         NOTREACHED(); | 
 |         FALLTHROUGH; | 
 |       case PIXEL_FORMAT_I420A: | 
 |       case PIXEL_FORMAT_I444: | 
 |       case PIXEL_FORMAT_RGB24: | 
 |       case PIXEL_FORMAT_MJPEG: | 
 |       case PIXEL_FORMAT_YUV420P9: | 
 |       case PIXEL_FORMAT_YUV420P10: | 
 |       case PIXEL_FORMAT_YUV422P9: | 
 |       case PIXEL_FORMAT_YUV422P10: | 
 |       case PIXEL_FORMAT_YUV444P9: | 
 |       case PIXEL_FORMAT_YUV444P10: | 
 |       case PIXEL_FORMAT_YUV420P12: | 
 |       case PIXEL_FORMAT_YUV422P12: | 
 |       case PIXEL_FORMAT_YUV444P12: | 
 |       case PIXEL_FORMAT_Y16: | 
 |       case PIXEL_FORMAT_XR30: | 
 |       case PIXEL_FORMAT_XB30: | 
 |       case PIXEL_FORMAT_RGBAF16: | 
 |       case PIXEL_FORMAT_UNKNOWN: | 
 |         break; | 
 |     } | 
 |   } else { | 
 |     switch (pixel_format) { | 
 |       case PIXEL_FORMAT_I420: | 
 |         return Fourcc(YM12); | 
 |       case PIXEL_FORMAT_YV12: | 
 |         return Fourcc(YM21); | 
 |       case PIXEL_FORMAT_NV12: | 
 |         return Fourcc(NM12); | 
 |       case PIXEL_FORMAT_I422: | 
 |         return Fourcc(YM16); | 
 |       case PIXEL_FORMAT_NV21: | 
 |         return Fourcc(NM21); | 
 |       case PIXEL_FORMAT_UYVY: | 
 |         NOTREACHED(); | 
 |         FALLTHROUGH; | 
 |       case PIXEL_FORMAT_I420A: | 
 |       case PIXEL_FORMAT_I444: | 
 |       case PIXEL_FORMAT_YUY2: | 
 |       case PIXEL_FORMAT_ARGB: | 
 |       case PIXEL_FORMAT_XRGB: | 
 |       case PIXEL_FORMAT_RGB24: | 
 |       case PIXEL_FORMAT_MJPEG: | 
 |       case PIXEL_FORMAT_YUV420P9: | 
 |       case PIXEL_FORMAT_YUV420P10: | 
 |       case PIXEL_FORMAT_YUV422P9: | 
 |       case PIXEL_FORMAT_YUV422P10: | 
 |       case PIXEL_FORMAT_YUV444P9: | 
 |       case PIXEL_FORMAT_YUV444P10: | 
 |       case PIXEL_FORMAT_YUV420P12: | 
 |       case PIXEL_FORMAT_YUV422P12: | 
 |       case PIXEL_FORMAT_YUV444P12: | 
 |       case PIXEL_FORMAT_Y16: | 
 |       case PIXEL_FORMAT_ABGR: | 
 |       case PIXEL_FORMAT_XBGR: | 
 |       case PIXEL_FORMAT_P016LE: | 
 |       case PIXEL_FORMAT_XR30: | 
 |       case PIXEL_FORMAT_XB30: | 
 |       case PIXEL_FORMAT_BGRA: | 
 |       case PIXEL_FORMAT_RGBAF16: | 
 |       case PIXEL_FORMAT_UNKNOWN: | 
 |         break; | 
 |     } | 
 |   } | 
 |   DVLOGF(3) << "Unmapped " << VideoPixelFormatToString(pixel_format) << " for " | 
 |             << (single_planar ? "single-planar" : "multi-planar"); | 
 |   return absl::nullopt; | 
 | } | 
 |  | 
 | VideoPixelFormat Fourcc::ToVideoPixelFormat() const { | 
 |   switch (value_) { | 
 |     case AR24: | 
 |       return PIXEL_FORMAT_ARGB; | 
 |     case AB24: | 
 |       return PIXEL_FORMAT_ABGR; | 
 |     case XR24: | 
 |       return PIXEL_FORMAT_XRGB; | 
 |     case XB24: | 
 |       return PIXEL_FORMAT_XBGR; | 
 |     case RGB4: | 
 |       return PIXEL_FORMAT_BGRA; | 
 |     case YU12: | 
 |     case YM12: | 
 |       return PIXEL_FORMAT_I420; | 
 |     case YV12: | 
 |     case YM21: | 
 |       return PIXEL_FORMAT_YV12; | 
 |     case YUYV: | 
 |       return PIXEL_FORMAT_YUY2; | 
 |     case NV12: | 
 |     case NM12: | 
 |       return PIXEL_FORMAT_NV12; | 
 |     case NV21: | 
 |     case NM21: | 
 |       return PIXEL_FORMAT_NV21; | 
 |     case YU16: | 
 |     case YM16: | 
 |       return PIXEL_FORMAT_I422; | 
 |     // V4L2_PIX_FMT_MT21C is only used for MT8173 hardware video decoder output | 
 |     // and should be converted by MT8173 image processor for compositor to | 
 |     // render. Since it is an intermediate format for video decoder, | 
 |     // VideoPixelFormat shall not have its mapping. However, we need to create a | 
 |     // VideoFrameLayout for the format to process the intermediate frame. Hence | 
 |     // we map V4L2_PIX_FMT_MT21C to PIXEL_FORMAT_NV12 as their layout are the | 
 |     // same. | 
 |     case MT21: | 
 |     // V4L2_PIX_FMT_MM21 is used for MT8183 hardware video decoder. It is | 
 |     // similar to V4L2_PIX_FMT_MT21C but is not compressed ; thus it can also | 
 |     // be mapped to PIXEL_FORMAT_NV12. | 
 |     case MM21: | 
 |       return PIXEL_FORMAT_NV12; | 
 |     case P010: | 
 |       return PIXEL_FORMAT_P016LE; | 
 |   } | 
 |   NOTREACHED() << "Unmapped Fourcc: " << ToString(); | 
 |   return PIXEL_FORMAT_UNKNOWN; | 
 | } | 
 |  | 
 | #if BUILDFLAG(USE_V4L2_CODEC) | 
 | // static | 
 | absl::optional<Fourcc> Fourcc::FromV4L2PixFmt(uint32_t v4l2_pix_fmt) { | 
 |   // We can do that because we adopt the same internal definition of Fourcc as | 
 |   // V4L2. | 
 |   return FromUint32(v4l2_pix_fmt); | 
 | } | 
 |  | 
 | uint32_t Fourcc::ToV4L2PixFmt() const { | 
 |   // Note that we can do that because we adopt the same internal definition of | 
 |   // Fourcc as V4L2. | 
 |   return static_cast<uint32_t>(value_); | 
 | } | 
 | #endif  // BUILDFLAG(USE_V4L2_CODEC) | 
 |  | 
 | #if BUILDFLAG(USE_VAAPI) | 
 | // static | 
 | absl::optional<Fourcc> Fourcc::FromVAFourCC(uint32_t va_fourcc) { | 
 |   switch (va_fourcc) { | 
 |     case VA_FOURCC_I420: | 
 |       return Fourcc(YU12); | 
 |     case VA_FOURCC_NV12: | 
 |       return Fourcc(NV12); | 
 |     case VA_FOURCC_NV21: | 
 |       return Fourcc(NV21); | 
 |     case VA_FOURCC_YV12: | 
 |       return Fourcc(YV12); | 
 |     case VA_FOURCC_YUY2: | 
 |       return Fourcc(YUYV); | 
 |     case VA_FOURCC_RGBA: | 
 |       return Fourcc(AB24); | 
 |     case VA_FOURCC_RGBX: | 
 |       return Fourcc(XB24); | 
 |     case VA_FOURCC_BGRA: | 
 |       return Fourcc(AR24); | 
 |     case VA_FOURCC_BGRX: | 
 |       return Fourcc(XR24); | 
 |     case VA_FOURCC_ARGB: | 
 |       return Fourcc(RGB4); | 
 |     case VA_FOURCC_P010: | 
 |       return Fourcc(P010); | 
 |   } | 
 |   DVLOGF(3) << "Unmapped VAFourCC: " << FourccToString(va_fourcc); | 
 |   return absl::nullopt; | 
 | } | 
 |  | 
 | absl::optional<uint32_t> Fourcc::ToVAFourCC() const { | 
 |   switch (value_) { | 
 |     case YU12: | 
 |       return VA_FOURCC_I420; | 
 |     case NV12: | 
 |       return VA_FOURCC_NV12; | 
 |     case NV21: | 
 |       return VA_FOURCC_NV21; | 
 |     case YV12: | 
 |       return VA_FOURCC_YV12; | 
 |     case YUYV: | 
 |       return VA_FOURCC_YUY2; | 
 |     case AB24: | 
 |       return VA_FOURCC_RGBA; | 
 |     case XB24: | 
 |       return VA_FOURCC_RGBX; | 
 |     case AR24: | 
 |       return VA_FOURCC_BGRA; | 
 |     case XR24: | 
 |       return VA_FOURCC_BGRX; | 
 |     case RGB4: | 
 |       return VA_FOURCC_ARGB; | 
 |     case P010: | 
 |       return VA_FOURCC_P010; | 
 |     case YM12: | 
 |     case YM21: | 
 |     case NM12: | 
 |     case NM21: | 
 |     case YU16: | 
 |     case YM16: | 
 |     case MT21: | 
 |     case MM21: | 
 |       // VAAPI does not know about these formats, so signal this by returning | 
 |       // nullopt. | 
 |       DVLOGF(3) << "Fourcc not convertible to VaFourCC: " << ToString(); | 
 |       return absl::nullopt; | 
 |   } | 
 |   NOTREACHED() << "Unmapped Fourcc: " << ToString(); | 
 |   return absl::nullopt; | 
 | } | 
 |  | 
 | #endif  // BUILDFLAG(USE_VAAPI) | 
 |  | 
 | absl::optional<Fourcc> Fourcc::ToSinglePlanar() const { | 
 |   switch (value_) { | 
 |     case AR24: | 
 |     case AB24: | 
 |     case XR24: | 
 |     case XB24: | 
 |     case RGB4: | 
 |     case YU12: | 
 |     case YV12: | 
 |     case YUYV: | 
 |     case NV12: | 
 |     case NV21: | 
 |     case P010: | 
 |       return Fourcc(value_); | 
 |     case YM12: | 
 |       return Fourcc(YU12); | 
 |     case YM21: | 
 |       return Fourcc(YV12); | 
 |     case NM12: | 
 |       return Fourcc(NV12); | 
 |     case NM21: | 
 |       return Fourcc(NV21); | 
 |     case YU16: | 
 |     case YM16: | 
 |       return Fourcc(YU16); | 
 |     case MT21: | 
 |     case MM21: | 
 |       return absl::nullopt; | 
 |   } | 
 | } | 
 |  | 
 | bool operator!=(const Fourcc& lhs, const Fourcc& rhs) { | 
 |   return !(lhs == rhs); | 
 | } | 
 |  | 
 | bool Fourcc::IsMultiPlanar() const { | 
 |   switch (value_) { | 
 |     case AR24: | 
 |     case AB24: | 
 |     case XR24: | 
 |     case XB24: | 
 |     case RGB4: | 
 |     case YU12: | 
 |     case YV12: | 
 |     case YUYV: | 
 |     case NV12: | 
 |     case NV21: | 
 |     case YU16: | 
 |     case P010: | 
 |       return false; | 
 |     case YM12: | 
 |     case YM21: | 
 |     case NM12: | 
 |     case NM21: | 
 |     case YM16: | 
 |     case MT21: | 
 |     case MM21: | 
 |       return true; | 
 |   } | 
 | } | 
 |  | 
 | std::string Fourcc::ToString() const { | 
 |   return FourccToString(static_cast<uint32_t>(value_)); | 
 | } | 
 |  | 
 | #if BUILDFLAG(USE_V4L2_CODEC) | 
 | static_assert(Fourcc::AR24 == V4L2_PIX_FMT_ABGR32, "Mismatch Fourcc"); | 
 | #ifdef V4L2_PIX_FMT_RGBA32 | 
 | // V4L2_PIX_FMT_RGBA32 is defined since v5.2 | 
 | static_assert(Fourcc::AB24 == V4L2_PIX_FMT_RGBA32, "Mismatch Fourcc"); | 
 | #endif  // V4L2_PIX_FMT_RGBA32 | 
 | static_assert(Fourcc::XR24 == V4L2_PIX_FMT_XBGR32, "Mismatch Fourcc"); | 
 | #ifdef V4L2_PIX_FMT_RGBX32 | 
 | // V4L2_PIX_FMT_RGBX32 is defined since v5.2 | 
 | static_assert(Fourcc::XB24 == V4L2_PIX_FMT_RGBX32, "Mismatch Fourcc"); | 
 | #endif  // V4L2_PIX_FMT_RGBX32 | 
 | static_assert(Fourcc::RGB4 == V4L2_PIX_FMT_RGB32, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YU12 == V4L2_PIX_FMT_YUV420, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YV12 == V4L2_PIX_FMT_YVU420, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YM12 == V4L2_PIX_FMT_YUV420M, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YM21 == V4L2_PIX_FMT_YVU420M, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YUYV == V4L2_PIX_FMT_YUYV, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::NV12 == V4L2_PIX_FMT_NV12, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::NV21 == V4L2_PIX_FMT_NV21, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::NM12 == V4L2_PIX_FMT_NV12M, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::NM21 == V4L2_PIX_FMT_NV21M, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YU16 == V4L2_PIX_FMT_YUV422P, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::YM16 == V4L2_PIX_FMT_YUV422M, "Mismatch Fourcc"); | 
 | static_assert(Fourcc::MT21 == V4L2_PIX_FMT_MT21C, "Mismatch Fourcc"); | 
 | #ifdef V4L2_PIX_FMT_MM21 | 
 | // V4L2_PIX_FMT_MM21 is not yet upstreamed. | 
 | static_assert(Fourcc::MM21 == V4L2_PIX_FMT_MM21, "Mismatch Fourcc"); | 
 | #endif  // V4L2_PIX_FMT_MM21 | 
 | #endif  // BUILDFLAG(USE_V4L2_CODEC) | 
 | }  // namespace media |