blob: a43b47706c3c33b9a96dca96cf03111fd9a99bd0 [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkYUVAInfo.h"
#include "src/core/SkSafeMath.h"
int SkYUVAInfo::PlaneDimensions(SkISize imageDimensions,
PlanarConfig planarConfig,
SkEncodedOrigin origin,
SkISize* planeDimensions) {
int w = imageDimensions.width();
int h = imageDimensions.height();
if (origin >= kLeftTop_SkEncodedOrigin) {
using std::swap;
swap(w, h);
}
auto down2 = [](int x) { return (x + 1)/2; };
auto down4 = [](int x) { return (x + 3)/4; };
switch (planarConfig) {
case PlanarConfig::kY_U_V_444:
planeDimensions[0] = planeDimensions[1] = planeDimensions[2] = {w, h};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_422:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), h};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_420:
case PlanarConfig::kY_V_U_420:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_UV_A_4204:
case PlanarConfig::kY_VU_A_4204:
planeDimensions[0] = planeDimensions[2] = {w, h};
planeDimensions[1] = {down2(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_440:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {w, down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_411:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down4(w), h};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_410:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down4(w), down2(h)};
planeDimensions[3] = {0, 0};
return 3;
case PlanarConfig::kY_U_V_A_4204:
case PlanarConfig::kY_V_U_A_4204:
planeDimensions[0] = planeDimensions[3] = {w, h};
planeDimensions[1] = planeDimensions[2] = {down2(w), down2(h)};
return 4;
case PlanarConfig::kY_UV_420:
case PlanarConfig::kY_VU_420:
planeDimensions[0] = {w, h};
planeDimensions[1] = {down2(w), down2(h)};
planeDimensions[2] = planeDimensions[3] = {0, 0};
return 2;
case PlanarConfig::kYUV_444:
case PlanarConfig::kUYV_444:
case PlanarConfig::kYUVA_4444:
case PlanarConfig::kUYVA_4444:
planeDimensions[0] = {w, h};
planeDimensions[1] = planeDimensions[2] = planeDimensions[3] = {0, 0};
return 1;
}
SkUNREACHABLE;
}
bool SkYUVAInfo::HasAlpha(PlanarConfig planarConfig) {
switch (planarConfig) {
case PlanarConfig::kY_U_V_444: return false;
case PlanarConfig::kY_U_V_422: return false;
case PlanarConfig::kY_U_V_420: return false;
case PlanarConfig::kY_V_U_420: return false;
case PlanarConfig::kY_U_V_440: return false;
case PlanarConfig::kY_U_V_411: return false;
case PlanarConfig::kY_U_V_410: return false;
case PlanarConfig::kY_U_V_A_4204: return true;
case PlanarConfig::kY_V_U_A_4204: return true;
case PlanarConfig::kY_UV_420: return false;
case PlanarConfig::kY_VU_420: return false;
case PlanarConfig::kY_UV_A_4204: return true;
case PlanarConfig::kY_VU_A_4204: return true;
case PlanarConfig::kYUV_444: return false;
case PlanarConfig::kUYV_444: return false;
case PlanarConfig::kYUVA_4444: return true;
case PlanarConfig::kUYVA_4444: return true;
}
SkUNREACHABLE;
}
SkYUVAInfo::SkYUVAInfo(SkISize dimensions,
PlanarConfig planarConfig,
SkYUVColorSpace yuvColorSpace,
SkEncodedOrigin origin,
Siting sitingX,
Siting sitingY)
: fDimensions(dimensions)
, fPlanarConfig(planarConfig)
, fYUVColorSpace(yuvColorSpace)
, fOrigin(origin)
, fSitingX(sitingX)
, fSitingY(sitingY) {}
size_t SkYUVAInfo::computeTotalBytes(const size_t rowBytes[kMaxPlanes],
size_t planeSizes[kMaxPlanes]) const {
if (fDimensions.isEmpty()) {
return 0;
}
SkSafeMath safe;
size_t totalBytes = 0;
SkISize planeDimensions[kMaxPlanes];
int n = this->planeDimensions(planeDimensions);
for (int i = 0; i < n; ++i) {
SkASSERT(!planeDimensions[i].isEmpty());
SkASSERT(rowBytes[i]);
size_t size = safe.mul(rowBytes[i], planeDimensions[i].height());
if (planeSizes) {
planeSizes[i] = size;
}
totalBytes = safe.add(totalBytes, size);
}
if (planeSizes) {
if (safe.ok()) {
for (int i = n; i < kMaxPlanes; ++i) {
planeSizes[i] = 0;
}
} else {
for (int i = 0; n < kMaxPlanes; ++i) {
planeSizes[i] = SIZE_MAX;
}
}
}
return safe.ok() ? totalBytes : SIZE_MAX;
}
bool SkYUVAInfo::operator==(const SkYUVAInfo& that) const {
return fPlanarConfig == that.fPlanarConfig &&
fYUVColorSpace == that.fYUVColorSpace &&
fDimensions == that.fDimensions &&
fSitingX == that.fSitingX &&
fSitingY == that.fSitingY &&
fOrigin == that.fOrigin;
}