libyuv/source/convert_argb.cc
George Steed 96bbdb53ed [AArch64] Add SVE2 implementation of I422ToRGBARow
This is almost identical to the existing I422ToARGBRow_SVE2 kernel, we
just need to interleave differently for the output.

The RGBA format actually saves us an instruction compared to ARGB since
there is no need to merge in the alpha component, we can just replace
the odd elements of the alpha vector itself during the narrowing.

Also rename some existing macros to make more sense when distinguishing
between ARGB and RGBA.

Reductions in runtime observed compared to the existing Neon code:

Cortex-A510: -27.0%
Cortex-A720:  -5.3%
  Cortex-X2: -14.7%

Bug: libyuv:973
Change-Id: I1e12ff608ee49c25b918097007e16d87b39cb067
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/5593797
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
2024-06-04 18:18:07 +00:00

8776 lines
272 KiB
C++

/*
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "libyuv/convert_argb.h"
#include <assert.h>
#include "libyuv/convert_from_argb.h"
#include "libyuv/cpu_id.h"
#include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle.
#include "libyuv/rotate_argb.h"
#include "libyuv/row.h"
#include "libyuv/scale_row.h" // For ScaleRowUp2_Linear and ScaleRowUp2_Bilinear
#include "libyuv/video_common.h"
#ifdef __cplusplus
namespace libyuv {
extern "C" {
#endif
// Copy ARGB with optional flipping
LIBYUV_API
int ARGBCopy(const uint8_t* src_argb,
int src_stride_argb,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
if (!src_argb || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4,
height);
return 0;
}
// Convert I420 to ARGB with matrix.
LIBYUV_API
int I420ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I422TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
(kCpuHasAVX512BW | kCpuHasAVX512VL)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_AVX512BW;
}
}
#endif
#if defined(HAS_I422TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToARGBRow = I422ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I422TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422ToARGBRow = I422ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I422TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToARGBRow = I422ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToARGBRow = I422ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToARGBRow = I422ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToARGBRow = I422ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to ARGB.
LIBYUV_API
int I420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert I420 to ABGR.
LIBYUV_API
int I420ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert J420 to ARGB.
LIBYUV_API
int J420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvJPEGConstants, width, height);
}
// Convert J420 to ABGR.
LIBYUV_API
int J420ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuJPEGConstants, // Use Yvu matrix
width, height);
}
// Convert H420 to ARGB.
LIBYUV_API
int H420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvH709Constants, width, height);
}
// Convert H420 to ABGR.
LIBYUV_API
int H420ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert U420 to ARGB.
LIBYUV_API
int U420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert U420 to ABGR.
LIBYUV_API
int U420ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I420ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvu2020Constants, // Use Yvu matrix
width, height);
}
// Convert I422 to ARGB with matrix.
LIBYUV_API
int I422ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
// Coalesce rows.
if (src_stride_y == width && src_stride_u * 2 == width &&
src_stride_v * 2 == width && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
}
#if defined(HAS_I422TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
(kCpuHasAVX512BW | kCpuHasAVX512VL)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_AVX512BW;
}
}
#endif
#if defined(HAS_I422TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToARGBRow = I422ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I422TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422ToARGBRow = I422ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I422TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToARGBRow = I422ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToARGBRow = I422ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToARGBRow = I422ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToARGBRow = I422ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I422 to ARGB.
LIBYUV_API
int I422ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert I422 to ABGR.
LIBYUV_API
int I422ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert J422 to ARGB.
LIBYUV_API
int J422ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvJPEGConstants, width, height);
}
// Convert J422 to ABGR.
LIBYUV_API
int J422ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuJPEGConstants, // Use Yvu matrix
width, height);
}
// Convert H422 to ARGB.
LIBYUV_API
int H422ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvH709Constants, width, height);
}
// Convert H422 to ABGR.
LIBYUV_API
int H422ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert U422 to ARGB.
LIBYUV_API
int U422ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert U422 to ABGR.
LIBYUV_API
int U422ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I422ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvu2020Constants, // Use Yvu matrix
width, height);
}
// Convert I444 to ARGB with matrix.
LIBYUV_API
int I444ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
// Coalesce rows.
if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
}
#if defined(HAS_I444TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToARGBRow = I444ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444ToARGBRow = I444ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToARGBRow = I444ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444ToARGBRow = I444ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444ToARGBRow = I444ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I444ToARGBRow = I444ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I444ToARGBRow = I444ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I444TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToARGBRow = I444ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I444 to ARGB.
LIBYUV_API
int I444ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert I444 to ABGR.
LIBYUV_API
int I444ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert J444 to ARGB.
LIBYUV_API
int J444ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvJPEGConstants, width, height);
}
// Convert J444 to ABGR.
LIBYUV_API
int J444ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuJPEGConstants, // Use Yvu matrix
width, height);
}
// Convert H444 to ARGB.
LIBYUV_API
int H444ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvH709Constants, width, height);
}
// Convert H444 to ABGR.
LIBYUV_API
int H444ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert U444 to ARGB.
LIBYUV_API
int U444ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert U444 to ABGR.
LIBYUV_API
int U444ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I444ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvu2020Constants, // Use Yvu matrix
width, height);
}
// Convert I444 to RGB24 with matrix.
LIBYUV_API
int I444ToRGB24Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToRGB24Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
// Coalesce rows.
if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
dst_stride_rgb24 == width * 3) {
width *= height;
height = 1;
src_stride_y = src_stride_u = src_stride_v = dst_stride_rgb24 = 0;
}
#if defined(HAS_I444TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
I444ToRGB24Row = I444ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
I444ToRGB24Row = I444ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToRGB24Row = I444ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444ToRGB24Row = I444ToRGB24Row_MSA;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I444ToRGB24Row = I444ToRGB24Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I444ToRGB24Row = I444ToRGB24Row_LSX;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToRGB24Row = I444ToRGB24Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I444ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I444 to RGB24.
LIBYUV_API
int I444ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return I444ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
&kYuvI601Constants, width, height);
}
// Convert I444 to RAW.
LIBYUV_API
int I444ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return I444ToRGB24Matrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_raw, dst_stride_raw,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert 10 bit YUV to ARGB with matrix.
// TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
// multiply 10 bit yuv into high bits to allow any number of bits.
LIBYUV_API
int I010ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I210ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I210TOAR30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210ToAR30Row = I210ToAR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210ToAR30Row = I210ToAR30Row_NEON;
}
}
#endif
#if defined(HAS_I210TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210ToAR30Row = I210ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I210TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210ToAR30Row = I210ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210ToAR30Row = I210ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I010 to AR30.
LIBYUV_API
int I010ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuvI601Constants, width, height);
}
// Convert H010 to AR30.
LIBYUV_API
int H010ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuvH709Constants, width, height);
}
// Convert U010 to AR30.
LIBYUV_API
int U010ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuv2020Constants, width, height);
}
// Convert I010 to AB30.
LIBYUV_API
int I010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuI601Constants, width, height);
}
// Convert H010 to AB30.
LIBYUV_API
int H010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuH709Constants, width, height);
}
// Convert U010 to AB30.
LIBYUV_API
int U010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYuv2020Constants, width, height);
}
// Convert 12 bit YUV to ARGB with matrix.
// TODO(fbarchard): Consider passing scale multiplier to I212ToARGB to
// multiply 12 bit yuv into high bits to allow any number of bits.
LIBYUV_API
int I012ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I212ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I212ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I212TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I212ToAR30Row = I212ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I212ToAR30Row = I212ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I212TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I212ToAR30Row = I212ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I212ToAR30Row = I212ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I212ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert 10 bit YUV to ARGB with matrix.
// TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
// multiply 10 bit yuv into high bits to allow any number of bits.
LIBYUV_API
int I210ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I210ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I210TOAR30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210ToAR30Row = I210ToAR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210ToAR30Row = I210ToAR30Row_NEON;
}
}
#endif
#if defined(HAS_I210TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210ToAR30Row = I210ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I210TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210ToAR30Row = I210ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210ToAR30Row = I210ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I210 to AR30.
LIBYUV_API
int I210ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuvI601Constants, width, height);
}
// Convert H210 to AR30.
LIBYUV_API
int H210ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuvH709Constants, width, height);
}
// Convert U210 to AR30.
LIBYUV_API
int U210ToAR30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuv2020Constants, width, height);
}
// Convert I210 to AB30.
LIBYUV_API
int I210ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuI601Constants, width, height);
}
// Convert H210 to AB30.
LIBYUV_API
int H210ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuH709Constants, width, height);
}
// Convert U210 to AB30.
LIBYUV_API
int U210ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYuv2020Constants, width, height);
}
LIBYUV_API
int I410ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I410TOAR30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToAR30Row = I410ToAR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_NEON;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToAR30Row = I410ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToAR30Row = I410ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I410ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert 10 bit YUV to ARGB with matrix.
LIBYUV_API
int I010ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I210ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I210TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210ToARGBRow = I210ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I210TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210ToARGBRow = I210ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210ToARGBRow = I210ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I210TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210ToARGBRow = I210ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210ToARGBRow = I210ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I010 to ARGB.
LIBYUV_API
int I010ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert I010 to ABGR.
LIBYUV_API
int I010ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert H010 to ARGB.
LIBYUV_API
int H010ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvH709Constants, width, height);
}
// Convert H010 to ABGR.
LIBYUV_API
int H010ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert U010 to ARGB.
LIBYUV_API
int U010ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert U010 to ABGR.
LIBYUV_API
int U010ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I010ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvu2020Constants, // Use Yvu matrix
width, height);
}
// Convert 12 bit YUV to ARGB with matrix.
LIBYUV_API
int I012ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I212ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I212ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I212TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I212ToARGBRow = I212ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I212ToARGBRow = I212ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I212TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I212ToARGBRow = I212ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I212ToARGBRow = I212ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I212ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert 10 bit 422 YUV to ARGB with matrix.
LIBYUV_API
int I210ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I210ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I210TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210ToARGBRow = I210ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I210TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210ToARGBRow = I210ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210ToARGBRow = I210ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I210TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210ToARGBRow = I210ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210ToARGBRow = I210ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I210 to ARGB.
LIBYUV_API
int I210ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert I210 to ABGR.
LIBYUV_API
int I210ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert H210 to ARGB.
LIBYUV_API
int H210ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuvH709Constants, width, height);
}
// Convert H210 to ABGR.
LIBYUV_API
int H210ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert U210 to ARGB.
LIBYUV_API
int U210ToARGB(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
&kYuv2020Constants, width, height);
}
// Convert U210 to ABGR.
LIBYUV_API
int U210ToABGR(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return I210ToARGBMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_abgr, dst_stride_abgr,
&kYvu2020Constants, // Use Yvu matrix
width, height);
}
LIBYUV_API
int I410ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToARGBRow = I410ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToARGBRow = I410ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToARGBRow = I410ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I410ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
LIBYUV_API
int P010ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P210ToARGBRow)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_P210TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P210ToARGBRow = P210ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_P210TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P210ToARGBRow = P210ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P210ToARGBRow = P210ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_uv += src_stride_uv;
}
}
return 0;
}
LIBYUV_API
int P210ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P210ToARGBRow)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_P210TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P210ToARGBRow = P210ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_P210TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P210ToARGBRow = P210ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P210ToARGBRow = P210ToARGBRow_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
return 0;
}
LIBYUV_API
int P010ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P210ToAR30Row)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_P210TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P210ToAR30Row = P210ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_P210TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P210ToAR30Row = P210ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P210ToAR30Row = P210ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
if (y & 1) {
src_uv += src_stride_uv;
}
}
return 0;
}
LIBYUV_API
int P210ToAR30Matrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P210ToAR30Row)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_P210TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P210ToAR30Row = P210ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_P210TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P210ToAR30Row = P210ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P210ToAR30Row = P210ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
return 0;
}
// Convert I420 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I420AlphaToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, const uint8_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I422AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I422ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_SVE2;
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I422 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I422AlphaToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, const uint8_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I422AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I422ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_SVE2;
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I422ALPHATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I444 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I444AlphaToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, const uint8_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I444AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I444AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I420 with Alpha to ARGB.
LIBYUV_API
int I420AlphaToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height,
int attenuate) {
return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, src_a, src_stride_a, dst_argb,
dst_stride_argb, &kYuvI601Constants, width,
height, attenuate);
}
// Convert I420 with Alpha to ABGR.
LIBYUV_API
int I420AlphaToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height,
int attenuate) {
return I420AlphaToARGBMatrix(
src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height, attenuate);
}
// Convert I422 with Alpha to ARGB.
LIBYUV_API
int I422AlphaToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height,
int attenuate) {
return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, src_a, src_stride_a, dst_argb,
dst_stride_argb, &kYuvI601Constants, width,
height, attenuate);
}
// Convert I422 with Alpha to ABGR.
LIBYUV_API
int I422AlphaToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height,
int attenuate) {
return I422AlphaToARGBMatrix(
src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height, attenuate);
}
// Convert I444 with Alpha to ARGB.
LIBYUV_API
int I444AlphaToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height,
int attenuate) {
return I444AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, src_a, src_stride_a, dst_argb,
dst_stride_argb, &kYuvI601Constants, width,
height, attenuate);
}
// Convert I444 with Alpha to ABGR.
LIBYUV_API
int I444AlphaToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height,
int attenuate) {
return I444AlphaToARGBMatrix(
src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
&kYvuI601Constants, // Use Yvu matrix
width, height, attenuate);
}
// Convert I010 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I010AlphaToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, const uint16_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I210AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I210ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I210ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I210ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I210 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I210AlphaToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, const uint16_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I210AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I210ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I210ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I210ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I410 with Alpha to preattenuated ARGB with matrix.
LIBYUV_API
int I410AlphaToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, const uint16_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I410AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I410AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I400 to ARGB with matrix.
LIBYUV_API
int I400ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I400ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
// Coalesce rows.
if (src_stride_y == width && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_y = dst_stride_argb = 0;
}
#if defined(HAS_I400TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
I400ToARGBRow = I400ToARGBRow_Any_SSE2;
if (IS_ALIGNED(width, 8)) {
I400ToARGBRow = I400ToARGBRow_SSE2;
}
}
#endif
#if defined(HAS_I400TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I400ToARGBRow = I400ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I400ToARGBRow = I400ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I400TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I400ToARGBRow = I400ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I400ToARGBRow = I400ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I400TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I400ToARGBRow = I400ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
I400ToARGBRow = I400ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I400TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I400ToARGBRow = I400ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I400ToARGBRow = I400ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I400TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I400ToARGBRow = I400ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
}
return 0;
}
// Convert I400 to ARGB.
LIBYUV_API
int I400ToARGB(const uint8_t* src_y,
int src_stride_y,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert J400 to ARGB.
LIBYUV_API
int J400ToARGB(const uint8_t* src_y,
int src_stride_y,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
J400ToARGBRow_C;
if (!src_y || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_y = src_y + (height - 1) * src_stride_y;
src_stride_y = -src_stride_y;
}
// Coalesce rows.
if (src_stride_y == width && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_y = dst_stride_argb = 0;
}
#if defined(HAS_J400TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
J400ToARGBRow = J400ToARGBRow_Any_SSE2;
if (IS_ALIGNED(width, 8)) {
J400ToARGBRow = J400ToARGBRow_SSE2;
}
}
#endif
#if defined(HAS_J400TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
J400ToARGBRow = J400ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
J400ToARGBRow = J400ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_J400TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
J400ToARGBRow = J400ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
J400ToARGBRow = J400ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_J400TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
J400ToARGBRow = J400ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
J400ToARGBRow = J400ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_J400TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
J400ToARGBRow = J400ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
J400ToARGBRow = J400ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_J400TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
J400ToARGBRow = J400ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
J400ToARGBRow(src_y, dst_argb, width);
src_y += src_stride_y;
dst_argb += dst_stride_argb;
}
return 0;
}
#ifndef __riscv
// Shuffle table for converting BGRA to ARGB.
static const uvec8 kShuffleMaskBGRAToARGB = {
3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
// Shuffle table for converting ABGR to ARGB.
static const uvec8 kShuffleMaskABGRToARGB = {
2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
// Shuffle table for converting RGBA to ARGB.
static const uvec8 kShuffleMaskRGBAToARGB = {
1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
// Shuffle table for converting AR64 to AB64.
static const uvec8 kShuffleMaskAR64ToAB64 = {
4u, 5u, 2u, 3u, 0u, 1u, 6u, 7u, 12u, 13u, 10u, 11u, 8u, 9u, 14u, 15u};
// Convert BGRA to ARGB.
LIBYUV_API
int BGRAToARGB(const uint8_t* src_bgra,
int src_stride_bgra,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
(const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
}
// Convert ARGB to BGRA (same as BGRAToARGB).
LIBYUV_API
int ARGBToBGRA(const uint8_t* src_bgra,
int src_stride_bgra,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
(const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
}
// Convert ABGR to ARGB.
LIBYUV_API
int ABGRToARGB(const uint8_t* src_abgr,
int src_stride_abgr,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
(const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
}
// Convert ARGB to ABGR to (same as ABGRToARGB).
LIBYUV_API
int ARGBToABGR(const uint8_t* src_abgr,
int src_stride_abgr,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
(const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
}
// Convert RGBA to ARGB.
LIBYUV_API
int RGBAToARGB(const uint8_t* src_rgba,
int src_stride_rgba,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
(const uint8_t*)&kShuffleMaskRGBAToARGB, width, height);
}
// Convert AR64 To AB64.
LIBYUV_API
int AR64ToAB64(const uint16_t* src_ar64,
int src_stride_ar64,
uint16_t* dst_ab64,
int dst_stride_ab64,
int width,
int height) {
return AR64Shuffle(src_ar64, src_stride_ar64, dst_ab64, dst_stride_ab64,
(const uint8_t*)&kShuffleMaskAR64ToAB64, width, height);
}
#else
// Convert BGRA to ARGB (same as ARGBToBGRA).
LIBYUV_API
int BGRAToARGB(const uint8_t* src_bgra,
int src_stride_bgra,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBToBGRA(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb, width,
height);
}
// Convert ARGB to BGRA.
LIBYUV_API
int ARGBToBGRA(const uint8_t* src_argb,
int src_stride_argb,
uint8_t* dst_bgra,
int dst_stride_bgra,
int width,
int height) {
int y;
void (*ARGBToBGRARow)(const uint8_t* src_argb, uint8_t* dst_bgra, int width) =
ARGBToBGRARow_C;
if (!src_argb || !dst_bgra || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
// Coalesce rows.
if (src_stride_argb == width * 4 && dst_stride_bgra == width * 4) {
width *= height;
height = 1;
src_stride_argb = dst_stride_bgra = 0;
}
#if defined(HAS_ARGBTOBGRAROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToBGRARow = ARGBToBGRARow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
ARGBToBGRARow(src_argb, dst_bgra, width);
src_argb += src_stride_argb;
dst_bgra += dst_stride_bgra;
}
return 0;
}
// Convert ARGB to ABGR.
LIBYUV_API
int ARGBToABGR(const uint8_t* src_argb,
int src_stride_argb,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
int y;
void (*ARGBToABGRRow)(const uint8_t* src_argb, uint8_t* dst_abgr, int width) =
ARGBToABGRRow_C;
if (!src_argb || !dst_abgr || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
// Coalesce rows.
if (src_stride_argb == width * 4 && dst_stride_abgr == width * 4) {
width *= height;
height = 1;
src_stride_argb = dst_stride_abgr = 0;
}
#if defined(HAS_ARGBTOABGRROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBToABGRRow = ARGBToABGRRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
ARGBToABGRRow(src_argb, dst_abgr, width);
src_argb += src_stride_argb;
dst_abgr += dst_stride_abgr;
}
return 0;
}
// Convert ABGR to ARGB (same as ARGBToABGR).
LIBYUV_API
int ABGRToARGB(const uint8_t* src_abgr,
int src_stride_abgr,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return ARGBToABGR(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb, width,
height);
}
// Convert RGBA to ARGB.
LIBYUV_API
int RGBAToARGB(const uint8_t* src_rgba,
int src_stride_rgba,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*RGBAToARGBRow)(const uint8_t* src_rgba, uint8_t* dst_argb, int width) =
RGBAToARGBRow_C;
if (!src_rgba || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_rgba = src_rgba + (height - 1) * src_stride_rgba;
src_stride_rgba = -src_stride_rgba;
}
// Coalesce rows.
if (src_stride_rgba == width * 4 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_rgba = dst_stride_argb = 0;
}
#if defined(HAS_RGBATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGBAToARGBRow = RGBAToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
RGBAToARGBRow(src_rgba, dst_argb, width);
src_rgba += src_stride_rgba;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert AR64 To AB64.
LIBYUV_API
int AR64ToAB64(const uint16_t* src_ar64,
int src_stride_ar64,
uint16_t* dst_ab64,
int dst_stride_ab64,
int width,
int height) {
int y;
void (*AR64ToAB64Row)(const uint16_t* src_ar64, uint16_t* dst_ab64,
int width) = AR64ToAB64Row_C;
if (!src_ar64 || !dst_ab64 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
src_stride_ar64 = -src_stride_ar64;
}
// Coalesce rows.
if (src_stride_ar64 == width * 4 && dst_stride_ab64 == width * 4) {
width *= height;
height = 1;
src_stride_ar64 = dst_stride_ab64 = 0;
}
#if defined(HAS_AR64TOAB64ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
AR64ToAB64Row = AR64ToAB64Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
AR64ToAB64Row(src_ar64, dst_ab64, width);
src_ar64 += src_stride_ar64;
dst_ab64 += dst_stride_ab64;
}
return 0;
}
#endif
// Convert RGB24 to ARGB.
LIBYUV_API
int RGB24ToARGB(const uint8_t* src_rgb24,
int src_stride_rgb24,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
RGB24ToARGBRow_C;
if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
src_stride_rgb24 = -src_stride_rgb24;
}
// Coalesce rows.
if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_rgb24 = dst_stride_argb = 0;
}
#if defined(HAS_RGB24TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_RGB24TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
RGB24ToARGBRow = RGB24ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_RGB24TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
RGB24ToARGBRow = RGB24ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_RGB24TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
RGB24ToARGBRow = RGB24ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
RGB24ToARGBRow = RGB24ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_RGB24TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
RGB24ToARGBRow = RGB24ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
RGB24ToARGBRow = RGB24ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_RGB24TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RGB24ToARGBRow = RGB24ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
RGB24ToARGBRow(src_rgb24, dst_argb, width);
src_rgb24 += src_stride_rgb24;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert RAW to ARGB.
LIBYUV_API
int RAWToARGB(const uint8_t* src_raw,
int src_stride_raw,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
RAWToARGBRow_C;
if (!src_raw || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_raw = src_raw + (height - 1) * src_stride_raw;
src_stride_raw = -src_stride_raw;
}
// Coalesce rows.
if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_raw = dst_stride_argb = 0;
}
#if defined(HAS_RAWTOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
RAWToARGBRow = RAWToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_RAWTOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RAWToARGBRow = RAWToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
RAWToARGBRow = RAWToARGBRow_NEON;
}
}
#endif
#if defined(HAS_RAWTOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
RAWToARGBRow = RAWToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
RAWToARGBRow = RAWToARGBRow_MSA;
}
}
#endif
#if defined(HAS_RAWTOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
RAWToARGBRow = RAWToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
RAWToARGBRow = RAWToARGBRow_LSX;
}
}
#endif
#if defined(HAS_RAWTOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
RAWToARGBRow = RAWToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
RAWToARGBRow = RAWToARGBRow_LASX;
}
}
#endif
#if defined(HAS_RAWTOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RAWToARGBRow = RAWToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
RAWToARGBRow(src_raw, dst_argb, width);
src_raw += src_stride_raw;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert RAW to RGBA.
LIBYUV_API
int RAWToRGBA(const uint8_t* src_raw,
int src_stride_raw,
uint8_t* dst_rgba,
int dst_stride_rgba,
int width,
int height) {
int y;
void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
RAWToRGBARow_C;
if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_raw = src_raw + (height - 1) * src_stride_raw;
src_stride_raw = -src_stride_raw;
}
// Coalesce rows.
if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
width *= height;
height = 1;
src_stride_raw = dst_stride_rgba = 0;
}
#if defined(HAS_RAWTORGBAROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
RAWToRGBARow = RAWToRGBARow_SSSE3;
}
}
#endif
#if defined(HAS_RAWTORGBAROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RAWToRGBARow = RAWToRGBARow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
RAWToRGBARow = RAWToRGBARow_NEON;
}
}
#endif
#if defined(HAS_RAWTORGBAROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
RAWToRGBARow = RAWToRGBARow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
RAWToRGBARow(src_raw, dst_rgba, width);
src_raw += src_stride_raw;
dst_rgba += dst_stride_rgba;
}
return 0;
}
// Convert RGB565 to ARGB.
LIBYUV_API
int RGB565ToARGB(const uint8_t* src_rgb565,
int src_stride_rgb565,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
int width) = RGB565ToARGBRow_C;
if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
src_stride_rgb565 = -src_stride_rgb565;
}
// Coalesce rows.
if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_rgb565 = dst_stride_argb = 0;
}
#if defined(HAS_RGB565TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
if (IS_ALIGNED(width, 8)) {
RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
}
}
#endif
#if defined(HAS_RGB565TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_RGB565TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
RGB565ToARGBRow = RGB565ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_RGB565TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
RGB565ToARGBRow = RGB565ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_RGB565TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
RGB565ToARGBRow = RGB565ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_RGB565TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
RGB565ToARGBRow = RGB565ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
RGB565ToARGBRow = RGB565ToARGBRow_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
RGB565ToARGBRow(src_rgb565, dst_argb, width);
src_rgb565 += src_stride_rgb565;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert ARGB1555 to ARGB.
LIBYUV_API
int ARGB1555ToARGB(const uint8_t* src_argb1555,
int src_stride_argb1555,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
int width) = ARGB1555ToARGBRow_C;
if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
src_stride_argb1555 = -src_stride_argb1555;
}
// Coalesce rows.
if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_argb1555 = dst_stride_argb = 0;
}
#if defined(HAS_ARGB1555TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
if (IS_ALIGNED(width, 8)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
}
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_SVE2;
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_ARGB1555TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
src_argb1555 += src_stride_argb1555;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert ARGB4444 to ARGB.
LIBYUV_API
int ARGB4444ToARGB(const uint8_t* src_argb4444,
int src_stride_argb4444,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
int width) = ARGB4444ToARGBRow_C;
if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
src_stride_argb4444 = -src_stride_argb4444;
}
// Coalesce rows.
if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_argb4444 = dst_stride_argb = 0;
}
#if defined(HAS_ARGB4444TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
if (IS_ALIGNED(width, 8)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
}
}
#endif
#if defined(HAS_ARGB4444TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGB4444TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_ARGB4444TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 16)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_ARGB4444TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_ARGB4444TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
src_argb4444 += src_stride_argb4444;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert AR30 to ARGB.
LIBYUV_API
int AR30ToARGB(const uint8_t* src_ar30,
int src_stride_ar30,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
src_stride_ar30 = -src_stride_ar30;
}
// Coalesce rows.
if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_ar30 = dst_stride_argb = 0;
}
for (y = 0; y < height; ++y) {
AR30ToARGBRow_C(src_ar30, dst_argb, width);
src_ar30 += src_stride_ar30;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert AR30 to ABGR.
LIBYUV_API
int AR30ToABGR(const uint8_t* src_ar30,
int src_stride_ar30,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
int y;
if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
src_stride_ar30 = -src_stride_ar30;
}
// Coalesce rows.
if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
width *= height;
height = 1;
src_stride_ar30 = dst_stride_abgr = 0;
}
for (y = 0; y < height; ++y) {
AR30ToABGRRow_C(src_ar30, dst_abgr, width);
src_ar30 += src_stride_ar30;
dst_abgr += dst_stride_abgr;
}
return 0;
}
// Convert AR30 to AB30.
LIBYUV_API
int AR30ToAB30(const uint8_t* src_ar30,
int src_stride_ar30,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
int y;
if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
src_stride_ar30 = -src_stride_ar30;
}
// Coalesce rows.
if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
width *= height;
height = 1;
src_stride_ar30 = dst_stride_ab30 = 0;
}
for (y = 0; y < height; ++y) {
AR30ToAB30Row_C(src_ar30, dst_ab30, width);
src_ar30 += src_stride_ar30;
dst_ab30 += dst_stride_ab30;
}
return 0;
}
// Convert AR64 to ARGB.
LIBYUV_API
int AR64ToARGB(const uint16_t* src_ar64,
int src_stride_ar64,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*AR64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
int width) = AR64ToARGBRow_C;
if (!src_ar64 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
src_stride_ar64 = -src_stride_ar64;
}
// Coalesce rows.
if (src_stride_ar64 == width * 4 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_ar64 = dst_stride_argb = 0;
}
#if defined(HAS_AR64TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
AR64ToARGBRow = AR64ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
AR64ToARGBRow = AR64ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_AR64TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
AR64ToARGBRow = AR64ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
AR64ToARGBRow = AR64ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_AR64TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AR64ToARGBRow = AR64ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AR64ToARGBRow = AR64ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_AR64TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
AR64ToARGBRow = AR64ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
AR64ToARGBRow(src_ar64, dst_argb, width);
src_ar64 += src_stride_ar64;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert AB64 to ARGB.
LIBYUV_API
int AB64ToARGB(const uint16_t* src_ab64,
int src_stride_ab64,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*AB64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
int width) = AB64ToARGBRow_C;
if (!src_ab64 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ab64 = src_ab64 + (height - 1) * src_stride_ab64;
src_stride_ab64 = -src_stride_ab64;
}
// Coalesce rows.
if (src_stride_ab64 == width * 4 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_ab64 = dst_stride_argb = 0;
}
#if defined(HAS_AB64TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
AB64ToARGBRow = AB64ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
AB64ToARGBRow = AB64ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_AB64TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
AB64ToARGBRow = AB64ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
AB64ToARGBRow = AB64ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_AB64TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
AB64ToARGBRow = AB64ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
AB64ToARGBRow = AB64ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_AB64TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
AB64ToARGBRow = AB64ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
AB64ToARGBRow(src_ab64, dst_argb, width);
src_ab64 += src_stride_ab64;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert NV12 to ARGB with matrix.
LIBYUV_API
int NV12ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*NV12ToARGBRow)(
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_NV12TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
NV12ToARGBRow = NV12ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
NV12ToARGBRow = NV12ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
NV12ToARGBRow = NV12ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
NV12ToARGBRow = NV12ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
NV12ToARGBRow = NV12ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
NV12ToARGBRow = NV12ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
NV12ToARGBRow = NV12ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
NV12ToARGBRow = NV12ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_NV12TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
NV12ToARGBRow = NV12ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_uv += src_stride_uv;
}
}
return 0;
}
// Convert NV21 to ARGB with matrix.
LIBYUV_API
int NV21ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*NV21ToARGBRow)(
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
assert(yuvconstants);
if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_NV21TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
NV21ToARGBRow = NV21ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
NV21ToARGBRow = NV21ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
NV21ToARGBRow = NV21ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
NV21ToARGBRow = NV21ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
NV21ToARGBRow = NV21ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
NV21ToARGBRow = NV21ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
NV21ToARGBRow = NV21ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
NV21ToARGBRow = NV21ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_NV21TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
NV21ToARGBRow = NV21ToARGBRow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
if (y & 1) {
src_vu += src_stride_vu;
}
}
return 0;
}
// Convert NV12 to ARGB.
LIBYUV_API
int NV12ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
dst_stride_argb, &kYuvI601Constants, width, height);
}
// Convert NV21 to ARGB.
LIBYUV_API
int NV21ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
dst_stride_argb, &kYuvI601Constants, width, height);
}
// Convert NV12 to ABGR.
// To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
// To swap the UV use NV12 instead of NV21.LIBYUV_API
LIBYUV_API
int NV12ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
dst_stride_abgr, &kYvuI601Constants, width, height);
}
// Convert NV21 to ABGR.
LIBYUV_API
int NV21ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
dst_stride_abgr, &kYvuI601Constants, width, height);
}
// TODO(fbarchard): Consider SSSE3 2 step conversion.
// Convert NV12 to RGB24 with matrix.
LIBYUV_API
int NV12ToRGB24Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*NV12ToRGB24Row)(
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_NV12TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
NV12ToRGB24Row = NV12ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_NV12TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_NV12TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_NV12TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
NV12ToRGB24Row = NV12ToRGB24Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
if (y & 1) {
src_uv += src_stride_uv;
}
}
return 0;
}
// Convert NV21 to RGB24 with matrix.
LIBYUV_API
int NV21ToRGB24Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*NV21ToRGB24Row)(
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
assert(yuvconstants);
if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_NV21TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
NV21ToRGB24Row = NV21ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_NV21TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_NV21TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_NV21TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
NV21ToRGB24Row = NV21ToRGB24Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
if (y & 1) {
src_vu += src_stride_vu;
}
}
return 0;
}
// Convert NV12 to RGB24.
LIBYUV_API
int NV12ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
width, height);
}
// Convert NV21 to RGB24.
LIBYUV_API
int NV21ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
width, height);
}
// Convert NV12 to RAW.
LIBYUV_API
int NV12ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
dst_stride_raw, &kYvuI601Constants, width, height);
}
// Convert NV21 to RAW.
LIBYUV_API
int NV21ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
dst_stride_raw, &kYvuI601Constants, width, height);
}
// Convert NV21 to YUV24
int NV21ToYUV24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_vu,
int src_stride_vu,
uint8_t* dst_yuv24,
int dst_stride_yuv24,
int width,
int height) {
int y;
void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
dst_stride_yuv24 = -dst_stride_yuv24;
}
#if defined(HAS_NV21TOYUV24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
if (IS_ALIGNED(width, 16)) {
NV21ToYUV24Row = NV21ToYUV24Row_NEON;
}
}
#endif
#if defined(HAS_NV21TOYUV24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV21ToYUV24Row = NV21ToYUV24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
NV21ToYUV24Row = NV21ToYUV24Row_SSSE3;
}
}
#endif
#if defined(HAS_NV21TOYUV24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
dst_yuv24 += dst_stride_yuv24;
src_y += src_stride_y;
if (y & 1) {
src_vu += src_stride_vu;
}
}
return 0;
}
// Convert YUY2 to ARGB with matrix.
LIBYUV_API
int YUY2ToARGBMatrix(const uint8_t* src_yuy2,
int src_stride_yuy2,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
const struct YuvConstants* yuvconstants, int width) =
YUY2ToARGBRow_C;
if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
src_stride_yuy2 = -src_stride_yuy2;
}
// Coalesce rows.
if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_yuy2 = dst_stride_argb = 0;
}
#if defined(HAS_YUY2TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_YUY2TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_YUY2TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
YUY2ToARGBRow = YUY2ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_YUY2TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
YUY2ToARGBRow = YUY2ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_YUY2TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
YUY2ToARGBRow = YUY2ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
YUY2ToARGBRow = YUY2ToARGBRow_LSX;
}
}
#endif
for (y = 0; y < height; ++y) {
YUY2ToARGBRow(src_yuy2, dst_argb, yuvconstants, width);
src_yuy2 += src_stride_yuy2;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert YUY2 to ARGB.
LIBYUV_API
int YUY2ToARGB(const uint8_t* src_yuy2,
int src_stride_yuy2,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return YUY2ToARGBMatrix(src_yuy2, src_stride_yuy2, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
// Convert UYVY to ARGB with matrix.
LIBYUV_API
int UYVYToARGBMatrix(const uint8_t* src_uyvy,
int src_stride_uyvy,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
const struct YuvConstants* yuvconstants, int width) =
UYVYToARGBRow_C;
if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
src_stride_uyvy = -src_stride_uyvy;
}
// Coalesce rows.
if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_uyvy = dst_stride_argb = 0;
}
#if defined(HAS_UYVYTOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
UYVYToARGBRow = UYVYToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_UYVYTOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
UYVYToARGBRow = UYVYToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_UYVYTOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
UYVYToARGBRow = UYVYToARGBRow_NEON;
}
}
#endif
#if defined(HAS_UYVYTOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
UYVYToARGBRow = UYVYToARGBRow_MSA;
}
}
#endif
#if defined(HAS_UYVYTOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
UYVYToARGBRow = UYVYToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
UYVYToARGBRow = UYVYToARGBRow_LSX;
}
}
#endif
for (y = 0; y < height; ++y) {
UYVYToARGBRow(src_uyvy, dst_argb, yuvconstants, width);
src_uyvy += src_stride_uyvy;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert UYVY to ARGB.
LIBYUV_API
int UYVYToARGB(const uint8_t* src_uyvy,
int src_stride_uyvy,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return UYVYToARGBMatrix(src_uyvy, src_stride_uyvy, dst_argb, dst_stride_argb,
&kYuvI601Constants, width, height);
}
static void WeavePixels(const uint8_t* src_u,
const uint8_t* src_v,
int src_pixel_stride_uv,
uint8_t* dst_uv,
int width) {
int i;
for (i = 0; i < width; ++i) {
dst_uv[0] = *src_u;
dst_uv[1] = *src_v;
dst_uv += 2;
src_u += src_pixel_stride_uv;
src_v += src_pixel_stride_uv;
}
}
// Convert Android420 to ARGB with matrix.
LIBYUV_API
int Android420ToARGBMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
int src_pixel_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
uint8_t* dst_uv;
const ptrdiff_t vu_off = src_v - src_u;
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
halfheight = (height + 1) >> 1;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
// I420
if (src_pixel_stride_uv == 1) {
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
yuvconstants, width, height);
// NV21
}
if (src_pixel_stride_uv == 2 && vu_off == -1 &&
src_stride_u == src_stride_v) {
return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
dst_stride_argb, yuvconstants, width, height);
// NV12
}
if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
dst_stride_argb, yuvconstants, width, height);
}
// General case fallback creates NV12
align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
if (!plane_uv)
return 1;
dst_uv = plane_uv;
for (y = 0; y < halfheight; ++y) {
WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
src_u += src_stride_u;
src_v += src_stride_v;
dst_uv += halfwidth * 2;
}
NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
dst_stride_argb, yuvconstants, width, height);
free_aligned_buffer_64(plane_uv);
return 0;
}
// Convert Android420 to ARGB.
LIBYUV_API
int Android420ToARGB(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
int src_pixel_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
int width,
int height) {
return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, src_pixel_stride_uv, dst_argb,
dst_stride_argb, &kYuvI601Constants, width,
height);
}
// Convert Android420 to ABGR.
LIBYUV_API
int Android420ToABGR(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
int src_pixel_stride_uv,
uint8_t* dst_abgr,
int dst_stride_abgr,
int width,
int height) {
return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, src_pixel_stride_uv, dst_abgr,
dst_stride_abgr, &kYvuI601Constants, width,
height);
}
// Convert I422 to RGBA with matrix.
LIBYUV_API
int I422ToRGBAMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgba,
int dst_stride_rgba,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGBARow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
dst_stride_rgba = -dst_stride_rgba;
}
#if defined(HAS_I422TORGBAROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGBAROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGBARow = I422ToRGBARow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToRGBARow = I422ToRGBARow_AVX2;
}
}
#endif
#if defined(HAS_I422TORGBAROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGBARow = I422ToRGBARow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_NEON;
}
}
#endif
#if defined(HAS_I422TORGBAROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422ToRGBARow = I422ToRGBARow_SVE2;
}
#endif
#if defined(HAS_I422TORGBAROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGBARow = I422ToRGBARow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_MSA;
}
}
#endif
#if defined(HAS_I422TORGBAROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGBARow = I422ToRGBARow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGBARow = I422ToRGBARow_LSX;
}
}
#endif
#if defined(HAS_I422TORGBAROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGBARow = I422ToRGBARow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGBARow = I422ToRGBARow_LASX;
}
}
#endif
#if defined(HAS_I422TORGBAROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToRGBARow = I422ToRGBARow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
dst_rgba += dst_stride_rgba;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I422 to RGBA.
LIBYUV_API
int I422ToRGBA(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgba,
int dst_stride_rgba,
int width,
int height) {
return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgba, dst_stride_rgba,
&kYuvI601Constants, width, height);
}
// Convert I422 to BGRA.
LIBYUV_API
int I422ToBGRA(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_bgra,
int dst_stride_bgra,
int width,
int height) {
return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_bgra, dst_stride_bgra,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert NV12 to RGB565 with matrix.
LIBYUV_API
int NV12ToRGB565Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*NV12ToRGB565Row)(
const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
dst_stride_rgb565 = -dst_stride_rgb565;
}
#if defined(HAS_NV12TORGB565ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
}
}
#endif
#if defined(HAS_NV12TORGB565ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
}
}
#endif
#if defined(HAS_NV12TORGB565ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
NV12ToRGB565Row = NV12ToRGB565Row_NEON;
}
}
#endif
#if defined(HAS_NV12TORGB565ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
NV12ToRGB565Row = NV12ToRGB565Row_MSA;
}
}
#endif
#if defined(HAS_NV12TORGB565ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_LSX;
if (IS_ALIGNED(width, 8)) {
NV12ToRGB565Row = NV12ToRGB565Row_LSX;
}
}
#endif
#if defined(HAS_NV12TORGB565ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
NV12ToRGB565Row = NV12ToRGB565Row_Any_LASX;
if (IS_ALIGNED(width, 16)) {
NV12ToRGB565Row = NV12ToRGB565Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
dst_rgb565 += dst_stride_rgb565;
src_y += src_stride_y;
if (y & 1) {
src_uv += src_stride_uv;
}
}
return 0;
}
// Convert NV12 to RGB565.
LIBYUV_API
int NV12ToRGB565(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
int width,
int height) {
return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
width, height);
}
// Convert I422 to RGBA with matrix.
LIBYUV_API
int I420ToRGBAMatrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgba,
int dst_stride_rgba,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGBARow_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
dst_stride_rgba = -dst_stride_rgba;
}
#if defined(HAS_I422TORGBAROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGBAROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGBARow = I422ToRGBARow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToRGBARow = I422ToRGBARow_AVX2;
}
}
#endif
#if defined(HAS_I422TORGBAROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGBARow = I422ToRGBARow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_NEON;
}
}
#endif
#if defined(HAS_I422TORGBAROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422ToRGBARow = I422ToRGBARow_SVE2;
}
#endif
#if defined(HAS_I422TORGBAROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGBARow = I422ToRGBARow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToRGBARow = I422ToRGBARow_MSA;
}
}
#endif
#if defined(HAS_I422TORGBAROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGBARow = I422ToRGBARow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGBARow = I422ToRGBARow_LSX;
}
}
#endif
#if defined(HAS_I422TORGBAROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGBARow = I422ToRGBARow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGBARow = I422ToRGBARow_LASX;
}
}
#endif
#if defined(HAS_I422TORGBAROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToRGBARow = I422ToRGBARow_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
dst_rgba += dst_stride_rgba;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to RGBA.
LIBYUV_API
int I420ToRGBA(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgba,
int dst_stride_rgba,
int width,
int height) {
return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgba, dst_stride_rgba,
&kYuvI601Constants, width, height);
}
// Convert I420 to BGRA.
LIBYUV_API
int I420ToBGRA(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_bgra,
int dst_stride_bgra,
int width,
int height) {
return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_bgra, dst_stride_bgra,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert I420 to RGB24 with matrix.
LIBYUV_API
int I420ToRGB24Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGB24Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_I422TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
I422ToRGB24Row = I422ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGB24Row = I422ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_MSA;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_LSX;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGB24Row = I422ToRGB24Row_LASX;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToRGB24Row = I422ToRGB24Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to RGB24.
LIBYUV_API
int I420ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
&kYuvI601Constants, width, height);
}
// Convert I420 to RAW.
LIBYUV_API
int I420ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_raw, dst_stride_raw,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert J420 to RGB24.
LIBYUV_API
int J420ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
&kYuvJPEGConstants, width, height);
}
// Convert J420 to RAW.
LIBYUV_API
int J420ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_raw, dst_stride_raw,
&kYvuJPEGConstants, // Use Yvu matrix
width, height);
}
// Convert H420 to RGB24.
LIBYUV_API
int H420ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
&kYuvH709Constants, width, height);
}
// Convert H420 to RAW.
LIBYUV_API
int H420ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_raw, dst_stride_raw,
&kYvuH709Constants, // Use Yvu matrix
width, height);
}
// Convert I422 to RGB24 with matrix.
LIBYUV_API
int I422ToRGB24Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGB24Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_I422TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
I422ToRGB24Row = I422ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGB24Row = I422ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_MSA;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGB24Row = I422ToRGB24Row_LSX;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGB24Row = I422ToRGB24Row_LASX;
}
}
#endif
#if defined(HAS_I422TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToRGB24Row = I422ToRGB24Row_RVV;
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I422 to RGB24.
LIBYUV_API
int I422ToRGB24(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
&kYuvI601Constants, width, height);
}
// Convert I422 to RAW.
LIBYUV_API
int I422ToRAW(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_raw,
int dst_stride_raw,
int width,
int height) {
return I422ToRGB24Matrix(src_y, src_stride_y, src_v,
src_stride_v, // Swap U and V
src_u, src_stride_u, dst_raw, dst_stride_raw,
&kYvuI601Constants, // Use Yvu matrix
width, height);
}
// Convert I420 to ARGB1555.
LIBYUV_API
int I420ToARGB1555(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb1555,
int dst_stride_argb1555,
int width,
int height) {
int y;
void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants,
int width) = I422ToARGB1555Row_C;
if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
dst_stride_argb1555 = -dst_stride_argb1555;
}
#if defined(HAS_I422TOARGB1555ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TOARGB1555ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
}
}
#endif
#if defined(HAS_I422TOARGB1555ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToARGB1555Row = I422ToARGB1555Row_NEON;
}
}
#endif
#if defined(HAS_I422TOARGB1555ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToARGB1555Row = I422ToARGB1555Row_MSA;
}
}
#endif
#if defined(HAS_I422TOARGB1555ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToARGB1555Row = I422ToARGB1555Row_LSX;
}
}
#endif
#if defined(HAS_I422TOARGB1555ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToARGB1555Row = I422ToARGB1555Row_Any_LASX;
if (IS_ALIGNED(width, 8)) {
I422ToARGB1555Row = I422ToARGB1555Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
width);
dst_argb1555 += dst_stride_argb1555;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to ARGB4444.
LIBYUV_API
int I420ToARGB4444(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb4444,
int dst_stride_argb4444,
int width,
int height) {
int y;
void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants,
int width) = I422ToARGB4444Row_C;
if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
dst_stride_argb4444 = -dst_stride_argb4444;
}
#if defined(HAS_I422TOARGB4444ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TOARGB4444ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
}
}
#endif
#if defined(HAS_I422TOARGB4444ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToARGB4444Row = I422ToARGB4444Row_NEON;
}
}
#endif
#if defined(HAS_I422TOARGB4444ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToARGB4444Row = I422ToARGB4444Row_MSA;
}
}
#endif
#if defined(HAS_I422TOARGB4444ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToARGB4444Row = I422ToARGB4444Row_LSX;
}
}
#endif
#if defined(HAS_I422TOARGB4444ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToARGB4444Row = I422ToARGB4444Row_Any_LASX;
if (IS_ALIGNED(width, 8)) {
I422ToARGB4444Row = I422ToARGB4444Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
width);
dst_argb4444 += dst_stride_argb4444;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to RGB565 with specified color matrix.
LIBYUV_API
int I420ToRGB565Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGB565Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
dst_stride_rgb565 = -dst_stride_rgb565;
}
#if defined(HAS_I422TORGB565ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToRGB565Row = I422ToRGB565Row_AVX2;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_NEON;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_MSA;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGB565Row = I422ToRGB565Row_LSX;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGB565Row = I422ToRGB565Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
dst_rgb565 += dst_stride_rgb565;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to RGB565.
LIBYUV_API
int I420ToRGB565(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
int width,
int height) {
return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb565, dst_stride_rgb565,
&kYuvI601Constants, width, height);
}
// Convert J420 to RGB565.
LIBYUV_API
int J420ToRGB565(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
int width,
int height) {
return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb565, dst_stride_rgb565,
&kYuvJPEGConstants, width, height);
}
// Convert H420 to RGB565.
LIBYUV_API
int H420ToRGB565(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
int width,
int height) {
return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb565, dst_stride_rgb565,
&kYuvH709Constants, width, height);
}
// Convert I422 to RGB565 with specified color matrix.
LIBYUV_API
int I422ToRGB565Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToRGB565Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
dst_stride_rgb565 = -dst_stride_rgb565;
}
#if defined(HAS_I422TORGB565ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToRGB565Row = I422ToRGB565Row_AVX2;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_NEON;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToRGB565Row = I422ToRGB565Row_MSA;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToRGB565Row = I422ToRGB565Row_LSX;
}
}
#endif
#if defined(HAS_I422TORGB565ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToRGB565Row = I422ToRGB565Row_LASX;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
dst_rgb565 += dst_stride_rgb565;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
return 0;
}
// Convert I422 to RGB565.
LIBYUV_API
int I422ToRGB565(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
int width,
int height) {
return I422ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb565, dst_stride_rgb565,
&kYuvI601Constants, width, height);
}
// Ordered 8x8 dither for 888 to 565. Values from 0 to 7.
static const uint8_t kDither565_4x4[16] = {
0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
};
// Convert I420 to RGB565 with dithering.
LIBYUV_API
int I420ToRGB565Dither(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb565,
int dst_stride_rgb565,
const uint8_t* dither4x4,
int width,
int height) {
int y;
void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToARGBRow_C;
void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
uint32_t dither4, int width) =
ARGBToRGB565DitherRow_C;
if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
dst_stride_rgb565 = -dst_stride_rgb565;
}
if (!dither4x4) {
dither4x4 = kDither565_4x4;
}
#if defined(HAS_I422TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I422TOARGBROW_AVX512BW)
if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
(kCpuHasAVX512BW | kCpuHasAVX512VL)) {
I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_AVX512BW;
}
}
#endif
#if defined(HAS_I422TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I422ToARGBRow = I422ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I422TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I422ToARGBRow = I422ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I422TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I422ToARGBRow = I422ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I422ToARGBRow = I422ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
I422ToARGBRow = I422ToARGBRow_Any_LSX;
if (IS_ALIGNED(width, 16)) {
I422ToARGBRow = I422ToARGBRow_LSX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I422ToARGBRow = I422ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I422ToARGBRow = I422ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I422TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I422ToARGBRow = I422ToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
if (IS_ALIGNED(width, 4)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
}
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
}
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SVE2;
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
}
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_LSX)
if (TestCpuFlag(kCpuHasLSX)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
if (IS_ALIGNED(width, 8)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
}
}
#endif
#if defined(HAS_ARGBTORGB565DITHERROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
}
}
#endif
{
// Allocate a row of argb.
align_buffer_64(row_argb, width * 4);
if (!row_argb)
return 1;
for (y = 0; y < height; ++y) {
I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
ARGBToRGB565DitherRow(row_argb, dst_rgb565,
*(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
width);
dst_rgb565 += dst_stride_rgb565;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
free_aligned_buffer_64(row_argb);
}
return 0;
}
// Convert I420 to AR30 with matrix.
LIBYUV_API
int I420ToAR30Matrix(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I422ToAR30Row_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I422TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I422ToAR30Row = I422ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I422TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I422ToAR30Row = I422ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I422ToAR30Row = I422ToAR30Row_AVX2;
}
}
#endif
for (y = 0; y < height; ++y) {
I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
if (y & 1) {
src_u += src_stride_u;
src_v += src_stride_v;
}
}
return 0;
}
// Convert I420 to AR30.
LIBYUV_API
int I420ToAR30(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYuvI601Constants, width, height);
}
// Convert H420 to AR30.
LIBYUV_API
int H420ToAR30(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
int width,
int height) {
return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
&kYvuH709Constants, width, height);
}
// Convert I420 to AB30.
LIBYUV_API
int I420ToAB30(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuI601Constants, width, height);
}
// Convert H420 to AB30.
LIBYUV_API
int H420ToAB30(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuH709Constants, width, height);
}
static int I420ToARGBMatrixBilinear(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToARGBRow_C;
void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
uint8_t* dst_ptr, ptrdiff_t dst_stride,
int dst_width) = ScaleRowUp2_Bilinear_Any_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I444TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToARGBRow = I444ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444ToARGBRow = I444ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToARGBRow = I444ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444ToARGBRow = I444ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444ToARGBRow = I444ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I444ToARGBRow = I444ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I444ToARGBRow = I444ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I444TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToARGBRow = I444ToARGBRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4);
uint8_t* temp_u_1 = row;
uint8_t* temp_u_2 = row + row_size;
uint8_t* temp_v_1 = row + row_size * 2;
uint8_t* temp_v_2 = row + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
I444ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
if (!(height & 1)) {
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int I422ToARGBMatrixLinear(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToARGBRow_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I444TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToARGBRow = I444ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444ToARGBRow = I444ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToARGBRow = I444ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444TOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444ToARGBRow = I444ToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444TOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444ToARGBRow = I444ToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444ToARGBRow = I444ToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444TOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I444ToARGBRow = I444ToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I444ToARGBRow = I444ToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I444TOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToARGBRow = I444ToARGBRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2);
uint8_t* temp_u = row;
uint8_t* temp_v = row + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_u, temp_u, width);
ScaleRowUp2_Linear(src_v, temp_v, width);
I444ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
static int I420ToRGB24MatrixBilinear(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToRGB24Row_C;
void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
uint8_t* dst_ptr, ptrdiff_t dst_stride,
int dst_width) = ScaleRowUp2_Bilinear_Any_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_I444TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
I444ToRGB24Row = I444ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
I444ToRGB24Row = I444ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToRGB24Row = I444ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444ToRGB24Row = I444ToRGB24Row_MSA;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I444ToRGB24Row = I444ToRGB24Row_Any_LASX;
if (IS_ALIGNED(width, 32)) {
I444ToRGB24Row = I444ToRGB24Row_LASX;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToRGB24Row = I444ToRGB24Row_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4);
uint8_t* temp_u_1 = row;
uint8_t* temp_u_2 = row + row_size;
uint8_t* temp_v_1 = row + row_size * 2;
uint8_t* temp_v_2 = row + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
I444ToRGB24Row(src_y, temp_u_2, temp_v_2, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
if (!(height & 1)) {
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int I010ToAR30MatrixBilinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToAR30Row_C;
void (*Scale2RowUp_Bilinear_12)(
const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I410TOAR30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToAR30Row = I410ToAR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_NEON;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToAR30Row = I410ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToAR30Row = I410ToAR30Row_AVX2;
}
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
uint16_t* temp_u_1 = (uint16_t*)(row);
uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
I410ToAR30Row(src_y, temp_u_2, temp_v_2, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
if (!(height & 1)) {
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int I210ToAR30MatrixLinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToAR30Row_C;
void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_I410TOAR30ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToAR30Row = I410ToAR30Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_NEON;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToAR30Row = I410ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_I410TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToAR30Row = I410ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToAR30Row = I410ToAR30Row_AVX2;
}
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
uint16_t* temp_u = (uint16_t*)(row);
uint16_t* temp_v = (uint16_t*)(row) + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear_12(src_u, temp_u, width);
ScaleRowUp2_Linear_12(src_v, temp_v, width);
I410ToAR30Row(src_y, temp_u, temp_v, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
static int I010ToARGBMatrixBilinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToARGBRow_C;
void (*Scale2RowUp_Bilinear_12)(
const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToARGBRow = I410ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToARGBRow = I410ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToARGBRow = I410ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
uint16_t* temp_u_1 = (uint16_t*)(row);
uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
I410ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
if (!(height & 1)) {
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int I210ToARGBMatrixLinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I410ToARGBRow_C;
void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410TOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410ToARGBRow = I410ToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410ToARGBRow = I410ToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410ToARGBRow = I410ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410ToARGBRow = I410ToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
uint16_t* temp_u = (uint16_t*)(row);
uint16_t* temp_v = (uint16_t*)(row) + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear_12(src_u, temp_u, width);
ScaleRowUp2_Linear_12(src_v, temp_v, width);
I410ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
static int I420AlphaToARGBMatrixBilinear(
const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, const uint8_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I444AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
uint8_t* dst_ptr, ptrdiff_t dst_stride,
int dst_width) = ScaleRowUp2_Bilinear_Any_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4);
uint8_t* temp_u_1 = row;
uint8_t* temp_u_2 = row + row_size;
uint8_t* temp_v_1 = row + row_size * 2;
uint8_t* temp_v_2 = row + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_a += src_stride_a;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_a += src_stride_a;
I444AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
src_a += src_stride_a;
}
if (!(height & 1)) {
ScaleRowUp2_Linear(src_u, temp_u_1, width);
ScaleRowUp2_Linear(src_v, temp_v_1, width);
I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
}
free_aligned_buffer_64(row);
return 0;
}
static int I422AlphaToARGBMatrixLinear(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, const uint8_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I444AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I444ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_SVE2)
if (TestCpuFlag(kCpuHasSVE2)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_SVE2;
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_LASX)
if (TestCpuFlag(kCpuHasLASX)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
if (IS_ALIGNED(width, 16)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
}
}
#endif
#if defined(HAS_I444ALPHATOARGBROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2);
uint8_t* temp_u = row;
uint8_t* temp_v = row + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_u, temp_u, width);
ScaleRowUp2_Linear(src_v, temp_v, width);
I444AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
static int I010AlphaToARGBMatrixBilinear(
const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, const uint16_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I410AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
void (*Scale2RowUp_Bilinear_12)(
const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 4 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
uint16_t* temp_u_1 = (uint16_t*)(row);
uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
if (!row)
return 1;
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_a += src_stride_a;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_a += src_stride_a;
I410AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_a += src_stride_a;
src_u += src_stride_u;
src_v += src_stride_v;
}
if (!(height & 1)) {
ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
}
free_aligned_buffer_64(row);
return 0;
}
static int I210AlphaToARGBMatrixLinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate) {
int y;
void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
const uint16_t* v_buf, const uint16_t* a_buf,
uint8_t* dst_argb,
const struct YuvConstants* yuvconstants,
int width) = I410AlphaToARGBRow_C;
void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
int width) = ARGBAttenuateRow_C;
void (*ScaleRowUp2_Linear)(const uint16_t* src_ptr, uint16_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_I410ALPHATOARGBROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_NEON;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_I410ALPHATOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
if (IS_ALIGNED(width, 4)) {
ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_NEON;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_MSA)
if (TestCpuFlag(kCpuHasMSA)) {
ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
if (IS_ALIGNED(width, 8)) {
ARGBAttenuateRow = ARGBAttenuateRow_MSA;
}
}
#endif
#if defined(HAS_ARGBATTENUATEROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ARGBAttenuateRow = ARGBAttenuateRow_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_NEON;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
uint16_t* temp_u = (uint16_t*)(row);
uint16_t* temp_v = (uint16_t*)(row) + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_u, temp_u, width);
ScaleRowUp2_Linear(src_v, temp_v, width);
I410AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
width);
if (attenuate) {
ARGBAttenuateRow(dst_argb, dst_argb, width);
}
dst_argb += dst_stride_argb;
src_a += src_stride_a;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
static int P010ToARGBMatrixBilinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P410ToARGBRow)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
void (*Scale2RowUp_Bilinear_16)(
const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_P410TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P410ToARGBRow = P410ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_P410TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P410ToARGBRow = P410ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P410ToARGBRow = P410ToARGBRow_AVX2;
}
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
if (TestCpuFlag(kCpuHasSSE41)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
}
#endif
// alloc 2 lines temp
const int row_size = (2 * width + 31) & ~31;
align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
uint16_t* temp_uv_1 = (uint16_t*)(row);
uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
if (!row)
return 1;
Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
P410ToARGBRow(src_y, temp_uv_2, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
if (!(height & 1)) {
Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int P210ToARGBMatrixLinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P410ToARGBRow)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_argb = dst_argb + (height - 1) * dst_stride_argb;
dst_stride_argb = -dst_stride_argb;
}
#if defined(HAS_P410TOARGBROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P410ToARGBRow = P410ToARGBRow_SSSE3;
}
}
#endif
#if defined(HAS_P410TOARGBROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P410ToARGBRow = P410ToARGBRow_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P410ToARGBRow = P410ToARGBRow_AVX2;
}
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
if (TestCpuFlag(kCpuHasSSE41)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
}
#endif
const int row_size = (2 * width + 31) & ~31;
align_buffer_64(row, row_size * sizeof(uint16_t));
uint16_t* temp_uv = (uint16_t*)(row);
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_uv, temp_uv, width);
P410ToARGBRow(src_y, temp_uv, dst_argb, yuvconstants, width);
dst_argb += dst_stride_argb;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
free_aligned_buffer_64(row);
return 0;
}
static int P010ToAR30MatrixBilinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P410ToAR30Row)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
void (*Scale2RowUp_Bilinear_16)(
const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_P410TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P410ToAR30Row = P410ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_P410TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P410ToAR30Row = P410ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P410ToAR30Row = P410ToAR30Row_AVX2;
}
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
if (TestCpuFlag(kCpuHasSSE41)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
if (TestCpuFlag(kCpuHasAVX2)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
}
#endif
#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
if (TestCpuFlag(kCpuHasNEON)) {
Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
}
#endif
// alloc 2 lines temp
const int row_size = (2 * width + 31) & ~31;
align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
uint16_t* temp_uv_1 = (uint16_t*)(row);
uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
if (!row)
return 1;
Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
for (y = 0; y < height - 2; y += 2) {
Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
P410ToAR30Row(src_y, temp_uv_2, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
if (!(height & 1)) {
Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
}
free_aligned_buffer_64(row);
return 0;
}
static int P210ToAR30MatrixLinear(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*P410ToAR30Row)(
const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
assert(yuvconstants);
if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
dst_stride_ar30 = -dst_stride_ar30;
}
#if defined(HAS_P410TOAR30ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
if (IS_ALIGNED(width, 8)) {
P410ToAR30Row = P410ToAR30Row_SSSE3;
}
}
#endif
#if defined(HAS_P410TOAR30ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
P410ToAR30Row = P410ToAR30Row_Any_AVX2;
if (IS_ALIGNED(width, 16)) {
P410ToAR30Row = P410ToAR30Row_AVX2;
}
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
if (TestCpuFlag(kCpuHasSSE41)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
}
#endif
#ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
}
#endif
const int row_size = (2 * width + 31) & ~31;
align_buffer_64(row, row_size * sizeof(uint16_t));
uint16_t* temp_uv = (uint16_t*)(row);
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_uv, temp_uv, width);
P410ToAR30Row(src_y, temp_uv, dst_ar30, yuvconstants, width);
dst_ar30 += dst_stride_ar30;
src_y += src_stride_y;
src_uv += src_stride_uv;
}
free_aligned_buffer_64(row);
return 0;
}
static int I422ToRGB24MatrixLinear(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height) {
int y;
void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
const uint8_t* v_buf, uint8_t* rgb_buf,
const struct YuvConstants* yuvconstants, int width) =
I444ToRGB24Row_C;
void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
int dst_width) = ScaleRowUp2_Linear_Any_C;
assert(yuvconstants);
if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
dst_stride_rgb24 = -dst_stride_rgb24;
}
#if defined(HAS_I444TORGB24ROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
I444ToRGB24Row = I444ToRGB24Row_SSSE3;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
if (IS_ALIGNED(width, 32)) {
I444ToRGB24Row = I444ToRGB24Row_AVX2;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
if (IS_ALIGNED(width, 8)) {
I444ToRGB24Row = I444ToRGB24Row_NEON;
}
}
#endif
#if defined(HAS_I444TORGB24ROW_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
I444ToRGB24Row = I444ToRGB24Row_RVV;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
if (TestCpuFlag(kCpuHasSSE2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
if (TestCpuFlag(kCpuHasAVX2)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
}
#endif
#if defined(HAS_SCALEROWUP2_LINEAR_RVV)
if (TestCpuFlag(kCpuHasRVV)) {
ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
}
#endif
// alloc 2 lines temp
const int row_size = (width + 31) & ~31;
align_buffer_64(row, row_size * 2);
uint8_t* temp_u = row;
uint8_t* temp_v = row + row_size;
if (!row)
return 1;
for (y = 0; y < height; ++y) {
ScaleRowUp2_Linear(src_u, temp_u, width);
ScaleRowUp2_Linear(src_v, temp_v, width);
I444ToRGB24Row(src_y, temp_u, temp_v, dst_rgb24, yuvconstants, width);
dst_rgb24 += dst_stride_rgb24;
src_y += src_stride_y;
src_u += src_stride_u;
src_v += src_stride_v;
}
free_aligned_buffer_64(row);
return 0;
}
LIBYUV_API
int I422ToRGB24MatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
yuvconstants, width, height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I422ToRGB24MatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I420ToARGBMatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
yuvconstants, width, height);
case kFilterBilinear:
case kFilterBox:
return I420ToARGBMatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_argb, dst_stride_argb, yuvconstants, width, height);
case kFilterLinear:
// Actually we can do this, but probably there's no usage.
return -1;
}
return -1;
}
LIBYUV_API
int I422ToARGBMatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
yuvconstants, width, height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I422ToARGBMatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_argb, dst_stride_argb, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I420ToRGB24MatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_rgb24, dst_stride_rgb24,
yuvconstants, width, height);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return I420ToRGB24MatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I010ToAR30MatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
yuvconstants, width, height);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return I010ToAR30MatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_ar30, dst_stride_ar30, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I210ToAR30MatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_ar30, dst_stride_ar30,
yuvconstants, width, height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I210ToAR30MatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_ar30, dst_stride_ar30, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I010ToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
yuvconstants, width, height);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return I010ToARGBMatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_argb, dst_stride_argb, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I210ToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
src_stride_v, dst_argb, dst_stride_argb,
yuvconstants, width, height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I210ToARGBMatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
dst_argb, dst_stride_argb, yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int I420AlphaToARGBMatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
src_v, src_stride_v, src_a, src_stride_a,
dst_argb, dst_stride_argb, yuvconstants,
width, height, attenuate);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return I420AlphaToARGBMatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
attenuate);
}
return -1;
}
LIBYUV_API
int I422AlphaToARGBMatrixFilter(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,
int src_stride_u,
const uint8_t* src_v,
int src_stride_v,
const uint8_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
src_v, src_stride_v, src_a, src_stride_a,
dst_argb, dst_stride_argb, yuvconstants,
width, height, attenuate);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I422AlphaToARGBMatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
attenuate);
}
return -1;
}
LIBYUV_API
int I010AlphaToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I010AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
src_v, src_stride_v, src_a, src_stride_a,
dst_argb, dst_stride_argb, yuvconstants,
width, height, attenuate);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return I010AlphaToARGBMatrixBilinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
attenuate);
}
return -1;
}
LIBYUV_API
int I210AlphaToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
const uint16_t* src_a,
int src_stride_a,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
int attenuate,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return I210AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
src_v, src_stride_v, src_a, src_stride_a,
dst_argb, dst_stride_argb, yuvconstants,
width, height, attenuate);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return I210AlphaToARGBMatrixLinear(
src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
attenuate);
}
return -1;
}
// TODO(fb): Verify this function works correctly. P010 is like NV12 but 10 bit
// UV is biplanar.
LIBYUV_API
int P010ToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return P010ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_argb, dst_stride_argb, yuvconstants, width,
height);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return P010ToARGBMatrixBilinear(src_y, src_stride_y, src_uv,
src_stride_uv, dst_argb, dst_stride_argb,
yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int P210ToARGBMatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_argb,
int dst_stride_argb,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return P210ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_argb, dst_stride_argb, yuvconstants, width,
height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return P210ToARGBMatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
dst_argb, dst_stride_argb, yuvconstants,
width, height);
}
return -1;
}
LIBYUV_API
int P010ToAR30MatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return P010ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_ar30, dst_stride_ar30, yuvconstants, width,
height);
case kFilterLinear: // TODO(fb): Implement Linear using Bilinear stride 0
case kFilterBilinear:
case kFilterBox:
return P010ToAR30MatrixBilinear(src_y, src_stride_y, src_uv,
src_stride_uv, dst_ar30, dst_stride_ar30,
yuvconstants, width, height);
}
return -1;
}
LIBYUV_API
int P210ToAR30MatrixFilter(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_uv,
int src_stride_uv,
uint8_t* dst_ar30,
int dst_stride_ar30,
const struct YuvConstants* yuvconstants,
int width,
int height,
enum FilterMode filter) {
switch (filter) {
case kFilterNone:
return P210ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
dst_ar30, dst_stride_ar30, yuvconstants, width,
height);
case kFilterBilinear:
case kFilterBox:
case kFilterLinear:
return P210ToAR30MatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
dst_ar30, dst_stride_ar30, yuvconstants,
width, height);
}
return -1;
}
#ifdef __cplusplus
} // extern "C"
} // namespace libyuv
#endif