mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2026-10-28 18:07:12 +08:00
Convert8To16 takes bits instead of scale.
- NV16/24 FOURCC and document - Rotate take uint8* for ubsan Bug: 537818862 Change-Id: I2bc7109abaffe2464e031e33c22296c007077d82 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/8339427 Commit-Queue: Frank Barchard <fbarchard@google.com> Reviewed-by: richard winterton <rrwinterton@gmail.com>
This commit is contained in:
parent
addfba3a7c
commit
2fcc1272dd
@ -1,6 +1,6 @@
|
||||
Name: libyuv
|
||||
URL: https://chromium.googlesource.com/libyuv/libyuv/
|
||||
Version: 1967
|
||||
Version: 1968
|
||||
Revision: DEPS
|
||||
License: BSD-3-Clause
|
||||
License File: LICENSE
|
||||
|
||||
@ -38,13 +38,15 @@ This is how OSX formats map to libyuv
|
||||
|
||||
The following is extracted from video_common.h as a complete list of formats supported by libyuv.
|
||||
enum FourCC {
|
||||
// 10 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
|
||||
// 12 Primary YUV formats: 5 planar, 4 biplanar, 2 packed.
|
||||
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
|
||||
FOURCC_I422 = FOURCC('I', '4', '2', '2'),
|
||||
FOURCC_I444 = FOURCC('I', '4', '4', '4'),
|
||||
FOURCC_I400 = FOURCC('I', '4', '0', '0'),
|
||||
FOURCC_NV21 = FOURCC('N', 'V', '2', '1'),
|
||||
FOURCC_NV12 = FOURCC('N', 'V', '1', '2'),
|
||||
FOURCC_NV16 = FOURCC('N', 'V', '1', '6'),
|
||||
FOURCC_NV24 = FOURCC('N', 'V', '2', '4'),
|
||||
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
|
||||
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
|
||||
FOURCC_H010 = FOURCC('H', '0', '1', '0'), // unofficial fourcc. 10 bit lsb
|
||||
|
||||
@ -51,12 +51,14 @@ void Convert16To8Plane(const uint16_t* src_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
// Convert 8 bit Y to 10/12/16 bit.
|
||||
// "bits" accepts bit depths (10, 12, 16) or legacy scale values (1024, 4096, 65536).
|
||||
LIBYUV_API
|
||||
void Convert8To16Plane(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
uint16_t* dst_y,
|
||||
int dst_stride_y,
|
||||
int scale, // 1024 for 10 bits
|
||||
int bits, // 10, 12, 16 bits (or 1024, 4096, 65536 scale)
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
||||
@ -3572,47 +3572,47 @@ void DivideRow_16_Any_NEON(const uint16_t* src_ptr,
|
||||
|
||||
void Convert8To16Row_C(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_SSE2(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_AVX2(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_AVX512BW(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_Any_SSE2(const uint8_t* src_ptr,
|
||||
uint16_t* dst_ptr,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_Any_AVX2(const uint8_t* src_ptr,
|
||||
uint16_t* dst_ptr,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_Any_AVX512BW(const uint8_t* src_ptr,
|
||||
uint16_t* dst_ptr,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_NEON(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_Any_NEON(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_SME(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
void Convert8To16Row_RVV(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width);
|
||||
|
||||
void Convert16To8Row_C(const uint16_t* src_y,
|
||||
|
||||
@ -11,6 +11,6 @@
|
||||
#ifndef INCLUDE_LIBYUV_VERSION_H_
|
||||
#define INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
#define LIBYUV_VERSION 1968
|
||||
#define LIBYUV_VERSION 1969
|
||||
|
||||
#endif // INCLUDE_LIBYUV_VERSION_H_
|
||||
|
||||
@ -53,13 +53,15 @@ extern "C" {
|
||||
// Secondary formats are converted in 2 steps.
|
||||
// Auxilliary formats call primary converters.
|
||||
enum FourCC {
|
||||
// 10 Primary YUV formats: 5 planar, 2 biplanar, 2 packed.
|
||||
// 12 Primary YUV formats: 5 planar, 4 biplanar, 2 packed.
|
||||
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
|
||||
FOURCC_I422 = FOURCC('I', '4', '2', '2'),
|
||||
FOURCC_I444 = FOURCC('I', '4', '4', '4'),
|
||||
FOURCC_I400 = FOURCC('I', '4', '0', '0'),
|
||||
FOURCC_NV21 = FOURCC('N', 'V', '2', '1'),
|
||||
FOURCC_NV12 = FOURCC('N', 'V', '1', '2'),
|
||||
FOURCC_NV16 = FOURCC('N', 'V', '1', '6'),
|
||||
FOURCC_NV24 = FOURCC('N', 'V', '2', '4'),
|
||||
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
|
||||
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
|
||||
FOURCC_I010 = FOURCC('I', '0', '1', '0'), // bt.601 10 bit 420
|
||||
@ -158,6 +160,8 @@ enum FourCCBpp {
|
||||
FOURCC_BPP_I400 = 8,
|
||||
FOURCC_BPP_NV21 = 12,
|
||||
FOURCC_BPP_NV12 = 12,
|
||||
FOURCC_BPP_NV16 = 16,
|
||||
FOURCC_BPP_NV24 = 24,
|
||||
FOURCC_BPP_YUY2 = 16,
|
||||
FOURCC_BPP_UYVY = 16,
|
||||
FOURCC_BPP_M420 = 12, // deprecated
|
||||
|
||||
@ -814,6 +814,43 @@ int ConvertFromI420(const uint8_t* y,
|
||||
height);
|
||||
break;
|
||||
}
|
||||
case FOURCC_NV16: {
|
||||
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
|
||||
int dst_uv_stride = dst_sample_stride ? dst_sample_stride : width;
|
||||
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * height;
|
||||
int halfwidth = (width + 1) / 2;
|
||||
int halfheight = (height + 1) / 2;
|
||||
CopyPlane(y, y_stride, dst_sample, dst_y_stride, width, height);
|
||||
MergeUVPlane(u, u_stride, v, v_stride, dst_uv, dst_uv_stride * 2,
|
||||
halfwidth, halfheight);
|
||||
if (height > 1) {
|
||||
MergeUVPlane(u, u_stride, v, v_stride, dst_uv + dst_uv_stride,
|
||||
dst_uv_stride * 2, halfwidth, height / 2);
|
||||
}
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
case FOURCC_NV24: {
|
||||
int dst_y_stride = dst_sample_stride ? dst_sample_stride : width;
|
||||
int dst_uv_stride = dst_sample_stride ? dst_sample_stride * 2 : width * 2;
|
||||
uint8_t* dst_uv = dst_sample + (ptrdiff_t)dst_y_stride * height;
|
||||
align_buffer_64(temp_u, (size_t)width * height);
|
||||
align_buffer_64(temp_v, (size_t)width * height);
|
||||
if (!temp_u || !temp_v) {
|
||||
free_aligned_buffer_64(temp_u);
|
||||
free_aligned_buffer_64(temp_v);
|
||||
return 1;
|
||||
}
|
||||
r = I420ToI444(y, y_stride, u, u_stride, v, v_stride, dst_sample,
|
||||
dst_y_stride, temp_u, width, temp_v, width, width, height);
|
||||
if (r == 0) {
|
||||
MergeUVPlane(temp_u, width, temp_v, width, dst_uv, dst_uv_stride, width,
|
||||
height);
|
||||
}
|
||||
free_aligned_buffer_64(temp_u);
|
||||
free_aligned_buffer_64(temp_v);
|
||||
break;
|
||||
}
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -28,6 +28,221 @@ namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static int NV16ToARGB(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) {
|
||||
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;
|
||||
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0 ||
|
||||
height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_argb = dst_argb + (ptrdiff_t)(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_SVE2)
|
||||
if (TestCpuFlag(kCpuHasSVE2)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_SVE2;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_NV12TOARGBROW_SME)
|
||||
if (TestCpuFlag(kCpuHasSME)) {
|
||||
NV12ToARGBRow = NV12ToARGBRow_SME;
|
||||
}
|
||||
#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, &kYuvI601Constants, width);
|
||||
dst_argb += dst_stride_argb;
|
||||
src_y += src_stride_y;
|
||||
src_uv += src_stride_uv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int NV24ToARGB(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) {
|
||||
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 (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v,
|
||||
int width) = SplitUVRow_C;
|
||||
if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0 ||
|
||||
height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_argb = dst_argb + (ptrdiff_t)(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_SME)
|
||||
if (TestCpuFlag(kCpuHasSME)) {
|
||||
I444ToARGBRow = I444ToARGBRow_SME;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_I444TOARGBROW_LSX)
|
||||
if (TestCpuFlag(kCpuHasLSX)) {
|
||||
I444ToARGBRow = I444ToARGBRow_Any_LSX;
|
||||
if (IS_ALIGNED(width, 8)) {
|
||||
I444ToARGBRow = I444ToARGBRow_LSX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_I444TOARGBROW_LASX)
|
||||
if (TestCpuFlag(kCpuHasLASX)) {
|
||||
I444ToARGBRow = I444ToARGBRow_Any_LASX;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
I444ToARGBRow = I444ToARGBRow_LASX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_I444TOARGBROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
I444ToARGBRow = I444ToARGBRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAS_SPLITUVROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
SplitUVRow = SplitUVRow_Any_SSE2;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
SplitUVRow = SplitUVRow_SSE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_SPLITUVROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
SplitUVRow = SplitUVRow_Any_AVX2;
|
||||
if (IS_ALIGNED(width, 32)) {
|
||||
SplitUVRow = SplitUVRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_SPLITUVROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
SplitUVRow = SplitUVRow_Any_NEON;
|
||||
if (IS_ALIGNED(width, 16)) {
|
||||
SplitUVRow = SplitUVRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_SPLITUVROW_RVV)
|
||||
if (TestCpuFlag(kCpuHasRVV)) {
|
||||
SplitUVRow = SplitUVRow_RVV;
|
||||
}
|
||||
#endif
|
||||
|
||||
align_buffer_64(row_u, width);
|
||||
align_buffer_64(row_v, width);
|
||||
if (!row_u || !row_v) {
|
||||
free_aligned_buffer_64(row_u);
|
||||
free_aligned_buffer_64(row_v);
|
||||
return 1;
|
||||
}
|
||||
for (y = 0; y < height; ++y) {
|
||||
SplitUVRow(src_uv, row_u, row_v, width);
|
||||
I444ToARGBRow(src_y, row_u, row_v, dst_argb, &kYuvI601Constants, width);
|
||||
dst_argb += dst_stride_argb;
|
||||
src_y += src_stride_y;
|
||||
src_uv += src_stride_uv;
|
||||
}
|
||||
free_aligned_buffer_64(row_u);
|
||||
free_aligned_buffer_64(row_v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert camera sample to ARGB with cropping, rotation and vertical flip.
|
||||
// src_width is used for source stride computation
|
||||
// src_height is used to compute location of planes, and indicate inversion
|
||||
@ -203,6 +418,23 @@ int ConvertToARGB(const uint8_t* sample,
|
||||
r = NV21ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
|
||||
dst_stride_argb, crop_width, inv_crop_height);
|
||||
break;
|
||||
case FOURCC_NV16:
|
||||
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
|
||||
src_uv = sample +
|
||||
aligned_src_width * ((ptrdiff_t)abs_src_height + crop_y) +
|
||||
(crop_x & ~1);
|
||||
r = NV16ToARGB(src, src_width, src_uv, aligned_src_width, dst_argb,
|
||||
dst_stride_argb, crop_width, inv_crop_height);
|
||||
break;
|
||||
case FOURCC_NV24:
|
||||
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
|
||||
src_uv = sample +
|
||||
(ptrdiff_t)aligned_src_width * abs_src_height +
|
||||
(ptrdiff_t)aligned_src_width * 2 * crop_y +
|
||||
(ptrdiff_t)crop_x * 2;
|
||||
r = NV24ToARGB(src, src_width, src_uv, aligned_src_width * 2, dst_argb,
|
||||
dst_stride_argb, crop_width, inv_crop_height);
|
||||
break;
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -14,7 +14,11 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/planar_functions.h"
|
||||
#include "libyuv/row.h"
|
||||
#include "libyuv/video_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -22,6 +26,158 @@ namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static void HalfRow_C(const uint8_t* src_uv,
|
||||
ptrdiff_t src_uv_stride,
|
||||
uint8_t* dst_uv,
|
||||
int width) {
|
||||
int x;
|
||||
for (x = 0; x < width; ++x) {
|
||||
dst_uv[x] = (src_uv[x] + src_uv[src_uv_stride + x] + 1) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int NV16ToI420(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
const uint8_t* src_uv,
|
||||
int src_stride_uv,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint8_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
void (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v,
|
||||
int width) = SplitUVRow_C;
|
||||
if ((!src_y && dst_y) || !src_uv || !dst_u || !dst_v || width <= 0 ||
|
||||
height == 0 || height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
halfheight = (height + 1) >> 1;
|
||||
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
|
||||
src_uv = src_uv + (ptrdiff_t)(height - 1) * src_stride_uv;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_uv = -src_stride_uv;
|
||||
}
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
#if defined(HAS_SPLITUVROW_SSE2)
|
||||
if (TestCpuFlag(kCpuHasSSE2)) {
|
||||
SplitUVRow = SplitUVRow_Any_SSE2;
|
||||
if (IS_ALIGNED(halfwidth, 16)) {
|
||||
SplitUVRow = SplitUVRow_SSE2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_SPLITUVROW_AVX2)
|
||||
if (TestCpuFlag(kCpuHasAVX2)) {
|
||||
SplitUVRow = SplitUVRow_Any_AVX2;
|
||||
if (IS_ALIGNED(halfwidth, 32)) {
|
||||
SplitUVRow = SplitUVRow_AVX2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_SPLITUVROW_NEON)
|
||||
if (TestCpuFlag(kCpuHasNEON)) {
|
||||
SplitUVRow = SplitUVRow_Any_NEON;
|
||||
if (IS_ALIGNED(halfwidth, 16)) {
|
||||
SplitUVRow = SplitUVRow_NEON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
align_buffer_64(row_uv, halfwidth * 2);
|
||||
if (!row_uv) {
|
||||
return 1;
|
||||
}
|
||||
for (y = 0; y < halfheight; ++y) {
|
||||
if (y * 2 + 1 < height) {
|
||||
HalfRow_C(src_uv, src_stride_uv, row_uv, halfwidth * 2);
|
||||
} else {
|
||||
memcpy(row_uv, src_uv, (size_t)halfwidth * 2);
|
||||
}
|
||||
SplitUVRow(row_uv, dst_u, dst_v, halfwidth);
|
||||
src_uv += (ptrdiff_t)src_stride_uv * 2;
|
||||
dst_u += dst_stride_u;
|
||||
dst_v += dst_stride_v;
|
||||
}
|
||||
free_aligned_buffer_64(row_uv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int NV24ToI420(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
const uint8_t* src_uv,
|
||||
int src_stride_uv,
|
||||
uint8_t* dst_y,
|
||||
int dst_stride_y,
|
||||
uint8_t* dst_u,
|
||||
int dst_stride_u,
|
||||
uint8_t* dst_v,
|
||||
int dst_stride_v,
|
||||
int width,
|
||||
int height) {
|
||||
int x, y;
|
||||
int halfwidth = (width + 1) >> 1;
|
||||
int halfheight = (height + 1) >> 1;
|
||||
if ((!src_y && dst_y) || !src_uv || !dst_u || !dst_v || width <= 0 ||
|
||||
height == 0 || height == INT_MIN) {
|
||||
return -1;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
halfheight = (height + 1) >> 1;
|
||||
src_y = src_y + (ptrdiff_t)(height - 1) * src_stride_y;
|
||||
src_uv = src_uv + (ptrdiff_t)(height - 1) * src_stride_uv;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_uv = -src_stride_uv;
|
||||
}
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
align_buffer_64(row_uv, width * 2);
|
||||
if (!row_uv) {
|
||||
return 1;
|
||||
}
|
||||
for (y = 0; y < halfheight; ++y) {
|
||||
if (y * 2 + 1 < height) {
|
||||
HalfRow_C(src_uv, src_stride_uv, row_uv, width * 2);
|
||||
} else {
|
||||
memcpy(row_uv, src_uv, (size_t)width * 2);
|
||||
}
|
||||
for (x = 0; x < halfwidth - 1; ++x) {
|
||||
dst_u[x] = (row_uv[x * 4 + 0] + row_uv[x * 4 + 2] + 1) >> 1;
|
||||
dst_v[x] = (row_uv[x * 4 + 1] + row_uv[x * 4 + 3] + 1) >> 1;
|
||||
}
|
||||
if (width & 1) {
|
||||
dst_u[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 0];
|
||||
dst_v[halfwidth - 1] = row_uv[(halfwidth - 1) * 4 + 1];
|
||||
} else {
|
||||
dst_u[halfwidth - 1] =
|
||||
(row_uv[(halfwidth - 1) * 4 + 0] + row_uv[(halfwidth - 1) * 4 + 2] +
|
||||
1) >>
|
||||
1;
|
||||
dst_v[halfwidth - 1] =
|
||||
(row_uv[(halfwidth - 1) * 4 + 1] + row_uv[(halfwidth - 1) * 4 + 3] +
|
||||
1) >>
|
||||
1;
|
||||
}
|
||||
src_uv += (ptrdiff_t)src_stride_uv * 2;
|
||||
dst_u += dst_stride_u;
|
||||
dst_v += dst_stride_v;
|
||||
}
|
||||
free_aligned_buffer_64(row_uv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert camera sample to I420 with cropping, rotation and vertical flip.
|
||||
// src_width is used for source stride computation
|
||||
// src_height is used to compute location of planes, and indicate inversion
|
||||
@ -204,6 +360,24 @@ int ConvertToI420(const uint8_t* sample,
|
||||
dst_stride_y, dst_v, dst_stride_v, dst_u,
|
||||
dst_stride_u, crop_width, inv_crop_height, rotation);
|
||||
break;
|
||||
case FOURCC_NV16:
|
||||
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
|
||||
src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) +
|
||||
((ptrdiff_t)crop_y * aligned_src_width) +
|
||||
((crop_x / 2) * 2);
|
||||
r = NV16ToI420(src, src_width, src_uv, aligned_src_width, dst_y,
|
||||
dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
|
||||
crop_width, inv_crop_height);
|
||||
break;
|
||||
case FOURCC_NV24:
|
||||
src = sample + ((ptrdiff_t)src_width * crop_y + crop_x);
|
||||
src_uv = sample + ((ptrdiff_t)aligned_src_width * abs_src_height) +
|
||||
((ptrdiff_t)crop_y * aligned_src_width * 2) +
|
||||
(crop_x * 2);
|
||||
r = NV24ToI420(src, src_width, src_uv, aligned_src_width * 2, dst_y,
|
||||
dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,
|
||||
crop_width, inv_crop_height);
|
||||
break;
|
||||
// Triplanar formats
|
||||
case FOURCC_I420:
|
||||
case FOURCC_YV12: {
|
||||
|
||||
@ -196,16 +196,25 @@ void Convert8To16Plane(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
uint16_t* dst_y,
|
||||
int dst_stride_y,
|
||||
int scale, // 1024 for 10 bits
|
||||
int bits, // 10, 12, 16 bits (or 1024, 4096, 65536 scale)
|
||||
int width,
|
||||
int height) {
|
||||
int y;
|
||||
void (*Convert8To16Row)(const uint8_t* src_y, uint16_t* dst_y, int scale,
|
||||
void (*Convert8To16Row)(const uint8_t* src_y, uint16_t* dst_y, int bits,
|
||||
int width) = Convert8To16Row_C;
|
||||
|
||||
if (width <= 0 || height == 0 || height == INT_MIN) {
|
||||
return;
|
||||
}
|
||||
// Convert legacy scale to bits if needed.
|
||||
if (bits > 16) {
|
||||
int b = 0;
|
||||
while (bits > 1) {
|
||||
bits >>= 1;
|
||||
++b;
|
||||
}
|
||||
bits = b;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
@ -264,7 +273,7 @@ void Convert8To16Plane(const uint8_t* src_y,
|
||||
|
||||
// Convert plane
|
||||
for (y = 0; y < height; ++y) {
|
||||
Convert8To16Row(src_y, dst_y, scale, width);
|
||||
Convert8To16Row(src_y, dst_y, bits, width);
|
||||
src_y += src_stride_y;
|
||||
dst_y += dst_stride_y;
|
||||
}
|
||||
|
||||
@ -145,6 +145,13 @@ void TransposeWxH_16_C(const uint16_t* src,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Copy4(uint8_t* dst, const uint8_t* src) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
// Transpose 32 bit values (ARGB)
|
||||
void Transpose4x4_32_C(const uint8_t* src,
|
||||
int src_stride,
|
||||
@ -159,38 +166,22 @@ void Transpose4x4_32_C(const uint8_t* src,
|
||||
uint8_t* dst3 = dst2 + dst_stride;
|
||||
int i;
|
||||
for (i = 0; i < width; i += 4) {
|
||||
uint32_t p00 = ((uint32_t*)(src))[0];
|
||||
uint32_t p10 = ((uint32_t*)(src))[1];
|
||||
uint32_t p20 = ((uint32_t*)(src))[2];
|
||||
uint32_t p30 = ((uint32_t*)(src))[3];
|
||||
uint32_t p01 = ((uint32_t*)(src1))[0];
|
||||
uint32_t p11 = ((uint32_t*)(src1))[1];
|
||||
uint32_t p21 = ((uint32_t*)(src1))[2];
|
||||
uint32_t p31 = ((uint32_t*)(src1))[3];
|
||||
uint32_t p02 = ((uint32_t*)(src2))[0];
|
||||
uint32_t p12 = ((uint32_t*)(src2))[1];
|
||||
uint32_t p22 = ((uint32_t*)(src2))[2];
|
||||
uint32_t p32 = ((uint32_t*)(src2))[3];
|
||||
uint32_t p03 = ((uint32_t*)(src3))[0];
|
||||
uint32_t p13 = ((uint32_t*)(src3))[1];
|
||||
uint32_t p23 = ((uint32_t*)(src3))[2];
|
||||
uint32_t p33 = ((uint32_t*)(src3))[3];
|
||||
((uint32_t*)(dst))[0] = p00;
|
||||
((uint32_t*)(dst))[1] = p01;
|
||||
((uint32_t*)(dst))[2] = p02;
|
||||
((uint32_t*)(dst))[3] = p03;
|
||||
((uint32_t*)(dst1))[0] = p10;
|
||||
((uint32_t*)(dst1))[1] = p11;
|
||||
((uint32_t*)(dst1))[2] = p12;
|
||||
((uint32_t*)(dst1))[3] = p13;
|
||||
((uint32_t*)(dst2))[0] = p20;
|
||||
((uint32_t*)(dst2))[1] = p21;
|
||||
((uint32_t*)(dst2))[2] = p22;
|
||||
((uint32_t*)(dst2))[3] = p23;
|
||||
((uint32_t*)(dst3))[0] = p30;
|
||||
((uint32_t*)(dst3))[1] = p31;
|
||||
((uint32_t*)(dst3))[2] = p32;
|
||||
((uint32_t*)(dst3))[3] = p33;
|
||||
Copy4(dst + 0, src + 0);
|
||||
Copy4(dst + 4, src1 + 0);
|
||||
Copy4(dst + 8, src2 + 0);
|
||||
Copy4(dst + 12, src3 + 0);
|
||||
Copy4(dst1 + 0, src + 4);
|
||||
Copy4(dst1 + 4, src1 + 4);
|
||||
Copy4(dst1 + 8, src2 + 4);
|
||||
Copy4(dst1 + 12, src3 + 4);
|
||||
Copy4(dst2 + 0, src + 8);
|
||||
Copy4(dst2 + 4, src1 + 8);
|
||||
Copy4(dst2 + 8, src2 + 8);
|
||||
Copy4(dst2 + 12, src3 + 8);
|
||||
Copy4(dst3 + 0, src + 12);
|
||||
Copy4(dst3 + 4, src1 + 12);
|
||||
Copy4(dst3 + 8, src2 + 12);
|
||||
Copy4(dst3 + 12, src3 + 12);
|
||||
src += (ptrdiff_t)src_stride * 4; // advance 4 rows
|
||||
src1 += (ptrdiff_t)src_stride * 4;
|
||||
src2 += (ptrdiff_t)src_stride * 4;
|
||||
|
||||
@ -1494,7 +1494,7 @@ ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
|
||||
|
||||
// Any 1 to 1 with parameter and shorts. BPP measures in shorts.
|
||||
#define ANY11C(NAMEANY, ANY_SIMD, SBPP, BPP, STYPE, DTYPE, MASK) \
|
||||
void NAMEANY(const STYPE* src_ptr, DTYPE* dst_ptr, int scale, int width) { \
|
||||
void NAMEANY(const STYPE* src_ptr, DTYPE* dst_ptr, int value, int width) { \
|
||||
SIMD_ALIGNED(STYPE vin[64]); \
|
||||
static_assert((MASK + 1) * SBPP <= sizeof(vin), "vin buffer too small"); \
|
||||
SIMD_ALIGNED(DTYPE vout[64]); \
|
||||
@ -1503,11 +1503,11 @@ ANY11T(AB64ToARGBRow_Any_NEON, AB64ToARGBRow_NEON, 8, 4, uint16_t, uint8_t, 7)
|
||||
int r = width & MASK; \
|
||||
int n = width & ~MASK; \
|
||||
if (n > 0) { \
|
||||
ANY_SIMD(src_ptr, dst_ptr, scale, n); \
|
||||
ANY_SIMD(src_ptr, dst_ptr, value, n); \
|
||||
} \
|
||||
ptrdiff_t np = n; \
|
||||
memcpy(vin, src_ptr + np, r * SBPP); \
|
||||
ANY_SIMD(vin, vout, scale, MASK + 1); \
|
||||
ANY_SIMD(vin, vout, value, MASK + 1); \
|
||||
memcpy(dst_ptr + np, vout, r * BPP); \
|
||||
}
|
||||
|
||||
|
||||
@ -2822,16 +2822,15 @@ void MirrorSplitUVRow_C(const uint8_t* src_uv,
|
||||
|
||||
void ARGBMirrorRow_C(const uint8_t* src, uint8_t* dst, int width) {
|
||||
int x;
|
||||
const uint32_t* src32 = (const uint32_t*)(src);
|
||||
uint32_t* dst32 = (uint32_t*)(dst);
|
||||
src32 += width - 1;
|
||||
for (x = 0; x < width - 1; x += 2) {
|
||||
dst32[x] = src32[0];
|
||||
dst32[x + 1] = src32[-1];
|
||||
src32 -= 2;
|
||||
}
|
||||
if (width & 1) {
|
||||
dst32[width - 1] = src32[0];
|
||||
const uint8_t* s = src + (ptrdiff_t)(width - 1) * 4;
|
||||
uint8_t* d = dst;
|
||||
for (x = 0; x < width; ++x) {
|
||||
d[0] = s[0];
|
||||
d[1] = s[1];
|
||||
d[2] = s[2];
|
||||
d[3] = s[3];
|
||||
s -= 4;
|
||||
d += 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3241,18 +3240,15 @@ void Convert16To8Row_C(const uint16_t* src_y,
|
||||
}
|
||||
}
|
||||
|
||||
// Use scale to convert lsb formats to msb, depending how many bits there are:
|
||||
// 1024 = 10 bits
|
||||
// 4096 = 12 bits
|
||||
// 65536 = 16 bits
|
||||
// Convert 8 bit values to 10, 12 or 16 bits.
|
||||
void Convert8To16Row_C(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
int x;
|
||||
scale *= 0x0101; // replicates the byte.
|
||||
int shift = 16 - bits;
|
||||
for (x = 0; x < width; ++x) {
|
||||
dst_y[x] = (src_y[x] * scale) >> 16;
|
||||
dst_y[x] = (src_y[x] * 0x0101) >> shift;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6218,9 +6218,9 @@ void HalfWidthRow_16To8_AVX512BW(const uint16_t* src_uv,
|
||||
// 65536 = 16 bits
|
||||
void Convert8To16Row_SSE2(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
const int shift = __builtin_clz(scale) - 15;
|
||||
const int shift = 16 - bits;
|
||||
asm volatile(
|
||||
"movd %3,%%xmm2 \n"
|
||||
|
||||
@ -6249,9 +6249,9 @@ void Convert8To16Row_SSE2(const uint8_t* src_y,
|
||||
#ifdef HAS_CONVERT8TO16ROW_AVX2
|
||||
void Convert8To16Row_AVX2(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
const int shift = __builtin_clz(scale) - 15;
|
||||
const int shift = 16 - bits;
|
||||
asm volatile("vmovd %3,%%xmm2 \n"
|
||||
|
||||
// 32 pixels per loop.
|
||||
@ -6279,16 +6279,11 @@ void Convert8To16Row_AVX2(const uint8_t* src_y,
|
||||
#endif // HAS_CONVERT8TO16ROW_AVX2
|
||||
|
||||
#ifdef HAS_CONVERT8TO16ROW_AVX512BW
|
||||
// Use scale to convert to lsb formats depending how many bits there are:
|
||||
// 512 = 9 bits
|
||||
// 1024 = 10 bits
|
||||
// 4096 = 12 bits
|
||||
// 65536 = 16 bits
|
||||
void Convert8To16Row_AVX512BW(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
const int shift = __builtin_clz(scale) - 15;
|
||||
const int shift = 16 - bits;
|
||||
asm volatile(
|
||||
"vpbroadcastw %4,%%zmm2 \n"
|
||||
"vmovd %3,%%xmm3 \n"
|
||||
|
||||
@ -3835,15 +3835,13 @@ void Convert8To8Row_NEON(const uint8_t* src_y,
|
||||
// 512 = 9 bits
|
||||
// 1024 = 10 bits
|
||||
// 4096 = 12 bits
|
||||
// 65536 = 16 bits
|
||||
void Convert8To16Row_NEON(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
// (src * 0x0101 * scale) >> 16.
|
||||
// Since scale is a power of two, compute the shift to use to avoid needing
|
||||
// to widen to int32.
|
||||
const int shift = 15 - __builtin_clz(scale);
|
||||
// (src * 0x0101) >> (16 - bits).
|
||||
// Use negative shift for right shift with vshl.
|
||||
const int shift = bits - 16;
|
||||
asm volatile(
|
||||
"vdup.16 q2, %3 \n"
|
||||
"1: \n"
|
||||
|
||||
@ -5273,12 +5273,11 @@ void Convert8To8Row_NEON(const uint8_t* src_y,
|
||||
// 65536 = 16 bits
|
||||
void Convert8To16Row_NEON(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
// (src * 0x0101 * scale) >> 16.
|
||||
// Since scale is a power of two, compute the shift to use to avoid needing
|
||||
// to widen to int32.
|
||||
const int shift = 15 - __builtin_clz(scale);
|
||||
// (src * 0x0101) >> (16 - bits).
|
||||
// Use negative shift for right shift with ushl.
|
||||
const int shift = bits - 16;
|
||||
asm volatile(
|
||||
"dup v2.8h, %w[shift] \n"
|
||||
"1: \n"
|
||||
|
||||
@ -1821,10 +1821,10 @@ void Convert16To8Row_RVV(const uint16_t* src_y,
|
||||
// 65536 = 16 bits
|
||||
void Convert8To16Row_RVV(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
size_t w = (size_t)width;
|
||||
const int shift = __builtin_clz((int32_t)scale) - 15;
|
||||
const int shift = 16 - bits;
|
||||
do {
|
||||
size_t vl = __riscv_vsetvl_e8m2(w);
|
||||
vuint8m2_t v_src = __riscv_vle8_v_u8m2(src_y, vl);
|
||||
|
||||
@ -1054,12 +1054,10 @@ __arm_locally_streaming void Convert8To8Row_SME(const uint8_t* src_y,
|
||||
|
||||
__arm_locally_streaming void Convert8To16Row_SME(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
// (src * 0x0101 * scale) >> 16.
|
||||
// Since scale is a power of two, compute the shift to use to avoid needing
|
||||
// to widen to int32.
|
||||
const int shift = __builtin_clz(scale) - 15;
|
||||
// (src * 0x0101) >> (16 - bits).
|
||||
const int shift = 16 - bits;
|
||||
|
||||
uint64_t vl;
|
||||
asm volatile(
|
||||
|
||||
@ -766,23 +766,12 @@ void ARGBToUVMatrixRow_AVX2(const uint8_t* src_argb,
|
||||
#endif // HAS_ARGBTOUVMATRIXROW_AVX2
|
||||
|
||||
#ifdef HAS_CONVERT8TO16ROW_AVX2
|
||||
// Use scale to convert to lsb formats depending how many bits there are:
|
||||
// 512 = 9 bits
|
||||
// 1024 = 10 bits
|
||||
// 4096 = 12 bits
|
||||
// 65536 = 16 bits
|
||||
LIBYUV_TARGET_AVX2
|
||||
void Convert8To16Row_AVX2(const uint8_t* src_y,
|
||||
uint16_t* dst_y,
|
||||
int scale,
|
||||
int bits,
|
||||
int width) {
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long index;
|
||||
_BitScanReverse(&index, (unsigned long)scale);
|
||||
const int shift = 16 - (int)index;
|
||||
#else
|
||||
const int shift = __builtin_clz(scale) - 15;
|
||||
#endif
|
||||
const int shift = 16 - bits;
|
||||
__m128i shift128 = _mm_cvtsi32_si128(shift);
|
||||
do {
|
||||
__m256i ymm0 = _mm256_loadu_si256((const __m256i*)src_y);
|
||||
|
||||
@ -1680,6 +1680,42 @@ TEST_F(LibYUVConvertTest, RotateWithARGBSource) {
|
||||
ASSERT_EQ(dst[3], src[1]);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertToARGB_NV16) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int sample_size = kWidth * kHeight * 2;
|
||||
align_buffer_page_end(src, sample_size);
|
||||
align_buffer_page_end(dst, kWidth * kHeight * 4);
|
||||
MemRandomize(src, sample_size);
|
||||
memset(dst, 0, kWidth * kHeight * 4);
|
||||
|
||||
int r = ConvertToARGB(src, sample_size, dst, kWidth * 4,
|
||||
0, 0, kWidth, kHeight, kWidth, kHeight,
|
||||
kRotate0, FOURCC_NV16);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src);
|
||||
free_aligned_buffer_page_end(dst);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertToARGB_NV24) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int sample_size = kWidth * kHeight * 3;
|
||||
align_buffer_page_end(src, sample_size);
|
||||
align_buffer_page_end(dst, kWidth * kHeight * 4);
|
||||
MemRandomize(src, sample_size);
|
||||
memset(dst, 0, kWidth * kHeight * 4);
|
||||
|
||||
int r = ConvertToARGB(src, sample_size, dst, kWidth * 4,
|
||||
0, 0, kWidth, kHeight, kWidth, kHeight,
|
||||
kRotate0, FOURCC_NV24);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src);
|
||||
free_aligned_buffer_page_end(dst);
|
||||
}
|
||||
|
||||
#ifdef HAS_ARGBTOAR30ROW_AVX2
|
||||
TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) {
|
||||
// ARGBToAR30Row_AVX2 expects a multiple of 8 pixels.
|
||||
|
||||
@ -1923,6 +1923,100 @@ TEST_F(LibYUVConvertTest, NV12Crop) {
|
||||
free_aligned_buffer_page_end(src_y);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertToI420_NV16) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int sample_size = kWidth * kHeight * 2;
|
||||
align_buffer_page_end(src, sample_size);
|
||||
align_buffer_page_end(dst_y, kWidth * kHeight);
|
||||
align_buffer_page_end(dst_u, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(dst_v, (kWidth / 2) * (kHeight / 2));
|
||||
MemRandomize(src, sample_size);
|
||||
memset(dst_y, 0, kWidth * kHeight);
|
||||
memset(dst_u, 0, (kWidth / 2) * (kHeight / 2));
|
||||
memset(dst_v, 0, (kWidth / 2) * (kHeight / 2));
|
||||
|
||||
int r = ConvertToI420(src, sample_size, dst_y, kWidth, dst_u, kWidth / 2,
|
||||
dst_v, kWidth / 2, 0, 0, kWidth, kHeight, kWidth,
|
||||
kHeight, kRotate0, FOURCC_NV16);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src);
|
||||
free_aligned_buffer_page_end(dst_y);
|
||||
free_aligned_buffer_page_end(dst_u);
|
||||
free_aligned_buffer_page_end(dst_v);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertToI420_NV24) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int sample_size = kWidth * kHeight * 3;
|
||||
align_buffer_page_end(src, sample_size);
|
||||
align_buffer_page_end(dst_y, kWidth * kHeight);
|
||||
align_buffer_page_end(dst_u, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(dst_v, (kWidth / 2) * (kHeight / 2));
|
||||
MemRandomize(src, sample_size);
|
||||
memset(dst_y, 0, kWidth * kHeight);
|
||||
memset(dst_u, 0, (kWidth / 2) * (kHeight / 2));
|
||||
memset(dst_v, 0, (kWidth / 2) * (kHeight / 2));
|
||||
|
||||
int r = ConvertToI420(src, sample_size, dst_y, kWidth, dst_u, kWidth / 2,
|
||||
dst_v, kWidth / 2, 0, 0, kWidth, kHeight, kWidth,
|
||||
kHeight, kRotate0, FOURCC_NV24);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src);
|
||||
free_aligned_buffer_page_end(dst_y);
|
||||
free_aligned_buffer_page_end(dst_u);
|
||||
free_aligned_buffer_page_end(dst_v);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertFromI420_NV16) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int dst_size = kWidth * kHeight * 2;
|
||||
align_buffer_page_end(src_y, kWidth * kHeight);
|
||||
align_buffer_page_end(src_u, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(src_v, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(dst, dst_size);
|
||||
MemRandomize(src_y, kWidth * kHeight);
|
||||
MemRandomize(src_u, (kWidth / 2) * (kHeight / 2));
|
||||
MemRandomize(src_v, (kWidth / 2) * (kHeight / 2));
|
||||
memset(dst, 0, dst_size);
|
||||
|
||||
int r = ConvertFromI420(src_y, kWidth, src_u, kWidth / 2, src_v, kWidth / 2,
|
||||
dst, kWidth, kWidth, kHeight, FOURCC_NV16);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src_y);
|
||||
free_aligned_buffer_page_end(src_u);
|
||||
free_aligned_buffer_page_end(src_v);
|
||||
free_aligned_buffer_page_end(dst);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, ConvertFromI420_NV24) {
|
||||
const int kWidth = 64;
|
||||
const int kHeight = 48;
|
||||
const int dst_size = kWidth * kHeight * 3;
|
||||
align_buffer_page_end(src_y, kWidth * kHeight);
|
||||
align_buffer_page_end(src_u, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(src_v, (kWidth / 2) * (kHeight / 2));
|
||||
align_buffer_page_end(dst, dst_size);
|
||||
MemRandomize(src_y, kWidth * kHeight);
|
||||
MemRandomize(src_u, (kWidth / 2) * (kHeight / 2));
|
||||
MemRandomize(src_v, (kWidth / 2) * (kHeight / 2));
|
||||
memset(dst, 0, dst_size);
|
||||
|
||||
int r = ConvertFromI420(src_y, kWidth, src_u, kWidth / 2, src_v, kWidth / 2,
|
||||
dst, kWidth, kWidth, kHeight, FOURCC_NV24);
|
||||
EXPECT_EQ(0, r);
|
||||
|
||||
free_aligned_buffer_page_end(src_y);
|
||||
free_aligned_buffer_page_end(src_u);
|
||||
free_aligned_buffer_page_end(src_v);
|
||||
free_aligned_buffer_page_end(dst);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVConvertTest, I420CropOddY) {
|
||||
const int SUBSAMP_X = 2;
|
||||
const int SUBSAMP_Y = 2;
|
||||
|
||||
@ -4159,7 +4159,7 @@ TEST_F(LibYUVPlanarTest, Convert8To16Plane) {
|
||||
MaskCpuFlags(disable_cpu_flags_);
|
||||
Convert8To16Plane(src_pixels_y, benchmark_width_,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_c),
|
||||
benchmark_width_, 1024, benchmark_width_,
|
||||
benchmark_width_, 10, benchmark_width_,
|
||||
benchmark_height_);
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
@ -4193,7 +4193,7 @@ TEST_F(LibYUVPlanarTest, Convert8To16Row_Opt) {
|
||||
memset(dst_pixels_y_c, 1, kPixels * 2);
|
||||
|
||||
Convert8To16Row_C(src_pixels_y, reinterpret_cast<uint16_t*>(dst_pixels_y_c),
|
||||
1024, kPixels);
|
||||
10, kPixels);
|
||||
|
||||
#if defined(HAS_CONVERT8TO16ROW_AVX512BW)
|
||||
int has_avx512 = TestCpuFlag(kCpuHasAVX512BW);
|
||||
@ -4205,20 +4205,20 @@ TEST_F(LibYUVPlanarTest, Convert8To16Row_Opt) {
|
||||
if (has_avx512) {
|
||||
Convert8To16Row_AVX512BW(src_pixels_y,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt),
|
||||
1024, kPixels);
|
||||
10, kPixels);
|
||||
} else
|
||||
#endif
|
||||
if (has_avx2) {
|
||||
Convert8To16Row_AVX2(src_pixels_y,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 1024,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 10,
|
||||
kPixels);
|
||||
} else if (has_sse2) {
|
||||
Convert8To16Row_SSE2(src_pixels_y,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 1024,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 10,
|
||||
kPixels);
|
||||
} else {
|
||||
Convert8To16Row_C(src_pixels_y,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 1024,
|
||||
reinterpret_cast<uint16_t*>(dst_pixels_y_opt), 10,
|
||||
kPixels);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,6 +63,8 @@ TEST_F(LibYUVBaseTest, TestFourCC) {
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_I400, FOURCC_BPP_I400));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_NV21, FOURCC_BPP_NV21));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_NV12, FOURCC_BPP_NV12));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_NV16, FOURCC_BPP_NV16));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_NV24, FOURCC_BPP_NV24));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_YUY2, FOURCC_BPP_YUY2));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_UYVY, FOURCC_BPP_UYVY));
|
||||
ASSERT_TRUE(TestValidFourCC(FOURCC_M420, FOURCC_BPP_M420)); // deprecated.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user