#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>
#elif BUILDFLAG(USE_VAAPI)
#include <va/va.h>
#endif
namespace media {
std::optional<Fourcc> Fourcc::FromUint32(uint32_t fourcc) {
switch (fourcc) {
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:
case MT2T:
case AR24:
case Q08C:
case Q10C:
return Fourcc(static_cast<Value>(fourcc));
}
DVLOGF(4) << "Unmapped fourcc: " << FourccToString(fourcc);
return std::nullopt;
}
std::optional<Fourcc> Fourcc::FromVideoPixelFormat(
VideoPixelFormat pixel_format,
bool single_planar) {
if (single_planar) {
switch (pixel_format) {
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_P010LE:
return Fourcc(P010);
case PIXEL_FORMAT_ARGB:
return Fourcc(AR24);
case PIXEL_FORMAT_UYVY:
NOTREACHED();
case PIXEL_FORMAT_ABGR:
case PIXEL_FORMAT_XRGB:
case PIXEL_FORMAT_XBGR:
case PIXEL_FORMAT_BGRA:
case PIXEL_FORMAT_I420A:
case PIXEL_FORMAT_I444:
case PIXEL_FORMAT_RGB24:
case PIXEL_FORMAT_MJPEG:
case PIXEL_FORMAT_NV12A:
case PIXEL_FORMAT_NV16:
case PIXEL_FORMAT_NV24:
case PIXEL_FORMAT_P210LE:
case PIXEL_FORMAT_P410LE:
case PIXEL_FORMAT_YUV420P10:
case PIXEL_FORMAT_YUV422P10:
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_I422A:
case PIXEL_FORMAT_I444A:
case PIXEL_FORMAT_YUV420AP10:
case PIXEL_FORMAT_YUV422AP10:
case PIXEL_FORMAT_YUV444AP10:
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();
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_NV12A:
case PIXEL_FORMAT_NV16:
case PIXEL_FORMAT_NV24:
case PIXEL_FORMAT_P210LE:
case PIXEL_FORMAT_P410LE:
case PIXEL_FORMAT_YUV420P10:
case PIXEL_FORMAT_YUV422P10:
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_P010LE:
case PIXEL_FORMAT_XR30:
case PIXEL_FORMAT_XB30:
case PIXEL_FORMAT_BGRA:
case PIXEL_FORMAT_RGBAF16:
case PIXEL_FORMAT_I422A:
case PIXEL_FORMAT_I444A:
case PIXEL_FORMAT_YUV420AP10:
case PIXEL_FORMAT_YUV422AP10:
case PIXEL_FORMAT_YUV444AP10:
case PIXEL_FORMAT_UNKNOWN:
break;
}
}
DVLOGF(3) << "Unmapped " << VideoPixelFormatToString(pixel_format) << " for "
<< (single_planar ? "single-planar" : "multi-planar");
return std::nullopt;
}
VideoPixelFormat Fourcc::ToVideoPixelFormat() const {
switch (value_) {
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;
case MT21:
case MM21:
return PIXEL_FORMAT_NV12;
case P010:
return PIXEL_FORMAT_P010LE;
case MT2T:
return PIXEL_FORMAT_P010LE;
case AR24:
return PIXEL_FORMAT_ARGB;
case Q08C:
return PIXEL_FORMAT_NV12;
case Q10C:
return PIXEL_FORMAT_P010LE;
case UNDEFINED:
break;
}
NOTREACHED() << "Unmapped Fourcc: " << ToString();
}
#if BUILDFLAG(USE_V4L2_CODEC)
std::optional<Fourcc> Fourcc::FromV4L2PixFmt(uint32_t v4l2_pix_fmt) {
return FromUint32(v4l2_pix_fmt);
}
uint32_t Fourcc::ToV4L2PixFmt() const {
return static_cast<uint32_t>(value_);
}
#elif BUILDFLAG(USE_VAAPI)
std::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_P010:
return Fourcc(P010);
case VA_FOURCC_ARGB:
return Fourcc(AR24);
}
DVLOGF(3) << "Unmapped VAFourCC: " << FourccToString(va_fourcc);
return std::nullopt;
}
std::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 P010:
return VA_FOURCC_P010;
case AR24:
return VA_FOURCC_ARGB;
case YM12:
case YM21:
case NM12:
case NM21:
case YU16:
case YM16:
case MT21:
case MM21:
case MT2T:
case Q08C:
case Q10C:
case UNDEFINED:
DVLOGF(3) << "Fourcc not convertible to VaFourCC: " << ToString();
return std::nullopt;
}
NOTREACHED() << "Unmapped Fourcc: " << ToString();
}
#endif
std::optional<Fourcc> Fourcc::ToSinglePlanar() const {
switch (value_) {
case YU12:
case YV12:
case YUYV:
case NV12:
case NV21:
case P010:
case MM21:
case MT2T:
case AR24:
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 Q08C:
case Q10C:
case UNDEFINED:
return std::nullopt;
}
}
bool operator!=(const Fourcc& lhs, const Fourcc& rhs) {
return !(lhs == rhs);
}
bool Fourcc::IsMultiPlanar() const {
switch (value_) {
case YU12:
case YV12:
case YUYV:
case NV12:
case NV21:
case YU16:
case P010:
case MT2T:
case AR24:
case Q08C:
case Q10C:
case UNDEFINED:
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::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::MM21 == V4L2_PIX_FMT_MM21, "Mismatch Fourcc");
static_assert(Fourcc::MT21 == V4L2_PIX_FMT_MT21C, "Mismatch Fourcc");
static_assert(Fourcc::AR24 == V4L2_PIX_FMT_ABGR32, "Mismatch Fourcc");
static_assert(Fourcc::P010 == V4L2_PIX_FMT_P010, "Mismatch Fourcc");
#ifdef V4L2_PIX_FMT_MT2T
static_assert(Fourcc::MT2T == V4L2_PIX_FMT_MT2T, "Mismatch Fourcc");
#endif
#ifdef V4L2_PIX_FMT_QC08C
static_assert(Fourcc::Q08C == V4L2_PIX_FMT_QC08C, "Mismatch Fourcc");
#endif
#ifdef V4L2_PIX_FMT_QC10C
static_assert(Fourcc::Q10C == V4L2_PIX_FMT_QC10C, "Mismatch Fourcc");
#endif
#endif
}