From f11cad157bf60f485474ce3aecf5365deea1bc0f Mon Sep 17 00:00:00 2001 From: Sergey Stepanov Date: Mon, 16 Oct 2023 00:02:16 +0300 Subject: [PATCH] Use static libyuv for macs --- .github/workflows/build.yml | 2 +- Makefile | 2 +- README.md | 2 +- pkg/encoder/yuv/libyuv/LICENSE | 29 - pkg/encoder/yuv/libyuv/basic_types.h | 29 - pkg/encoder/yuv/libyuv/convert.c | 336 --- pkg/encoder/yuv/libyuv/convert.h | 113 - pkg/encoder/yuv/libyuv/convert_argb.h | 24 - pkg/encoder/yuv/libyuv/convert_to_i420.c | 116 - pkg/encoder/yuv/libyuv/cpu_id.c | 204 -- pkg/encoder/yuv/libyuv/cpu_id.h | 106 - pkg/encoder/yuv/libyuv/libyuv.go | 49 +- pkg/encoder/yuv/libyuv/libyuv2.go | 89 - pkg/encoder/yuv/libyuv/libyuv_darwin_arm64.a | Bin 0 -> 486312 bytes pkg/encoder/yuv/libyuv/libyuv_darwin_x86_64.a | Bin 0 -> 669112 bytes pkg/encoder/yuv/libyuv/planar_functions.c | 68 - pkg/encoder/yuv/libyuv/planar_functions.h | 46 - pkg/encoder/yuv/libyuv/rotate.c | 217 -- pkg/encoder/yuv/libyuv/rotate.h | 79 - pkg/encoder/yuv/libyuv/rotate_any.c | 54 - pkg/encoder/yuv/libyuv/rotate_common.c | 77 - pkg/encoder/yuv/libyuv/rotate_gcc.c | 370 --- pkg/encoder/yuv/libyuv/rotate_row.h | 106 - pkg/encoder/yuv/libyuv/row.h | 426 --- pkg/encoder/yuv/libyuv/row_any.c | 206 -- pkg/encoder/yuv/libyuv/row_common.c | 887 ------ pkg/encoder/yuv/libyuv/row_gcc.c | 1090 ------- pkg/encoder/yuv/libyuv/scale.c | 946 ------ pkg/encoder/yuv/libyuv/scale.h | 53 - pkg/encoder/yuv/libyuv/scale_any.c | 632 ---- pkg/encoder/yuv/libyuv/scale_common.c | 930 ------ pkg/encoder/yuv/libyuv/scale_gcc.c | 2651 ----------------- pkg/encoder/yuv/libyuv/scale_row.h | 768 ----- pkg/encoder/yuv/libyuv/version.h | 16 - pkg/encoder/yuv/libyuv/video_common.c | 50 - pkg/encoder/yuv/libyuv/video_common.h | 212 -- pkg/encoder/yuv/yuv_test.go | 3 + 37 files changed, 45 insertions(+), 10943 deletions(-) delete mode 100644 pkg/encoder/yuv/libyuv/LICENSE delete mode 100644 pkg/encoder/yuv/libyuv/basic_types.h delete mode 100644 pkg/encoder/yuv/libyuv/convert.c delete mode 100644 pkg/encoder/yuv/libyuv/convert.h delete mode 100644 pkg/encoder/yuv/libyuv/convert_argb.h delete mode 100644 pkg/encoder/yuv/libyuv/convert_to_i420.c delete mode 100644 pkg/encoder/yuv/libyuv/cpu_id.c delete mode 100644 pkg/encoder/yuv/libyuv/cpu_id.h delete mode 100644 pkg/encoder/yuv/libyuv/libyuv2.go create mode 100644 pkg/encoder/yuv/libyuv/libyuv_darwin_arm64.a create mode 100644 pkg/encoder/yuv/libyuv/libyuv_darwin_x86_64.a delete mode 100644 pkg/encoder/yuv/libyuv/planar_functions.c delete mode 100644 pkg/encoder/yuv/libyuv/planar_functions.h delete mode 100644 pkg/encoder/yuv/libyuv/rotate.c delete mode 100644 pkg/encoder/yuv/libyuv/rotate.h delete mode 100644 pkg/encoder/yuv/libyuv/rotate_any.c delete mode 100644 pkg/encoder/yuv/libyuv/rotate_common.c delete mode 100644 pkg/encoder/yuv/libyuv/rotate_gcc.c delete mode 100644 pkg/encoder/yuv/libyuv/rotate_row.h delete mode 100644 pkg/encoder/yuv/libyuv/row.h delete mode 100644 pkg/encoder/yuv/libyuv/row_any.c delete mode 100644 pkg/encoder/yuv/libyuv/row_common.c delete mode 100644 pkg/encoder/yuv/libyuv/row_gcc.c delete mode 100644 pkg/encoder/yuv/libyuv/scale.c delete mode 100644 pkg/encoder/yuv/libyuv/scale.h delete mode 100644 pkg/encoder/yuv/libyuv/scale_any.c delete mode 100644 pkg/encoder/yuv/libyuv/scale_common.c delete mode 100644 pkg/encoder/yuv/libyuv/scale_gcc.c delete mode 100644 pkg/encoder/yuv/libyuv/scale_row.h delete mode 100644 pkg/encoder/yuv/libyuv/version.h delete mode 100644 pkg/encoder/yuv/libyuv/video_common.c delete mode 100644 pkg/encoder/yuv/libyuv/video_common.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccae921f1..4da180c58 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,7 @@ jobs: - name: Get MacOS dev libraries and tools if: matrix.os == 'macos-latest' run: | - brew install pkg-config libvpx x264 opus sdl2 + brew install pkg-config libvpx x264 opus sdl2 jpeg-turbo - name: Get Windows dev libraries and tools if: matrix.os == 'windows-latest' diff --git a/Makefile b/Makefile index f0afe6ad7..748aa595f 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ test: go test -v ./pkg/... verify-cores: - go test -run TestAll ./pkg/worker/room -v -renderFrames $(GL_CTX) -outputPath "../../../_rendered" + go test -run TestAll ./pkg/worker/room -v -renderFrames $(GL_CTX) -outputPath "./_rendered" dev.build: compile build diff --git a/README.md b/README.md index b3f181c31..d1d837ad7 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ a better sense of performance. apt-get install -y make gcc pkg-config libvpx-dev libx264-dev libopus-dev libsdl2-dev libyuv-dev # MacOS -brew install pkg-config libvpx x264 opus sdl2 +brew install pkg-config libvpx x264 opus sdl2 jpeg-turbo # Windows (MSYS2) pacman -Sy --noconfirm --needed git make mingw-w64-x86_64-{gcc,pkgconf,dlfcn,libvpx,opus,x264-git,SDL2,libyuv} diff --git a/pkg/encoder/yuv/libyuv/LICENSE b/pkg/encoder/yuv/libyuv/LICENSE deleted file mode 100644 index c911747a6..000000000 --- a/pkg/encoder/yuv/libyuv/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -Copyright 2011 The LibYuv Project Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of Google nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/encoder/yuv/libyuv/basic_types.h b/pkg/encoder/yuv/libyuv/basic_types.h deleted file mode 100644 index 9c66a132a..000000000 --- a/pkg/encoder/yuv/libyuv/basic_types.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_ -#define INCLUDE_LIBYUV_BASIC_TYPES_H_ - -#include // For size_t and NULL - -#if !defined(INT_TYPES_DEFINED) && !defined(GG_LONGLONG) -#define INT_TYPES_DEFINED - -#include // for uintptr_t and C99 types - -#endif // INT_TYPES_DEFINED - -#if !defined(LIBYUV_API) -#define LIBYUV_API -#endif // LIBYUV_API - -#define LIBYUV_BOOL int - -#endif // INCLUDE_LIBYUV_BASIC_TYPES_H_ diff --git a/pkg/encoder/yuv/libyuv/convert.c b/pkg/encoder/yuv/libyuv/convert.c deleted file mode 100644 index c59da3b1b..000000000 --- a/pkg/encoder/yuv/libyuv/convert.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * 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 "convert.h" - -#include "basic_types.h" -#include "cpu_id.h" -#include "planar_functions.h" -#include "row.h" - -// Subsample amount uses a shift. -// v is value -// a is amount to add to round up -// s is shift to subsample down -#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) - -static __inline int Abs(int v) { - return v >= 0 ? v : -v; -} - -// Copy I420 with optional flipping. -// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure -// is does row coalescing. -LIBYUV_API -int I420Copy(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_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 halfwidth = (width + 1) >> 1; - int halfheight = (height + 1) >> 1; - if ((!src_y && dst_y) || !src_u || !src_v || !dst_u || !dst_v || width <= 0 || - height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - halfheight = (height + 1) >> 1; - src_y = src_y + (height - 1) * src_stride_y; - src_u = src_u + (halfheight - 1) * src_stride_u; - src_v = src_v + (halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; - src_stride_u = -src_stride_u; - src_stride_v = -src_stride_v; - } - - if (dst_y) { - CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); - } - // Copy UV planes. - CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight); - CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight); - return 0; -} - -// Convert ARGB to I420. -LIBYUV_API -int ARGBToI420(const uint8_t *src_argb, - int src_stride_argb, - 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; - void (*ARGBToUVRow)(const uint8_t *src_argb0, int src_stride_argb, - uint8_t *dst_u, uint8_t *dst_v, int width) = - ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8_t *src_argb, uint8_t *dst_y, int width) = - ARGBToYRow_C; - if (!src_argb || !dst_y || !dst_u || !dst_v || 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; - } -#if defined(HAS_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ARGBToYRow = ARGBToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } -#endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; - } - } -#endif -#if defined(HAS_ARGBTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ARGBToYRow = ARGBToYRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ARGBToYRow = ARGBToYRow_AVX2; - } - } -#endif -#if defined(HAS_ARGBTOUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ARGBToUVRow = ARGBToUVRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ARGBToUVRow = ARGBToUVRow_AVX2; - } - } -#endif - - for (y = 0; y < height - 1; y += 2) { - ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width); - ARGBToYRow(src_argb, dst_y, width); - ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width); - src_argb += src_stride_argb * 2; - dst_y += dst_stride_y * 2; - dst_u += dst_stride_u; - dst_v += dst_stride_v; - } - if (height & 1) { - ARGBToUVRow(src_argb, 0, dst_u, dst_v, width); - ARGBToYRow(src_argb, dst_y, width); - } - return 0; -} - -// Convert ABGR to I420. -LIBYUV_API -int ABGRToI420(const uint8_t *src_abgr, - int src_stride_abgr, - 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; - void (*ABGRToUVRow)(const uint8_t *src_abgr0, int src_stride_abgr, - uint8_t *dst_u, uint8_t *dst_v, int width) = - ABGRToUVRow_C; - void (*ABGRToYRow)(const uint8_t *src_abgr, uint8_t *dst_y, int width) = - ABGRToYRow_C; - if (!src_abgr || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { - return -1; - } - // Negative height means invert the image. - if (height < 0) { - height = -height; - src_abgr = src_abgr + (height - 1) * src_stride_abgr; - src_stride_abgr = -src_stride_abgr; - } -#if defined(HAS_ABGRTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ABGRToYRow = ABGRToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ABGRToYRow = ABGRToYRow_SSSE3; - } - } -#endif -#if defined(HAS_ABGRTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ABGRToUVRow = ABGRToUVRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ABGRToUVRow = ABGRToUVRow_SSSE3; - } - } -#endif -#if defined(HAS_ABGRTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ABGRToYRow = ABGRToYRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ABGRToYRow = ABGRToYRow_AVX2; - } - } -#endif -#if defined(HAS_ABGRTOUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ABGRToUVRow = ABGRToUVRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ABGRToUVRow = ABGRToUVRow_AVX2; - } - } -#endif - - for (y = 0; y < height - 1; y += 2) { - ABGRToUVRow(src_abgr, src_stride_abgr, dst_u, dst_v, width); - ABGRToYRow(src_abgr, dst_y, width); - ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width); - src_abgr += src_stride_abgr * 2; - dst_y += dst_stride_y * 2; - dst_u += dst_stride_u; - dst_v += dst_stride_v; - } - if (height & 1) { - ABGRToUVRow(src_abgr, 0, dst_u, dst_v, width); - ABGRToYRow(src_abgr, dst_y, width); - } - return 0; -} - -// Convert RGB565 to I420. -LIBYUV_API -int RGB565ToI420(const uint8_t *src_rgb565, - int src_stride_rgb565, - 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; - void (*RGB565ToARGBRow)(const uint8_t *src_rgb, uint8_t *dst_argb, - int width) = RGB565ToARGBRow_C; - void (*ARGBToUVRow)(const uint8_t *src_argb0, int src_stride_argb, - uint8_t *dst_u, uint8_t *dst_v, int width) = - ARGBToUVRow_C; - void (*ARGBToYRow)(const uint8_t *src_argb, uint8_t *dst_y, int width) = - ARGBToYRow_C; - if (!src_rgb565 || !dst_y || !dst_u || !dst_v || 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; - } - -#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_ARGBTOYROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ARGBToYRow = ARGBToYRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToYRow = ARGBToYRow_SSSE3; - } - } -#endif -#if defined(HAS_ARGBTOUVROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ARGBToUVRow = ARGBToUVRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - ARGBToUVRow = ARGBToUVRow_SSSE3; - } - } -#endif -#if defined(HAS_ARGBTOYROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ARGBToYRow = ARGBToYRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ARGBToYRow = ARGBToYRow_AVX2; - } - } -#endif -#if defined(HAS_ARGBTOUVROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ARGBToUVRow = ARGBToUVRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - ARGBToUVRow = ARGBToUVRow_AVX2; - } - } -#endif - { -#if !(defined(HAS_RGB565TOYROW_NEON)) - // Allocate 2 rows of ARGB. - const int row_size = (width * 4 + 31) & ~31; - align_buffer_64(row, row_size * 2); -#endif - for (y = 0; y < height - 1; y += 2) { -#if (defined(HAS_RGB565TOYROW_NEON)) -#else - RGB565ToARGBRow(src_rgb565, row, width); - RGB565ToARGBRow(src_rgb565 + src_stride_rgb565, row + row_size, width); - ARGBToUVRow(row, row_size, dst_u, dst_v, width); - ARGBToYRow(row, dst_y, width); - ARGBToYRow(row + row_size, dst_y + dst_stride_y, width); -#endif - src_rgb565 += src_stride_rgb565 * 2; - dst_y += dst_stride_y * 2; - dst_u += dst_stride_u; - dst_v += dst_stride_v; - } - if (height & 1) { -#if (defined(HAS_RGB565TOYROW_NEON)) -#else - RGB565ToARGBRow(src_rgb565, row, width); - ARGBToUVRow(row, 0, dst_u, dst_v, width); - ARGBToYRow(row, dst_y, width); -#endif - } -#if !(defined(HAS_RGB565TOYROW_NEON)) - free_aligned_buffer_64(row); -#endif - } - return 0; -} diff --git a/pkg/encoder/yuv/libyuv/convert.h b/pkg/encoder/yuv/libyuv/convert.h deleted file mode 100644 index 9a81c509c..000000000 --- a/pkg/encoder/yuv/libyuv/convert.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_CONVERT_H_ -#define INCLUDE_LIBYUV_CONVERT_H_ - -#include "rotate.h" // For enum RotationMode. - -// Copy I420 to I420. -#define I420ToI420 I420Copy -LIBYUV_API -int I420Copy(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_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); - -// ARGB little endian (bgra in memory) to I420. -LIBYUV_API -int ARGBToI420(const uint8_t *src_argb, - int src_stride_argb, - 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); - -// ABGR little endian (rgba in memory) to I420. -LIBYUV_API -int ABGRToI420(const uint8_t *src_abgr, - int src_stride_abgr, - 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); - -// RGB16 (RGBP fourcc) little endian to I420. -LIBYUV_API -int RGB565ToI420(const uint8_t *src_rgb565, - int src_stride_rgb565, - 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); - -// Convert camera sample to I420 with cropping, rotation and vertical flip. -// "src_size" is needed to parse MJPG. -// "dst_stride_y" number of bytes in a row of the dst_y plane. -// Normally this would be the same as dst_width, with recommended alignment -// to 16 bytes for better efficiency. -// If rotation of 90 or 270 is used, stride is affected. The caller should -// allocate the I420 buffer according to rotation. -// "dst_stride_u" number of bytes in a row of the dst_u plane. -// Normally this would be the same as (dst_width + 1) / 2, with -// recommended alignment to 16 bytes for better efficiency. -// If rotation of 90 or 270 is used, stride is affected. -// "crop_x" and "crop_y" are starting position for cropping. -// To center, crop_x = (src_width - dst_width) / 2 -// crop_y = (src_height - dst_height) / 2 -// "src_width" / "src_height" is size of src_frame in pixels. -// "src_height" can be negative indicating a vertically flipped image source. -// "crop_width" / "crop_height" is the size to crop the src to. -// Must be less than or equal to src_width/src_height -// Cropping parameters are pre-rotation. -// "rotation" can be 0, 90, 180 or 270. -// "fourcc" is a fourcc. ie 'I420', 'YUY2' -// Returns 0 for successful; -1 for invalid parameter. Non-zero for failure. -LIBYUV_API -int ConvertToI420(const uint8_t *sample, - size_t sample_size, - 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 crop_x, - int crop_y, - int src_width, - int src_height, - int crop_width, - int crop_height, - enum RotationMode rotation, - uint32_t fourcc); - -#endif // INCLUDE_LIBYUV_CONVERT_H_ \ No newline at end of file diff --git a/pkg/encoder/yuv/libyuv/convert_argb.h b/pkg/encoder/yuv/libyuv/convert_argb.h deleted file mode 100644 index ac8e97169..000000000 --- a/pkg/encoder/yuv/libyuv/convert_argb.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2012 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. - */ - -#ifndef INCLUDE_LIBYUV_CONVERT_ARGB_H_ -#define INCLUDE_LIBYUV_CONVERT_ARGB_H_ - -#include "basic_types.h" - -// Conversion matrix for YVU to BGR -LIBYUV_API extern const struct YuvConstants kYvuI601Constants; // BT.601 -LIBYUV_API extern const struct YuvConstants kYvuJPEGConstants; // BT.601 full -LIBYUV_API extern const struct YuvConstants kYvuH709Constants; // BT.709 -LIBYUV_API extern const struct YuvConstants kYvuF709Constants; // BT.709 full -LIBYUV_API extern const struct YuvConstants kYvu2020Constants; // BT.2020 -LIBYUV_API extern const struct YuvConstants kYvuV2020Constants; // BT.2020 full - -#endif // INCLUDE_LIBYUV_CONVERT_ARGB_H_ diff --git a/pkg/encoder/yuv/libyuv/convert_to_i420.c b/pkg/encoder/yuv/libyuv/convert_to_i420.c deleted file mode 100644 index 848021427..000000000 --- a/pkg/encoder/yuv/libyuv/convert_to_i420.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 - -#include "convert.h" -#include "video_common.h" - -// 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 -// sample_size is measured in bytes and is the size of the frame. -// With MJPEG it is the compressed size of the frame. -LIBYUV_API -int ConvertToI420(const uint8_t *sample, - size_t sample_size, - 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 crop_x, - int crop_y, - int src_width, - int src_height, - int crop_width, - int crop_height, - enum RotationMode rotation, - uint32_t fourcc) { - uint32_t format = CanonicalFourCC(fourcc); - const uint8_t *src; - // TODO(nisse): Why allow crop_height < 0? - const int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height; - int r = 0; - LIBYUV_BOOL need_buf = - (rotation && format != FOURCC_I420 && format != FOURCC_NV12 && - format != FOURCC_NV21 && format != FOURCC_YV12) || - dst_y == sample; - uint8_t *tmp_y = dst_y; - uint8_t *tmp_u = dst_u; - uint8_t *tmp_v = dst_v; - int tmp_y_stride = dst_stride_y; - int tmp_u_stride = dst_stride_u; - int tmp_v_stride = dst_stride_v; - uint8_t *rotate_buffer = NULL; - const int inv_crop_height = - (src_height < 0) ? -abs_crop_height : abs_crop_height; - - if (!dst_y || !dst_u || !dst_v || !sample || src_width <= 0 || - crop_width <= 0 || src_height == 0 || crop_height == 0) { - return -1; - } - - // One pass rotation is available for some formats. For the rest, convert - // to I420 (with optional vertical flipping) into a temporary I420 buffer, - // and then rotate the I420 to the final destination buffer. - // For in-place conversion, if destination dst_y is same as source sample, - // also enable temporary buffer. - if (need_buf) { - int y_size = crop_width * abs_crop_height; - int uv_size = ((crop_width + 1) / 2) * ((abs_crop_height + 1) / 2); - rotate_buffer = (uint8_t *) malloc(y_size + uv_size * 2); /* NOLINT */ - if (!rotate_buffer) { - return 1; // Out of memory runtime error. - } - dst_y = rotate_buffer; - dst_u = dst_y + y_size; - dst_v = dst_u + uv_size; - dst_stride_y = crop_width; - dst_stride_u = dst_stride_v = ((crop_width + 1) / 2); - } - - switch (format) { - // Single plane formats - case FOURCC_RGBP: - src = sample + (src_width * crop_y + crop_x) * 2; - r = RGB565ToI420(src, src_width * 2, dst_y, dst_stride_y, dst_u, - dst_stride_u, dst_v, dst_stride_v, crop_width, - inv_crop_height); - break; - case FOURCC_ARGB: - src = sample + (src_width * crop_y + crop_x) * 4; - r = ARGBToI420(src, src_width * 4, dst_y, dst_stride_y, dst_u, - dst_stride_u, dst_v, dst_stride_v, crop_width, - inv_crop_height); - break; - case FOURCC_ABGR: - src = sample + (src_width * crop_y + crop_x) * 4; - r = ABGRToI420(src, src_width * 4, dst_y, dst_stride_y, dst_u, - dst_stride_u, dst_v, dst_stride_v, crop_width, - inv_crop_height); - break; - default: - r = -1; // unknown fourcc - return failure code. - } - - if (need_buf) { - if (!r) { - r = I420Rotate(dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, - dst_stride_v, tmp_y, tmp_y_stride, tmp_u, tmp_u_stride, - tmp_v, tmp_v_stride, crop_width, abs_crop_height, - rotation); - } - free(rotate_buffer); - } - - return r; -} diff --git a/pkg/encoder/yuv/libyuv/cpu_id.c b/pkg/encoder/yuv/libyuv/cpu_id.c deleted file mode 100644 index 166057de5..000000000 --- a/pkg/encoder/yuv/libyuv/cpu_id.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 "cpu_id.h" - -#if !defined(__pnacl__) && !defined(__CLR_VER) && \ - !defined(__native_client__) && (defined(_M_IX86) || defined(_M_X64)) && \ - defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) -#include // For _xgetbv() -#endif - -// For ArmCpuCaps() but unittested on all platforms -#include // For fopen() -#include - -// For functions that use the stack and have runtime checks for overflow, -// use SAFEBUFFERS to avoid additional check. -#define SAFEBUFFERS - -// cpu_info_ variable for SIMD instruction sets detected. -LIBYUV_API int cpu_info_ = 0; - -// Low level cpuid for X86. -#if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ - defined(__x86_64__)) && \ - !defined(__pnacl__) && !defined(__CLR_VER) -LIBYUV_API -void CpuId(int info_eax, int info_ecx, int *cpu_info) { -#if defined(_MSC_VER) - // GCC version uses inline x86 assembly. -#else // defined(_MSC_VER) - int info_ebx, info_edx; - asm volatile( -#if defined(__i386__) && defined(__PIC__) - // Preserve ebx for fpic 32 bit. - "mov %%ebx, %%edi \n" - "cpuid \n" - "xchg %%edi, %%ebx \n" - : "=D"(info_ebx), -#else - "cpuid \n" - : "=b"(info_ebx), -#endif // defined( __i386__) && defined(__PIC__) - "+a"(info_eax), "+c"(info_ecx), "=d"(info_edx)); - cpu_info[0] = info_eax; - cpu_info[1] = info_ebx; - cpu_info[2] = info_ecx; - cpu_info[3] = info_edx; -#endif // defined(_MSC_VER) -} - -#else // (defined(_M_IX86) || defined(_M_X64) ... -LIBYUV_API -void CpuId(int eax, int ecx, int* cpu_info) { - (void)eax; - (void)ecx; - cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; -} -#endif - -// For VS2010 and earlier emit can be used: -// _asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0 // For VS2010 and earlier. -// __asm { -// xor ecx, ecx // xcr 0 -// xgetbv -// mov xcr0, eax -// } -// For VS2013 and earlier 32 bit, the _xgetbv(0) optimizer produces bad code. -// https://code.google.com/p/libyuv/issues/detail?id=529 -#if defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER < 1900) -#pragma optimize("g", off) -#endif -#if (defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ - defined(__x86_64__)) && \ - !defined(__pnacl__) && !defined(__CLR_VER) && !defined(__native_client__) - -// X86 CPUs have xgetbv to detect OS saves high parts of ymm registers. -static int GetXCR0() { - int xcr0 = 0; -#if defined(__i386__) || defined(__x86_64__) - asm(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr0) : "c"(0) : "%edx"); -#endif // defined(__i386__) || defined(__x86_64__) - return xcr0; -} - -#else -// xgetbv unavailable to query for OSSave support. Return 0. -#define GetXCR0() 0 -#endif // defined(_M_IX86) || defined(_M_X64) .. -// Return optimization to previous setting. -#if defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER < 1900) -#pragma optimize("g", on) -#endif - -// Based on libvpx arm_cpudetect.c -// For Arm, but public to allow testing on any CPU -LIBYUV_API SAFEBUFFERS int ArmCpuCaps(const char *cpuinfo_name) { - char cpuinfo_line[512]; - FILE *f = fopen(cpuinfo_name, "re"); - if (!f) { - // Assume Neon if /proc/cpuinfo is unavailable. - // This will occur for Chrome sandbox for Pepper or Render process. - return kCpuHasNEON; - } - memset(cpuinfo_line, 0, sizeof(cpuinfo_line)); - while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f)) { - if (memcmp(cpuinfo_line, "Features", 8) == 0) { - char *p = strstr(cpuinfo_line, " neon"); - if (p && (p[5] == ' ' || p[5] == '\n')) { - fclose(f); - return kCpuHasNEON; - } - // aarch64 uses asimd for Neon. - p = strstr(cpuinfo_line, " asimd"); - if (p) { - fclose(f); - return kCpuHasNEON; - } - } - } - fclose(f); - return 0; -} - -static SAFEBUFFERS int GetCpuFlags(void) { - int cpu_info = 0; -#if !defined(__pnacl__) && !defined(__CLR_VER) && \ - (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ - defined(_M_IX86)) - int cpu_info0[4] = {0, 0, 0, 0}; - int cpu_info1[4] = {0, 0, 0, 0}; - int cpu_info7[4] = {0, 0, 0, 0}; - CpuId(0, 0, cpu_info0); - CpuId(1, 0, cpu_info1); - if (cpu_info0[0] >= 7) { - CpuId(7, 0, cpu_info7); - } - cpu_info = kCpuHasX86 | ((cpu_info1[3] & 0x04000000) ? kCpuHasSSE2 : 0) | - ((cpu_info1[2] & 0x00000200) ? kCpuHasSSSE3 : 0) | - ((cpu_info1[2] & 0x00080000) ? kCpuHasSSE41 : 0) | - ((cpu_info1[2] & 0x00100000) ? kCpuHasSSE42 : 0) | - ((cpu_info7[1] & 0x00000200) ? kCpuHasERMS : 0); - - // AVX requires OS saves YMM registers. - if (((cpu_info1[2] & 0x1c000000) == 0x1c000000) && // AVX and OSXSave - ((GetXCR0() & 6) == 6)) { // Test OS saves YMM registers - cpu_info |= kCpuHasAVX | ((cpu_info7[1] & 0x00000020) ? kCpuHasAVX2 : 0) | - ((cpu_info1[2] & 0x00001000) ? kCpuHasFMA3 : 0) | - ((cpu_info1[2] & 0x20000000) ? kCpuHasF16C : 0); - - // Detect AVX512bw - if ((GetXCR0() & 0xe0) == 0xe0) { - cpu_info |= (cpu_info7[1] & 0x40000000) ? kCpuHasAVX512BW : 0; - cpu_info |= (cpu_info7[1] & 0x80000000) ? kCpuHasAVX512VL : 0; - cpu_info |= (cpu_info7[2] & 0x00000002) ? kCpuHasAVX512VBMI : 0; - cpu_info |= (cpu_info7[2] & 0x00000040) ? kCpuHasAVX512VBMI2 : 0; - cpu_info |= (cpu_info7[2] & 0x00000800) ? kCpuHasAVX512VNNI : 0; - cpu_info |= (cpu_info7[2] & 0x00001000) ? kCpuHasAVX512VBITALG : 0; - cpu_info |= (cpu_info7[2] & 0x00004000) ? kCpuHasAVX512VPOPCNTDQ : 0; - cpu_info |= (cpu_info7[2] & 0x00000100) ? kCpuHasGFNI : 0; - } - } -#endif -#if defined(__arm__) || defined(__aarch64__) - // gcc -mfpu=neon defines __ARM_NEON__ - // __ARM_NEON__ generates code that requires Neon. NaCL also requires Neon. - // For Linux, /proc/cpuinfo can be tested but without that assume Neon. -#if defined(__ARM_NEON__) || defined(__native_client__) || !defined(__linux__) - cpu_info = kCpuHasNEON; - // For aarch64(arm64), /proc/cpuinfo's feature is not complete, e.g. no neon - // flag in it. - // So for aarch64, neon enabling is hard coded here. -#endif -#if defined(__aarch64__) - cpu_info = kCpuHasNEON; -#else - // Linux arm parse text file for neon detect. - cpu_info = ArmCpuCaps("/proc/cpuinfo"); -#endif - cpu_info |= kCpuHasARM; -#endif // __arm__ - cpu_info |= kCpuInitialized; - return cpu_info; -} - -// Note that use of this function is not thread safe. -LIBYUV_API -int MaskCpuFlags(int enable_flags) { - int cpu_info = GetCpuFlags() & enable_flags; - SetCpuFlags(cpu_info); - return cpu_info; -} - -LIBYUV_API -int InitCpuFlags(void) { - return MaskCpuFlags(-1); -} diff --git a/pkg/encoder/yuv/libyuv/cpu_id.h b/pkg/encoder/yuv/libyuv/cpu_id.h deleted file mode 100644 index bf50b9cd1..000000000 --- a/pkg/encoder/yuv/libyuv/cpu_id.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_CPU_ID_H_ -#define INCLUDE_LIBYUV_CPU_ID_H_ - -#include "basic_types.h" - -// Internal flag to indicate cpuid requires initialization. -static const int kCpuInitialized = 0x1; - -// These flags are only valid on ARM processors. -static const int kCpuHasARM = 0x2; -static const int kCpuHasNEON = 0x4; -// 0x8 reserved for future ARM flag. - -// These flags are only valid on x86 processors. -static const int kCpuHasX86 = 0x10; -static const int kCpuHasSSE2 = 0x20; -static const int kCpuHasSSSE3 = 0x40; -static const int kCpuHasSSE41 = 0x80; -static const int kCpuHasSSE42 = 0x100; // unused at this time. -static const int kCpuHasAVX = 0x200; -static const int kCpuHasAVX2 = 0x400; -static const int kCpuHasERMS = 0x800; -static const int kCpuHasFMA3 = 0x1000; -static const int kCpuHasF16C = 0x2000; -static const int kCpuHasGFNI = 0x4000; -static const int kCpuHasAVX512BW = 0x8000; -static const int kCpuHasAVX512VL = 0x10000; -static const int kCpuHasAVX512VNNI = 0x20000; -static const int kCpuHasAVX512VBMI = 0x40000; -static const int kCpuHasAVX512VBMI2 = 0x80000; -static const int kCpuHasAVX512VBITALG = 0x100000; -static const int kCpuHasAVX512VPOPCNTDQ = 0x200000; - -// Optional init function. TestCpuFlag does an auto-init. -// Returns cpu_info flags. -LIBYUV_API -int InitCpuFlags(void); - -// Detect CPU has SSE2 etc. -// Test_flag parameter should be one of kCpuHas constants above. -// Returns non-zero if instruction set is detected -static __inline int TestCpuFlag(int test_flag) { - LIBYUV_API extern int cpu_info_; -#ifdef __ATOMIC_RELAXED - int cpu_info = __atomic_load_n(&cpu_info_, __ATOMIC_RELAXED); -#else - int cpu_info = cpu_info_; -#endif - return (!cpu_info ? InitCpuFlags() : cpu_info) & test_flag; -} - -// Internal function for parsing /proc/cpuinfo. -LIBYUV_API -int ArmCpuCaps(const char *cpuinfo_name); - -// For testing, allow CPU flags to be disabled. -// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. -// MaskCpuFlags(-1) to enable all cpu specific optimizations. -// MaskCpuFlags(1) to disable all cpu specific optimizations. -// MaskCpuFlags(0) to reset state so next call will auto init. -// Returns cpu_info flags. -LIBYUV_API -int MaskCpuFlags(int enable_flags); - -// Sets the CPU flags to |cpu_flags|, bypassing the detection code. |cpu_flags| -// should be a valid combination of the kCpuHas constants above and include -// kCpuInitialized. Use this method when running in a sandboxed process where -// the detection code might fail (as it might access /proc/cpuinfo). In such -// cases the cpu_info can be obtained from a non sandboxed process by calling -// InitCpuFlags() and passed to the sandboxed process (via command line -// parameters, IPC...) which can then call this method to initialize the CPU -// flags. -// Notes: -// - when specifying 0 for |cpu_flags|, the auto initialization is enabled -// again. -// - enabling CPU features that are not supported by the CPU will result in -// undefined behavior. -// TODO(fbarchard): consider writing a helper function that translates from -// other library CPU info to libyuv CPU info and add a .md doc that explains -// CPU detection. -static __inline void SetCpuFlags(int cpu_flags) { - LIBYUV_API extern int cpu_info_; -#ifdef __ATOMIC_RELAXED - __atomic_store_n(&cpu_info_, cpu_flags, __ATOMIC_RELAXED); -#else - cpu_info_ = cpu_flags; -#endif -} - -// Low level cpuid for X86. Returns zeros on other CPUs. -// eax is the info type that you want. -// ecx is typically the cpu number, and should normally be zero. -LIBYUV_API -void CpuId(int info_eax, int info_ecx, int *cpu_info); - -#endif // INCLUDE_LIBYUV_CPU_ID_H_ \ No newline at end of file diff --git a/pkg/encoder/yuv/libyuv/libyuv.go b/pkg/encoder/yuv/libyuv/libyuv.go index 98d4276ff..8bde0ad89 100644 --- a/pkg/encoder/yuv/libyuv/libyuv.go +++ b/pkg/encoder/yuv/libyuv/libyuv.go @@ -1,18 +1,43 @@ -//go:build !darwin && !no_libyuv - +// Package libyuv contains the wrapper for: https://chromium.googlesource.com/libyuv/libyuv. +// Libs are downloaded from: https://packages.macports.org/libyuv/. package libyuv -// see: https://chromium.googlesource.com/libyuv/libyuv - /* -#cgo CFLAGS: -Wall -#cgo LDFLAGS: -lyuv +#cgo !darwin LDFLAGS: -lyuv + +#cgo darwin CFLAGS: -DINCLUDE_LIBYUV_VERSION_H_ +#cgo darwin LDFLAGS: -L${SRCDIR} -lstdc++ +#cgo darwin,amd64 LDFLAGS: -lyuv_darwin_x86_64 -ljpeg -lstdc++ +#cgo darwin,arm64 LDFLAGS: -lyuv_darwin_arm64 -ljpeg -lstdc++ -#include +#include // for uintptr_t and C99 types + +#if !defined(LIBYUV_API) +#define LIBYUV_API +#endif // LIBYUV_API + +#ifndef INCLUDE_LIBYUV_VERSION_H_ #include "libyuv/version.h" -#include "libyuv/video_common.h" +#else +#define LIBYUV_VERSION 1874 // darwin static libs version +#endif // INCLUDE_LIBYUV_VERSION_H_ + +#ifdef __cplusplus +namespace libyuv { +extern "C" { +#endif + +#define FOURCC(a, b, c, d) \ + (((uint32_t)(a)) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) + +enum FourCC { + FOURCC_I420 = FOURCC('I', '4', '2', '0'), + FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), + FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'), + FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE. + FOURCC_ANY = -1, +}; -// typedef enum RotationMode { kRotate0 = 0, // No rotation. kRotate90 = 90, // Rotate 90 degrees clockwise. @@ -20,7 +45,6 @@ typedef enum RotationMode { kRotate270 = 270, // Rotate 270 degrees clockwise. } RotationModeEnum; -// LIBYUV_API int ConvertToI420(const uint8_t* sample, size_t sample_size, @@ -65,6 +89,11 @@ int I420Scale(const uint8_t *src_y, int dst_width, int dst_height, enum FilterMode filtering); + +#ifdef __cplusplus +} // extern "C" +} // namespace libyuv +#endif */ import "C" import "fmt" diff --git a/pkg/encoder/yuv/libyuv/libyuv2.go b/pkg/encoder/yuv/libyuv/libyuv2.go deleted file mode 100644 index f4f6a68b5..000000000 --- a/pkg/encoder/yuv/libyuv/libyuv2.go +++ /dev/null @@ -1,89 +0,0 @@ -//go:build darwin || no_libyuv - -package libyuv - -/* -#cgo CFLAGS: -Wall - -#include "basic_types.h" -#include "version.h" -#include "video_common.h" -#include "rotate.h" -#include "scale.h" -#include "convert.h" - -*/ -import "C" -import "fmt" - -const FourccRgbp uint32 = C.FOURCC_RGBP -const FourccArgb uint32 = C.FOURCC_ARGB -const FourccAbgr uint32 = C.FOURCC_ABGR - -func Y420(src []byte, dst []byte, _, h, stride int, dw, dh int, rot uint, pix uint32, cx, cy int) { - cw := (dw + 1) / 2 - ch := (dh + 1) / 2 - i0 := dw * dh - i1 := i0 + cw*ch - yStride := dw - cStride := cw - - C.ConvertToI420( - (*C.uchar)(&src[0]), - C.size_t(0), - (*C.uchar)(&dst[0]), - C.int(yStride), - (*C.uchar)(&dst[i0]), - C.int(cStride), - (*C.uchar)(&dst[i1]), - C.int(cStride), - C.int(0), - C.int(0), - C.int(stride), - C.int(h), - C.int(cx), - C.int(cy), - C.enum_RotationMode(rot), - C.uint32_t(pix)) -} - -func Y420Scale(src []byte, dst []byte, w, h int, dw, dh int) { - srcWidthUV, dstWidthUV := (w+1)>>1, (dw+1)>>1 - srcHeightUV, dstHeightUV := (h+1)>>1, (dh+1)>>1 - - srcYPlaneSize, dstYPlaneSize := w*h, dw*dh - srcUVPlaneSize, dstUVPlaneSize := srcWidthUV*srcHeightUV, dstWidthUV*dstHeightUV - - srcStrideY, dstStrideY := w, dw - srcStrideU, dstStrideU := srcWidthUV, dstWidthUV - srcStrideV, dstStrideV := srcWidthUV, dstWidthUV - - srcY := (*C.uchar)(&src[0]) - srcU := (*C.uchar)(&src[srcYPlaneSize]) - srcV := (*C.uchar)(&src[srcYPlaneSize+srcUVPlaneSize]) - - dstY := (*C.uchar)(&dst[0]) - dstU := (*C.uchar)(&dst[dstYPlaneSize]) - dstV := (*C.uchar)(&dst[dstYPlaneSize+dstUVPlaneSize]) - - C.I420Scale( - srcY, - C.int(srcStrideY), - srcU, - C.int(srcStrideU), - srcV, - C.int(srcStrideV), - C.int(w), - C.int(h), - dstY, - C.int(dstStrideY), - dstU, - C.int(dstStrideU), - dstV, - C.int(dstStrideV), - C.int(dw), - C.int(dh), - C.enum_FilterMode(C.kFilterNone)) -} - -func Version() string { return fmt.Sprintf("%v mod", int(C.LIBYUV_VERSION)) } diff --git a/pkg/encoder/yuv/libyuv/libyuv_darwin_arm64.a b/pkg/encoder/yuv/libyuv/libyuv_darwin_arm64.a new file mode 100644 index 0000000000000000000000000000000000000000..f399a41c7b388e33a68b3ababd47a275f6a7c6d1 GIT binary patch literal 486312 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

?oAcRr$*J_4zhM|3Z-{t>-_ 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 literal 0 HcmV?d00001 diff --git a/pkg/encoder/yuv/libyuv/libyuv_darwin_x86_64.a b/pkg/encoder/yuv/libyuv/libyuv_darwin_x86_64.a new file mode 100644 index 0000000000000000000000000000000000000000..63cd5c74a4cd168a60f56ff6892a911cedcc82f4 GIT binary patch literal 669112 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%0DkwMRw!ai=t9j2r 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 _%VHFx_%>r))-(QDmB#bsOY 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 8) { - TransposeWx8(src, src_stride, dst, dst_stride, width); - src += 8 * src_stride; // Go down 8 rows. - dst += 8; // Move over 8 columns. - i -= 8; - } - - if (i > 0) { - TransposeWxH_C(src, src_stride, dst, dst_stride, width, i); - } -} - -LIBYUV_API -void RotatePlane90(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height) { - // Rotate by 90 is a transpose with the source read - // from bottom to top. So set the source pointer to the end - // of the buffer and flip the sign of the source stride. - src += src_stride * (height - 1); - src_stride = -src_stride; - TransposePlane(src, src_stride, dst, dst_stride, width, height); -} - -LIBYUV_API -void RotatePlane270(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height) { - // Rotate by 270 is a transpose with the destination written - // from bottom to top. So set the destination pointer to the end - // of the buffer and flip the sign of the destination stride. - dst += dst_stride * (width - 1); - dst_stride = -dst_stride; - TransposePlane(src, src_stride, dst, dst_stride, width, height); -} - -LIBYUV_API -void RotatePlane180(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height) { - // Swap top and bottom row and mirror the content. Uses a temporary row. - align_buffer_64(row, width); - const uint8_t *src_bot = src + src_stride * (height - 1); - uint8_t *dst_bot = dst + dst_stride * (height - 1); - int half_height = (height + 1) >> 1; - int y; - void (*MirrorRow)(const uint8_t *src, uint8_t *dst, int width) = MirrorRow_C; - void (*CopyRow)(const uint8_t *src, uint8_t *dst, int width) = CopyRow_C; -#if defined(HAS_MIRRORROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - MirrorRow = MirrorRow_Any_SSSE3; - if (IS_ALIGNED(width, 16)) { - MirrorRow = MirrorRow_SSSE3; - } - } -#endif -#if defined(HAS_MIRRORROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - MirrorRow = MirrorRow_Any_AVX2; - if (IS_ALIGNED(width, 32)) { - MirrorRow = MirrorRow_AVX2; - } - } -#endif -#if defined(HAS_COPYROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2)) { - CopyRow = IS_ALIGNED(width, 32) ? CopyRow_SSE2 : CopyRow_Any_SSE2; - } -#endif -#if defined(HAS_COPYROW_AVX) - if (TestCpuFlag(kCpuHasAVX)) { - CopyRow = IS_ALIGNED(width, 64) ? CopyRow_AVX : CopyRow_Any_AVX; - } -#endif -#if defined(HAS_COPYROW_ERMS) - if (TestCpuFlag(kCpuHasERMS)) { - CopyRow = CopyRow_ERMS; - } -#endif -#if defined(HAS_COPYROW_NEON) -#endif - // Odd height will harmlessly mirror the middle row twice. - for (y = 0; y < half_height; ++y) { - CopyRow(src, row, width); // Copy top row into buffer - MirrorRow(src_bot, dst, width); // Mirror bottom row into top row - MirrorRow(row, dst_bot, width); // Mirror buffer into bottom row - src += src_stride; - dst += dst_stride; - src_bot -= src_stride; - dst_bot -= dst_stride; - } - free_aligned_buffer_64(row); -} - -LIBYUV_API -int I420Rotate(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_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, - enum RotationMode mode) { - int halfwidth = (width + 1) >> 1; - int halfheight = (height + 1) >> 1; - if ((!src_y && dst_y) || !src_u || !src_v || width <= 0 || height == 0 || - !dst_y || !dst_u || !dst_v) { - return -1; - } - - // Negative height means invert the image. - if (height < 0) { - height = -height; - halfheight = (height + 1) >> 1; - src_y = src_y + (height - 1) * src_stride_y; - src_u = src_u + (halfheight - 1) * src_stride_u; - src_v = src_v + (halfheight - 1) * src_stride_v; - src_stride_y = -src_stride_y; - src_stride_u = -src_stride_u; - src_stride_v = -src_stride_v; - } - - switch (mode) { - case kRotate0: - // copy frame - return I420Copy(src_y, src_stride_y, src_u, src_stride_u, src_v, - src_stride_v, dst_y, dst_stride_y, dst_u, dst_stride_u, - dst_v, dst_stride_v, width, height); - case kRotate90: - RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width, height); - RotatePlane90(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, - halfheight); - RotatePlane90(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, - halfheight); - return 0; - case kRotate270: - RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width, height); - RotatePlane270(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, - halfheight); - RotatePlane270(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, - halfheight); - return 0; - case kRotate180: - RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width, height); - RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, - halfheight); - RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, - halfheight); - return 0; - default: - break; - } - return -1; -} diff --git a/pkg/encoder/yuv/libyuv/rotate.h b/pkg/encoder/yuv/libyuv/rotate.h deleted file mode 100644 index 59b9ec3cb..000000000 --- a/pkg/encoder/yuv/libyuv/rotate.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_ROTATE_H_ -#define INCLUDE_LIBYUV_ROTATE_H_ - -#include "basic_types.h" - -// Supported rotation. -typedef enum RotationMode { - kRotate0 = 0, // No rotation. - kRotate90 = 90, // Rotate 90 degrees clockwise. - kRotate180 = 180, // Rotate 180 degrees. - kRotate270 = 270, // Rotate 270 degrees clockwise. -} RotationModeEnum; - -// Rotate I420 frame. -LIBYUV_API -int I420Rotate(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_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, - enum RotationMode mode); - -// Rotate planes by 90, 180, 270. Deprecated. -LIBYUV_API -void RotatePlane90(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height); - -LIBYUV_API -void RotatePlane180(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height); - -LIBYUV_API -void RotatePlane270(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height); - -// The 90 and 270 functions are based on transposes. -// Doing a transpose with reversing the read/write -// order will result in a rotation by +- 90 degrees. -// Deprecated. -LIBYUV_API -void TransposePlane(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height); - -#endif // INCLUDE_LIBYUV_ROTATE_H_ diff --git a/pkg/encoder/yuv/libyuv/rotate_any.c b/pkg/encoder/yuv/libyuv/rotate_any.c deleted file mode 100644 index 9af8c04ab..000000000 --- a/pkg/encoder/yuv/libyuv/rotate_any.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2015 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 "rotate_row.h" - -#define TANY(NAMEANY, TPOS_SIMD, MASK) \ - void NAMEANY(const uint8_t* src, int src_stride, uint8_t* dst, \ - int dst_stride, int width) { \ - int r = width & MASK; \ - int n = width - r; \ - if (n > 0) { \ - TPOS_SIMD(src, src_stride, dst, dst_stride, n); \ - } \ - TransposeWx8_C(src + n, src_stride, dst + n * dst_stride, dst_stride, r); \ - } - -#ifdef HAS_TRANSPOSEWX8_SSSE3 - -TANY(TransposeWx8_Any_SSSE3, TransposeWx8_SSSE3, 7) - -#endif -#ifdef HAS_TRANSPOSEWX8_FAST_SSSE3 - -TANY(TransposeWx8_Fast_Any_SSSE3, TransposeWx8_Fast_SSSE3, 15) - -#endif -#undef TANY - -#define TUVANY(NAMEANY, TPOS_SIMD, MASK) \ - void NAMEANY(const uint8_t* src, int src_stride, uint8_t* dst_a, \ - int dst_stride_a, uint8_t* dst_b, int dst_stride_b, \ - int width) { \ - int r = width & MASK; \ - int n = width - r; \ - if (n > 0) { \ - TPOS_SIMD(src, src_stride, dst_a, dst_stride_a, dst_b, dst_stride_b, n); \ - } \ - TransposeUVWx8_C(src + n * 2, src_stride, dst_a + n * dst_stride_a, \ - dst_stride_a, dst_b + n * dst_stride_b, dst_stride_b, r); \ - } - -#ifdef HAS_TRANSPOSEUVWX8_SSE2 - -TUVANY(TransposeUVWx8_Any_SSE2, TransposeUVWx8_SSE2, 7) - -#endif -#undef TUVANY diff --git a/pkg/encoder/yuv/libyuv/rotate_common.c b/pkg/encoder/yuv/libyuv/rotate_common.c deleted file mode 100644 index 20c1481a7..000000000 --- a/pkg/encoder/yuv/libyuv/rotate_common.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 "rotate_row.h" - -void TransposeWx8_C(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width) { - int i; - for (i = 0; i < width; ++i) { - dst[0] = src[0 * src_stride]; - dst[1] = src[1 * src_stride]; - dst[2] = src[2 * src_stride]; - dst[3] = src[3 * src_stride]; - dst[4] = src[4 * src_stride]; - dst[5] = src[5 * src_stride]; - dst[6] = src[6 * src_stride]; - dst[7] = src[7 * src_stride]; - ++src; - dst += dst_stride; - } -} - -void TransposeUVWx8_C(const uint8_t *src, - int src_stride, - uint8_t *dst_a, - int dst_stride_a, - uint8_t *dst_b, - int dst_stride_b, - int width) { - int i; - for (i = 0; i < width; ++i) { - dst_a[0] = src[0 * src_stride + 0]; - dst_b[0] = src[0 * src_stride + 1]; - dst_a[1] = src[1 * src_stride + 0]; - dst_b[1] = src[1 * src_stride + 1]; - dst_a[2] = src[2 * src_stride + 0]; - dst_b[2] = src[2 * src_stride + 1]; - dst_a[3] = src[3 * src_stride + 0]; - dst_b[3] = src[3 * src_stride + 1]; - dst_a[4] = src[4 * src_stride + 0]; - dst_b[4] = src[4 * src_stride + 1]; - dst_a[5] = src[5 * src_stride + 0]; - dst_b[5] = src[5 * src_stride + 1]; - dst_a[6] = src[6 * src_stride + 0]; - dst_b[6] = src[6 * src_stride + 1]; - dst_a[7] = src[7 * src_stride + 0]; - dst_b[7] = src[7 * src_stride + 1]; - src += 2; - dst_a += dst_stride_a; - dst_b += dst_stride_b; - } -} - -void TransposeWxH_C(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height) { - int i; - for (i = 0; i < width; ++i) { - int j; - for (j = 0; j < height; ++j) { - dst[i * dst_stride + j] = src[j * src_stride + i]; - } - } -} diff --git a/pkg/encoder/yuv/libyuv/rotate_gcc.c b/pkg/encoder/yuv/libyuv/rotate_gcc.c deleted file mode 100644 index 54fdafff8..000000000 --- a/pkg/encoder/yuv/libyuv/rotate_gcc.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright 2015 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 "rotate_row.h" -#include "row.h" - -// This module is for GCC x86 and x64. -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -// Transpose 8x8. 32 or 64 bit, but not NaCL for 64 bit. -#if defined(HAS_TRANSPOSEWX8_SSSE3) - -void TransposeWx8_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width) { - asm volatile( - // Read in the data from the source pointer. - // First round of bit swap. - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" - "movq (%0,%3),%%xmm1 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "movq (%0),%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "palignr $0x8,%%xmm1,%%xmm1 \n" - "movq (%0,%3),%%xmm3 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "movdqa %%xmm2,%%xmm3 \n" - "movq (%0),%%xmm4 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "movq (%0,%3),%%xmm5 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "movq (%0),%%xmm6 \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq (%0,%3),%%xmm7 \n" - "lea (%0,%3,2),%0 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "neg %3 \n" - "movdqa %%xmm6,%%xmm7 \n" - "lea 0x8(%0,%3,8),%0 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "neg %3 \n" - // Second round of bit swap. - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "palignr $0x8,%%xmm2,%%xmm2 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm4,%%xmm6 \n" - "movdqa %%xmm5,%%xmm7 \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - // Third round of bit swap. - // Write to the destination pointer. - "punpckldq %%xmm4,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "movdqa %%xmm0,%%xmm4 \n" - "palignr $0x8,%%xmm4,%%xmm4 \n" - "movq %%xmm4,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movdqa %%xmm2,%%xmm6 \n" - "movq %%xmm2,(%1) \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movq %%xmm6,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm1,%%xmm5 \n" - "movq %%xmm1,(%1) \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq %%xmm5,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movq %%xmm3,(%1) \n" - "movdqa %%xmm3,%%xmm7 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "sub $0x8,%2 \n" - "movq %%xmm7,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // defined(HAS_TRANSPOSEWX8_SSSE3) - -// Transpose 16x8. 64 bit -#if defined(HAS_TRANSPOSEWX8_FAST_SSSE3) - -void TransposeWx8_Fast_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width) { - asm volatile( - // Read in the data from the source pointer. - // First round of bit swap. - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu (%0,%3),%%xmm1 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm0,%%xmm8 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm8 \n" - "movdqu (%0),%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm8,%%xmm9 \n" - "palignr $0x8,%%xmm1,%%xmm1 \n" - "palignr $0x8,%%xmm9,%%xmm9 \n" - "movdqu (%0,%3),%%xmm3 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm2,%%xmm10 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "punpckhbw %%xmm3,%%xmm10 \n" - "movdqa %%xmm2,%%xmm3 \n" - "movdqa %%xmm10,%%xmm11 \n" - "movdqu (%0),%%xmm4 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "palignr $0x8,%%xmm11,%%xmm11 \n" - "movdqu (%0,%3),%%xmm5 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm4,%%xmm12 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "punpckhbw %%xmm5,%%xmm12 \n" - "movdqa %%xmm4,%%xmm5 \n" - "movdqa %%xmm12,%%xmm13 \n" - "movdqu (%0),%%xmm6 \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "palignr $0x8,%%xmm13,%%xmm13 \n" - "movdqu (%0,%3),%%xmm7 \n" - "lea (%0,%3,2),%0 \n" - "movdqa %%xmm6,%%xmm14 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "punpckhbw %%xmm7,%%xmm14 \n" - "neg %3 \n" - "movdqa %%xmm6,%%xmm7 \n" - "movdqa %%xmm14,%%xmm15 \n" - "lea 0x10(%0,%3,8),%0 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - "neg %3 \n" - // Second round of bit swap. - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "palignr $0x8,%%xmm2,%%xmm2 \n" - "palignr $0x8,%%xmm3,%%xmm3 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm4,%%xmm6 \n" - "movdqa %%xmm5,%%xmm7 \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "punpcklwd %%xmm10,%%xmm8 \n" - "punpcklwd %%xmm11,%%xmm9 \n" - "movdqa %%xmm8,%%xmm10 \n" - "movdqa %%xmm9,%%xmm11 \n" - "palignr $0x8,%%xmm10,%%xmm10 \n" - "palignr $0x8,%%xmm11,%%xmm11 \n" - "punpcklwd %%xmm14,%%xmm12 \n" - "punpcklwd %%xmm15,%%xmm13 \n" - "movdqa %%xmm12,%%xmm14 \n" - "movdqa %%xmm13,%%xmm15 \n" - "palignr $0x8,%%xmm14,%%xmm14 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - // Third round of bit swap. - // Write to the destination pointer. - "punpckldq %%xmm4,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "movdqa %%xmm0,%%xmm4 \n" - "palignr $0x8,%%xmm4,%%xmm4 \n" - "movq %%xmm4,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movdqa %%xmm2,%%xmm6 \n" - "movq %%xmm2,(%1) \n" - "palignr $0x8,%%xmm6,%%xmm6 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movq %%xmm6,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm1,%%xmm5 \n" - "movq %%xmm1,(%1) \n" - "palignr $0x8,%%xmm5,%%xmm5 \n" - "movq %%xmm5,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movq %%xmm3,(%1) \n" - "movdqa %%xmm3,%%xmm7 \n" - "palignr $0x8,%%xmm7,%%xmm7 \n" - "movq %%xmm7,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm12,%%xmm8 \n" - "movq %%xmm8,(%1) \n" - "movdqa %%xmm8,%%xmm12 \n" - "palignr $0x8,%%xmm12,%%xmm12 \n" - "movq %%xmm12,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm14,%%xmm10 \n" - "movdqa %%xmm10,%%xmm14 \n" - "movq %%xmm10,(%1) \n" - "palignr $0x8,%%xmm14,%%xmm14 \n" - "punpckldq %%xmm13,%%xmm9 \n" - "movq %%xmm14,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "movdqa %%xmm9,%%xmm13 \n" - "movq %%xmm9,(%1) \n" - "palignr $0x8,%%xmm13,%%xmm13 \n" - "movq %%xmm13,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "punpckldq %%xmm15,%%xmm11 \n" - "movq %%xmm11,(%1) \n" - "movdqa %%xmm11,%%xmm15 \n" - "palignr $0x8,%%xmm15,%%xmm15 \n" - "sub $0x10,%2 \n" - "movq %%xmm15,(%1,%4) \n" - "lea (%1,%4,2),%1 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", - "xmm15"); -} - -#endif // defined(HAS_TRANSPOSEWX8_FAST_SSSE3) - -// Transpose UV 8x8. 64 bit. -#if defined(HAS_TRANSPOSEUVWX8_SSE2) - -void TransposeUVWx8_SSE2(const uint8_t *src, - int src_stride, - uint8_t *dst_a, - int dst_stride_a, - uint8_t *dst_b, - int dst_stride_b, - int width) { - asm volatile( - // Read in the data from the source pointer. - // First round of bit swap. - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu (%0,%4),%%xmm1 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm0,%%xmm8 \n" - "punpcklbw %%xmm1,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm8 \n" - "movdqa %%xmm8,%%xmm1 \n" - "movdqu (%0),%%xmm2 \n" - "movdqu (%0,%4),%%xmm3 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm2,%%xmm8 \n" - "punpcklbw %%xmm3,%%xmm2 \n" - "punpckhbw %%xmm3,%%xmm8 \n" - "movdqa %%xmm8,%%xmm3 \n" - "movdqu (%0),%%xmm4 \n" - "movdqu (%0,%4),%%xmm5 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm4,%%xmm8 \n" - "punpcklbw %%xmm5,%%xmm4 \n" - "punpckhbw %%xmm5,%%xmm8 \n" - "movdqa %%xmm8,%%xmm5 \n" - "movdqu (%0),%%xmm6 \n" - "movdqu (%0,%4),%%xmm7 \n" - "lea (%0,%4,2),%0 \n" - "movdqa %%xmm6,%%xmm8 \n" - "punpcklbw %%xmm7,%%xmm6 \n" - "neg %4 \n" - "lea 0x10(%0,%4,8),%0 \n" - "punpckhbw %%xmm7,%%xmm8 \n" - "movdqa %%xmm8,%%xmm7 \n" - "neg %4 \n" - // Second round of bit swap. - "movdqa %%xmm0,%%xmm8 \n" - "movdqa %%xmm1,%%xmm9 \n" - "punpckhwd %%xmm2,%%xmm8 \n" - "punpckhwd %%xmm3,%%xmm9 \n" - "punpcklwd %%xmm2,%%xmm0 \n" - "punpcklwd %%xmm3,%%xmm1 \n" - "movdqa %%xmm8,%%xmm2 \n" - "movdqa %%xmm9,%%xmm3 \n" - "movdqa %%xmm4,%%xmm8 \n" - "movdqa %%xmm5,%%xmm9 \n" - "punpckhwd %%xmm6,%%xmm8 \n" - "punpckhwd %%xmm7,%%xmm9 \n" - "punpcklwd %%xmm6,%%xmm4 \n" - "punpcklwd %%xmm7,%%xmm5 \n" - "movdqa %%xmm8,%%xmm6 \n" - "movdqa %%xmm9,%%xmm7 \n" - // Third round of bit swap. - // Write to the destination pointer. - "movdqa %%xmm0,%%xmm8 \n" - "punpckldq %%xmm4,%%xmm0 \n" - "movlpd %%xmm0,(%1) \n" // Write back U channel - "movhpd %%xmm0,(%2) \n" // Write back V channel - "punpckhdq %%xmm4,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm2,%%xmm8 \n" - "punpckldq %%xmm6,%%xmm2 \n" - "movlpd %%xmm2,(%1) \n" - "movhpd %%xmm2,(%2) \n" - "punpckhdq %%xmm6,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm1,%%xmm8 \n" - "punpckldq %%xmm5,%%xmm1 \n" - "movlpd %%xmm1,(%1) \n" - "movhpd %%xmm1,(%2) \n" - "punpckhdq %%xmm5,%%xmm8 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "movdqa %%xmm3,%%xmm8 \n" - "punpckldq %%xmm7,%%xmm3 \n" - "movlpd %%xmm3,(%1) \n" - "movhpd %%xmm3,(%2) \n" - "punpckhdq %%xmm7,%%xmm8 \n" - "sub $0x8,%3 \n" - "movlpd %%xmm8,(%1,%5) \n" - "lea (%1,%5,2),%1 \n" - "movhpd %%xmm8,(%2,%6) \n" - "lea (%2,%6,2),%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst_a), // %1 - "+r"(dst_b), // %2 - "+r"(width) // %3 - : "r"((intptr_t) (src_stride)), // %4 - "r"((intptr_t) (dst_stride_a)), // %5 - "r"((intptr_t) (dst_stride_b)) // %6 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7", "xmm8", "xmm9"); -} - -#endif // defined(HAS_TRANSPOSEUVWX8_SSE2) - -#endif // defined(__x86_64__) || defined(__i386__) diff --git a/pkg/encoder/yuv/libyuv/rotate_row.h b/pkg/encoder/yuv/libyuv/rotate_row.h deleted file mode 100644 index afdae49f0..000000000 --- a/pkg/encoder/yuv/libyuv/rotate_row.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef INCLUDE_LIBYUV_ROTATE_ROW_H_ -#define INCLUDE_LIBYUV_ROTATE_ROW_H_ - -#include "basic_types.h" - -#if defined(__pnacl__) || defined(__CLR_VER) || \ - (defined(__native_client__) && defined(__x86_64__)) || \ - (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) -#define LIBYUV_DISABLE_X86 -#endif -#if defined(__native_client__) -#define LIBYUV_DISABLE_NEON -#endif -// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_NEON) -#define LIBYUV_DISABLE_NEON -#endif -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_X86) -#define LIBYUV_DISABLE_X86 -#endif -#endif - -// The following are available for GCC 32 or 64 bit: -#if !defined(LIBYUV_DISABLE_X86) && (defined(__i386__) || defined(__x86_64__)) -#define HAS_TRANSPOSEWX8_SSSE3 -#endif - -// The following are available for 64 bit GCC: -#if !defined(LIBYUV_DISABLE_X86) && defined(__x86_64__) -#define HAS_TRANSPOSEWX8_FAST_SSSE3 -#define HAS_TRANSPOSEUVWX8_SSE2 -#endif - -void TransposeWxH_C(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width, - int height); - -void TransposeWx8_C(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width); - -void TransposeWx8_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width); - -void TransposeWx8_Fast_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width); - -void TransposeWx8_Any_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width); - -void TransposeWx8_Fast_Any_SSSE3(const uint8_t *src, - int src_stride, - uint8_t *dst, - int dst_stride, - int width); - -void TransposeUVWx8_C(const uint8_t *src, - int src_stride, - uint8_t *dst_a, - int dst_stride_a, - uint8_t *dst_b, - int dst_stride_b, - int width); - -void TransposeUVWx8_SSE2(const uint8_t *src, - int src_stride, - uint8_t *dst_a, - int dst_stride_a, - uint8_t *dst_b, - int dst_stride_b, - int width); - -void TransposeUVWx8_Any_SSE2(const uint8_t *src, - int src_stride, - uint8_t *dst_a, - int dst_stride_a, - uint8_t *dst_b, - int dst_stride_b, - int width); - -#endif // INCLUDE_LIBYUV_ROTATE_ROW_H_ diff --git a/pkg/encoder/yuv/libyuv/row.h b/pkg/encoder/yuv/libyuv/row.h deleted file mode 100644 index ca1c0c298..000000000 --- a/pkg/encoder/yuv/libyuv/row.h +++ /dev/null @@ -1,426 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_ROW_H_ -#define INCLUDE_LIBYUV_ROW_H_ - -#include // For NULL -#include // For malloc - -#include "basic_types.h" - -#if defined(__pnacl__) || defined(__CLR_VER) || \ - (defined(__native_client__) && defined(__x86_64__)) || \ - (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) -#define LIBYUV_DISABLE_X86 -#endif -#if defined(__native_client__) -#define LIBYUV_DISABLE_NEON -#endif -// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_NEON) -#define LIBYUV_DISABLE_NEON -#endif -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_X86) -#define LIBYUV_DISABLE_X86 -#endif -#endif - -// GCC >= 4.7.0 required for AVX2. -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) -#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) -#define GCC_HAS_AVX2 1 -#endif // GNUC >= 4.7 -#endif // __GNUC__ - -// The following are available on all x86 platforms: -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -// Conversions: -#define HAS_ABGRTOYROW_SSSE3 -#define HAS_ARGBTOYROW_SSSE3 -#define HAS_BGRATOYROW_SSSE3 -#define HAS_COPYROW_ERMS -#define HAS_COPYROW_SSE2 -#define HAS_INTERPOLATEROW_SSSE3 -#define HAS_MIRRORROW_SSSE3 -#define HAS_MIRRORSPLITUVROW_SSSE3 -#if !defined(LIBYUV_BIT_EXACT) -#define HAS_ABGRTOUVROW_SSSE3 -#define HAS_ARGBTOUVROW_SSSE3 -#endif - -// Effects: -#define HAS_ARGBGRAYROW_SSSE3 -#define HAS_ARGBMIRRORROW_SSE2 - -#endif - -// The following are available on all x86 platforms, but -// require VS2012, clang 3.4 or gcc 4.7. -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2) || \ - defined(GCC_HAS_AVX2)) -#define HAS_ARGBEXTRACTALPHAROW_AVX2 -#define HAS_ARGBMIRRORROW_AVX2 -#define HAS_ARGBTOYROW_AVX2 -#define HAS_COPYROW_AVX -#define HAS_INTERPOLATEROW_AVX2 -#define HAS_MIRRORROW_AVX2 -#if !defined(LIBYUV_BIT_EXACT) -#define HAS_ARGBTOUVROW_AVX2 -#endif - -#endif - -// The following are available for gcc/clang x86 platforms: -// TODO(fbarchard): Port to Visual C -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) -#define HAS_MIRRORUVROW_SSSE3 - -#endif - -// The following are available for AVX2 gcc/clang x86 platforms: -// TODO(fbarchard): Port to Visual C -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(__x86_64__) || defined(__i386__)) && \ - (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) -#define HAS_ABGRTOYROW_AVX2 -#define HAS_MIRRORUVROW_AVX2 -#if !defined(LIBYUV_BIT_EXACT) -#define HAS_ABGRTOUVROW_AVX2 -#endif - -#endif - -#if defined(_MSC_VER) && !defined(__CLR_VER) && !defined(__clang__) - #if defined(VISUALC_HAS_AVX2) -#define SIMD_ALIGNED(var) __declspec(align(32)) var -#else -#define SIMD_ALIGNED(var) __declspec(align(16)) var -#endif -#define LIBYUV_NOINLINE __declspec(noinline) -typedef __declspec(align(16)) int16_t vec16[8]; -typedef __declspec(align(16)) int32_t vec32[4]; -typedef __declspec(align(16)) float vecf32[4]; -typedef __declspec(align(16)) int8_t vec8[16]; -typedef __declspec(align(16)) uint16_t uvec16[8]; -typedef __declspec(align(16)) uint32_t uvec32[4]; -typedef __declspec(align(16)) uint8_t uvec8[16]; -typedef __declspec(align(32)) int16_t lvec16[16]; -typedef __declspec(align(32)) int32_t lvec32[8]; -typedef __declspec(align(32)) int8_t lvec8[32]; -typedef __declspec(align(32)) uint16_t ulvec16[16]; -typedef __declspec(align(32)) uint32_t ulvec32[8]; -typedef __declspec(align(32)) uint8_t ulvec8[32]; -#elif !defined(__pnacl__) && (defined(__GNUC__) || defined(__clang__)) -// Caveat GCC 4.2 to 4.7 have a known issue using vectors with const. -#if defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2) -#define SIMD_ALIGNED(var) var __attribute__((aligned(32))) -#else -#define SIMD_ALIGNED(var) var __attribute__((aligned(16))) -#endif -#define LIBYUV_NOINLINE __attribute__((noinline)) -typedef int16_t __attribute__((vector_size(16))) vec16; -typedef int32_t __attribute__((vector_size(16))) vec32; -typedef float __attribute__((vector_size(16))) vecf32; -typedef int8_t __attribute__((vector_size(16))) vec8; -typedef uint16_t __attribute__((vector_size(16))) uvec16; -typedef uint32_t __attribute__((vector_size(16))) uvec32; -typedef uint8_t __attribute__((vector_size(16))) uvec8; -typedef int16_t __attribute__((vector_size(32))) lvec16; -typedef int32_t __attribute__((vector_size(32))) lvec32; -typedef int8_t __attribute__((vector_size(32))) lvec8; -typedef uint16_t __attribute__((vector_size(32))) ulvec16; -typedef uint32_t __attribute__((vector_size(32))) ulvec32; -typedef uint8_t __attribute__((vector_size(32))) ulvec8; -#else -#define SIMD_ALIGNED(var) var -#define LIBYUV_NOINLINE -typedef int16_t vec16[8]; -typedef int32_t vec32[4]; -typedef float vecf32[4]; -typedef int8_t vec8[16]; -typedef uint16_t uvec16[8]; -typedef uint32_t uvec32[4]; -typedef uint8_t uvec8[16]; -typedef int16_t lvec16[16]; -typedef int32_t lvec32[8]; -typedef int8_t lvec8[32]; -typedef uint16_t ulvec16[16]; -typedef uint32_t ulvec32[8]; -typedef uint8_t ulvec8[32]; -#endif - -#if !defined(__aarch64__) || !defined(__arm__) -// This struct is for Intel color conversion. -struct YuvConstants { - uint8_t kUVToB[32]; - uint8_t kUVToG[32]; - uint8_t kUVToR[32]; - int16_t kYToRgb[16]; - int16_t kYBiasToRgb[16]; -}; -#endif - -#define IS_ALIGNED(p, a) (!((uintptr_t)(p) & ((a)-1))) - -#define align_buffer_64(var, size) \ - void* var##_mem = malloc((size) + 63); /* NOLINT */ \ - uint8_t* var = (uint8_t*)(((intptr_t)var##_mem + 63) & ~63) /* NOLINT */ - -#define free_aligned_buffer_64(var) \ - free(var##_mem); \ - var = NULL - -#if defined(__APPLE__) || defined(__x86_64__) || defined(__llvm__) -#define OMITFP -#else -#define OMITFP __attribute__((optimize("omit-frame-pointer"))) -#endif - -// NaCL macros for GCC x86 and x64. -#if defined(__native_client__) -#define LABELALIGN ".p2align 5\n" -#else -#define LABELALIGN -#endif - -void ARGBToYRow_AVX2(const uint8_t *src_argb, uint8_t *dst_y, int width); - -void ARGBToYRow_Any_AVX2(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void ABGRToYRow_AVX2(const uint8_t *src_abgr, uint8_t *dst_y, int width); - -void ABGRToYRow_Any_AVX2(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void ARGBToYRow_SSSE3(const uint8_t *src_argb, uint8_t *dst_y, int width); - -void ABGRToYRow_SSSE3(const uint8_t *src_abgr, uint8_t *dst_y, int width); - -void BGRAToYRow_SSSE3(const uint8_t *src_bgra, uint8_t *dst_y, int width); - -void ABGRToYRow_SSSE3(const uint8_t *src_abgr, uint8_t *dst_y, int width); - -void ARGBToYRow_C(const uint8_t *src_rgb, uint8_t *dst_y, int width); - -void ABGRToYRow_C(const uint8_t *src_rgb, uint8_t *dst_y, int width); - -void RGB565ToYRow_C(const uint8_t *src_rgb565, uint8_t *dst_y, int width); - -void ARGBToYRow_Any_SSSE3(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void BGRAToYRow_Any_SSSE3(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void ABGRToYRow_Any_SSSE3(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void ARGBToUVRow_AVX2(const uint8_t *src_argb, - int src_stride_argb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ABGRToUVRow_AVX2(const uint8_t *src_abgr, - int src_stride_abgr, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ARGBToUVRow_SSSE3(const uint8_t *src_argb, - int src_stride_argb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void BGRAToUVRow_SSSE3(const uint8_t *src_bgra, - int src_stride_bgra, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ABGRToUVRow_SSSE3(const uint8_t *src_abgr, - int src_stride_abgr, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void RGBAToUVRow_SSSE3(const uint8_t *src_rgba, - int src_stride_rgba, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ARGBToUVRow_Any_AVX2(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ABGRToUVRow_Any_AVX2(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ARGBToUVRow_Any_SSSE3(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void BGRAToUVRow_Any_SSSE3(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ABGRToUVRow_Any_SSSE3(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void RGBAToUVRow_Any_SSSE3(const uint8_t *src_ptr, - int src_stride, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ARGBToUVRow_C(const uint8_t *src_rgb, - int src_stride_rgb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ARGBToUVRow_C(const uint8_t *src_rgb, - int src_stride_rgb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void BGRAToUVRow_C(const uint8_t *src_rgb, - int src_stride_rgb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void ABGRToUVRow_C(const uint8_t *src_rgb, - int src_stride_rgb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void RGBAToUVRow_C(const uint8_t *src_rgb, - int src_stride_rgb, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void RGB565ToUVRow_C(const uint8_t *src_rgb565, - int src_stride_rgb565, - uint8_t *dst_u, - uint8_t *dst_v, - int width); - -void MirrorRow_AVX2(const uint8_t *src, uint8_t *dst, int width); - -void MirrorRow_SSSE3(const uint8_t *src, uint8_t *dst, int width); - -void MirrorRow_C(const uint8_t *src, uint8_t *dst, int width); - -void MirrorRow_Any_AVX2(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void MirrorRow_Any_SSSE3(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void MirrorRow_Any_SSE2(const uint8_t *src, uint8_t *dst, int width); - -void MirrorUVRow_AVX2(const uint8_t *src_uv, uint8_t *dst_uv, int width); - -void MirrorUVRow_SSSE3(const uint8_t *src_uv, uint8_t *dst_uv, int width); - -void MirrorUVRow_Any_AVX2(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void MirrorUVRow_Any_SSSE3(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void ARGBMirrorRow_AVX2(const uint8_t *src, uint8_t *dst, int width); - -void ARGBMirrorRow_SSE2(const uint8_t *src, uint8_t *dst, int width); - -void ARGBMirrorRow_C(const uint8_t *src, uint8_t *dst, int width); - -void ARGBMirrorRow_Any_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int width); - -void ARGBMirrorRow_Any_SSE2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int width); - -void CopyRow_SSE2(const uint8_t *src, uint8_t *dst, int width); - -void CopyRow_AVX(const uint8_t *src, uint8_t *dst, int width); - -void CopyRow_ERMS(const uint8_t *src, uint8_t *dst, int width); - -void CopyRow_C(const uint8_t *src, uint8_t *dst, int count); - -void CopyRow_Any_SSE2(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void CopyRow_Any_AVX(const uint8_t *src_ptr, uint8_t *dst_ptr, int width); - -void RGB565ToARGBRow_SSE2(const uint8_t *src, uint8_t *dst, int width); - -void RGB565ToARGBRow_AVX2(const uint8_t *src_rgb565, - uint8_t *dst_argb, - int width); - -void RGB565ToARGBRow_C(const uint8_t *src_rgb565, uint8_t *dst_argb, int width); - -void RGB565ToARGBRow_Any_SSE2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int width); - -void RGB565ToARGBRow_Any_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int width); - -// Used for I420Scale, ARGBScale, and ARGBInterpolate. -void InterpolateRow_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int width, - int source_y_fraction); - -void InterpolateRow_SSSE3(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int dst_width, - int source_y_fraction); - -void InterpolateRow_AVX2(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int dst_width, - int source_y_fraction); - -void InterpolateRow_Any_SSSE3(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride_ptr, - int width, - int source_y_fraction); - -void InterpolateRow_Any_AVX2(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride_ptr, - int width, - int source_y_fraction); - -#endif // INCLUDE_LIBYUV_ROW_H_ \ No newline at end of file diff --git a/pkg/encoder/yuv/libyuv/row_any.c b/pkg/encoder/yuv/libyuv/row_any.c deleted file mode 100644 index fcc49c672..000000000 --- a/pkg/encoder/yuv/libyuv/row_any.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2012 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 "row.h" - -#include // For memset. - -// Subsampled source needs to be increase by 1 of not even. -#define SS(width, shift) (((width) + (1 << (shift)) - 1) >> (shift)) - -// Any 1 to 1. -#define ANY11(NAMEANY, ANY_SIMD, UVSHIFT, SBPP, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width) { \ - SIMD_ALIGNED(uint8_t vin[128]); \ - SIMD_ALIGNED(uint8_t vout[128]); \ - memset(vin, 0, sizeof(vin)); /* for YUY2 and msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(src_ptr, dst_ptr, n); \ - } \ - memcpy(vin, src_ptr + (n >> UVSHIFT) * SBPP, SS(r, UVSHIFT) * SBPP); \ - ANY_SIMD(vin, vout, MASK + 1); \ - memcpy(dst_ptr + n * BPP, vout, r * BPP); \ - } - -#ifdef HAS_COPYROW_AVX - -ANY11(CopyRow_Any_AVX, CopyRow_AVX, 0, 1, 1, 63) - -#endif -#ifdef HAS_COPYROW_SSE2 - -ANY11(CopyRow_Any_SSE2, CopyRow_SSE2, 0, 1, 1, 31) - -#endif - -#ifdef HAS_ARGBTOYROW_AVX2 - -ANY11(ARGBToYRow_Any_AVX2, ARGBToYRow_AVX2, 0, 4, 1, 31) - -#endif -#ifdef HAS_ABGRTOYROW_AVX2 - -ANY11(ABGRToYRow_Any_AVX2, ABGRToYRow_AVX2, 0, 4, 1, 31) - -#endif -#ifdef HAS_ARGBTOYROW_SSSE3 - -ANY11(ARGBToYRow_Any_SSSE3, ARGBToYRow_SSSE3, 0, 4, 1, 15) - -#endif -#ifdef HAS_BGRATOYROW_SSSE3 - -ANY11(BGRAToYRow_Any_SSSE3, BGRAToYRow_SSSE3, 0, 4, 1, 15) - -ANY11(ABGRToYRow_Any_SSSE3, ABGRToYRow_SSSE3, 0, 4, 1, 15) - -#endif - -#undef ANY11 - -// Any 1 to 1 interpolate. Takes 2 rows of source via stride. -#define ANY11I(NAMEANY, ANY_SIMD, TD, TS, SBPP, BPP, MASK) \ - void NAMEANY(TD* dst_ptr, const TS* src_ptr, ptrdiff_t src_stride, \ - int width, int source_y_fraction) { \ - SIMD_ALIGNED(TS vin[64 * 2]); \ - SIMD_ALIGNED(TD vout[64]); \ - memset(vin, 0, sizeof(vin)); /* for msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(dst_ptr, src_ptr, src_stride, n, source_y_fraction); \ - } \ - memcpy(vin, src_ptr + n * SBPP, r * SBPP * sizeof(TS)); \ - if (source_y_fraction) { \ - memcpy(vin + 64, src_ptr + src_stride + n * SBPP, \ - r * SBPP * sizeof(TS)); \ - } \ - ANY_SIMD(vout, vin, 64, MASK + 1, source_y_fraction); \ - memcpy(dst_ptr + n * BPP, vout, r * BPP * sizeof(TD)); \ - } - -#ifdef HAS_INTERPOLATEROW_AVX2 - -ANY11I(InterpolateRow_Any_AVX2, InterpolateRow_AVX2, uint8_t, uint8_t, 1, 1, 31) - -#endif -#ifdef HAS_INTERPOLATEROW_SSSE3 - -ANY11I(InterpolateRow_Any_SSSE3, - InterpolateRow_SSSE3, - uint8_t, - uint8_t, - 1, - 1, - 15) - -#endif - -#undef ANY11I - -// Any 1 to 1 mirror. -#define ANY11M(NAMEANY, ANY_SIMD, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, uint8_t* dst_ptr, int width) { \ - SIMD_ALIGNED(uint8_t vin[64]); \ - SIMD_ALIGNED(uint8_t vout[64]); \ - memset(vin, 0, sizeof(vin)); /* for msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(src_ptr + r * BPP, dst_ptr, n); \ - } \ - memcpy(vin, src_ptr, r* BPP); \ - ANY_SIMD(vin, vout, MASK + 1); \ - memcpy(dst_ptr + n * BPP, vout + (MASK + 1 - r) * BPP, r * BPP); \ - } - -#ifdef HAS_MIRRORROW_AVX2 - -ANY11M(MirrorRow_Any_AVX2, MirrorRow_AVX2, 1, 31) - -#endif -#ifdef HAS_MIRRORROW_SSSE3 - -ANY11M(MirrorRow_Any_SSSE3, MirrorRow_SSSE3, 1, 15) - -#endif -#ifdef HAS_MIRRORUVROW_AVX2 - -ANY11M(MirrorUVRow_Any_AVX2, MirrorUVRow_AVX2, 2, 15) - -#endif -#ifdef HAS_MIRRORUVROW_SSSE3 - -ANY11M(MirrorUVRow_Any_SSSE3, MirrorUVRow_SSSE3, 2, 7) - -#endif -#ifdef HAS_ARGBMIRRORROW_AVX2 - -ANY11M(ARGBMirrorRow_Any_AVX2, ARGBMirrorRow_AVX2, 4, 7) - -#endif -#ifdef HAS_ARGBMIRRORROW_SSE2 - -ANY11M(ARGBMirrorRow_Any_SSE2, ARGBMirrorRow_SSE2, 4, 3) - -#endif -#undef ANY11M - -// Any 1 to 2 with source stride (2 rows of source). Outputs UV planes. -// 128 byte row allows for 32 avx ARGB pixels. -#define ANY12S(NAMEANY, ANY_SIMD, UVSHIFT, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, int src_stride, uint8_t* dst_u, \ - uint8_t* dst_v, int width) { \ - SIMD_ALIGNED(uint8_t vin[128 * 2]); \ - SIMD_ALIGNED(uint8_t vout[128 * 2]); \ - memset(vin, 0, sizeof(vin)); /* for msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(src_ptr, src_stride, dst_u, dst_v, n); \ - } \ - memcpy(vin, src_ptr + (n >> UVSHIFT) * BPP, SS(r, UVSHIFT) * BPP); \ - memcpy(vin + 128, src_ptr + src_stride + (n >> UVSHIFT) * BPP, \ - SS(r, UVSHIFT) * BPP); \ - if ((width & 1) && UVSHIFT == 0) { /* repeat last pixel for subsample */ \ - memcpy(vin + SS(r, UVSHIFT) * BPP, vin + SS(r, UVSHIFT) * BPP - BPP, \ - BPP); \ - memcpy(vin + 128 + SS(r, UVSHIFT) * BPP, \ - vin + 128 + SS(r, UVSHIFT) * BPP - BPP, BPP); \ - } \ - ANY_SIMD(vin, 128, vout, vout + 128, MASK + 1); \ - memcpy(dst_u + (n >> 1), vout, SS(r, 1)); \ - memcpy(dst_v + (n >> 1), vout + 128, SS(r, 1)); \ - } - -#ifdef HAS_ARGBTOUVROW_AVX2 - -ANY12S(ARGBToUVRow_Any_AVX2, ARGBToUVRow_AVX2, 0, 4, 31) - -#endif -#ifdef HAS_ABGRTOUVROW_AVX2 - -ANY12S(ABGRToUVRow_Any_AVX2, ABGRToUVRow_AVX2, 0, 4, 31) - -#endif -#ifdef HAS_ARGBTOUVROW_SSSE3 - -ANY12S(ARGBToUVRow_Any_SSSE3, ARGBToUVRow_SSSE3, 0, 4, 15) - -ANY12S(BGRAToUVRow_Any_SSSE3, BGRAToUVRow_SSSE3, 0, 4, 15) - -ANY12S(ABGRToUVRow_Any_SSSE3, ABGRToUVRow_SSSE3, 0, 4, 15) - -ANY12S(RGBAToUVRow_Any_SSSE3, RGBAToUVRow_SSSE3, 0, 4, 15) - -#endif -#undef ANY12S diff --git a/pkg/encoder/yuv/libyuv/row_common.c b/pkg/encoder/yuv/libyuv/row_common.c deleted file mode 100644 index 34a93a074..000000000 --- a/pkg/encoder/yuv/libyuv/row_common.c +++ /dev/null @@ -1,887 +0,0 @@ -/* - * 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 "row.h" - -#include -#include // For memcpy and memset. - -#define STATIC_CAST(type, expr) (type)(expr) - -// This macro controls YUV to RGB using unsigned math to extend range of -// YUV to RGB coefficients to 0 to 4 instead of 0 to 2 for more accuracy on B: -// LIBYUV_UNLIMITED_DATA - -// Macros to enable unlimited data for each colorspace -// LIBYUV_UNLIMITED_BT601 -// LIBYUV_UNLIMITED_BT709 -// LIBYUV_UNLIMITED_BT2020 - -#if !defined(LIBYUV_BIT_EXACT) && (defined(__x86_64__) || defined(_M_X64) || \ - defined(__i386__) || defined(_M_IX86)) -#define LIBYUV_ARGBTOUV_PAVGB 1 -#define LIBYUV_RGBTOU_TRUNCATE 1 -#endif -#if defined(LIBYUV_BIT_EXACT) -#define LIBYUV_UNATTENUATE_DUP 1 -#endif - -// llvm x86 is poor at ternary operator, so use branchless min/max. - -#define USE_BRANCHLESS 1 -#if USE_BRANCHLESS - -static __inline int32_t clamp0(int32_t v) { - return -(v >= 0) & v; -} - -// TODO(fbarchard): make clamp255 preserve negative values. -static __inline int32_t clamp255(int32_t v) { - return (-(v >= 255) | v) & 255; -} - -static __inline int32_t clamp1023(int32_t v) { - return (-(v >= 1023) | v) & 1023; -} - -// clamp to max -static __inline int32_t ClampMax(int32_t v, int32_t max) { - return (-(v >= max) | v) & max; -} - -static __inline uint32_t Abs(int32_t v) { - int m = -(v < 0); - return (v + m) ^ m; -} - -#else // USE_BRANCHLESS -static __inline int32_t clamp0(int32_t v) { - return (v < 0) ? 0 : v; -} - -static __inline int32_t clamp255(int32_t v) { - return (v > 255) ? 255 : v; -} - -static __inline int32_t clamp1023(int32_t v) { - return (v > 1023) ? 1023 : v; -} - -static __inline int32_t ClampMax(int32_t v, int32_t max) { - return (v > max) ? max : v; -} - -static __inline uint32_t Abs(int32_t v) { - return (v < 0) ? -v : v; -} -#endif // USE_BRANCHLESS - -static __inline uint32_t Clamp(int32_t val) { - int v = clamp0(val); - return (uint32_t) (clamp255(v)); -} - -static __inline uint32_t Clamp10(int32_t val) { - int v = clamp0(val); - return (uint32_t) (clamp1023(v)); -} - -// Little Endian -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ - defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) || \ - (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define WRITEWORD(p, v) *(uint32_t*)(p) = v -#else -static inline void WRITEWORD(uint8_t* p, uint32_t v) { - p[0] = (uint8_t)(v & 255); - p[1] = (uint8_t)((v >> 8) & 255); - p[2] = (uint8_t)((v >> 16) & 255); - p[3] = (uint8_t)((v >> 24) & 255); -} -#endif - -void RGB565ToARGBRow_C(const uint8_t *src_rgb565, - uint8_t *dst_argb, - int width) { - int x; - for (x = 0; x < width; ++x) { - uint8_t b = STATIC_CAST(uint8_t, src_rgb565[0] & 0x1f); - uint8_t g = STATIC_CAST( - uint8_t, (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3)); - uint8_t r = STATIC_CAST(uint8_t, src_rgb565[1] >> 3); - dst_argb[0] = STATIC_CAST(uint8_t, (b << 3) | (b >> 2)); - dst_argb[1] = STATIC_CAST(uint8_t, (g << 2) | (g >> 4)); - dst_argb[2] = STATIC_CAST(uint8_t, (r << 3) | (r >> 2)); - dst_argb[3] = 255u; - dst_argb += 4; - src_rgb565 += 2; - } -} - -// 8 bit -// Intel SSE/AVX uses the following equivalent formula -// 0x7e80 = (66 + 129 + 25) * -128 + 0x1000 (for +16) and 0x0080 for round. -// return (66 * ((int)r - 128) + 129 * ((int)g - 128) + 25 * ((int)b - 128) + -// 0x7e80) >> 8; - -static __inline uint8_t RGBToY(uint8_t r, uint8_t g, uint8_t b) { - return STATIC_CAST(uint8_t, (66 * r + 129 * g + 25 * b + 0x1080) >> 8); -} - -#define AVGB(a, b) (((a) + (b) + 1) >> 1) - -// LIBYUV_RGBTOU_TRUNCATE mimics x86 code that does not round. -#ifdef LIBYUV_RGBTOU_TRUNCATE - -static __inline uint8_t RGBToU(uint8_t r, uint8_t g, uint8_t b) { - return STATIC_CAST(uint8_t, (112 * b - 74 * g - 38 * r + 0x8000) >> 8); -} - -static __inline uint8_t RGBToV(uint8_t r, uint8_t g, uint8_t b) { - return STATIC_CAST(uint8_t, (112 * r - 94 * g - 18 * b + 0x8000) >> 8); -} - -#else -// TODO(fbarchard): Add rounding to x86 SIMD and use this -static __inline uint8_t RGBToU(uint8_t r, uint8_t g, uint8_t b) { - return STATIC_CAST(uint8_t, (112 * b - 74 * g - 38 * r + 0x8080) >> 8); -} -static __inline uint8_t RGBToV(uint8_t r, uint8_t g, uint8_t b) { - return STATIC_CAST(uint8_t, (112 * r - 94 * g - 18 * b + 0x8080) >> 8); -} -#endif - -// LIBYUV_ARGBTOUV_PAVGB mimics x86 code that subsamples with 2 pavgb. -#if !defined(LIBYUV_ARGBTOUV_PAVGB) -static __inline int RGB2xToU(uint16_t r, uint16_t g, uint16_t b) { - return STATIC_CAST( - uint8_t, ((112 / 2) * b - (74 / 2) * g - (38 / 2) * r + 0x8080) >> 8); -} -static __inline int RGB2xToV(uint16_t r, uint16_t g, uint16_t b) { - return STATIC_CAST( - uint8_t, ((112 / 2) * r - (94 / 2) * g - (18 / 2) * b + 0x8080) >> 8); -} -#endif - -// ARGBToY_C and ARGBToUV_C -// Intel version mimic SSE/AVX which does 2 pavgb -#if LIBYUV_ARGBTOUV_PAVGB -#define MAKEROWY(NAME, R, G, B, BPP) \ - void NAME##ToYRow_C(const uint8_t* src_rgb, uint8_t* dst_y, int width) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - dst_y[0] = RGBToY(src_rgb[R], src_rgb[G], src_rgb[B]); \ - src_rgb += BPP; \ - dst_y += 1; \ - } \ - } \ - void NAME##ToUVRow_C(const uint8_t* src_rgb, int src_stride_rgb, \ - uint8_t* dst_u, uint8_t* dst_v, int width) { \ - const uint8_t* src_rgb1 = src_rgb + src_stride_rgb; \ - int x; \ - for (x = 0; x < width - 1; x += 2) { \ - uint8_t ab = AVGB(AVGB(src_rgb[B], src_rgb1[B]), \ - AVGB(src_rgb[B + BPP], src_rgb1[B + BPP])); \ - uint8_t ag = AVGB(AVGB(src_rgb[G], src_rgb1[G]), \ - AVGB(src_rgb[G + BPP], src_rgb1[G + BPP])); \ - uint8_t ar = AVGB(AVGB(src_rgb[R], src_rgb1[R]), \ - AVGB(src_rgb[R + BPP], src_rgb1[R + BPP])); \ - dst_u[0] = RGBToU(ar, ag, ab); \ - dst_v[0] = RGBToV(ar, ag, ab); \ - src_rgb += BPP * 2; \ - src_rgb1 += BPP * 2; \ - dst_u += 1; \ - dst_v += 1; \ - } \ - if (width & 1) { \ - uint8_t ab = AVGB(src_rgb[B], src_rgb1[B]); \ - uint8_t ag = AVGB(src_rgb[G], src_rgb1[G]); \ - uint8_t ar = AVGB(src_rgb[R], src_rgb1[R]); \ - dst_u[0] = RGBToU(ar, ag, ab); \ - dst_v[0] = RGBToV(ar, ag, ab); \ - } \ - } -#else -// ARM version does sum / 2 then multiply by 2x smaller coefficients -#define MAKEROWY(NAME, R, G, B, BPP) \ - void NAME##ToYRow_C(const uint8_t* src_rgb, uint8_t* dst_y, int width) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - dst_y[0] = RGBToY(src_rgb[R], src_rgb[G], src_rgb[B]); \ - src_rgb += BPP; \ - dst_y += 1; \ - } \ - } \ - void NAME##ToUVRow_C(const uint8_t* src_rgb, int src_stride_rgb, \ - uint8_t* dst_u, uint8_t* dst_v, int width) { \ - const uint8_t* src_rgb1 = src_rgb + src_stride_rgb; \ - int x; \ - for (x = 0; x < width - 1; x += 2) { \ - uint16_t ab = (src_rgb[B] + src_rgb[B + BPP] + src_rgb1[B] + \ - src_rgb1[B + BPP] + 1) >> \ - 1; \ - uint16_t ag = (src_rgb[G] + src_rgb[G + BPP] + src_rgb1[G] + \ - src_rgb1[G + BPP] + 1) >> \ - 1; \ - uint16_t ar = (src_rgb[R] + src_rgb[R + BPP] + src_rgb1[R] + \ - src_rgb1[R + BPP] + 1) >> \ - 1; \ - dst_u[0] = RGB2xToU(ar, ag, ab); \ - dst_v[0] = RGB2xToV(ar, ag, ab); \ - src_rgb += BPP * 2; \ - src_rgb1 += BPP * 2; \ - dst_u += 1; \ - dst_v += 1; \ - } \ - if (width & 1) { \ - uint16_t ab = src_rgb[B] + src_rgb1[B]; \ - uint16_t ag = src_rgb[G] + src_rgb1[G]; \ - uint16_t ar = src_rgb[R] + src_rgb1[R]; \ - dst_u[0] = RGB2xToU(ar, ag, ab); \ - dst_v[0] = RGB2xToV(ar, ag, ab); \ - } \ - } -#endif - -MAKEROWY(ARGB, 2, 1, 0, 4) - -MAKEROWY(BGRA, 1, 2, 3, 4) - -MAKEROWY(ABGR, 0, 1, 2, 4) - -MAKEROWY(RGBA, 3, 2, 1, 4) - -#undef MAKEROWY - -// JPeg uses a variation on BT.601-1 full range -// y = 0.29900 * r + 0.58700 * g + 0.11400 * b -// u = -0.16874 * r - 0.33126 * g + 0.50000 * b + center -// v = 0.50000 * r - 0.41869 * g - 0.08131 * b + center -// BT.601 Mpeg range uses: -// b 0.1016 * 255 = 25.908 = 25 -// g 0.5078 * 255 = 129.489 = 129 -// r 0.2578 * 255 = 65.739 = 66 -// JPeg 7 bit Y (deprecated) -// b 0.11400 * 128 = 14.592 = 15 -// g 0.58700 * 128 = 75.136 = 75 -// r 0.29900 * 128 = 38.272 = 38 -// JPeg 8 bit Y: -// b 0.11400 * 256 = 29.184 = 29 -// g 0.58700 * 256 = 150.272 = 150 -// r 0.29900 * 256 = 76.544 = 77 -// JPeg 8 bit U: -// b 0.50000 * 255 = 127.5 = 127 -// g -0.33126 * 255 = -84.4713 = -84 -// r -0.16874 * 255 = -43.0287 = -43 -// JPeg 8 bit V: -// b -0.08131 * 255 = -20.73405 = -20 -// g -0.41869 * 255 = -106.76595 = -107 -// r 0.50000 * 255 = 127.5 = 127 - -// 8 bit -static __inline uint8_t RGBToYJ(uint8_t r, uint8_t g, uint8_t b) { - return (77 * r + 150 * g + 29 * b + 128) >> 8; -} - -#if defined(LIBYUV_ARGBTOUV_PAVGB) - -static __inline uint8_t RGBToUJ(uint8_t r, uint8_t g, uint8_t b) { - return (127 * b - 84 * g - 43 * r + 0x8080) >> 8; -} - -static __inline uint8_t RGBToVJ(uint8_t r, uint8_t g, uint8_t b) { - return (127 * r - 107 * g - 20 * b + 0x8080) >> 8; -} - -#else -static __inline uint8_t RGB2xToUJ(uint16_t r, uint16_t g, uint16_t b) { - return ((127 / 2) * b - (84 / 2) * g - (43 / 2) * r + 0x8080) >> 8; -} -static __inline uint8_t RGB2xToVJ(uint16_t r, uint16_t g, uint16_t b) { - return ((127 / 2) * r - (107 / 2) * g - (20 / 2) * b + 0x8080) >> 8; -} -#endif - -// ARGBToYJ_C and ARGBToUVJ_C -// Intel version mimic SSE/AVX which does 2 pavgb -#if LIBYUV_ARGBTOUV_PAVGB -#define MAKEROWYJ(NAME, R, G, B, BPP) \ - void NAME##ToYJRow_C(const uint8_t* src_rgb, uint8_t* dst_y, int width) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - dst_y[0] = RGBToYJ(src_rgb[R], src_rgb[G], src_rgb[B]); \ - src_rgb += BPP; \ - dst_y += 1; \ - } \ - } \ - void NAME##ToUVJRow_C(const uint8_t* src_rgb, int src_stride_rgb, \ - uint8_t* dst_u, uint8_t* dst_v, int width) { \ - const uint8_t* src_rgb1 = src_rgb + src_stride_rgb; \ - int x; \ - for (x = 0; x < width - 1; x += 2) { \ - uint8_t ab = AVGB(AVGB(src_rgb[B], src_rgb1[B]), \ - AVGB(src_rgb[B + BPP], src_rgb1[B + BPP])); \ - uint8_t ag = AVGB(AVGB(src_rgb[G], src_rgb1[G]), \ - AVGB(src_rgb[G + BPP], src_rgb1[G + BPP])); \ - uint8_t ar = AVGB(AVGB(src_rgb[R], src_rgb1[R]), \ - AVGB(src_rgb[R + BPP], src_rgb1[R + BPP])); \ - dst_u[0] = RGBToUJ(ar, ag, ab); \ - dst_v[0] = RGBToVJ(ar, ag, ab); \ - src_rgb += BPP * 2; \ - src_rgb1 += BPP * 2; \ - dst_u += 1; \ - dst_v += 1; \ - } \ - if (width & 1) { \ - uint8_t ab = AVGB(src_rgb[B], src_rgb1[B]); \ - uint8_t ag = AVGB(src_rgb[G], src_rgb1[G]); \ - uint8_t ar = AVGB(src_rgb[R], src_rgb1[R]); \ - dst_u[0] = RGBToUJ(ar, ag, ab); \ - dst_v[0] = RGBToVJ(ar, ag, ab); \ - } \ - } -#else -// ARM version does sum / 2 then multiply by 2x smaller coefficients -#define MAKEROWYJ(NAME, R, G, B, BPP) \ - void NAME##ToYJRow_C(const uint8_t* src_rgb, uint8_t* dst_y, int width) { \ - int x; \ - for (x = 0; x < width; ++x) { \ - dst_y[0] = RGBToYJ(src_rgb[R], src_rgb[G], src_rgb[B]); \ - src_rgb += BPP; \ - dst_y += 1; \ - } \ - } \ - void NAME##ToUVJRow_C(const uint8_t* src_rgb, int src_stride_rgb, \ - uint8_t* dst_u, uint8_t* dst_v, int width) { \ - const uint8_t* src_rgb1 = src_rgb + src_stride_rgb; \ - int x; \ - for (x = 0; x < width - 1; x += 2) { \ - uint16_t ab = (src_rgb[B] + src_rgb[B + BPP] + src_rgb1[B] + \ - src_rgb1[B + BPP] + 1) >> \ - 1; \ - uint16_t ag = (src_rgb[G] + src_rgb[G + BPP] + src_rgb1[G] + \ - src_rgb1[G + BPP] + 1) >> \ - 1; \ - uint16_t ar = (src_rgb[R] + src_rgb[R + BPP] + src_rgb1[R] + \ - src_rgb1[R + BPP] + 1) >> \ - 1; \ - dst_u[0] = RGB2xToUJ(ar, ag, ab); \ - dst_v[0] = RGB2xToVJ(ar, ag, ab); \ - src_rgb += BPP * 2; \ - src_rgb1 += BPP * 2; \ - dst_u += 1; \ - dst_v += 1; \ - } \ - if (width & 1) { \ - uint16_t ab = (src_rgb[B] + src_rgb1[B]); \ - uint16_t ag = (src_rgb[G] + src_rgb1[G]); \ - uint16_t ar = (src_rgb[R] + src_rgb1[R]); \ - dst_u[0] = RGB2xToUJ(ar, ag, ab); \ - dst_v[0] = RGB2xToVJ(ar, ag, ab); \ - } \ - } - -#endif - -MAKEROWYJ(ARGB, 2, 1, 0, 4) - -MAKEROWYJ(ABGR, 0, 1, 2, 4) - -MAKEROWYJ(RGBA, 3, 2, 1, 4) - -MAKEROWYJ(RGB24, 2, 1, 0, 3) - -MAKEROWYJ(RAW, 0, 1, 2, 3) - -#undef MAKEROWYJ - -void RGB565ToYRow_C(const uint8_t *src_rgb565, uint8_t *dst_y, int width) { - int x; - for (x = 0; x < width; ++x) { - uint8_t b = src_rgb565[0] & 0x1f; - uint8_t g = STATIC_CAST( - uint8_t, (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3)); - uint8_t r = src_rgb565[1] >> 3; - b = STATIC_CAST(uint8_t, (b << 3) | (b >> 2)); - g = STATIC_CAST(uint8_t, (g << 2) | (g >> 4)); - r = STATIC_CAST(uint8_t, (r << 3) | (r >> 2)); - dst_y[0] = RGBToY(r, g, b); - src_rgb565 += 2; - dst_y += 1; - } -} - -void RGB565ToUVRow_C(const uint8_t *src_rgb565, - int src_stride_rgb565, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - const uint8_t *next_rgb565 = src_rgb565 + src_stride_rgb565; - int x; - for (x = 0; x < width - 1; x += 2) { - uint8_t b0 = STATIC_CAST(uint8_t, src_rgb565[0] & 0x1f); - uint8_t g0 = STATIC_CAST( - uint8_t, (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3)); - uint8_t r0 = STATIC_CAST(uint8_t, src_rgb565[1] >> 3); - uint8_t b1 = STATIC_CAST(uint8_t, src_rgb565[2] & 0x1f); - uint8_t g1 = STATIC_CAST( - uint8_t, (src_rgb565[2] >> 5) | ((src_rgb565[3] & 0x07) << 3)); - uint8_t r1 = STATIC_CAST(uint8_t, src_rgb565[3] >> 3); - uint8_t b2 = STATIC_CAST(uint8_t, next_rgb565[0] & 0x1f); - uint8_t g2 = STATIC_CAST( - uint8_t, (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3)); - uint8_t r2 = STATIC_CAST(uint8_t, next_rgb565[1] >> 3); - uint8_t b3 = STATIC_CAST(uint8_t, next_rgb565[2] & 0x1f); - uint8_t g3 = STATIC_CAST( - uint8_t, (next_rgb565[2] >> 5) | ((next_rgb565[3] & 0x07) << 3)); - uint8_t r3 = STATIC_CAST(uint8_t, next_rgb565[3] >> 3); - - b0 = STATIC_CAST(uint8_t, (b0 << 3) | (b0 >> 2)); - g0 = STATIC_CAST(uint8_t, (g0 << 2) | (g0 >> 4)); - r0 = STATIC_CAST(uint8_t, (r0 << 3) | (r0 >> 2)); - b1 = STATIC_CAST(uint8_t, (b1 << 3) | (b1 >> 2)); - g1 = STATIC_CAST(uint8_t, (g1 << 2) | (g1 >> 4)); - r1 = STATIC_CAST(uint8_t, (r1 << 3) | (r1 >> 2)); - b2 = STATIC_CAST(uint8_t, (b2 << 3) | (b2 >> 2)); - g2 = STATIC_CAST(uint8_t, (g2 << 2) | (g2 >> 4)); - r2 = STATIC_CAST(uint8_t, (r2 << 3) | (r2 >> 2)); - b3 = STATIC_CAST(uint8_t, (b3 << 3) | (b3 >> 2)); - g3 = STATIC_CAST(uint8_t, (g3 << 2) | (g3 >> 4)); - r3 = STATIC_CAST(uint8_t, (r3 << 3) | (r3 >> 2)); - -#if LIBYUV_ARGBTOUV_PAVGB - uint8_t ab = AVGB(AVGB(b0, b2), AVGB(b1, b3)); - uint8_t ag = AVGB(AVGB(g0, g2), AVGB(g1, g3)); - uint8_t ar = AVGB(AVGB(r0, r2), AVGB(r1, r3)); - dst_u[0] = RGBToU(ar, ag, ab); - dst_v[0] = RGBToV(ar, ag, ab); -#else - uint16_t b = (b0 + b1 + b2 + b3 + 1) >> 1; - uint16_t g = (g0 + g1 + g2 + g3 + 1) >> 1; - uint16_t r = (r0 + r1 + r2 + r3 + 1) >> 1; - dst_u[0] = RGB2xToU(r, g, b); - dst_v[0] = RGB2xToV(r, g, b); -#endif - - src_rgb565 += 4; - next_rgb565 += 4; - dst_u += 1; - dst_v += 1; - } - if (width & 1) { - uint8_t b0 = STATIC_CAST(uint8_t, src_rgb565[0] & 0x1f); - uint8_t g0 = STATIC_CAST( - uint8_t, (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3)); - uint8_t r0 = STATIC_CAST(uint8_t, src_rgb565[1] >> 3); - uint8_t b2 = STATIC_CAST(uint8_t, next_rgb565[0] & 0x1f); - uint8_t g2 = STATIC_CAST( - uint8_t, (next_rgb565[0] >> 5) | ((next_rgb565[1] & 0x07) << 3)); - uint8_t r2 = STATIC_CAST(uint8_t, next_rgb565[1] >> 3); - b0 = STATIC_CAST(uint8_t, (b0 << 3) | (b0 >> 2)); - g0 = STATIC_CAST(uint8_t, (g0 << 2) | (g0 >> 4)); - r0 = STATIC_CAST(uint8_t, (r0 << 3) | (r0 >> 2)); - b2 = STATIC_CAST(uint8_t, (b2 << 3) | (b2 >> 2)); - g2 = STATIC_CAST(uint8_t, (g2 << 2) | (g2 >> 4)); - r2 = STATIC_CAST(uint8_t, (r2 << 3) | (r2 >> 2)); - -#if LIBYUV_ARGBTOUV_PAVGB - uint8_t ab = AVGB(b0, b2); - uint8_t ag = AVGB(g0, g2); - uint8_t ar = AVGB(r0, r2); - dst_u[0] = RGBToU(ar, ag, ab); - dst_v[0] = RGBToV(ar, ag, ab); -#else - uint16_t b = b0 + b2; - uint16_t g = g0 + g2; - uint16_t r = r0 + r2; - dst_u[0] = RGB2xToU(r, g, b); - dst_v[0] = RGB2xToV(r, g, b); -#endif - } -} - -#define REPEAT8(v) (v) | ((v) << 8) -#define SHADE(f, v) v* f >> 24 - -#undef REPEAT8 -#undef SHADE - -#define REPEAT8(v) (v) | ((v) << 8) -#define SHADE(f, v) v* f >> 16 - -#undef REPEAT8 -#undef SHADE - -#define SHADE(f, v) clamp255(v + f) - -#undef SHADE - -#define SHADE(f, v) clamp0(f - v) - -#undef SHADE - -// Macros to create SIMD specific yuv to rgb conversion constants. - -// clang-format off - -#if defined(__aarch64__) || defined(__arm__) -// Bias values include subtract 128 from U and V, bias from Y and rounding. -// For B and R bias is negative. For G bias is positive. -#define YUVCONSTANTSBODY(YG, YB, UB, UG, VG, VR) \ - {{UB, VR, UG, VG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \ - {YG, (UB * 128 - YB), (UG * 128 + VG * 128 + YB), (VR * 128 - YB), YB, 0, \ - 0, 0}} -#else -#define YUVCONSTANTSBODY(YG, YB, UB, UG, VG, VR) \ - {{UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, \ - UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0}, \ - {UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, \ - UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG}, \ - {0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, \ - 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR}, \ - {YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG}, \ - {YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB, YB}} -#endif - -// clang-format on - -#define MAKEYUVCONSTANTS(name, YG, YB, UB, UG, VG, VR) \ - const struct YuvConstants SIMD_ALIGNED(kYuv##name##Constants) = \ - YUVCONSTANTSBODY(YG, YB, UB, UG, VG, VR); \ - const struct YuvConstants SIMD_ALIGNED(kYvu##name##Constants) = \ - YUVCONSTANTSBODY(YG, YB, VR, VG, UG, UB); - -// TODO(fbarchard): Generate SIMD structures from float matrix. - -// BT.601 limited range YUV to RGB reference -// R = (Y - 16) * 1.164 + V * 1.596 -// G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 -// B = (Y - 16) * 1.164 + U * 2.018 -// KR = 0.299; KB = 0.114 - -// U and V contributions to R,G,B. -#if defined(LIBYUV_UNLIMITED_DATA) || defined(LIBYUV_UNLIMITED_BT601) -#define UB 129 /* round(2.018 * 64) */ -#else -#define UB 128 /* max(128, round(2.018 * 64)) */ -#endif -#define UG 25 /* round(0.391 * 64) */ -#define VG 52 /* round(0.813 * 64) */ -#define VR 102 /* round(1.596 * 64) */ - -// Y contribution to R,G,B. Scale and bias. -#define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ -#define YB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ - -MAKEYUVCONSTANTS(I601, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -// BT.601 full range YUV to RGB reference (aka JPEG) -// * R = Y + V * 1.40200 -// * G = Y - U * 0.34414 - V * 0.71414 -// * B = Y + U * 1.77200 -// KR = 0.299; KB = 0.114 - -// U and V contributions to R,G,B. -#define UB 113 /* round(1.77200 * 64) */ -#define UG 22 /* round(0.34414 * 64) */ -#define VG 46 /* round(0.71414 * 64) */ -#define VR 90 /* round(1.40200 * 64) */ - -// Y contribution to R,G,B. Scale and bias. -#define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */ -#define YB 32 /* 64 / 2 */ - -MAKEYUVCONSTANTS(JPEG, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -// BT.709 limited range YUV to RGB reference -// R = (Y - 16) * 1.164 + V * 1.793 -// G = (Y - 16) * 1.164 - U * 0.213 - V * 0.533 -// B = (Y - 16) * 1.164 + U * 2.112 -// KR = 0.2126, KB = 0.0722 - -// U and V contributions to R,G,B. -#if defined(LIBYUV_UNLIMITED_DATA) || defined(LIBYUV_UNLIMITED_BT709) -#define UB 135 /* round(2.112 * 64) */ -#else -#define UB 128 /* max(128, round(2.112 * 64)) */ -#endif -#define UG 14 /* round(0.213 * 64) */ -#define VG 34 /* round(0.533 * 64) */ -#define VR 115 /* round(1.793 * 64) */ - -// Y contribution to R,G,B. Scale and bias. -#define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ -#define YB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ - -MAKEYUVCONSTANTS(H709, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -// BT.709 full range YUV to RGB reference -// R = Y + V * 1.5748 -// G = Y - U * 0.18732 - V * 0.46812 -// B = Y + U * 1.8556 -// KR = 0.2126, KB = 0.0722 - -// U and V contributions to R,G,B. -#define UB 119 /* round(1.8556 * 64) */ -#define UG 12 /* round(0.18732 * 64) */ -#define VG 30 /* round(0.46812 * 64) */ -#define VR 101 /* round(1.5748 * 64) */ - -// Y contribution to R,G,B. Scale and bias. (same as jpeg) -#define YG 16320 /* round(1 * 64 * 256 * 256 / 257) */ -#define YB 32 /* 64 / 2 */ - -MAKEYUVCONSTANTS(F709, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -// BT.2020 limited range YUV to RGB reference -// R = (Y - 16) * 1.164384 + V * 1.67867 -// G = (Y - 16) * 1.164384 - U * 0.187326 - V * 0.65042 -// B = (Y - 16) * 1.164384 + U * 2.14177 -// KR = 0.2627; KB = 0.0593 - -// U and V contributions to R,G,B. -#if defined(LIBYUV_UNLIMITED_DATA) || defined(LIBYUV_UNLIMITED_BT2020) -#define UB 137 /* round(2.142 * 64) */ -#else -#define UB 128 /* max(128, round(2.142 * 64)) */ -#endif -#define UG 12 /* round(0.187326 * 64) */ -#define VG 42 /* round(0.65042 * 64) */ -#define VR 107 /* round(1.67867 * 64) */ - -// Y contribution to R,G,B. Scale and bias. -#define YG 19003 /* round(1.164384 * 64 * 256 * 256 / 257) */ -#define YB -1160 /* 1.164384 * 64 * -16 + 64 / 2 */ - -MAKEYUVCONSTANTS(2020, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -// BT.2020 full range YUV to RGB reference -// R = Y + V * 1.474600 -// G = Y - U * 0.164553 - V * 0.571353 -// B = Y + U * 1.881400 -// KR = 0.2627; KB = 0.0593 - -#define UB 120 /* round(1.881400 * 64) */ -#define UG 11 /* round(0.164553 * 64) */ -#define VG 37 /* round(0.571353 * 64) */ -#define VR 94 /* round(1.474600 * 64) */ - -// Y contribution to R,G,B. Scale and bias. (same as jpeg) -#define YG 16320 /* round(1 * 64 * 256 * 256 / 257) */ -#define YB 32 /* 64 / 2 */ - -MAKEYUVCONSTANTS(V2020, YG, YB, UB, UG, VG, VR) - -#undef YG -#undef YB -#undef UB -#undef UG -#undef VG -#undef VR - -#undef BB -#undef BG -#undef BR - -#undef MAKEYUVCONSTANTS - -#if defined(__aarch64__) || defined(__arm__) -#define LOAD_YUV_CONSTANTS \ - int ub = yuvconstants->kUVCoeff[0]; \ - int vr = yuvconstants->kUVCoeff[1]; \ - int ug = yuvconstants->kUVCoeff[2]; \ - int vg = yuvconstants->kUVCoeff[3]; \ - int yg = yuvconstants->kRGBCoeffBias[0]; \ - int bb = yuvconstants->kRGBCoeffBias[1]; \ - int bg = yuvconstants->kRGBCoeffBias[2]; \ - int br = yuvconstants->kRGBCoeffBias[3] - -#define CALC_RGB16 \ - int32_t y1 = (uint32_t)(y32 * yg) >> 16; \ - int b16 = y1 + (u * ub) - bb; \ - int g16 = y1 + bg - (u * ug + v * vg); \ - int r16 = y1 + (v * vr) - br -#else -#define LOAD_YUV_CONSTANTS \ - int ub = yuvconstants->kUVToB[0]; \ - int ug = yuvconstants->kUVToG[0]; \ - int vg = yuvconstants->kUVToG[1]; \ - int vr = yuvconstants->kUVToR[1]; \ - int yg = yuvconstants->kYToRgb[0]; \ - int yb = yuvconstants->kYBiasToRgb[0] - -#define CALC_RGB16 \ - int32_t y1 = ((uint32_t)(y32 * yg) >> 16) + yb; \ - int8_t ui = (int8_t)u; \ - int8_t vi = (int8_t)v; \ - ui -= 0x80; \ - vi -= 0x80; \ - int b16 = y1 + (ui * ub); \ - int g16 = y1 - (ui * ug + vi * vg); \ - int r16 = y1 + (vi * vr) -#endif - -void MirrorRow_C(const uint8_t *src, uint8_t *dst, int width) { - int x; - src += width - 1; - for (x = 0; x < width - 1; x += 2) { - dst[x] = src[0]; - dst[x + 1] = src[-1]; - src -= 2; - } - if (width & 1) { - dst[width - 1] = src[0]; - } -} - -// Use scale to convert lsb formats to msb, depending how many bits there are: -// 32768 = 9 bits -// 16384 = 10 bits -// 4096 = 12 bits -// 256 = 16 bits -// TODO(fbarchard): change scale to bits -#define C16TO8(v, scale) clamp255(((v) * (scale)) >> 16) - -void CopyRow_C(const uint8_t *src, uint8_t *dst, int count) { - memcpy(dst, src, count); -} - -// Divide source RGB by alpha and store to destination. -// b = (b * 255 + (a / 2)) / a; -// g = (g * 255 + (a / 2)) / a; -// r = (r * 255 + (a / 2)) / a; -// Reciprocal method is off by 1 on some values. ie 125 -// 8.8 fixed point inverse table with 1.0 in upper short and 1 / a in lower. -#define T(a) 0x01000000 + (0x10000 / a) -const uint32_t fixed_invtbl8[256] = { - 0x01000000, 0x0100ffff, T(0x02), T(0x03), T(0x04), T(0x05), T(0x06), - T(0x07), T(0x08), T(0x09), T(0x0a), T(0x0b), T(0x0c), T(0x0d), - T(0x0e), T(0x0f), T(0x10), T(0x11), T(0x12), T(0x13), T(0x14), - T(0x15), T(0x16), T(0x17), T(0x18), T(0x19), T(0x1a), T(0x1b), - T(0x1c), T(0x1d), T(0x1e), T(0x1f), T(0x20), T(0x21), T(0x22), - T(0x23), T(0x24), T(0x25), T(0x26), T(0x27), T(0x28), T(0x29), - T(0x2a), T(0x2b), T(0x2c), T(0x2d), T(0x2e), T(0x2f), T(0x30), - T(0x31), T(0x32), T(0x33), T(0x34), T(0x35), T(0x36), T(0x37), - T(0x38), T(0x39), T(0x3a), T(0x3b), T(0x3c), T(0x3d), T(0x3e), - T(0x3f), T(0x40), T(0x41), T(0x42), T(0x43), T(0x44), T(0x45), - T(0x46), T(0x47), T(0x48), T(0x49), T(0x4a), T(0x4b), T(0x4c), - T(0x4d), T(0x4e), T(0x4f), T(0x50), T(0x51), T(0x52), T(0x53), - T(0x54), T(0x55), T(0x56), T(0x57), T(0x58), T(0x59), T(0x5a), - T(0x5b), T(0x5c), T(0x5d), T(0x5e), T(0x5f), T(0x60), T(0x61), - T(0x62), T(0x63), T(0x64), T(0x65), T(0x66), T(0x67), T(0x68), - T(0x69), T(0x6a), T(0x6b), T(0x6c), T(0x6d), T(0x6e), T(0x6f), - T(0x70), T(0x71), T(0x72), T(0x73), T(0x74), T(0x75), T(0x76), - T(0x77), T(0x78), T(0x79), T(0x7a), T(0x7b), T(0x7c), T(0x7d), - T(0x7e), T(0x7f), T(0x80), T(0x81), T(0x82), T(0x83), T(0x84), - T(0x85), T(0x86), T(0x87), T(0x88), T(0x89), T(0x8a), T(0x8b), - T(0x8c), T(0x8d), T(0x8e), T(0x8f), T(0x90), T(0x91), T(0x92), - T(0x93), T(0x94), T(0x95), T(0x96), T(0x97), T(0x98), T(0x99), - T(0x9a), T(0x9b), T(0x9c), T(0x9d), T(0x9e), T(0x9f), T(0xa0), - T(0xa1), T(0xa2), T(0xa3), T(0xa4), T(0xa5), T(0xa6), T(0xa7), - T(0xa8), T(0xa9), T(0xaa), T(0xab), T(0xac), T(0xad), T(0xae), - T(0xaf), T(0xb0), T(0xb1), T(0xb2), T(0xb3), T(0xb4), T(0xb5), - T(0xb6), T(0xb7), T(0xb8), T(0xb9), T(0xba), T(0xbb), T(0xbc), - T(0xbd), T(0xbe), T(0xbf), T(0xc0), T(0xc1), T(0xc2), T(0xc3), - T(0xc4), T(0xc5), T(0xc6), T(0xc7), T(0xc8), T(0xc9), T(0xca), - T(0xcb), T(0xcc), T(0xcd), T(0xce), T(0xcf), T(0xd0), T(0xd1), - T(0xd2), T(0xd3), T(0xd4), T(0xd5), T(0xd6), T(0xd7), T(0xd8), - T(0xd9), T(0xda), T(0xdb), T(0xdc), T(0xdd), T(0xde), T(0xdf), - T(0xe0), T(0xe1), T(0xe2), T(0xe3), T(0xe4), T(0xe5), T(0xe6), - T(0xe7), T(0xe8), T(0xe9), T(0xea), T(0xeb), T(0xec), T(0xed), - T(0xee), T(0xef), T(0xf0), T(0xf1), T(0xf2), T(0xf3), T(0xf4), - T(0xf5), T(0xf6), T(0xf7), T(0xf8), T(0xf9), T(0xfa), T(0xfb), - T(0xfc), T(0xfd), T(0xfe), 0x01000100}; -#undef T - -// Blend 2 rows into 1. -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; - } -} - -// C version 2x2 -> 2x1. -void InterpolateRow_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int width, - int source_y_fraction) { - int y1_fraction = source_y_fraction; - int y0_fraction = 256 - y1_fraction; - const uint8_t *src_ptr1 = src_ptr + src_stride; - int x; - assert(source_y_fraction >= 0); - assert(source_y_fraction < 256); - - if (y1_fraction == 0) { - memcpy(dst_ptr, src_ptr, width); - return; - } - if (y1_fraction == 128) { - HalfRow_C(src_ptr, src_stride, dst_ptr, width); - return; - } - for (x = 0; x < width; ++x) { - dst_ptr[0] = STATIC_CAST( - uint8_t, - (src_ptr[0] * y0_fraction + src_ptr1[0] * y1_fraction + 128) >> 8); - ++src_ptr; - ++src_ptr1; - ++dst_ptr; - } -} - -// Work around GCC 7 punning warning -Wstrict-aliasing -#if defined(__GNUC__) -typedef uint32_t __attribute__((__may_alias__)) uint32_alias_t; -#else -typedef uint32_t uint32_alias_t; -#endif - -#undef STATIC_CAST diff --git a/pkg/encoder/yuv/libyuv/row_gcc.c b/pkg/encoder/yuv/libyuv/row_gcc.c deleted file mode 100644 index 07e795e60..000000000 --- a/pkg/encoder/yuv/libyuv/row_gcc.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * 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 "row.h" - -// This module is for GCC x86 and x64. -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3) - -// Constants for ARGB -static const uvec8 kARGBToY = {25u, 129u, 66u, 0u, 25u, 129u, 66u, 0u, - 25u, 129u, 66u, 0u, 25u, 129u, 66u, 0u}; - - -#endif // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_ARGBGRAYROW_SSSE3) - -#if defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3) - -static const vec8 kARGBToU = {112, -74, -38, 0, 112, -74, -38, 0, - 112, -74, -38, 0, 112, -74, -38, 0}; - -static const vec8 kARGBToV = {-18, -94, 112, 0, -18, -94, 112, 0, - -18, -94, 112, 0, -18, -94, 112, 0}; - -// Constants for BGRA -static const uvec8 kBGRAToY = {0u, 66u, 129u, 25u, 0u, 66u, 129u, 25u, - 0u, 66u, 129u, 25u, 0u, 66u, 129u, 25u}; - -static const vec8 kBGRAToU = {0, -38, -74, 112, 0, -38, -74, 112, - 0, -38, -74, 112, 0, -38, -74, 112}; - -static const vec8 kBGRAToV = {0, 112, -94, -18, 0, 112, -94, -18, - 0, 112, -94, -18, 0, 112, -94, -18}; - -// Constants for ABGR -static const uvec8 kABGRToY = {66u, 129u, 25u, 0u, 66u, 129u, 25u, 0u, - 66u, 129u, 25u, 0u, 66u, 129u, 25u, 0u}; - -static const vec8 kABGRToU = {-38, -74, 112, 0, -38, -74, 112, 0, - -38, -74, 112, 0, -38, -74, 112, 0}; - -static const vec8 kABGRToV = {112, -94, -18, 0, 112, -94, -18, 0, - 112, -94, -18, 0, 112, -94, -18, 0}; - -// Constants for RGBA. -//static const uvec8 kRGBAToY = {0u, 25u, 129u, 66u, 0u, 25u, 129u, 66u, -// 0u, 25u, 129u, 66u, 0u, 25u, 129u, 66u}; - -static const vec8 kRGBAToU = {0, 112, -74, -38, 0, 112, -74, -38, - 0, 112, -74, -38, 0, 112, -74, -38}; - -static const vec8 kRGBAToV = {0, -18, -94, 112, 0, -18, -94, 112, - 0, -18, -94, 112, 0, -18, -94, 112}; - -static const uvec16 kAddY16 = {0x7e80u, 0x7e80u, 0x7e80u, 0x7e80u, - 0x7e80u, 0x7e80u, 0x7e80u, 0x7e80u}; - -static const uvec8 kAddUV128 = {128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u, - 128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u}; - -static const uvec16 kSub128 = {0x8080u, 0x8080u, 0x8080u, 0x8080u, - 0x8080u, 0x8080u, 0x8080u, 0x8080u}; - -#endif // defined(HAS_ARGBTOYROW_SSSE3) || defined(HAS_I422TOARGBROW_SSSE3) - -// clang-format off - -// TODO(mraptis): Consider passing R, G, B multipliers as parameter. -// round parameter is register containing value to add before shift. -#define RGBTOY(round) \ - "1: \n" \ - "movdqu (%0),%%xmm0 \n" \ - "movdqu 0x10(%0),%%xmm1 \n" \ - "movdqu 0x20(%0),%%xmm2 \n" \ - "movdqu 0x30(%0),%%xmm3 \n" \ - "psubb %%xmm5,%%xmm0 \n" \ - "psubb %%xmm5,%%xmm1 \n" \ - "psubb %%xmm5,%%xmm2 \n" \ - "psubb %%xmm5,%%xmm3 \n" \ - "movdqu %%xmm4,%%xmm6 \n" \ - "pmaddubsw %%xmm0,%%xmm6 \n" \ - "movdqu %%xmm4,%%xmm0 \n" \ - "pmaddubsw %%xmm1,%%xmm0 \n" \ - "movdqu %%xmm4,%%xmm1 \n" \ - "pmaddubsw %%xmm2,%%xmm1 \n" \ - "movdqu %%xmm4,%%xmm2 \n" \ - "pmaddubsw %%xmm3,%%xmm2 \n" \ - "lea 0x40(%0),%0 \n" \ - "phaddw %%xmm0,%%xmm6 \n" \ - "phaddw %%xmm2,%%xmm1 \n" \ - "prefetcht0 1280(%0) \n" \ - "paddw %%" #round ",%%xmm6 \n" \ - "paddw %%" #round ",%%xmm1 \n" \ - "psrlw $0x8,%%xmm6 \n" \ - "psrlw $0x8,%%xmm1 \n" \ - "packuswb %%xmm1,%%xmm6 \n" \ - "movdqu %%xmm6,(%1) \n" \ - "lea 0x10(%1),%1 \n" \ - "sub $0x10,%2 \n" \ - "jg 1b \n" - -#define RGBTOY_AVX2(round) \ - "1: \n" \ - "vmovdqu (%0),%%ymm0 \n" \ - "vmovdqu 0x20(%0),%%ymm1 \n" \ - "vmovdqu 0x40(%0),%%ymm2 \n" \ - "vmovdqu 0x60(%0),%%ymm3 \n" \ - "vpsubb %%ymm5, %%ymm0, %%ymm0 \n" \ - "vpsubb %%ymm5, %%ymm1, %%ymm1 \n" \ - "vpsubb %%ymm5, %%ymm2, %%ymm2 \n" \ - "vpsubb %%ymm5, %%ymm3, %%ymm3 \n" \ - "vpmaddubsw %%ymm0,%%ymm4,%%ymm0 \n" \ - "vpmaddubsw %%ymm1,%%ymm4,%%ymm1 \n" \ - "vpmaddubsw %%ymm2,%%ymm4,%%ymm2 \n" \ - "vpmaddubsw %%ymm3,%%ymm4,%%ymm3 \n" \ - "lea 0x80(%0),%0 \n" \ - "vphaddw %%ymm1,%%ymm0,%%ymm0 \n" /* mutates. */ \ - "vphaddw %%ymm3,%%ymm2,%%ymm2 \n" \ - "prefetcht0 1280(%0) \n" \ - "vpaddw %%" #round ",%%ymm0,%%ymm0 \n" /* Add .5 for rounding. */ \ - "vpaddw %%" #round ",%%ymm2,%%ymm2 \n" \ - "vpsrlw $0x8,%%ymm0,%%ymm0 \n" \ - "vpsrlw $0x8,%%ymm2,%%ymm2 \n" \ - "vpackuswb %%ymm2,%%ymm0,%%ymm0 \n" /* mutates. */ \ - "vpermd %%ymm0,%%ymm6,%%ymm0 \n" /* unmutate. */ \ - "vmovdqu %%ymm0,(%1) \n" \ - "lea 0x20(%1),%1 \n" \ - "sub $0x20,%2 \n" \ - "jg 1b \n" \ - "vzeroupper \n" - -// clang-format on - -#ifdef HAS_ARGBTOYROW_SSSE3 - -// Convert 16 ARGB pixels (64 bytes) to 16 Y values. -void ARGBToYRow_SSSE3(const uint8_t *src_argb, uint8_t *dst_y, int width) { - asm volatile( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - "movdqa %5,%%xmm7 \n" - - LABELALIGN RGBTOY(xmm7) - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(width) // %2 - : "m"(kARGBToY), // %3 - "m"(kSub128), // %4 - "m"(kAddY16) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // HAS_ARGBTOYROW_SSSE3 - -#if defined(HAS_ARGBTOYROW_AVX2) || defined(HAS_ABGRTOYROW_AVX2) || \ - defined(HAS_ARGBEXTRACTALPHAROW_AVX2) -// vpermd for vphaddw + vpackuswb vpermd. -static const lvec32 kPermdARGBToY_AVX = {0, 4, 1, 5, 2, 6, 3, 7}; -#endif - -#ifdef HAS_ARGBTOYROW_AVX2 - -// Convert 32 ARGB pixels (128 bytes) to 32 Y values. -void ARGBToYRow_AVX2(const uint8_t *src_argb, uint8_t *dst_y, int width) { - asm volatile( - "vbroadcastf128 %3,%%ymm4 \n" - "vbroadcastf128 %4,%%ymm5 \n" - "vbroadcastf128 %5,%%ymm7 \n" - "vmovdqu %6,%%ymm6 \n" LABELALIGN RGBTOY_AVX2( - ymm7) "vzeroupper \n" - : "+r"(src_argb), // %0 - "+r"(dst_y), // %1 - "+r"(width) // %2 - : "m"(kARGBToY), // %3 - "m"(kSub128), // %4 - "m"(kAddY16), // %5 - "m"(kPermdARGBToY_AVX) // %6 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // HAS_ARGBTOYROW_AVX2 - -#ifdef HAS_ABGRTOYROW_AVX2 - -// Convert 32 ABGR pixels (128 bytes) to 32 Y values. -void ABGRToYRow_AVX2(const uint8_t *src_abgr, uint8_t *dst_y, int width) { - asm volatile( - "vbroadcastf128 %3,%%ymm4 \n" - "vbroadcastf128 %4,%%ymm5 \n" - "vbroadcastf128 %5,%%ymm7 \n" - "vmovdqu %6,%%ymm6 \n" LABELALIGN RGBTOY_AVX2( - ymm7) "vzeroupper \n" - : "+r"(src_abgr), // %0 - "+r"(dst_y), // %1 - "+r"(width) // %2 - : "m"(kABGRToY), // %3 - "m"(kSub128), // %4 - "m"(kAddY16), // %5 - "m"(kPermdARGBToY_AVX) // %6 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // HAS_ABGRTOYROW_AVX2 - -#ifdef HAS_ARGBTOUVROW_SSSE3 - -void ARGBToUVRow_SSSE3(const uint8_t *src_argb, - int src_stride_argb, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "movdqa %5,%%xmm3 \n" - "movdqa %6,%%xmm4 \n" - "movdqa %7,%%xmm5 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x10(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm1 \n" - "movdqu 0x20(%0),%%xmm2 \n" - "movdqu 0x20(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqu 0x30(%0),%%xmm6 \n" - "movdqu 0x30(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - - "lea 0x40(%0),%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "movlps %%xmm0,(%1) \n" - "movhps %%xmm0,0x00(%1,%2,1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_argb), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_argb)), // %4 - "m"(kARGBToV), // %5 - "m"(kARGBToU), // %6 - "m"(kAddUV128) // %7 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm6", "xmm7"); -} - -#endif // HAS_ARGBTOUVROW_SSSE3 - -#if defined(HAS_ARGBTOUVROW_AVX2) || defined(HAS_ABGRTOUVROW_AVX2) || \ - defined(HAS_ARGBTOUVJROW_AVX2) || defined(HAS_ABGRTOUVJROW_AVX2) -// vpshufb for vphaddw + vpackuswb packed to shorts. -static const lvec8 kShufARGBToUV_AVX = { - 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15, - 0, 1, 8, 9, 2, 3, 10, 11, 4, 5, 12, 13, 6, 7, 14, 15}; -#endif - -#if defined(HAS_ARGBTOUVROW_AVX2) - -void ARGBToUVRow_AVX2(const uint8_t *src_argb, - int src_stride_argb, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "vbroadcastf128 %5,%%ymm5 \n" - "vbroadcastf128 %6,%%ymm6 \n" - "vbroadcastf128 %7,%%ymm7 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "vmovdqu 0x40(%0),%%ymm2 \n" - "vmovdqu 0x60(%0),%%ymm3 \n" - "vpavgb 0x00(%0,%4,1),%%ymm0,%%ymm0 \n" - "vpavgb 0x20(%0,%4,1),%%ymm1,%%ymm1 \n" - "vpavgb 0x40(%0,%4,1),%%ymm2,%%ymm2 \n" - "vpavgb 0x60(%0,%4,1),%%ymm3,%%ymm3 \n" - "lea 0x80(%0),%0 \n" - "vshufps $0x88,%%ymm1,%%ymm0,%%ymm4 \n" - "vshufps $0xdd,%%ymm1,%%ymm0,%%ymm0 \n" - "vpavgb %%ymm4,%%ymm0,%%ymm0 \n" - "vshufps $0x88,%%ymm3,%%ymm2,%%ymm4 \n" - "vshufps $0xdd,%%ymm3,%%ymm2,%%ymm2 \n" - "vpavgb %%ymm4,%%ymm2,%%ymm2 \n" - - "vpmaddubsw %%ymm7,%%ymm0,%%ymm1 \n" - "vpmaddubsw %%ymm7,%%ymm2,%%ymm3 \n" - "vpmaddubsw %%ymm6,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm6,%%ymm2,%%ymm2 \n" - "vphaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vphaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpsraw $0x8,%%ymm1,%%ymm1 \n" - "vpsraw $0x8,%%ymm0,%%ymm0 \n" - "vpacksswb %%ymm0,%%ymm1,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vpshufb %8,%%ymm0,%%ymm0 \n" - "vpaddb %%ymm5,%%ymm0,%%ymm0 \n" - - "vextractf128 $0x0,%%ymm0,(%1) \n" - "vextractf128 $0x1,%%ymm0,0x0(%1,%2,1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x20,%3 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_argb), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_argb)), // %4 - "m"(kAddUV128), // %5 - "m"(kARGBToV), // %6 - "m"(kARGBToU), // %7 - "m"(kShufARGBToUV_AVX) // %8 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // HAS_ARGBTOUVROW_AVX2 - -#ifdef HAS_ABGRTOUVROW_AVX2 - -void ABGRToUVRow_AVX2(const uint8_t *src_abgr, - int src_stride_abgr, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "vbroadcastf128 %5,%%ymm5 \n" - "vbroadcastf128 %6,%%ymm6 \n" - "vbroadcastf128 %7,%%ymm7 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "vmovdqu 0x40(%0),%%ymm2 \n" - "vmovdqu 0x60(%0),%%ymm3 \n" - "vpavgb 0x00(%0,%4,1),%%ymm0,%%ymm0 \n" - "vpavgb 0x20(%0,%4,1),%%ymm1,%%ymm1 \n" - "vpavgb 0x40(%0,%4,1),%%ymm2,%%ymm2 \n" - "vpavgb 0x60(%0,%4,1),%%ymm3,%%ymm3 \n" - "lea 0x80(%0),%0 \n" - "vshufps $0x88,%%ymm1,%%ymm0,%%ymm4 \n" - "vshufps $0xdd,%%ymm1,%%ymm0,%%ymm0 \n" - "vpavgb %%ymm4,%%ymm0,%%ymm0 \n" - "vshufps $0x88,%%ymm3,%%ymm2,%%ymm4 \n" - "vshufps $0xdd,%%ymm3,%%ymm2,%%ymm2 \n" - "vpavgb %%ymm4,%%ymm2,%%ymm2 \n" - - "vpmaddubsw %%ymm7,%%ymm0,%%ymm1 \n" - "vpmaddubsw %%ymm7,%%ymm2,%%ymm3 \n" - "vpmaddubsw %%ymm6,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm6,%%ymm2,%%ymm2 \n" - "vphaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vphaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpsraw $0x8,%%ymm1,%%ymm1 \n" - "vpsraw $0x8,%%ymm0,%%ymm0 \n" - "vpacksswb %%ymm0,%%ymm1,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vpshufb %8,%%ymm0,%%ymm0 \n" - "vpaddb %%ymm5,%%ymm0,%%ymm0 \n" - - "vextractf128 $0x0,%%ymm0,(%1) \n" - "vextractf128 $0x1,%%ymm0,0x0(%1,%2,1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x20,%3 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_abgr), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_abgr)), // %4 - "m"(kAddUV128), // %5 - "m"(kABGRToV), // %6 - "m"(kABGRToU), // %7 - "m"(kShufARGBToUV_AVX) // %8 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif // HAS_ABGRTOUVROW_AVX2 - -void BGRAToYRow_SSSE3(const uint8_t *src_bgra, uint8_t *dst_y, int width) { - asm volatile( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - "movdqa %5,%%xmm7 \n" - - LABELALIGN RGBTOY(xmm7) - : "+r"(src_bgra), // %0 - "+r"(dst_y), // %1 - "+r"(width) // %2 - : "m"(kBGRAToY), // %3 - "m"(kSub128), // %4 - "m"(kAddY16) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -void BGRAToUVRow_SSSE3(const uint8_t *src_bgra, - int src_stride_bgra, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "movdqa %5,%%xmm3 \n" - "movdqa %6,%%xmm4 \n" - "movdqa %7,%%xmm5 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x10(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm1 \n" - "movdqu 0x20(%0),%%xmm2 \n" - "movdqu 0x20(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqu 0x30(%0),%%xmm6 \n" - "movdqu 0x30(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - - "lea 0x40(%0),%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "movlps %%xmm0,(%1) \n" - "movhps %%xmm0,0x00(%1,%2,1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_bgra), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_bgra)), // %4 - "m"(kBGRAToV), // %5 - "m"(kBGRAToU), // %6 - "m"(kAddUV128) // %7 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm6", "xmm7"); -} - -void ABGRToYRow_SSSE3(const uint8_t *src_abgr, uint8_t *dst_y, int width) { - asm volatile( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - "movdqa %5,%%xmm7 \n" - - LABELALIGN RGBTOY(xmm7) - : "+r"(src_abgr), // %0 - "+r"(dst_y), // %1 - "+r"(width) // %2 - : "m"(kABGRToY), // %3 - "m"(kSub128), // %4 - "m"(kAddY16) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -void ABGRToUVRow_SSSE3(const uint8_t *src_abgr, - int src_stride_abgr, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "movdqa %5,%%xmm3 \n" - "movdqa %6,%%xmm4 \n" - "movdqa %7,%%xmm5 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x10(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm1 \n" - "movdqu 0x20(%0),%%xmm2 \n" - "movdqu 0x20(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqu 0x30(%0),%%xmm6 \n" - "movdqu 0x30(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - - "lea 0x40(%0),%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "movlps %%xmm0,(%1) \n" - "movhps %%xmm0,0x00(%1,%2,1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_abgr), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_abgr)), // %4 - "m"(kABGRToV), // %5 - "m"(kABGRToU), // %6 - "m"(kAddUV128) // %7 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm6", "xmm7"); -} - -void RGBAToUVRow_SSSE3(const uint8_t *src_rgba, - int src_stride_rgba, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - asm volatile( - "movdqa %5,%%xmm3 \n" - "movdqa %6,%%xmm4 \n" - "movdqa %7,%%xmm5 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x10(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm1 \n" - "movdqu 0x20(%0),%%xmm2 \n" - "movdqu 0x20(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqu 0x30(%0),%%xmm6 \n" - "movdqu 0x30(%0,%4,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - - "lea 0x40(%0),%0 \n" - "movdqa %%xmm0,%%xmm7 \n" - "shufps $0x88,%%xmm1,%%xmm0 \n" - "shufps $0xdd,%%xmm1,%%xmm7 \n" - "pavgb %%xmm7,%%xmm0 \n" - "movdqa %%xmm2,%%xmm7 \n" - "shufps $0x88,%%xmm6,%%xmm2 \n" - "shufps $0xdd,%%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "movdqa %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm3,%%xmm1 \n" - "pmaddubsw %%xmm3,%%xmm6 \n" - "phaddw %%xmm2,%%xmm0 \n" - "phaddw %%xmm6,%%xmm1 \n" - "psraw $0x8,%%xmm0 \n" - "psraw $0x8,%%xmm1 \n" - "packsswb %%xmm1,%%xmm0 \n" - "paddb %%xmm5,%%xmm0 \n" - "movlps %%xmm0,(%1) \n" - "movhps %%xmm0,0x00(%1,%2,1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x10,%3 \n" - "jg 1b \n" - : "+r"(src_rgba), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+rm"(width) // %3 - : "r"((intptr_t) (src_stride_rgba)), // %4 - "m"(kRGBAToV), // %5 - "m"(kRGBAToU), // %6 - "m"(kAddUV128) // %7 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm6", "xmm7"); -} - -#ifdef HAS_MIRRORROW_SSSE3 -// Shuffle table for reversing the bytes. -static const uvec8 kShuffleMirror = {15u, 14u, 13u, 12u, 11u, 10u, 9u, 8u, - 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u}; - -void MirrorRow_SSSE3(const uint8_t *src, uint8_t *dst, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "movdqa %3,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu -0x10(%0,%2,1),%%xmm0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : "m"(kShuffleMirror) // %3 - : "memory", "cc", "xmm0", "xmm5"); -} - -#endif // HAS_MIRRORROW_SSSE3 - -#ifdef HAS_MIRRORROW_AVX2 - -void MirrorRow_AVX2(const uint8_t *src, uint8_t *dst, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "vbroadcastf128 %3,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu -0x20(%0,%2,1),%%ymm0 \n" - "vpshufb %%ymm5,%%ymm0,%%ymm0 \n" - "vpermq $0x4e,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : "m"(kShuffleMirror) // %3 - : "memory", "cc", "xmm0", "xmm5"); -} - -#endif // HAS_MIRRORROW_AVX2 - -#ifdef HAS_MIRRORUVROW_SSSE3 -// Shuffle table for reversing the UV. -static const uvec8 kShuffleMirrorUV = {14u, 15u, 12u, 13u, 10u, 11u, 8u, 9u, - 6u, 7u, 4u, 5u, 2u, 3u, 0u, 1u}; - -void MirrorUVRow_SSSE3(const uint8_t *src_uv, uint8_t *dst_uv, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "movdqa %3,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu -0x10(%0,%2,2),%%xmm0 \n" - "pshufb %%xmm5,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_uv), // %0 - "+r"(dst_uv), // %1 - "+r"(temp_width) // %2 - : "m"(kShuffleMirrorUV) // %3 - : "memory", "cc", "xmm0", "xmm5"); -} - -#endif // HAS_MIRRORUVROW_SSSE3 - -#ifdef HAS_MIRRORUVROW_AVX2 - -void MirrorUVRow_AVX2(const uint8_t *src_uv, uint8_t *dst_uv, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "vbroadcastf128 %3,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu -0x20(%0,%2,2),%%ymm0 \n" - "vpshufb %%ymm5,%%ymm0,%%ymm0 \n" - "vpermq $0x4e,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_uv), // %0 - "+r"(dst_uv), // %1 - "+r"(temp_width) // %2 - : "m"(kShuffleMirrorUV) // %3 - : "memory", "cc", "xmm0", "xmm5"); -} - -#endif // HAS_MIRRORUVROW_AVX2 - -#ifdef HAS_MIRRORSPLITUVROW_SSSE3 -// Shuffle table for reversing the bytes of UV channels. -static const uvec8 kShuffleMirrorSplitUV = {14u, 12u, 10u, 8u, 6u, 4u, 2u, 0u, - 15u, 13u, 11u, 9u, 7u, 5u, 3u, 1u}; - -void MirrorSplitUVRow_SSSE3(const uint8_t *src, - uint8_t *dst_u, - uint8_t *dst_v, - int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - "movdqa %4,%%xmm1 \n" - "lea -0x10(%0,%3,2),%0 \n" - "sub %1,%2 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "lea -0x10(%0),%0 \n" - "pshufb %%xmm1,%%xmm0 \n" - "movlpd %%xmm0,(%1) \n" - "movhpd %%xmm0,0x00(%1,%2,1) \n" - "lea 0x8(%1),%1 \n" - "sub $8,%3 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst_u), // %1 - "+r"(dst_v), // %2 - "+r"(temp_width) // %3 - : "m"(kShuffleMirrorSplitUV) // %4 - : "memory", "cc", "xmm0", "xmm1"); -} - -#endif // HAS_MIRRORSPLITUVROW_SSSE3 - -#ifdef HAS_ARGBMIRRORROW_SSE2 - -void ARGBMirrorRow_SSE2(const uint8_t *src, uint8_t *dst, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "lea -0x10(%0,%2,4),%0 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "pshufd $0x1b,%%xmm0,%%xmm0 \n" - "lea -0x10(%0),%0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : - : "memory", "cc", "xmm0"); -} - -#endif // HAS_ARGBMIRRORROW_SSE2 - -#ifdef HAS_ARGBMIRRORROW_AVX2 -// Shuffle table for reversing the bytes. -static const ulvec32 kARGBShuffleMirror_AVX2 = {7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u}; - -void ARGBMirrorRow_AVX2(const uint8_t *src, uint8_t *dst, int width) { - intptr_t temp_width = (intptr_t) (width); - asm volatile( - - "vmovdqu %3,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vpermd -0x20(%0,%2,4),%%ymm5,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(temp_width) // %2 - : "m"(kARGBShuffleMirror_AVX2) // %3 - : "memory", "cc", "xmm0", "xmm5"); -} - -#endif // HAS_ARGBMIRRORROW_AVX2 - - -#ifdef HAS_COPYROW_SSE2 - -void CopyRow_SSE2(const uint8_t *src, uint8_t *dst, int width) { - asm volatile( - "test $0xf,%0 \n" - "jne 2f \n" - "test $0xf,%1 \n" - "jne 2f \n" - - LABELALIGN - "1: \n" - "movdqa (%0),%%xmm0 \n" - "movdqa 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "movdqa %%xmm0,(%1) \n" - "movdqa %%xmm1,0x10(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "jmp 9f \n" - - LABELALIGN - "2: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "movdqu %%xmm0,(%1) \n" - "movdqu %%xmm1,0x10(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 2b \n" - - LABELALIGN "9: \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc", "xmm0", "xmm1"); -} - -#endif // HAS_COPYROW_SSE2 - -#ifdef HAS_COPYROW_AVX - -void CopyRow_AVX(const uint8_t *src, uint8_t *dst, int width) { - asm volatile( - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "lea 0x40(%0),%0 \n" - "vmovdqu %%ymm0,(%1) \n" - "vmovdqu %%ymm1,0x20(%1) \n" - "lea 0x40(%1),%1 \n" - "sub $0x40,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src), // %0 - "+r"(dst), // %1 - "+r"(width) // %2 - : - : "memory", "cc", "xmm0", "xmm1"); -} - -#endif // HAS_COPYROW_AVX - -#ifdef HAS_COPYROW_ERMS - -// Multiple of 1. -void CopyRow_ERMS(const uint8_t *src, uint8_t *dst, int width) { - size_t width_tmp = (size_t) (width); - asm volatile( - - "rep movsb \n" - : "+S"(src), // %0 - "+D"(dst), // %1 - "+c"(width_tmp) // %2 - : - : "memory", "cc"); -} - -#endif // HAS_COPYROW_ERMS - -#ifdef HAS_INTERPOLATEROW_SSSE3 - -// Bilinear filter 16x2 -> 16x1 -void InterpolateRow_SSSE3(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int width, - int source_y_fraction) { - asm volatile( - "sub %1,%0 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x80,%3 \n" - "je 50f \n" - - "movd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x100,%3 \n" - "movd %3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" - "punpcklwd %%xmm5,%%xmm5 \n" - "pshufd $0x0,%%xmm5,%%xmm5 \n" - "mov $0x80808080,%%eax \n" - "movd %%eax,%%xmm4 \n" - "pshufd $0x0,%%xmm4,%%xmm4 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "movdqu (%1),%%xmm0 \n" - "movdqu 0x00(%1,%4,1),%%xmm2 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm2,%%xmm0 \n" - "punpckhbw %%xmm2,%%xmm1 \n" - "psubb %%xmm4,%%xmm0 \n" - "psubb %%xmm4,%%xmm1 \n" - "movdqa %%xmm5,%%xmm2 \n" - "movdqa %%xmm5,%%xmm3 \n" - "pmaddubsw %%xmm0,%%xmm2 \n" - "pmaddubsw %%xmm1,%%xmm3 \n" - "paddw %%xmm4,%%xmm2 \n" - "paddw %%xmm4,%%xmm3 \n" - "psrlw $0x8,%%xmm2 \n" - "psrlw $0x8,%%xmm3 \n" - "packuswb %%xmm3,%%xmm2 \n" - "movdqu %%xmm2,0x00(%1,%0,1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "movdqu (%1),%%xmm0 \n" - "movdqu 0x00(%1,%4,1),%%xmm1 \n" - "pavgb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0,0x00(%1,%0,1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "movdqu (%1),%%xmm0 \n" - "movdqu %%xmm0,0x00(%1,%0,1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 100b \n" - - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+rm"(width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t) (src_stride)) // %4 - : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif // HAS_INTERPOLATEROW_SSSE3 - -#ifdef HAS_INTERPOLATEROW_AVX2 - -// Bilinear filter 32x2 -> 32x1 -void InterpolateRow_AVX2(uint8_t *dst_ptr, - const uint8_t *src_ptr, - ptrdiff_t src_stride, - int width, - int source_y_fraction) { - asm volatile( - "sub %1,%0 \n" - "cmp $0x0,%3 \n" - "je 100f \n" - "cmp $0x80,%3 \n" - "je 50f \n" - - "vmovd %3,%%xmm0 \n" - "neg %3 \n" - "add $0x100,%3 \n" - "vmovd %3,%%xmm5 \n" - "vpunpcklbw %%xmm0,%%xmm5,%%xmm5 \n" - "vpunpcklwd %%xmm5,%%xmm5,%%xmm5 \n" - "vbroadcastss %%xmm5,%%ymm5 \n" - "mov $0x80808080,%%eax \n" - "vmovd %%eax,%%xmm4 \n" - "vbroadcastss %%xmm4,%%ymm4 \n" - - // General purpose row blend. - LABELALIGN - "1: \n" - "vmovdqu (%1),%%ymm0 \n" - "vmovdqu 0x00(%1,%4,1),%%ymm2 \n" - "vpunpckhbw %%ymm2,%%ymm0,%%ymm1 \n" - "vpunpcklbw %%ymm2,%%ymm0,%%ymm0 \n" - "vpsubb %%ymm4,%%ymm1,%%ymm1 \n" - "vpsubb %%ymm4,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm1,%%ymm5,%%ymm1 \n" - "vpmaddubsw %%ymm0,%%ymm5,%%ymm0 \n" - "vpaddw %%ymm4,%%ymm1,%%ymm1 \n" - "vpaddw %%ymm4,%%ymm0,%%ymm0 \n" - "vpsrlw $0x8,%%ymm1,%%ymm1 \n" - "vpsrlw $0x8,%%ymm0,%%ymm0 \n" - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,0x00(%1,%0,1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "jmp 99f \n" - - // Blend 50 / 50. - LABELALIGN - "50: \n" - "vmovdqu (%1),%%ymm0 \n" - "vpavgb 0x00(%1,%4,1),%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,0x00(%1,%0,1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 50b \n" - "jmp 99f \n" - - // Blend 100 / 0 - Copy row unchanged. - LABELALIGN - "100: \n" - "vmovdqu (%1),%%ymm0 \n" - "vmovdqu %%ymm0,0x00(%1,%0,1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 100b \n" - - "99: \n" - "vzeroupper \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(width), // %2 - "+r"(source_y_fraction) // %3 - : "r"((intptr_t) (src_stride)) // %4 - : "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm4", "xmm5"); -} - -#endif // HAS_INTERPOLATEROW_AVX2 - -#endif // defined(__x86_64__) || defined(__i386__) diff --git a/pkg/encoder/yuv/libyuv/scale.c b/pkg/encoder/yuv/libyuv/scale.c deleted file mode 100644 index c4bd5b0b4..000000000 --- a/pkg/encoder/yuv/libyuv/scale.c +++ /dev/null @@ -1,946 +0,0 @@ -/* - * 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 "scale.h" - -#include -#include - -#include "cpu_id.h" -#include "planar_functions.h" // For CopyPlane -#include "row.h" -#include "scale_row.h" - -static __inline int Abs(int v) { - return v >= 0 ? v : -v; -} - -#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) -#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s) - -// Scale plane, 1/2 -// This is an optimized version for scaling down a plane to 1/2 of -// its original size. - -static void ScalePlaneDown2(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - int y; - void (*ScaleRowDown2)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width) = - filtering == kFilterNone - ? ScaleRowDown2_C - : (filtering == kFilterLinear ? ScaleRowDown2Linear_C - : ScaleRowDown2Box_C); - int row_stride = src_stride * 2; - (void) src_width; - (void) src_height; - if (!filtering) { - src_ptr += src_stride; // Point to odd rows. - src_stride = 0; - } - - -#if defined(HAS_SCALEROWDOWN2_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ScaleRowDown2 = - filtering == kFilterNone - ? ScaleRowDown2_Any_SSSE3 - : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3 - : ScaleRowDown2Box_Any_SSSE3); - if (IS_ALIGNED(dst_width, 16)) { - ScaleRowDown2 = - filtering == kFilterNone - ? ScaleRowDown2_SSSE3 - : (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3 - : ScaleRowDown2Box_SSSE3); - } - } -#endif -#if defined(HAS_SCALEROWDOWN2_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ScaleRowDown2 = - filtering == kFilterNone - ? ScaleRowDown2_Any_AVX2 - : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2 - : ScaleRowDown2Box_Any_AVX2); - if (IS_ALIGNED(dst_width, 32)) { - ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2 - : (filtering == kFilterLinear - ? ScaleRowDown2Linear_AVX2 - : ScaleRowDown2Box_AVX2); - } - } -#endif - - if (filtering == kFilterLinear) { - src_stride = 0; - } - // TODO(fbarchard): Loop through source height to allow odd height. - for (y = 0; y < dst_height; ++y) { - ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width); - src_ptr += row_stride; - dst_ptr += dst_stride; - } -} - -// Scale plane, 1/4 -// This is an optimized version for scaling down a plane to 1/4 of -// its original size. - -static void ScalePlaneDown4(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - int y; - void (*ScaleRowDown4)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width) = - filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C; - int row_stride = src_stride * 4; - (void) src_width; - (void) src_height; - if (!filtering) { - src_ptr += src_stride * 2; // Point to row 2. - src_stride = 0; - } - -#if defined(HAS_SCALEROWDOWN4_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - ScaleRowDown4 = - filtering ? ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3; - if (IS_ALIGNED(dst_width, 8)) { - ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3; - } - } -#endif -#if defined(HAS_SCALEROWDOWN4_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ScaleRowDown4 = - filtering ? ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2; - if (IS_ALIGNED(dst_width, 16)) { - ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2; - } - } -#endif - - if (filtering == kFilterLinear) { - src_stride = 0; - } - for (y = 0; y < dst_height; ++y) { - ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width); - src_ptr += row_stride; - dst_ptr += dst_stride; - } -} - -// Scale plane down, 3/4 -static void ScalePlaneDown34(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - int y; - void (*ScaleRowDown34_0)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width); - void (*ScaleRowDown34_1)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width); - const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; - (void) src_width; - (void) src_height; - assert(dst_width % 3 == 0); - if (!filtering) { - ScaleRowDown34_0 = ScaleRowDown34_C; - ScaleRowDown34_1 = ScaleRowDown34_C; - } else { - ScaleRowDown34_0 = ScaleRowDown34_0_Box_C; - ScaleRowDown34_1 = ScaleRowDown34_1_Box_C; - } - -#if defined(HAS_SCALEROWDOWN34_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - if (!filtering) { - ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3; - } else { - ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3; - } - if (dst_width % 24 == 0) { - if (!filtering) { - ScaleRowDown34_0 = ScaleRowDown34_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_SSSE3; - } else { - ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3; - ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3; - } - } - } -#endif - - for (y = 0; y < dst_height - 2; y += 3) { - ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride; - dst_ptr += dst_stride; - ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride; - dst_ptr += dst_stride; - ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width); - src_ptr += src_stride * 2; - dst_ptr += dst_stride; - } - - // Remainder 1 or 2 rows with last row vertically unfiltered - if ((dst_height % 3) == 2) { - ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride; - dst_ptr += dst_stride; - ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width); - } else if ((dst_height % 3) == 1) { - ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width); - } -} - -// Scale plane, 3/8 -// This is an optimized version for scaling down a plane to 3/8 -// of its original size. -// -// Uses box filter arranges like this -// aaabbbcc -> abc -// aaabbbcc def -// aaabbbcc ghi -// dddeeeff -// dddeeeff -// dddeeeff -// ggghhhii -// ggghhhii -// Boxes are 3x3, 2x3, 3x2 and 2x2 - -static void ScalePlaneDown38(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - int y; - void (*ScaleRowDown38_3)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width); - void (*ScaleRowDown38_2)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, int dst_width); - const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride; - assert(dst_width % 3 == 0); - (void) src_width; - (void) src_height; - if (!filtering) { - ScaleRowDown38_3 = ScaleRowDown38_C; - ScaleRowDown38_2 = ScaleRowDown38_C; - } else { - ScaleRowDown38_3 = ScaleRowDown38_3_Box_C; - ScaleRowDown38_2 = ScaleRowDown38_2_Box_C; - } - -#if defined(HAS_SCALEROWDOWN38_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - if (!filtering) { - ScaleRowDown38_3 = ScaleRowDown38_Any_SSSE3; - ScaleRowDown38_2 = ScaleRowDown38_Any_SSSE3; - } else { - ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_SSSE3; - ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_SSSE3; - } - if (dst_width % 12 == 0 && !filtering) { - ScaleRowDown38_3 = ScaleRowDown38_SSSE3; - ScaleRowDown38_2 = ScaleRowDown38_SSSE3; - } - if (dst_width % 6 == 0 && filtering) { - ScaleRowDown38_3 = ScaleRowDown38_3_Box_SSSE3; - ScaleRowDown38_2 = ScaleRowDown38_2_Box_SSSE3; - } - } -#endif - - for (y = 0; y < dst_height - 2; y += 3) { - ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride * 3; - dst_ptr += dst_stride; - ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride * 3; - dst_ptr += dst_stride; - ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride * 2; - dst_ptr += dst_stride; - } - - // Remainder 1 or 2 rows with last row vertically unfiltered - if ((dst_height % 3) == 2) { - ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width); - src_ptr += src_stride * 3; - dst_ptr += dst_stride; - ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width); - } else if ((dst_height % 3) == 1) { - ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width); - } -} - -#define MIN1(x) ((x) < 1 ? 1 : (x)) - -static __inline uint32_t SumPixels(int iboxwidth, const uint16_t *src_ptr) { - uint32_t sum = 0u; - int x; - assert(iboxwidth > 0); - for (x = 0; x < iboxwidth; ++x) { - sum += src_ptr[x]; - } - return sum; -} - -static __inline uint32_t SumPixels_16(int iboxwidth, const uint32_t *src_ptr) { - uint32_t sum = 0u; - int x; - assert(iboxwidth > 0); - for (x = 0; x < iboxwidth; ++x) { - sum += src_ptr[x]; - } - return sum; -} - -static void ScaleAddCols2_C(int dst_width, - int boxheight, - int x, - int dx, - const uint16_t *src_ptr, - uint8_t *dst_ptr) { - int i; - int scaletbl[2]; - int minboxwidth = dx >> 16; - int boxwidth; - scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight); - scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight); - for (i = 0; i < dst_width; ++i) { - int ix = x >> 16; - x += dx; - boxwidth = MIN1((x >> 16) - ix); - int scaletbl_index = boxwidth - minboxwidth; - assert((scaletbl_index == 0) || (scaletbl_index == 1)); - *dst_ptr++ = (uint8_t) (SumPixels(boxwidth, src_ptr + ix) * - scaletbl[scaletbl_index] >> - 16); - } -} - -static void ScaleAddCols0_C(int dst_width, - int boxheight, - int x, - int dx, - const uint16_t *src_ptr, - uint8_t *dst_ptr) { - int scaleval = 65536 / boxheight; - int i; - (void) dx; - src_ptr += (x >> 16); - for (i = 0; i < dst_width; ++i) { - *dst_ptr++ = (uint8_t) (src_ptr[i] * scaleval >> 16); - } -} - -static void ScaleAddCols1_C(int dst_width, - int boxheight, - int x, - int dx, - const uint16_t *src_ptr, - uint8_t *dst_ptr) { - int boxwidth = MIN1(dx >> 16); - int scaleval = 65536 / (boxwidth * boxheight); - int i; - x >>= 16; - for (i = 0; i < dst_width; ++i) { - *dst_ptr++ = (uint8_t) (SumPixels(boxwidth, src_ptr + x) * scaleval >> 16); - x += boxwidth; - } -} - -// Scale plane down to any dimensions, with interpolation. -// (boxfilter). -// -// Same method as SimpleScale, which is fixed point, outputting -// one pixel of destination using fixed point (16.16) to step -// through source, sampling a box of pixel with simple -// averaging. -static void ScalePlaneBox(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr) { - int j, k; - // Initial source x/y coordinate and step values as 16.16 fixed point. - int x = 0; - int y = 0; - int dx = 0; - int dy = 0; - const int max_y = (src_height << 16); - ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y, - &dx, &dy); - src_width = Abs(src_width); - { - // Allocate a row buffer of uint16_t. - align_buffer_64(row16, src_width * 2); - void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx, - const uint16_t *src_ptr, uint8_t *dst_ptr) = - (dx & 0xffff) ? ScaleAddCols2_C - : ((dx != 0x10000) ? ScaleAddCols1_C : ScaleAddCols0_C); - void (*ScaleAddRow)(const uint8_t *src_ptr, uint16_t *dst_ptr, - int src_width) = ScaleAddRow_C; -#if defined(HAS_SCALEADDROW_SSE2) - if (TestCpuFlag(kCpuHasSSE2)) { - ScaleAddRow = ScaleAddRow_Any_SSE2; - if (IS_ALIGNED(src_width, 16)) { - ScaleAddRow = ScaleAddRow_SSE2; - } - } -#endif -#if defined(HAS_SCALEADDROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - ScaleAddRow = ScaleAddRow_Any_AVX2; - if (IS_ALIGNED(src_width, 32)) { - ScaleAddRow = ScaleAddRow_AVX2; - } - } -#endif - - - for (j = 0; j < dst_height; ++j) { - int boxheight; - int iy = y >> 16; - const uint8_t *src = src_ptr + iy * (int64_t) src_stride; - y += dy; - if (y > max_y) { - y = max_y; - } - boxheight = MIN1((y >> 16) - iy); - memset(row16, 0, src_width * 2); - for (k = 0; k < boxheight; ++k) { - ScaleAddRow(src, (uint16_t *) (row16), src_width); - src += src_stride; - } - ScaleAddCols(dst_width, boxheight, x, dx, (uint16_t *) (row16), dst_ptr); - dst_ptr += dst_stride; - } - free_aligned_buffer_64(row16); - } -} - -// Scale plane down with bilinear interpolation. -static void ScalePlaneBilinearDown(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - // Initial source x/y coordinate and step values as 16.16 fixed point. - int x = 0; - int y = 0; - int dx = 0; - int dy = 0; - // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear. - // Allocate a row buffer. - align_buffer_64(row, src_width); - - const int max_y = (src_height - 1) << 16; - int j; - void (*ScaleFilterCols)(uint8_t *dst_ptr, const uint8_t *src_ptr, - int dst_width, int x, int dx) = - (src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C; - void (*InterpolateRow)(uint8_t *dst_ptr, const uint8_t *src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) = InterpolateRow_C; - ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, - &dx, &dy); - src_width = Abs(src_width); - -#if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - InterpolateRow = InterpolateRow_Any_SSSE3; - if (IS_ALIGNED(src_width, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } - } -#endif -#if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - InterpolateRow = InterpolateRow_Any_AVX2; - if (IS_ALIGNED(src_width, 32)) { - InterpolateRow = InterpolateRow_AVX2; - } - } -#endif - -#if defined(HAS_SCALEFILTERCOLS_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) { - ScaleFilterCols = ScaleFilterCols_SSSE3; - } -#endif - - if (y > max_y) { - y = max_y; - } - - for (j = 0; j < dst_height; ++j) { - int yi = y >> 16; - const uint8_t *src = src_ptr + yi * (int64_t) src_stride; - if (filtering == kFilterLinear) { - ScaleFilterCols(dst_ptr, src, dst_width, x, dx); - } else { - int yf = (y >> 8) & 255; - InterpolateRow(row, src, src_stride, src_width, yf); - ScaleFilterCols(dst_ptr, row, dst_width, x, dx); - } - dst_ptr += dst_stride; - y += dy; - if (y > max_y) { - y = max_y; - } - } - free_aligned_buffer_64(row); -} - -// Scale up down with bilinear interpolation. -static void ScalePlaneBilinearUp(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr, - enum FilterMode filtering) { - int j; - // Initial source x/y coordinate and step values as 16.16 fixed point. - int x = 0; - int y = 0; - int dx = 0; - int dy = 0; - const int max_y = (src_height - 1) << 16; - void (*InterpolateRow)(uint8_t *dst_ptr, const uint8_t *src_ptr, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) = InterpolateRow_C; - void (*ScaleFilterCols)(uint8_t *dst_ptr, const uint8_t *src_ptr, - int dst_width, int x, int dx) = - filtering ? ScaleFilterCols_C : ScaleCols_C; - ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y, - &dx, &dy); - src_width = Abs(src_width); - -#if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - InterpolateRow = InterpolateRow_Any_SSSE3; - if (IS_ALIGNED(dst_width, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } - } -#endif -#if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - InterpolateRow = InterpolateRow_Any_AVX2; - if (IS_ALIGNED(dst_width, 32)) { - InterpolateRow = InterpolateRow_AVX2; - } - } -#endif - - if (filtering && src_width >= 32768) { - ScaleFilterCols = ScaleFilterCols64_C; - } -#if defined(HAS_SCALEFILTERCOLS_SSSE3) - if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) { - ScaleFilterCols = ScaleFilterCols_SSSE3; - } -#endif - - if (!filtering && src_width * 2 == dst_width && x < 0x8000) { - ScaleFilterCols = ScaleColsUp2_C; -#if defined(HAS_SCALECOLS_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { - ScaleFilterCols = ScaleColsUp2_SSE2; - } -#endif - } - - if (y > max_y) { - y = max_y; - } - { - int yi = y >> 16; - const uint8_t *src = src_ptr + yi * (int64_t) src_stride; - - // Allocate 2 row buffers. - const int row_size = (dst_width + 31) & ~31; - align_buffer_64(row, row_size * 2); - - uint8_t *rowptr = row; - int rowstride = row_size; - int lasty = yi; - - ScaleFilterCols(rowptr, src, dst_width, x, dx); - if (src_height > 1) { - src += src_stride; - } - ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx); - if (src_height > 2) { - src += src_stride; - } - - for (j = 0; j < dst_height; ++j) { - yi = y >> 16; - if (yi != lasty) { - if (y > max_y) { - y = max_y; - yi = y >> 16; - src = src_ptr + yi * (int64_t) src_stride; - } - if (yi != lasty) { - ScaleFilterCols(rowptr, src, dst_width, x, dx); - rowptr += rowstride; - rowstride = -rowstride; - lasty = yi; - if ((y + 65536) < max_y) { - src += src_stride; - } - } - } - if (filtering == kFilterLinear) { - InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0); - } else { - int yf = (y >> 8) & 255; - InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf); - } - dst_ptr += dst_stride; - y += dy; - } - free_aligned_buffer_64(row); - } -} - -// Scale plane, horizontally up by 2 times. -// Uses linear filter horizontally, nearest vertically. -// This is an optimized version for scaling up a plane to 2 times of -// its original width, using linear interpolation. -// This is used to scale U and V planes of I422 to I444. -static void ScalePlaneUp2_Linear(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr) { - void (*ScaleRowUp)(const uint8_t *src_ptr, uint8_t *dst_ptr, int dst_width) = - ScaleRowUp2_Linear_Any_C; - int i; - int y; - int dy; - - (void) src_width; - // This function can only scale up by 2 times horizontally. - assert(src_width == ((dst_width + 1) / 2)); - -#ifdef HAS_SCALEROWUP2_LINEAR_SSE2 - if (TestCpuFlag(kCpuHasSSE2)) { - ScaleRowUp = ScaleRowUp2_Linear_Any_SSE2; - } -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_SSSE3 - if (TestCpuFlag(kCpuHasSSSE3)) { - ScaleRowUp = ScaleRowUp2_Linear_Any_SSSE3; - } -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_AVX2 - if (TestCpuFlag(kCpuHasAVX2)) { - ScaleRowUp = ScaleRowUp2_Linear_Any_AVX2; - } -#endif - - - if (dst_height == 1) { - ScaleRowUp(src_ptr + ((src_height - 1) / 2) * (int64_t) src_stride, dst_ptr, - dst_width); - } else { - dy = FixedDiv(src_height - 1, dst_height - 1); - y = (1 << 15) - 1; - for (i = 0; i < dst_height; ++i) { - ScaleRowUp(src_ptr + (y >> 16) * (int64_t) src_stride, dst_ptr, dst_width); - dst_ptr += dst_stride; - y += dy; - } - } -} - -// Scale plane, up by 2 times. -// This is an optimized version for scaling up a plane to 2 times of -// its original size, using bilinear interpolation. -// This is used to scale U and V planes of I420 to I444. -static void ScalePlaneUp2_Bilinear(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr) { - void (*Scale2RowUp)(const uint8_t *src_ptr, ptrdiff_t src_stride, - uint8_t *dst_ptr, ptrdiff_t dst_stride, int dst_width) = - ScaleRowUp2_Bilinear_Any_C; - int x; - - (void) src_width; - // This function can only scale up by 2 times. - assert(src_width == ((dst_width + 1) / 2)); - assert(src_height == ((dst_height + 1) / 2)); - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSE2 - if (TestCpuFlag(kCpuHasSSE2)) { - Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSE2; - } -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSSE3 - if (TestCpuFlag(kCpuHasSSSE3)) { - Scale2RowUp = ScaleRowUp2_Bilinear_Any_SSSE3; - } -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_AVX2 - if (TestCpuFlag(kCpuHasAVX2)) { - Scale2RowUp = ScaleRowUp2_Bilinear_Any_AVX2; - } -#endif - - - Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width); - dst_ptr += dst_stride; - for (x = 0; x < src_height - 1; ++x) { - Scale2RowUp(src_ptr, src_stride, dst_ptr, dst_stride, dst_width); - src_ptr += src_stride; - // TODO(fbarchard): Test performance of writing one row of destination at a - // time. - dst_ptr += 2 * dst_stride; - } - if (!(dst_height & 1)) { - Scale2RowUp(src_ptr, 0, dst_ptr, 0, dst_width); - } -} - -// Scale Plane to/from any dimensions, without interpolation. -// Fixed point math is used for performance: The upper 16 bits -// of x and dx is the integer part of the source position and -// the lower 16 bits are the fixed decimal part. - -static void ScalePlaneSimple(int src_width, - int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_ptr, - uint8_t *dst_ptr) { - int i; - void (*ScaleCols)(uint8_t *dst_ptr, const uint8_t *src_ptr, int dst_width, - int x, int dx) = ScaleCols_C; - // Initial source x/y coordinate and step values as 16.16 fixed point. - int x = 0; - int y = 0; - int dx = 0; - int dy = 0; - ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone, &x, &y, - &dx, &dy); - src_width = Abs(src_width); - - if (src_width * 2 == dst_width && x < 0x8000) { - ScaleCols = ScaleColsUp2_C; -#if defined(HAS_SCALECOLS_SSE2) - if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) { - ScaleCols = ScaleColsUp2_SSE2; - } -#endif - } - - for (i = 0; i < dst_height; ++i) { - ScaleCols(dst_ptr, src_ptr + (y >> 16) * (int64_t) src_stride, dst_width, x, - dx); - dst_ptr += dst_stride; - y += dy; - } -} - -// Scale a plane. -// This function dispatches to a specialized scaler based on scale factor. -LIBYUV_API -void ScalePlane(const uint8_t *src, - int src_stride, - int src_width, - int src_height, - uint8_t *dst, - int dst_stride, - int dst_width, - int dst_height, - enum FilterMode filtering) { - // Simplify filtering when possible. - filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height, - filtering); - - // Negative height means invert the image. - if (src_height < 0) { - src_height = -src_height; - src = src + (src_height - 1) * (int64_t) src_stride; - src_stride = -src_stride; - } - // Use specialized scales to improve performance for common resolutions. - // For example, all the 1/2 scalings will use ScalePlaneDown2() - if (dst_width == src_width && dst_height == src_height) { - // Straight copy. - CopyPlane(src, src_stride, dst, dst_stride, dst_width, dst_height); - return; - } - if (dst_width == src_width && filtering != kFilterBox) { - int dy = 0; - int y = 0; - // When scaling down, use the center 2 rows to filter. - // When scaling up, last row of destination uses the last 2 source rows. - if (dst_height <= src_height) { - dy = FixedDiv(src_height, dst_height); - y = CENTERSTART(dy, -32768); // Subtract 0.5 (32768) to center filter. - } else if (src_height > 1 && dst_height > 1) { - dy = FixedDiv1(src_height, dst_height); - } - // Arbitrary scale vertically, but unscaled horizontally. - ScalePlaneVertical(src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst, 0, y, dy, /*bpp=*/1, filtering); - return; - } - if (dst_width <= Abs(src_width) && dst_height <= src_height) { - // Scale down. - if (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height) { - // optimized, 3/4 - ScalePlaneDown34(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst, filtering); - return; - } - if (2 * dst_width == src_width && 2 * dst_height == src_height) { - // optimized, 1/2 - ScalePlaneDown2(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst, filtering); - return; - } - // 3/8 rounded up for odd sized chroma height. - if (8 * dst_width == 3 * src_width && 8 * dst_height == 3 * src_height) { - // optimized, 3/8 - ScalePlaneDown38(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst, filtering); - return; - } - if (4 * dst_width == src_width && 4 * dst_height == src_height && - (filtering == kFilterBox || filtering == kFilterNone)) { - // optimized, 1/4 - ScalePlaneDown4(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst, filtering); - return; - } - } - if (filtering == kFilterBox && dst_height * 2 < src_height) { - ScalePlaneBox(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst); - return; - } - if ((dst_width + 1) / 2 == src_width && filtering == kFilterLinear) { - ScalePlaneUp2_Linear(src_width, src_height, dst_width, dst_height, - src_stride, dst_stride, src, dst); - return; - } - if ((dst_height + 1) / 2 == src_height && (dst_width + 1) / 2 == src_width && - (filtering == kFilterBilinear || filtering == kFilterBox)) { - ScalePlaneUp2_Bilinear(src_width, src_height, dst_width, dst_height, - src_stride, dst_stride, src, dst); - return; - } - if (filtering && dst_height > src_height) { - ScalePlaneBilinearUp(src_width, src_height, dst_width, dst_height, - src_stride, dst_stride, src, dst, filtering); - return; - } - if (filtering) { - ScalePlaneBilinearDown(src_width, src_height, dst_width, dst_height, - src_stride, dst_stride, src, dst, filtering); - return; - } - ScalePlaneSimple(src_width, src_height, dst_width, dst_height, src_stride, - dst_stride, src, dst); -} - -LIBYUV_API -int I420Scale(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_width, - int src_height, - 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 dst_width, - int dst_height, - enum FilterMode filtering) { - int src_halfwidth = SUBSAMPLE(src_width, 1, 1); - int src_halfheight = SUBSAMPLE(src_height, 1, 1); - int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1); - int dst_halfheight = SUBSAMPLE(dst_height, 1, 1); - - if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 || - src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v || - dst_width <= 0 || dst_height <= 0) { - return -1; - } - - ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y, - dst_width, dst_height, filtering); - ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u, - dst_stride_u, dst_halfwidth, dst_halfheight, filtering); - ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v, - dst_stride_v, dst_halfwidth, dst_halfheight, filtering); - return 0; -} diff --git a/pkg/encoder/yuv/libyuv/scale.h b/pkg/encoder/yuv/libyuv/scale.h deleted file mode 100644 index ed0a1983f..000000000 --- a/pkg/encoder/yuv/libyuv/scale.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -#ifndef INCLUDE_LIBYUV_SCALE_H_ -#define INCLUDE_LIBYUV_SCALE_H_ - -#include "basic_types.h" - -// Supported filtering. -typedef enum FilterMode { - kFilterNone = 0, // Point sample; Fastest. - kFilterLinear = 1, // Filter horizontally only. - kFilterBilinear = 2, // Faster than box, but lower quality scaling down. - kFilterBox = 3 // Highest quality. -} FilterModeEnum; - -// Scales a YUV 4:2:0 image from the src width and height to the -// dst width and height. -// If filtering is kFilterNone, a simple nearest-neighbor algorithm is -// used. This produces basic (blocky) quality at the fastest speed. -// If filtering is kFilterBilinear, interpolation is used to produce a better -// quality image, at the expense of speed. -// If filtering is kFilterBox, averaging is used to produce ever better -// quality image, at further expense of speed. -// Returns 0 if successful. - -LIBYUV_API -int I420Scale(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_width, - int src_height, - 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 dst_width, - int dst_height, - enum FilterMode filtering); - -#endif // INCLUDE_LIBYUV_SCALE_H_ diff --git a/pkg/encoder/yuv/libyuv/scale_any.c b/pkg/encoder/yuv/libyuv/scale_any.c deleted file mode 100644 index f05e55b6e..000000000 --- a/pkg/encoder/yuv/libyuv/scale_any.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright 2015 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 "scale_row.h" - -// Fixed scale down. -// Mask may be non-power of 2, so use MOD -#define SDANY(NAMEANY, SCALEROWDOWN_SIMD, SCALEROWDOWN_C, FACTOR, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, \ - int dst_width) { \ - int r = (int)((unsigned int)dst_width % (MASK + 1)); /* NOLINT */ \ - int n = dst_width - r; \ - if (n > 0) { \ - SCALEROWDOWN_SIMD(src_ptr, src_stride, dst_ptr, n); \ - } \ - SCALEROWDOWN_C(src_ptr + (n * FACTOR) * BPP, src_stride, \ - dst_ptr + n * BPP, r); \ - } - -// Fixed scale down for odd source width. Used by I420Blend subsampling. -// Since dst_width is (width + 1) / 2, this function scales one less pixel -// and copies the last pixel. -#define SDODD(NAMEANY, SCALEROWDOWN_SIMD, SCALEROWDOWN_C, FACTOR, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, ptrdiff_t src_stride, uint8_t* dst_ptr, \ - int dst_width) { \ - int r = (int)((unsigned int)(dst_width - 1) % (MASK + 1)); /* NOLINT */ \ - int n = (dst_width - 1) - r; \ - if (n > 0) { \ - SCALEROWDOWN_SIMD(src_ptr, src_stride, dst_ptr, n); \ - } \ - SCALEROWDOWN_C(src_ptr + (n * FACTOR) * BPP, src_stride, \ - dst_ptr + n * BPP, r + 1); \ - } - -#ifdef HAS_SCALEROWDOWN2_SSSE3 - -SDANY(ScaleRowDown2_Any_SSSE3, ScaleRowDown2_SSSE3, ScaleRowDown2_C, 2, 1, 15) - -SDANY(ScaleRowDown2Linear_Any_SSSE3, - ScaleRowDown2Linear_SSSE3, - ScaleRowDown2Linear_C, - 2, - 1, - 15) - -SDANY(ScaleRowDown2Box_Any_SSSE3, - ScaleRowDown2Box_SSSE3, - ScaleRowDown2Box_C, - 2, - 1, - 15) - -SDODD(ScaleRowDown2Box_Odd_SSSE3, - ScaleRowDown2Box_SSSE3, - ScaleRowDown2Box_Odd_C, - 2, - 1, - 15) - -#endif -#ifdef HAS_SCALEUVROWDOWN2BOX_SSSE3 - -SDANY(ScaleUVRowDown2Box_Any_SSSE3, - ScaleUVRowDown2Box_SSSE3, - ScaleUVRowDown2Box_C, - 2, - 2, - 3) - -#endif -#ifdef HAS_SCALEUVROWDOWN2BOX_AVX2 - -SDANY(ScaleUVRowDown2Box_Any_AVX2, - ScaleUVRowDown2Box_AVX2, - ScaleUVRowDown2Box_C, - 2, - 2, - 7) - -#endif -#ifdef HAS_SCALEROWDOWN2_AVX2 - -SDANY(ScaleRowDown2_Any_AVX2, ScaleRowDown2_AVX2, ScaleRowDown2_C, 2, 1, 31) - -SDANY(ScaleRowDown2Linear_Any_AVX2, - ScaleRowDown2Linear_AVX2, - ScaleRowDown2Linear_C, - 2, - 1, - 31) - -SDANY(ScaleRowDown2Box_Any_AVX2, - ScaleRowDown2Box_AVX2, - ScaleRowDown2Box_C, - 2, - 1, - 31) - -SDODD(ScaleRowDown2Box_Odd_AVX2, - ScaleRowDown2Box_AVX2, - ScaleRowDown2Box_Odd_C, - 2, - 1, - 31) - -#endif -#ifdef HAS_SCALEROWDOWN4_SSSE3 - -SDANY(ScaleRowDown4_Any_SSSE3, ScaleRowDown4_SSSE3, ScaleRowDown4_C, 4, 1, 7) - -SDANY(ScaleRowDown4Box_Any_SSSE3, - ScaleRowDown4Box_SSSE3, - ScaleRowDown4Box_C, - 4, - 1, - 7) - -#endif -#ifdef HAS_SCALEROWDOWN4_AVX2 - -SDANY(ScaleRowDown4_Any_AVX2, ScaleRowDown4_AVX2, ScaleRowDown4_C, 4, 1, 15) - -SDANY(ScaleRowDown4Box_Any_AVX2, - ScaleRowDown4Box_AVX2, - ScaleRowDown4Box_C, - 4, - 1, - 15) - -#endif -#ifdef HAS_SCALEROWDOWN34_SSSE3 - -SDANY(ScaleRowDown34_Any_SSSE3, - ScaleRowDown34_SSSE3, - ScaleRowDown34_C, - 4 / 3, - 1, - 23) - -SDANY(ScaleRowDown34_0_Box_Any_SSSE3, - ScaleRowDown34_0_Box_SSSE3, - ScaleRowDown34_0_Box_C, - 4 / 3, - 1, - 23) - -SDANY(ScaleRowDown34_1_Box_Any_SSSE3, - ScaleRowDown34_1_Box_SSSE3, - ScaleRowDown34_1_Box_C, - 4 / 3, - 1, - 23) - -#endif - -#ifdef HAS_SCALEROWDOWN38_SSSE3 - -SDANY(ScaleRowDown38_Any_SSSE3, - ScaleRowDown38_SSSE3, - ScaleRowDown38_C, - 8 / 3, - 1, - 11) - -SDANY(ScaleRowDown38_3_Box_Any_SSSE3, - ScaleRowDown38_3_Box_SSSE3, - ScaleRowDown38_3_Box_C, - 8 / 3, - 1, - 5) - -SDANY(ScaleRowDown38_2_Box_Any_SSSE3, - ScaleRowDown38_2_Box_SSSE3, - ScaleRowDown38_2_Box_C, - 8 / 3, - 1, - 5) - -#endif - - -#undef SDANY - -// Scale down by even scale factor. -#define SDAANY(NAMEANY, SCALEROWDOWN_SIMD, SCALEROWDOWN_C, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, ptrdiff_t src_stride, int src_stepx, \ - uint8_t* dst_ptr, int dst_width) { \ - int r = dst_width & MASK; \ - int n = dst_width & ~MASK; \ - if (n > 0) { \ - SCALEROWDOWN_SIMD(src_ptr, src_stride, src_stepx, dst_ptr, n); \ - } \ - SCALEROWDOWN_C(src_ptr + (n * src_stepx) * BPP, src_stride, src_stepx, \ - dst_ptr + n * BPP, r); \ - } - - - -#ifdef SASIMDONLY -// This also works and uses memcpy and SIMD instead of C, but is slower on ARM - -// Add rows box filter scale down. Using macro from row_any -#define SAROW(NAMEANY, ANY_SIMD, SBPP, BPP, MASK) \ - void NAMEANY(const uint8_t* src_ptr, uint16_t* dst_ptr, int width) { \ - SIMD_ALIGNED(uint16_t dst_temp[32]); \ - SIMD_ALIGNED(uint8_t src_temp[32]); \ - memset(dst_temp, 0, 32 * 2); /* for msan */ \ - int r = width & MASK; \ - int n = width & ~MASK; \ - if (n > 0) { \ - ANY_SIMD(src_ptr, dst_ptr, n); \ - } \ - memcpy(src_temp, src_ptr + n * SBPP, r * SBPP); \ - memcpy(dst_temp, dst_ptr + n * BPP, r * BPP); \ - ANY_SIMD(src_temp, dst_temp, MASK + 1); \ - memcpy(dst_ptr + n * BPP, dst_temp, r * BPP); \ - } - -#ifdef HAS_SCALEADDROW_SSE2 -SAROW(ScaleAddRow_Any_SSE2, ScaleAddRow_SSE2, 1, 2, 15) -#endif -#ifdef HAS_SCALEADDROW_AVX2 -SAROW(ScaleAddRow_Any_AVX2, ScaleAddRow_AVX2, 1, 2, 31) -#endif -#undef SAANY - -#else - -// Add rows box filter scale down. -#define SAANY(NAMEANY, SCALEADDROW_SIMD, SCALEADDROW_C, MASK) \ - void NAMEANY(const uint8_t* src_ptr, uint16_t* dst_ptr, int src_width) { \ - int n = src_width & ~MASK; \ - if (n > 0) { \ - SCALEADDROW_SIMD(src_ptr, dst_ptr, n); \ - } \ - SCALEADDROW_C(src_ptr + n, dst_ptr + n, src_width & MASK); \ - } - -#ifdef HAS_SCALEADDROW_SSE2 - -SAANY(ScaleAddRow_Any_SSE2, ScaleAddRow_SSE2, ScaleAddRow_C, 15) - -#endif -#ifdef HAS_SCALEADDROW_AVX2 - -SAANY(ScaleAddRow_Any_AVX2, ScaleAddRow_AVX2, ScaleAddRow_C, 31) - -#endif -#undef SAANY - -#endif // SASIMDONLY - -// Scale up horizontally 2 times using linear filter. -#define SUH2LANY(NAME, SIMD, C, MASK, PTYPE) \ - void NAME(const PTYPE* src_ptr, PTYPE* dst_ptr, int dst_width) { \ - int work_width = (dst_width - 1) & ~1; \ - int r = work_width & MASK; \ - int n = work_width & ~MASK; \ - dst_ptr[0] = src_ptr[0]; \ - if (work_width > 0) { \ - if (n != 0) { \ - SIMD(src_ptr, dst_ptr + 1, n); \ - } \ - C(src_ptr + (n / 2), dst_ptr + n + 1, r); \ - } \ - dst_ptr[dst_width - 1] = src_ptr[(dst_width - 1) / 2]; \ - } - -// Even the C versions need to be wrapped, because boundary pixels have to -// be handled differently - -SUH2LANY(ScaleRowUp2_Linear_Any_C, - ScaleRowUp2_Linear_C, - ScaleRowUp2_Linear_C, - 0, - uint8_t) - -SUH2LANY(ScaleRowUp2_Linear_16_Any_C, - ScaleRowUp2_Linear_16_C, - ScaleRowUp2_Linear_16_C, - 0, - uint16_t) - -#ifdef HAS_SCALEROWUP2_LINEAR_SSE2 - -SUH2LANY(ScaleRowUp2_Linear_Any_SSE2, - ScaleRowUp2_Linear_SSE2, - ScaleRowUp2_Linear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_SSSE3 - -SUH2LANY(ScaleRowUp2_Linear_Any_SSSE3, - ScaleRowUp2_Linear_SSSE3, - ScaleRowUp2_Linear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_12_SSSE3 - -SUH2LANY(ScaleRowUp2_Linear_12_Any_SSSE3, - ScaleRowUp2_Linear_12_SSSE3, - ScaleRowUp2_Linear_16_C, - 15, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_16_SSE2 - -SUH2LANY(ScaleRowUp2_Linear_16_Any_SSE2, - ScaleRowUp2_Linear_16_SSE2, - ScaleRowUp2_Linear_16_C, - 7, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_AVX2 - -SUH2LANY(ScaleRowUp2_Linear_Any_AVX2, - ScaleRowUp2_Linear_AVX2, - ScaleRowUp2_Linear_C, - 31, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_12_AVX2 - -SUH2LANY(ScaleRowUp2_Linear_12_Any_AVX2, - ScaleRowUp2_Linear_12_AVX2, - ScaleRowUp2_Linear_16_C, - 31, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_16_AVX2 - -SUH2LANY(ScaleRowUp2_Linear_16_Any_AVX2, - ScaleRowUp2_Linear_16_AVX2, - ScaleRowUp2_Linear_16_C, - 15, - uint16_t) - -#endif -#undef SUH2LANY - -// Scale up 2 times using bilinear filter. -// This function produces 2 rows at a time. -#define SU2BLANY(NAME, SIMD, C, MASK, PTYPE) \ - void NAME(const PTYPE* src_ptr, ptrdiff_t src_stride, PTYPE* dst_ptr, \ - ptrdiff_t dst_stride, int dst_width) { \ - int work_width = (dst_width - 1) & ~1; \ - int r = work_width & MASK; \ - int n = work_width & ~MASK; \ - const PTYPE* sa = src_ptr; \ - const PTYPE* sb = src_ptr + src_stride; \ - PTYPE* da = dst_ptr; \ - PTYPE* db = dst_ptr + dst_stride; \ - da[0] = (3 * sa[0] + sb[0] + 2) >> 2; \ - db[0] = (sa[0] + 3 * sb[0] + 2) >> 2; \ - if (work_width > 0) { \ - if (n != 0) { \ - SIMD(sa, sb - sa, da + 1, db - da, n); \ - } \ - C(sa + (n / 2), sb - sa, da + n + 1, db - da, r); \ - } \ - da[dst_width - 1] = \ - (3 * sa[(dst_width - 1) / 2] + sb[(dst_width - 1) / 2] + 2) >> 2; \ - db[dst_width - 1] = \ - (sa[(dst_width - 1) / 2] + 3 * sb[(dst_width - 1) / 2] + 2) >> 2; \ - } - -SU2BLANY(ScaleRowUp2_Bilinear_Any_C, - ScaleRowUp2_Bilinear_C, - ScaleRowUp2_Bilinear_C, - 0, - uint8_t) - -SU2BLANY(ScaleRowUp2_Bilinear_16_Any_C, - ScaleRowUp2_Bilinear_16_C, - ScaleRowUp2_Bilinear_16_C, - 0, - uint16_t) - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSE2 - -SU2BLANY(ScaleRowUp2_Bilinear_Any_SSE2, - ScaleRowUp2_Bilinear_SSE2, - ScaleRowUp2_Bilinear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_12_SSSE3 - -SU2BLANY(ScaleRowUp2_Bilinear_12_Any_SSSE3, - ScaleRowUp2_Bilinear_12_SSSE3, - ScaleRowUp2_Bilinear_16_C, - 15, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_16_SSE2 - -SU2BLANY(ScaleRowUp2_Bilinear_16_Any_SSE2, - ScaleRowUp2_Bilinear_16_SSE2, - ScaleRowUp2_Bilinear_16_C, - 7, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSSE3 - -SU2BLANY(ScaleRowUp2_Bilinear_Any_SSSE3, - ScaleRowUp2_Bilinear_SSSE3, - ScaleRowUp2_Bilinear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_AVX2 - -SU2BLANY(ScaleRowUp2_Bilinear_Any_AVX2, - ScaleRowUp2_Bilinear_AVX2, - ScaleRowUp2_Bilinear_C, - 31, - uint8_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_12_AVX2 - -SU2BLANY(ScaleRowUp2_Bilinear_12_Any_AVX2, - ScaleRowUp2_Bilinear_12_AVX2, - ScaleRowUp2_Bilinear_16_C, - 15, - uint16_t) - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_16_AVX2 - -SU2BLANY(ScaleRowUp2_Bilinear_16_Any_AVX2, - ScaleRowUp2_Bilinear_16_AVX2, - ScaleRowUp2_Bilinear_16_C, - 15, - uint16_t) - -#endif - -#undef SU2BLANY - -// Scale bi-planar plane up horizontally 2 times using linear filter. -#define SBUH2LANY(NAME, SIMD, C, MASK, PTYPE) \ - void NAME(const PTYPE* src_ptr, PTYPE* dst_ptr, int dst_width) { \ - int work_width = (dst_width - 1) & ~1; \ - int r = work_width & MASK; \ - int n = work_width & ~MASK; \ - dst_ptr[0] = src_ptr[0]; \ - dst_ptr[1] = src_ptr[1]; \ - if (work_width > 0) { \ - if (n != 0) { \ - SIMD(src_ptr, dst_ptr + 2, n); \ - } \ - C(src_ptr + n, dst_ptr + 2 * n + 2, r); \ - } \ - dst_ptr[2 * dst_width - 2] = src_ptr[((dst_width + 1) & ~1) - 2]; \ - dst_ptr[2 * dst_width - 1] = src_ptr[((dst_width + 1) & ~1) - 1]; \ - } - -SBUH2LANY(ScaleUVRowUp2_Linear_Any_C, - ScaleUVRowUp2_Linear_C, - ScaleUVRowUp2_Linear_C, - 0, - uint8_t) - -SBUH2LANY(ScaleUVRowUp2_Linear_16_Any_C, - ScaleUVRowUp2_Linear_16_C, - ScaleUVRowUp2_Linear_16_C, - 0, - uint16_t) - -#ifdef HAS_SCALEUVROWUP2_LINEAR_SSSE3 - -SBUH2LANY(ScaleUVRowUp2_Linear_Any_SSSE3, - ScaleUVRowUp2_Linear_SSSE3, - ScaleUVRowUp2_Linear_C, - 7, - uint8_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_AVX2 - -SBUH2LANY(ScaleUVRowUp2_Linear_Any_AVX2, - ScaleUVRowUp2_Linear_AVX2, - ScaleUVRowUp2_Linear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41 - -SBUH2LANY(ScaleUVRowUp2_Linear_16_Any_SSE41, - ScaleUVRowUp2_Linear_16_SSE41, - ScaleUVRowUp2_Linear_16_C, - 3, - uint16_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2 - -SBUH2LANY(ScaleUVRowUp2_Linear_16_Any_AVX2, - ScaleUVRowUp2_Linear_16_AVX2, - ScaleUVRowUp2_Linear_16_C, - 7, - uint16_t) - -#endif - -#undef SBUH2LANY - -// Scale bi-planar plane up 2 times using bilinear filter. -// This function produces 2 rows at a time. -#define SBU2BLANY(NAME, SIMD, C, MASK, PTYPE) \ - void NAME(const PTYPE* src_ptr, ptrdiff_t src_stride, PTYPE* dst_ptr, \ - ptrdiff_t dst_stride, int dst_width) { \ - int work_width = (dst_width - 1) & ~1; \ - int r = work_width & MASK; \ - int n = work_width & ~MASK; \ - const PTYPE* sa = src_ptr; \ - const PTYPE* sb = src_ptr + src_stride; \ - PTYPE* da = dst_ptr; \ - PTYPE* db = dst_ptr + dst_stride; \ - da[0] = (3 * sa[0] + sb[0] + 2) >> 2; \ - db[0] = (sa[0] + 3 * sb[0] + 2) >> 2; \ - da[1] = (3 * sa[1] + sb[1] + 2) >> 2; \ - db[1] = (sa[1] + 3 * sb[1] + 2) >> 2; \ - if (work_width > 0) { \ - if (n != 0) { \ - SIMD(sa, sb - sa, da + 2, db - da, n); \ - } \ - C(sa + n, sb - sa, da + 2 * n + 2, db - da, r); \ - } \ - da[2 * dst_width - 2] = (3 * sa[((dst_width + 1) & ~1) - 2] + \ - sb[((dst_width + 1) & ~1) - 2] + 2) >> \ - 2; \ - db[2 * dst_width - 2] = (sa[((dst_width + 1) & ~1) - 2] + \ - 3 * sb[((dst_width + 1) & ~1) - 2] + 2) >> \ - 2; \ - da[2 * dst_width - 1] = (3 * sa[((dst_width + 1) & ~1) - 1] + \ - sb[((dst_width + 1) & ~1) - 1] + 2) >> \ - 2; \ - db[2 * dst_width - 1] = (sa[((dst_width + 1) & ~1) - 1] + \ - 3 * sb[((dst_width + 1) & ~1) - 1] + 2) >> \ - 2; \ - } - -SBU2BLANY(ScaleUVRowUp2_Bilinear_Any_C, - ScaleUVRowUp2_Bilinear_C, - ScaleUVRowUp2_Bilinear_C, - 0, - uint8_t) - -SBU2BLANY(ScaleUVRowUp2_Bilinear_16_Any_C, - ScaleUVRowUp2_Bilinear_16_C, - ScaleUVRowUp2_Bilinear_16_C, - 0, - uint16_t) - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_SSSE3 - -SBU2BLANY(ScaleUVRowUp2_Bilinear_Any_SSSE3, - ScaleUVRowUp2_Bilinear_SSSE3, - ScaleUVRowUp2_Bilinear_C, - 7, - uint8_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_AVX2 - -SBU2BLANY(ScaleUVRowUp2_Bilinear_Any_AVX2, - ScaleUVRowUp2_Bilinear_AVX2, - ScaleUVRowUp2_Bilinear_C, - 15, - uint8_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41 - -SBU2BLANY(ScaleUVRowUp2_Bilinear_16_Any_SSE41, - ScaleUVRowUp2_Bilinear_16_SSE41, - ScaleUVRowUp2_Bilinear_16_C, - 7, - uint16_t) - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2 - -SBU2BLANY(ScaleUVRowUp2_Bilinear_16_Any_AVX2, - ScaleUVRowUp2_Bilinear_16_AVX2, - ScaleUVRowUp2_Bilinear_16_C, - 7, - uint16_t) - -#endif - -#undef SBU2BLANY diff --git a/pkg/encoder/yuv/libyuv/scale_common.c b/pkg/encoder/yuv/libyuv/scale_common.c deleted file mode 100644 index 17eedd992..000000000 --- a/pkg/encoder/yuv/libyuv/scale_common.c +++ /dev/null @@ -1,930 +0,0 @@ -/* - * Copyright 2013 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 "scale.h" - -#include - -#include "cpu_id.h" -#include "row.h" -#include "scale_row.h" - -#define STATIC_CAST(type, expr) (type)(expr) - -// TODO(fbarchard): make clamp255 preserve negative values. -static __inline int32_t clamp255(int32_t v) { - return (-(v >= 255) | v) & 255; -} - -// Use scale to convert lsb formats to msb, depending how many bits there are: -// 32768 = 9 bits -// 16384 = 10 bits -// 4096 = 12 bits -// 256 = 16 bits -// TODO(fbarchard): change scale to bits -#define C16TO8(v, scale) clamp255(((v) * (scale)) >> 16) - -static __inline int Abs(int v) { - return v >= 0 ? v : -v; -} - -// CPU agnostic row functions -void ScaleRowDown2_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - int x; - (void) src_stride; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = src_ptr[1]; - dst[1] = src_ptr[3]; - dst += 2; - src_ptr += 4; - } - if (dst_width & 1) { - dst[0] = src_ptr[1]; - } -} - -void ScaleRowDown2Linear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - const uint8_t *s = src_ptr; - int x; - (void) src_stride; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = (s[0] + s[1] + 1) >> 1; - dst[1] = (s[2] + s[3] + 1) >> 1; - dst += 2; - s += 4; - } - if (dst_width & 1) { - dst[0] = (s[0] + s[1] + 1) >> 1; - } -} - -void ScaleRowDown2Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - int x; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2; - dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2; - dst += 2; - s += 4; - t += 4; - } - if (dst_width & 1) { - dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2; - } -} - -void ScaleRowDown2Box_Odd_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - int x; - dst_width -= 1; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2; - dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2; - dst += 2; - s += 4; - t += 4; - } - if (dst_width & 1) { - dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2; - dst += 1; - s += 2; - t += 2; - } - dst[0] = (s[0] + t[0] + 1) >> 1; -} - -void ScaleRowDown4_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - int x; - (void) src_stride; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = src_ptr[2]; - dst[1] = src_ptr[6]; - dst += 2; - src_ptr += 8; - } - if (dst_width & 1) { - dst[0] = src_ptr[2]; - } -} - -void ScaleRowDown4Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - intptr_t stride = src_stride; - int x; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] + - src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] + - src_ptr[stride + 3] + src_ptr[stride * 2 + 0] + - src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] + - src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] + - src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] + - src_ptr[stride * 3 + 3] + 8) >> - 4; - dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] + - src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride + 6] + - src_ptr[stride + 7] + src_ptr[stride * 2 + 4] + - src_ptr[stride * 2 + 5] + src_ptr[stride * 2 + 6] + - src_ptr[stride * 2 + 7] + src_ptr[stride * 3 + 4] + - src_ptr[stride * 3 + 5] + src_ptr[stride * 3 + 6] + - src_ptr[stride * 3 + 7] + 8) >> - 4; - dst += 2; - src_ptr += 8; - } - if (dst_width & 1) { - dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] + - src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] + - src_ptr[stride + 3] + src_ptr[stride * 2 + 0] + - src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] + - src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] + - src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] + - src_ptr[stride * 3 + 3] + 8) >> - 4; - } -} - -void ScaleRowDown34_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - int x; - (void) src_stride; - assert((dst_width % 3 == 0) && (dst_width > 0)); - for (x = 0; x < dst_width; x += 3) { - dst[0] = src_ptr[0]; - dst[1] = src_ptr[1]; - dst[2] = src_ptr[3]; - dst += 3; - src_ptr += 4; - } -} - -// Filter rows 0 and 1 together, 3 : 1 -void ScaleRowDown34_0_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *d, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - int x; - assert((dst_width % 3 == 0) && (dst_width > 0)); - for (x = 0; x < dst_width; x += 3) { - uint8_t a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2; - uint8_t a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1; - uint8_t a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2; - uint8_t b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2; - uint8_t b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1; - uint8_t b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2; - d[0] = (a0 * 3 + b0 + 2) >> 2; - d[1] = (a1 * 3 + b1 + 2) >> 2; - d[2] = (a2 * 3 + b2 + 2) >> 2; - d += 3; - s += 4; - t += 4; - } -} - -// Filter rows 1 and 2 together, 1 : 1 -void ScaleRowDown34_1_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *d, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - int x; - assert((dst_width % 3 == 0) && (dst_width > 0)); - for (x = 0; x < dst_width; x += 3) { - uint8_t a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2; - uint8_t a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1; - uint8_t a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2; - uint8_t b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2; - uint8_t b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1; - uint8_t b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2; - d[0] = (a0 + b0 + 1) >> 1; - d[1] = (a1 + b1 + 1) >> 1; - d[2] = (a2 + b2 + 1) >> 1; - d += 3; - s += 4; - t += 4; - } -} - -// Sample position: (O is src sample position, X is dst sample position) -// -// v dst_ptr at here v stop at here -// X O X X O X X O X X O X X O X -// ^ src_ptr at here -void ScaleRowUp2_Linear_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - dst_ptr[2 * x + 0] = (src_ptr[x + 0] * 3 + src_ptr[x + 1] * 1 + 2) >> 2; - dst_ptr[2 * x + 1] = (src_ptr[x + 0] * 1 + src_ptr[x + 1] * 3 + 2) >> 2; - } -} - -// Sample position: (O is src sample position, X is dst sample position) -// -// src_ptr at here -// X v X X X X X X X X X -// O O O O O -// X X X X X X X X X X -// ^ dst_ptr at here ^ stop at here -// X X X X X X X X X X -// O O O O O -// X X X X X X X X X X -void ScaleRowUp2_Bilinear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - uint8_t *d = dst_ptr; - uint8_t *e = dst_ptr + dst_stride; - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - d[2 * x + 0] = - (s[x + 0] * 9 + s[x + 1] * 3 + t[x + 0] * 3 + t[x + 1] * 1 + 8) >> 4; - d[2 * x + 1] = - (s[x + 0] * 3 + s[x + 1] * 9 + t[x + 0] * 1 + t[x + 1] * 3 + 8) >> 4; - e[2 * x + 0] = - (s[x + 0] * 3 + s[x + 1] * 1 + t[x + 0] * 9 + t[x + 1] * 3 + 8) >> 4; - e[2 * x + 1] = - (s[x + 0] * 1 + s[x + 1] * 3 + t[x + 0] * 3 + t[x + 1] * 9 + 8) >> 4; - } -} - -// Only suitable for at most 14 bit range. -void ScaleRowUp2_Linear_16_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - dst_ptr[2 * x + 0] = (src_ptr[x + 0] * 3 + src_ptr[x + 1] * 1 + 2) >> 2; - dst_ptr[2 * x + 1] = (src_ptr[x + 0] * 1 + src_ptr[x + 1] * 3 + 2) >> 2; - } -} - -// Only suitable for at most 12bit range. -void ScaleRowUp2_Bilinear_16_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - const uint16_t *s = src_ptr; - const uint16_t *t = src_ptr + src_stride; - uint16_t *d = dst_ptr; - uint16_t *e = dst_ptr + dst_stride; - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - d[2 * x + 0] = - (s[x + 0] * 9 + s[x + 1] * 3 + t[x + 0] * 3 + t[x + 1] * 1 + 8) >> 4; - d[2 * x + 1] = - (s[x + 0] * 3 + s[x + 1] * 9 + t[x + 0] * 1 + t[x + 1] * 3 + 8) >> 4; - e[2 * x + 0] = - (s[x + 0] * 3 + s[x + 1] * 1 + t[x + 0] * 9 + t[x + 1] * 3 + 8) >> 4; - e[2 * x + 1] = - (s[x + 0] * 1 + s[x + 1] * 3 + t[x + 0] * 3 + t[x + 1] * 9 + 8) >> 4; - } -} - -// (1-f)a + fb can be replaced with a + f(b-a) -#if defined(__arm__) || defined(__aarch64__) -#define BLENDER(a, b, f) \ - (uint8_t)((int)(a) + ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16)) -#else -// Intel uses 7 bit math with rounding. -#define BLENDER(a, b, f) \ - (uint8_t)((int)(a) + (((int)((f) >> 9) * ((int)(b) - (int)(a)) + 0x40) >> 7)) -#endif - -void ScaleFilterCols_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx) { - int j; - for (j = 0; j < dst_width - 1; j += 2) { - int xi = x >> 16; - int a = src_ptr[xi]; - int b = src_ptr[xi + 1]; - dst_ptr[0] = BLENDER(a, b, x & 0xffff); - x += dx; - xi = x >> 16; - a = src_ptr[xi]; - b = src_ptr[xi + 1]; - dst_ptr[1] = BLENDER(a, b, x & 0xffff); - x += dx; - dst_ptr += 2; - } - if (dst_width & 1) { - int xi = x >> 16; - int a = src_ptr[xi]; - int b = src_ptr[xi + 1]; - dst_ptr[0] = BLENDER(a, b, x & 0xffff); - } -} - -void ScaleFilterCols64_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x32, - int dx) { - int64_t x = (int64_t) (x32); - int j; - for (j = 0; j < dst_width - 1; j += 2) { - int64_t xi = x >> 16; - int a = src_ptr[xi]; - int b = src_ptr[xi + 1]; - dst_ptr[0] = BLENDER(a, b, x & 0xffff); - x += dx; - xi = x >> 16; - a = src_ptr[xi]; - b = src_ptr[xi + 1]; - dst_ptr[1] = BLENDER(a, b, x & 0xffff); - x += dx; - dst_ptr += 2; - } - if (dst_width & 1) { - int64_t xi = x >> 16; - int a = src_ptr[xi]; - int b = src_ptr[xi + 1]; - dst_ptr[0] = BLENDER(a, b, x & 0xffff); - } -} - -#undef BLENDER - -// Same as 8 bit arm blender but return is cast to uint16_t -#define BLENDER(a, b, f) \ - (uint16_t)( \ - (int)(a) + \ - (int)((((int64_t)((f)) * ((int64_t)(b) - (int)(a))) + 0x8000) >> 16)) -#undef BLENDER - -void ScaleRowDown38_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width) { - int x; - (void) src_stride; - assert(dst_width % 3 == 0); - for (x = 0; x < dst_width; x += 3) { - dst[0] = src_ptr[0]; - dst[1] = src_ptr[3]; - dst[2] = src_ptr[6]; - dst += 3; - src_ptr += 8; - } -} - -// 8x3 -> 3x1 -void ScaleRowDown38_3_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - intptr_t stride = src_stride; - int i; - assert((dst_width % 3 == 0) && (dst_width > 0)); - for (i = 0; i < dst_width; i += 3) { - dst_ptr[0] = - (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] + - src_ptr[stride + 1] + src_ptr[stride + 2] + src_ptr[stride * 2 + 0] + - src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) * - (65536 / 9) >> - 16; - dst_ptr[1] = - (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] + - src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride * 2 + 3] + - src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) * - (65536 / 9) >> - 16; - dst_ptr[2] = - (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7] + - src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) * - (65536 / 6) >> - 16; - src_ptr += 8; - dst_ptr += 3; - } -} - -// 8x2 -> 3x1 -void ScaleRowDown38_2_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - intptr_t stride = src_stride; - int i; - assert((dst_width % 3 == 0) && (dst_width > 0)); - for (i = 0; i < dst_width; i += 3) { - dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] + - src_ptr[stride + 1] + src_ptr[stride + 2]) * - (65536 / 6) >> - 16; - dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] + - src_ptr[stride + 4] + src_ptr[stride + 5]) * - (65536 / 6) >> - 16; - dst_ptr[2] = - (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7]) * - (65536 / 4) >> - 16; - src_ptr += 8; - dst_ptr += 3; - } -} - -void ScaleAddRow_C(const uint8_t *src_ptr, uint16_t *dst_ptr, int src_width) { - int x; - assert(src_width > 0); - for (x = 0; x < src_width - 1; x += 2) { - dst_ptr[0] += src_ptr[0]; - dst_ptr[1] += src_ptr[1]; - src_ptr += 2; - dst_ptr += 2; - } - if (src_width & 1) { - dst_ptr[0] += src_ptr[0]; - } -} - -// UV scale row functions -// same as ARGB but 2 channels - -void ScaleUVRowDown2_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width) { - int x; - (void) src_stride; - for (x = 0; x < dst_width; ++x) { - dst_uv[0] = src_uv[2]; // Store the 2nd UV - dst_uv[1] = src_uv[3]; - src_uv += 4; - dst_uv += 2; - } -} - -void ScaleUVRowDown2Linear_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width) { - int x; - (void) src_stride; - for (x = 0; x < dst_width; ++x) { - dst_uv[0] = (src_uv[0] + src_uv[2] + 1) >> 1; - dst_uv[1] = (src_uv[1] + src_uv[3] + 1) >> 1; - src_uv += 4; - dst_uv += 2; - } -} - -void ScaleUVRowDown2Box_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width) { - int x; - for (x = 0; x < dst_width; ++x) { - dst_uv[0] = (src_uv[0] + src_uv[2] + src_uv[src_stride] + - src_uv[src_stride + 2] + 2) >> - 2; - dst_uv[1] = (src_uv[1] + src_uv[3] + src_uv[src_stride + 1] + - src_uv[src_stride + 3] + 2) >> - 2; - src_uv += 4; - dst_uv += 2; - } -} - -void ScaleUVRowDownEven_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - int src_stepx, - uint8_t *dst_uv, - int dst_width) { - const uint16_t *src = (const uint16_t *) (src_uv); - uint16_t *dst = (uint16_t *) (dst_uv); - (void) src_stride; - int x; - for (x = 0; x < dst_width - 1; x += 2) { - dst[0] = src[0]; - dst[1] = src[src_stepx]; - src += src_stepx * 2; - dst += 2; - } - if (dst_width & 1) { - dst[0] = src[0]; - } -} - -// Scales a single row of pixels using point sampling. -void ScaleCols_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx) { - int j; - for (j = 0; j < dst_width - 1; j += 2) { - dst_ptr[0] = src_ptr[x >> 16]; - x += dx; - dst_ptr[1] = src_ptr[x >> 16]; - x += dx; - dst_ptr += 2; - } - if (dst_width & 1) { - dst_ptr[0] = src_ptr[x >> 16]; - } -} - -// Scales a single row of pixels up by 2x using point sampling. -void ScaleColsUp2_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx) { - int j; - (void) x; - (void) dx; - for (j = 0; j < dst_width - 1; j += 2) { - dst_ptr[1] = dst_ptr[0] = src_ptr[0]; - src_ptr += 1; - dst_ptr += 2; - } - if (dst_width & 1) { - dst_ptr[0] = src_ptr[0]; - } -} - -void ScaleUVRowUp2_Linear_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - dst_ptr[4 * x + 0] = - (src_ptr[2 * x + 0] * 3 + src_ptr[2 * x + 2] * 1 + 2) >> 2; - dst_ptr[4 * x + 1] = - (src_ptr[2 * x + 1] * 3 + src_ptr[2 * x + 3] * 1 + 2) >> 2; - dst_ptr[4 * x + 2] = - (src_ptr[2 * x + 0] * 1 + src_ptr[2 * x + 2] * 3 + 2) >> 2; - dst_ptr[4 * x + 3] = - (src_ptr[2 * x + 1] * 1 + src_ptr[2 * x + 3] * 3 + 2) >> 2; - } -} - -void ScaleUVRowUp2_Bilinear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - const uint8_t *s = src_ptr; - const uint8_t *t = src_ptr + src_stride; - uint8_t *d = dst_ptr; - uint8_t *e = dst_ptr + dst_stride; - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - d[4 * x + 0] = (s[2 * x + 0] * 9 + s[2 * x + 2] * 3 + t[2 * x + 0] * 3 + - t[2 * x + 2] * 1 + 8) >> - 4; - d[4 * x + 1] = (s[2 * x + 1] * 9 + s[2 * x + 3] * 3 + t[2 * x + 1] * 3 + - t[2 * x + 3] * 1 + 8) >> - 4; - d[4 * x + 2] = (s[2 * x + 0] * 3 + s[2 * x + 2] * 9 + t[2 * x + 0] * 1 + - t[2 * x + 2] * 3 + 8) >> - 4; - d[4 * x + 3] = (s[2 * x + 1] * 3 + s[2 * x + 3] * 9 + t[2 * x + 1] * 1 + - t[2 * x + 3] * 3 + 8) >> - 4; - e[4 * x + 0] = (s[2 * x + 0] * 3 + s[2 * x + 2] * 1 + t[2 * x + 0] * 9 + - t[2 * x + 2] * 3 + 8) >> - 4; - e[4 * x + 1] = (s[2 * x + 1] * 3 + s[2 * x + 3] * 1 + t[2 * x + 1] * 9 + - t[2 * x + 3] * 3 + 8) >> - 4; - e[4 * x + 2] = (s[2 * x + 0] * 1 + s[2 * x + 2] * 3 + t[2 * x + 0] * 3 + - t[2 * x + 2] * 9 + 8) >> - 4; - e[4 * x + 3] = (s[2 * x + 1] * 1 + s[2 * x + 3] * 3 + t[2 * x + 1] * 3 + - t[2 * x + 3] * 9 + 8) >> - 4; - } -} - -void ScaleUVRowUp2_Linear_16_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - dst_ptr[4 * x + 0] = - (src_ptr[2 * x + 0] * 3 + src_ptr[2 * x + 2] * 1 + 2) >> 2; - dst_ptr[4 * x + 1] = - (src_ptr[2 * x + 1] * 3 + src_ptr[2 * x + 3] * 1 + 2) >> 2; - dst_ptr[4 * x + 2] = - (src_ptr[2 * x + 0] * 1 + src_ptr[2 * x + 2] * 3 + 2) >> 2; - dst_ptr[4 * x + 3] = - (src_ptr[2 * x + 1] * 1 + src_ptr[2 * x + 3] * 3 + 2) >> 2; - } -} - -void ScaleUVRowUp2_Bilinear_16_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - const uint16_t *s = src_ptr; - const uint16_t *t = src_ptr + src_stride; - uint16_t *d = dst_ptr; - uint16_t *e = dst_ptr + dst_stride; - int src_width = dst_width >> 1; - int x; - assert((dst_width % 2 == 0) && (dst_width >= 0)); - for (x = 0; x < src_width; ++x) { - d[4 * x + 0] = (s[2 * x + 0] * 9 + s[2 * x + 2] * 3 + t[2 * x + 0] * 3 + - t[2 * x + 2] * 1 + 8) >> - 4; - d[4 * x + 1] = (s[2 * x + 1] * 9 + s[2 * x + 3] * 3 + t[2 * x + 1] * 3 + - t[2 * x + 3] * 1 + 8) >> - 4; - d[4 * x + 2] = (s[2 * x + 0] * 3 + s[2 * x + 2] * 9 + t[2 * x + 0] * 1 + - t[2 * x + 2] * 3 + 8) >> - 4; - d[4 * x + 3] = (s[2 * x + 1] * 3 + s[2 * x + 3] * 9 + t[2 * x + 1] * 1 + - t[2 * x + 3] * 3 + 8) >> - 4; - e[4 * x + 0] = (s[2 * x + 0] * 3 + s[2 * x + 2] * 1 + t[2 * x + 0] * 9 + - t[2 * x + 2] * 3 + 8) >> - 4; - e[4 * x + 1] = (s[2 * x + 1] * 3 + s[2 * x + 3] * 1 + t[2 * x + 1] * 9 + - t[2 * x + 3] * 3 + 8) >> - 4; - e[4 * x + 2] = (s[2 * x + 0] * 1 + s[2 * x + 2] * 3 + t[2 * x + 0] * 3 + - t[2 * x + 2] * 9 + 8) >> - 4; - e[4 * x + 3] = (s[2 * x + 1] * 1 + s[2 * x + 3] * 3 + t[2 * x + 1] * 3 + - t[2 * x + 3] * 9 + 8) >> - 4; - } -} - -// TODO(fbarchard): Replace 0x7f ^ f with 128-f. bug=607. -// Mimics SSSE3 blender -#define BLENDER1(a, b, f) ((a) * (0x7f ^ f) + (b)*f) >> 7 -#define BLENDERC(a, b, f, s) \ - (uint16_t)(BLENDER1(((a) >> s) & 255, ((b) >> s) & 255, f) << s) -#define BLENDER(a, b, f) BLENDERC(a, b, f, 8) | BLENDERC(a, b, f, 0) - -void ScaleUVFilterCols_C(uint8_t *dst_uv, - const uint8_t *src_uv, - int dst_width, - int x, - int dx) { - const uint16_t *src = (const uint16_t *) (src_uv); - uint16_t *dst = (uint16_t *) (dst_uv); - int j; - for (j = 0; j < dst_width - 1; j += 2) { - int xi = x >> 16; - int xf = (x >> 9) & 0x7f; - uint16_t a = src[xi]; - uint16_t b = src[xi + 1]; - dst[0] = BLENDER(a, b, xf); - x += dx; - xi = x >> 16; - xf = (x >> 9) & 0x7f; - a = src[xi]; - b = src[xi + 1]; - dst[1] = BLENDER(a, b, xf); - x += dx; - dst += 2; - } - if (dst_width & 1) { - int xi = x >> 16; - int xf = (x >> 9) & 0x7f; - uint16_t a = src[xi]; - uint16_t b = src[xi + 1]; - dst[0] = BLENDER(a, b, xf); - } -} - -#undef BLENDER1 -#undef BLENDERC -#undef BLENDER - -// Scale plane vertically with bilinear interpolation. -void ScalePlaneVertical(int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_argb, - uint8_t *dst_argb, - int x, - int y, - int dy, - int bpp, // bytes per pixel. 4 for ARGB. - enum FilterMode filtering) { - // TODO(fbarchard): Allow higher bpp. - int dst_width_bytes = dst_width * bpp; - void (*InterpolateRow)(uint8_t *dst_argb, const uint8_t *src_argb, - ptrdiff_t src_stride, int dst_width, - int source_y_fraction) = InterpolateRow_C; - const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0; - int j; - assert(bpp >= 1 && bpp <= 4); - assert(src_height != 0); - assert(dst_width > 0); - assert(dst_height > 0); - src_argb += (x >> 16) * bpp; -#if defined(HAS_INTERPOLATEROW_SSSE3) - if (TestCpuFlag(kCpuHasSSSE3)) { - InterpolateRow = InterpolateRow_Any_SSSE3; - if (IS_ALIGNED(dst_width_bytes, 16)) { - InterpolateRow = InterpolateRow_SSSE3; - } - } -#endif -#if defined(HAS_INTERPOLATEROW_AVX2) - if (TestCpuFlag(kCpuHasAVX2)) { - InterpolateRow = InterpolateRow_Any_AVX2; - if (IS_ALIGNED(dst_width_bytes, 32)) { - InterpolateRow = InterpolateRow_AVX2; - } - } -#endif - - - for (j = 0; j < dst_height; ++j) { - int yi; - int yf; - if (y > max_y) { - y = max_y; - } - yi = y >> 16; - yf = filtering ? ((y >> 8) & 255) : 0; - InterpolateRow(dst_argb, src_argb + yi * src_stride, src_stride, - dst_width_bytes, yf); - dst_argb += dst_stride; - y += dy; - } -} - -// Simplify the filtering based on scale factors. -enum FilterMode ScaleFilterReduce(int src_width, - int src_height, - int dst_width, - int dst_height, - enum FilterMode filtering) { - if (src_width < 0) { - src_width = -src_width; - } - if (src_height < 0) { - src_height = -src_height; - } - if (filtering == kFilterBox) { - // If scaling either axis to 0.5 or larger, switch from Box to Bilinear. - if (dst_width * 2 >= src_width || dst_height * 2 >= src_height) { - filtering = kFilterBilinear; - } - } - if (filtering == kFilterBilinear) { - if (src_height == 1) { - filtering = kFilterLinear; - } - // TODO(fbarchard): Detect any odd scale factor and reduce to Linear. - if (dst_height == src_height || dst_height * 3 == src_height) { - filtering = kFilterLinear; - } - // TODO(fbarchard): Remove 1 pixel wide filter restriction, which is to - // avoid reading 2 pixels horizontally that causes memory exception. - if (src_width == 1) { - filtering = kFilterNone; - } - } - if (filtering == kFilterLinear) { - if (src_width == 1) { - filtering = kFilterNone; - } - // TODO(fbarchard): Detect any odd scale factor and reduce to None. - if (dst_width == src_width || dst_width * 3 == src_width) { - filtering = kFilterNone; - } - } - return filtering; -} - -#define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s) - -// Compute slope values for stepping. -void ScaleSlope(int src_width, - int src_height, - int dst_width, - int dst_height, - enum FilterMode filtering, - int *x, - int *y, - int *dx, - int *dy) { - assert(x != NULL); - assert(y != NULL); - assert(dx != NULL); - assert(dy != NULL); - assert(src_width != 0); - assert(src_height != 0); - assert(dst_width > 0); - assert(dst_height > 0); - // Check for 1 pixel and avoid FixedDiv overflow. - if (dst_width == 1 && src_width >= 32768) { - dst_width = src_width; - } - if (dst_height == 1 && src_height >= 32768) { - dst_height = src_height; - } - if (filtering == kFilterBox) { - // Scale step for point sampling duplicates all pixels equally. - *dx = FixedDiv(Abs(src_width), dst_width); - *dy = FixedDiv(src_height, dst_height); - *x = 0; - *y = 0; - } else if (filtering == kFilterBilinear) { - // Scale step for bilinear sampling renders last pixel once for upsample. - if (dst_width <= Abs(src_width)) { - *dx = FixedDiv(Abs(src_width), dst_width); - *x = CENTERSTART(*dx, -32768); // Subtract 0.5 (32768) to center filter. - } else if (src_width > 1 && dst_width > 1) { - *dx = FixedDiv1(Abs(src_width), dst_width); - *x = 0; - } - if (dst_height <= src_height) { - *dy = FixedDiv(src_height, dst_height); - *y = CENTERSTART(*dy, -32768); // Subtract 0.5 (32768) to center filter. - } else if (src_height > 1 && dst_height > 1) { - *dy = FixedDiv1(src_height, dst_height); - *y = 0; - } - } else if (filtering == kFilterLinear) { - // Scale step for bilinear sampling renders last pixel once for upsample. - if (dst_width <= Abs(src_width)) { - *dx = FixedDiv(Abs(src_width), dst_width); - *x = CENTERSTART(*dx, -32768); // Subtract 0.5 (32768) to center filter. - } else if (src_width > 1 && dst_width > 1) { - *dx = FixedDiv1(Abs(src_width), dst_width); - *x = 0; - } - *dy = FixedDiv(src_height, dst_height); - *y = *dy >> 1; - } else { - // Scale step for point sampling duplicates all pixels equally. - *dx = FixedDiv(Abs(src_width), dst_width); - *dy = FixedDiv(src_height, dst_height); - *x = CENTERSTART(*dx, 0); - *y = CENTERSTART(*dy, 0); - } - // Negative src_width means horizontally mirror. - if (src_width < 0) { - *x += (dst_width - 1) * *dx; - *dx = -*dx; - // src_width = -src_width; // Caller must do this. - } -} - -#undef CENTERSTART diff --git a/pkg/encoder/yuv/libyuv/scale_gcc.c b/pkg/encoder/yuv/libyuv/scale_gcc.c deleted file mode 100644 index 716d6cfdb..000000000 --- a/pkg/encoder/yuv/libyuv/scale_gcc.c +++ /dev/null @@ -1,2651 +0,0 @@ -/* - * Copyright 2013 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 "row.h" -#include "scale_row.h" - -// This module is for GCC x86 and x64. -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) - -// Offsets for source bytes 0 to 9 -static const uvec8 kShuf0 = {0, 1, 3, 4, 5, 7, 8, 9, - 128, 128, 128, 128, 128, 128, 128, 128}; - -// Offsets for source bytes 11 to 20 with 8 subtracted = 3 to 12. -static const uvec8 kShuf1 = {3, 4, 5, 7, 8, 9, 11, 12, - 128, 128, 128, 128, 128, 128, 128, 128}; - -// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31. -static const uvec8 kShuf2 = {5, 7, 8, 9, 11, 12, 13, 15, - 128, 128, 128, 128, 128, 128, 128, 128}; - -// Offsets for source bytes 0 to 10 -static const uvec8 kShuf01 = {0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9, 10}; - -// Offsets for source bytes 10 to 21 with 8 subtracted = 3 to 13. -static const uvec8 kShuf11 = {2, 3, 4, 5, 5, 6, 6, 7, - 8, 9, 9, 10, 10, 11, 12, 13}; - -// Offsets for source bytes 21 to 31 with 16 subtracted = 5 to 31. -static const uvec8 kShuf21 = {5, 6, 6, 7, 8, 9, 9, 10, - 10, 11, 12, 13, 13, 14, 14, 15}; - -// Coefficients for source bytes 0 to 10 -static const uvec8 kMadd01 = {3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2}; - -// Coefficients for source bytes 10 to 21 -static const uvec8 kMadd11 = {1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1}; - -// Coefficients for source bytes 21 to 31 -static const uvec8 kMadd21 = {2, 2, 1, 3, 3, 1, 2, 2, 1, 3, 3, 1, 2, 2, 1, 3}; - -// Coefficients for source bytes 21 to 31 -static const vec16 kRound34 = {2, 2, 2, 2, 2, 2, 2, 2}; - -static const uvec8 kShuf38a = {0, 3, 6, 8, 11, 14, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128}; - -static const uvec8 kShuf38b = {128, 128, 128, 128, 128, 128, 0, 3, - 6, 8, 11, 14, 128, 128, 128, 128}; - -// Arrange words 0,3,6 into 0,1,2 -static const uvec8 kShufAc = {0, 1, 6, 7, 12, 13, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128}; - -// Arrange words 0,3,6 into 3,4,5 -static const uvec8 kShufAc3 = {128, 128, 128, 128, 128, 128, 0, 1, - 6, 7, 12, 13, 128, 128, 128, 128}; - -// Scaling values for boxes of 3x3 and 2x3 -static const uvec16 kScaleAc33 = {65536 / 9, 65536 / 9, 65536 / 6, 65536 / 9, - 65536 / 9, 65536 / 6, 0, 0}; - -// Arrange first value for pixels 0,1,2,3,4,5 -static const uvec8 kShufAb0 = {0, 128, 3, 128, 6, 128, 8, 128, - 11, 128, 14, 128, 128, 128, 128, 128}; - -// Arrange second value for pixels 0,1,2,3,4,5 -static const uvec8 kShufAb1 = {1, 128, 4, 128, 7, 128, 9, 128, - 12, 128, 15, 128, 128, 128, 128, 128}; - -// Arrange third value for pixels 0,1,2,3,4,5 -static const uvec8 kShufAb2 = {2, 128, 5, 128, 128, 128, 10, 128, - 13, 128, 128, 128, 128, 128, 128, 128}; - -// Scaling values for boxes of 3x2 and 2x2 -static const uvec16 kScaleAb2 = {65536 / 3, 65536 / 3, 65536 / 2, 65536 / 3, - 65536 / 3, 65536 / 2, 0, 0}; - -// GCC versions of row functions are verbatim conversions from Visual C. -// Generated using gcc disassembly on Visual C object file: -// objdump -D yuvscaler.obj >yuvscaler.txt - -void ScaleRowDown2_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - // 16 pixel loop. - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "psrlw $0x8,%%xmm0 \n" - "psrlw $0x8,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1"); -} - -void ScaleRowDown2Linear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "pcmpeqb %%xmm4,%%xmm4 \n" - "psrlw $0xf,%%xmm4 \n" - "packuswb %%xmm4,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pavgw %%xmm5,%%xmm0 \n" - "pavgw %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1", "xmm4", "xmm5"); -} - -void ScaleRowDown2Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "pcmpeqb %%xmm4,%%xmm4 \n" - "psrlw $0xf,%%xmm4 \n" - "packuswb %%xmm4,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x00(%0,%3,1),%%xmm2 \n" - "movdqu 0x10(%0,%3,1),%%xmm3 \n" - "lea 0x20(%0),%0 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "psrlw $0x1,%%xmm0 \n" - "psrlw $0x1,%%xmm1 \n" - "pavgw %%xmm5,%%xmm0 \n" - "pavgw %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); -} - -#ifdef HAS_SCALEROWDOWN2_AVX2 - -void ScaleRowDown2_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile(LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "lea 0x40(%0),%0 \n" - "vpsrlw $0x8,%%ymm0,%%ymm0 \n" - "vpsrlw $0x8,%%ymm1,%%ymm1 \n" - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1"); -} - -void ScaleRowDown2Linear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $0xf,%%ymm4,%%ymm4 \n" - "vpackuswb %%ymm4,%%ymm4,%%ymm4 \n" - "vpxor %%ymm5,%%ymm5,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "lea 0x40(%0),%0 \n" - "vpmaddubsw %%ymm4,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm4,%%ymm1,%%ymm1 \n" - "vpavgw %%ymm5,%%ymm0,%%ymm0 \n" - "vpavgw %%ymm5,%%ymm1,%%ymm1 \n" - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1", "xmm4", "xmm5"); -} - -void ScaleRowDown2Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $0xf,%%ymm4,%%ymm4 \n" - "vpackuswb %%ymm4,%%ymm4,%%ymm4 \n" - "vpxor %%ymm5,%%ymm5,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "vmovdqu 0x00(%0,%3,1),%%ymm2 \n" - "vmovdqu 0x20(%0,%3,1),%%ymm3 \n" - "lea 0x40(%0),%0 \n" - "vpmaddubsw %%ymm4,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm4,%%ymm1,%%ymm1 \n" - "vpmaddubsw %%ymm4,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm4,%%ymm3,%%ymm3 \n" - "vpaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vpsrlw $0x1,%%ymm0,%%ymm0 \n" - "vpsrlw $0x1,%%ymm1,%%ymm1 \n" - "vpavgw %%ymm5,%%ymm0,%%ymm0 \n" - "vpavgw %%ymm5,%%ymm1,%%ymm1 \n" - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); -} - -#endif // HAS_SCALEROWDOWN2_AVX2 - -void ScaleRowDown4_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "pcmpeqb %%xmm5,%%xmm5 \n" - "psrld $0x18,%%xmm5 \n" - "pslld $0x10,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "pand %%xmm5,%%xmm0 \n" - "pand %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm0 \n" - "psrlw $0x8,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1", "xmm5"); -} - -void ScaleRowDown4Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - intptr_t stridex3; - asm volatile( - "pcmpeqb %%xmm4,%%xmm4 \n" - "psrlw $0xf,%%xmm4 \n" - "movdqa %%xmm4,%%xmm5 \n" - "packuswb %%xmm4,%%xmm4 \n" - "psllw $0x3,%%xmm5 \n" - "lea 0x00(%4,%4,2),%3 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "movdqu 0x00(%0,%4,1),%%xmm2 \n" - "movdqu 0x10(%0,%4,1),%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" - "pmaddubsw %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "movdqu 0x00(%0,%4,2),%%xmm2 \n" - "movdqu 0x10(%0,%4,2),%%xmm3 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "movdqu 0x00(%0,%3,1),%%xmm2 \n" - "movdqu 0x10(%0,%3,1),%%xmm3 \n" - "lea 0x20(%0),%0 \n" - "pmaddubsw %%xmm4,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm3 \n" - "paddw %%xmm2,%%xmm0 \n" - "paddw %%xmm3,%%xmm1 \n" - "phaddw %%xmm1,%%xmm0 \n" - "paddw %%xmm5,%%xmm0 \n" - "psrlw $0x4,%%xmm0 \n" - "packuswb %%xmm0,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "lea 0x8(%1),%1 \n" - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width), // %2 - "=&r"(stridex3) // %3 - : "r"((intptr_t) (src_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#ifdef HAS_SCALEROWDOWN4_AVX2 - -void ScaleRowDown4_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "vpcmpeqb %%ymm5,%%ymm5,%%ymm5 \n" - "vpsrld $0x18,%%ymm5,%%ymm5 \n" - "vpslld $0x10,%%ymm5,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "lea 0x40(%0),%0 \n" - "vpand %%ymm5,%%ymm0,%%ymm0 \n" - "vpand %%ymm5,%%ymm1,%%ymm1 \n" - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vpsrlw $0x8,%%ymm0,%%ymm0 \n" - "vpackuswb %%ymm0,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vmovdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1", "xmm5"); -} - -void ScaleRowDown4Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $0xf,%%ymm4,%%ymm4 \n" - "vpsllw $0x3,%%ymm4,%%ymm5 \n" - "vpackuswb %%ymm4,%%ymm4,%%ymm4 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" - "vmovdqu 0x20(%0),%%ymm1 \n" - "vmovdqu 0x00(%0,%3,1),%%ymm2 \n" - "vmovdqu 0x20(%0,%3,1),%%ymm3 \n" - "vpmaddubsw %%ymm4,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm4,%%ymm1,%%ymm1 \n" - "vpmaddubsw %%ymm4,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm4,%%ymm3,%%ymm3 \n" - "vpaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vmovdqu 0x00(%0,%3,2),%%ymm2 \n" - "vmovdqu 0x20(%0,%3,2),%%ymm3 \n" - "vpmaddubsw %%ymm4,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm4,%%ymm3,%%ymm3 \n" - "vpaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vmovdqu 0x00(%0,%4,1),%%ymm2 \n" - "vmovdqu 0x20(%0,%4,1),%%ymm3 \n" - "lea 0x40(%0),%0 \n" - "vpmaddubsw %%ymm4,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm4,%%ymm3,%%ymm3 \n" - "vpaddw %%ymm2,%%ymm0,%%ymm0 \n" - "vpaddw %%ymm3,%%ymm1,%%ymm1 \n" - "vphaddw %%ymm1,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vpaddw %%ymm5,%%ymm0,%%ymm0 \n" - "vpsrlw $0x4,%%ymm0,%%ymm0 \n" - "vpackuswb %%ymm0,%%ymm0,%%ymm0 \n" - "vpermq $0xd8,%%ymm0,%%ymm0 \n" - "vmovdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (src_stride * 3)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif // HAS_SCALEROWDOWN4_AVX2 - -void ScaleRowDown34_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "movdqa %0,%%xmm3 \n" - "movdqa %1,%%xmm4 \n" - "movdqa %2,%%xmm5 \n" - : - : "m"(kShuf0), // %0 - "m"(kShuf1), // %1 - "m"(kShuf2) // %2 - ); - asm volatile(LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm2 \n" - "lea 0x20(%0),%0 \n" - "movdqa %%xmm2,%%xmm1 \n" - "palignr $0x8,%%xmm0,%%xmm1 \n" - "pshufb %%xmm3,%%xmm0 \n" - "pshufb %%xmm4,%%xmm1 \n" - "pshufb %%xmm5,%%xmm2 \n" - "movq %%xmm0,(%1) \n" - "movq %%xmm1,0x8(%1) \n" - "movq %%xmm2,0x10(%1) \n" - "lea 0x18(%1),%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -void ScaleRowDown34_1_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "movdqa %0,%%xmm2 \n" // kShuf01 - "movdqa %1,%%xmm3 \n" // kShuf11 - "movdqa %2,%%xmm4 \n" // kShuf21 - : - : "m"(kShuf01), // %0 - "m"(kShuf11), // %1 - "m"(kShuf21) // %2 - ); - asm volatile( - "movdqa %0,%%xmm5 \n" // kMadd01 - "movdqa %1,%%xmm0 \n" // kMadd11 - "movdqa %2,%%xmm1 \n" // kRound34 - : - : "m"(kMadd01), // %0 - "m"(kMadd11), // %1 - "m"(kRound34) // %2 - ); - asm volatile(LABELALIGN - "1: \n" - "movdqu (%0),%%xmm6 \n" - "movdqu 0x00(%0,%3,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm5,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,(%1) \n" - "movdqu 0x8(%0),%%xmm6 \n" - "movdqu 0x8(%0,%3,1),%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "pmaddubsw %%xmm0,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,0x8(%1) \n" - "movdqu 0x10(%0),%%xmm6 \n" - "movdqu 0x10(%0,%3,1),%%xmm7 \n" - "lea 0x20(%0),%0 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm4,%%xmm6 \n" - "pmaddubsw %4,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,0x10(%1) \n" - "lea 0x18(%1),%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "m"(kMadd21) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7"); -} - -void ScaleRowDown34_0_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "movdqa %0,%%xmm2 \n" // kShuf01 - "movdqa %1,%%xmm3 \n" // kShuf11 - "movdqa %2,%%xmm4 \n" // kShuf21 - : - : "m"(kShuf01), // %0 - "m"(kShuf11), // %1 - "m"(kShuf21) // %2 - ); - asm volatile( - "movdqa %0,%%xmm5 \n" // kMadd01 - "movdqa %1,%%xmm0 \n" // kMadd11 - "movdqa %2,%%xmm1 \n" // kRound34 - : - : "m"(kMadd01), // %0 - "m"(kMadd11), // %1 - "m"(kRound34) // %2 - ); - - asm volatile(LABELALIGN - "1: \n" - "movdqu (%0),%%xmm6 \n" - "movdqu 0x00(%0,%3,1),%%xmm7 \n" - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "pmaddubsw %%xmm5,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,(%1) \n" - "movdqu 0x8(%0),%%xmm6 \n" - "movdqu 0x8(%0,%3,1),%%xmm7 \n" - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "pmaddubsw %%xmm0,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,0x8(%1) \n" - "movdqu 0x10(%0),%%xmm6 \n" - "movdqu 0x10(%0,%3,1),%%xmm7 \n" - "lea 0x20(%0),%0 \n" - "pavgb %%xmm6,%%xmm7 \n" - "pavgb %%xmm7,%%xmm6 \n" - "pshufb %%xmm4,%%xmm6 \n" - "pmaddubsw %4,%%xmm6 \n" - "paddsw %%xmm1,%%xmm6 \n" - "psrlw $0x2,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movq %%xmm6,0x10(%1) \n" - "lea 0x18(%1),%1 \n" - "sub $0x18,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "m"(kMadd21) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7"); -} - -void ScaleRowDown38_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - (void) src_stride; - asm volatile( - "movdqa %3,%%xmm4 \n" - "movdqa %4,%%xmm5 \n" - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x10(%0),%%xmm1 \n" - "lea 0x20(%0),%0 \n" - "pshufb %%xmm4,%%xmm0 \n" - "pshufb %%xmm5,%%xmm1 \n" - "paddusb %%xmm1,%%xmm0 \n" - "movq %%xmm0,(%1) \n" - "movhlps %%xmm0,%%xmm1 \n" - "movd %%xmm1,0x8(%1) \n" - "lea 0xc(%1),%1 \n" - "sub $0xc,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kShuf38a), // %3 - "m"(kShuf38b) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm4", "xmm5"); -} - -void ScaleRowDown38_2_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "movdqa %0,%%xmm2 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm4 \n" - "movdqa %3,%%xmm5 \n" - : - : "m"(kShufAb0), // %0 - "m"(kShufAb1), // %1 - "m"(kShufAb2), // %2 - "m"(kScaleAb2) // %3 - ); - asm volatile(LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%3,1),%%xmm1 \n" - "lea 0x10(%0),%0 \n" - "pavgb %%xmm1,%%xmm0 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pshufb %%xmm2,%%xmm1 \n" - "movdqa %%xmm0,%%xmm6 \n" - "pshufb %%xmm3,%%xmm6 \n" - "paddusw %%xmm6,%%xmm1 \n" - "pshufb %%xmm4,%%xmm0 \n" - "paddusw %%xmm0,%%xmm1 \n" - "pmulhuw %%xmm5,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movd %%xmm1,(%1) \n" - "psrlq $0x10,%%xmm1 \n" - "movd %%xmm1,0x2(%1) \n" - "lea 0x6(%1),%1 \n" - "sub $0x6,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6"); -} - -void ScaleRowDown38_3_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "movdqa %0,%%xmm2 \n" - "movdqa %1,%%xmm3 \n" - "movdqa %2,%%xmm4 \n" - "pxor %%xmm5,%%xmm5 \n" - : - : "m"(kShufAc), // %0 - "m"(kShufAc3), // %1 - "m"(kScaleAc33) // %2 - ); - asm volatile(LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" - "movdqu 0x00(%0,%3,1),%%xmm6 \n" - "movhlps %%xmm0,%%xmm1 \n" - "movhlps %%xmm6,%%xmm7 \n" - "punpcklbw %%xmm5,%%xmm0 \n" - "punpcklbw %%xmm5,%%xmm1 \n" - "punpcklbw %%xmm5,%%xmm6 \n" - "punpcklbw %%xmm5,%%xmm7 \n" - "paddusw %%xmm6,%%xmm0 \n" - "paddusw %%xmm7,%%xmm1 \n" - "movdqu 0x00(%0,%3,2),%%xmm6 \n" - "lea 0x10(%0),%0 \n" - "movhlps %%xmm6,%%xmm7 \n" - "punpcklbw %%xmm5,%%xmm6 \n" - "punpcklbw %%xmm5,%%xmm7 \n" - "paddusw %%xmm6,%%xmm0 \n" - "paddusw %%xmm7,%%xmm1 \n" - "movdqa %%xmm0,%%xmm6 \n" - "psrldq $0x2,%%xmm0 \n" - "paddusw %%xmm0,%%xmm6 \n" - "psrldq $0x2,%%xmm0 \n" - "paddusw %%xmm0,%%xmm6 \n" - "pshufb %%xmm2,%%xmm6 \n" - "movdqa %%xmm1,%%xmm7 \n" - "psrldq $0x2,%%xmm1 \n" - "paddusw %%xmm1,%%xmm7 \n" - "psrldq $0x2,%%xmm1 \n" - "paddusw %%xmm1,%%xmm7 \n" - "pshufb %%xmm3,%%xmm7 \n" - "paddusw %%xmm7,%%xmm6 \n" - "pmulhuw %%xmm4,%%xmm6 \n" - "packuswb %%xmm6,%%xmm6 \n" - "movd %%xmm6,(%1) \n" - "psrlq $0x10,%%xmm6 \n" - "movd %%xmm6,0x2(%1) \n" - "lea 0x6(%1),%1 \n" - "sub $0x6,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", - "xmm6", "xmm7"); -} - -static const uvec8 kLinearShuffleFar = {2, 3, 0, 1, 6, 7, 4, 5, - 10, 11, 8, 9, 14, 15, 12, 13}; - -static const uvec8 kLinearMadd31 = {3, 1, 1, 3, 3, 1, 1, 3, - 3, 1, 1, 3, 3, 1, 1, 3}; - -#ifdef HAS_SCALEROWUP2_LINEAR_SSE2 - -void ScaleRowUp2_Linear_SSE2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "pxor %%xmm0,%%xmm0 \n" // 0 - "pcmpeqw %%xmm6,%%xmm6 \n" - "psrlw $15,%%xmm6 \n" - "psllw $1,%%xmm6 \n" // all 2 - - LABELALIGN - "1: \n" - "movq (%0),%%xmm1 \n" // 01234567 - "movq 1(%0),%%xmm2 \n" // 12345678 - "movdqa %%xmm1,%%xmm3 \n" - "punpcklbw %%xmm2,%%xmm3 \n" // 0112233445566778 - "punpcklbw %%xmm1,%%xmm1 \n" // 0011223344556677 - "punpcklbw %%xmm2,%%xmm2 \n" // 1122334455667788 - "movdqa %%xmm1,%%xmm4 \n" - "punpcklbw %%xmm0,%%xmm4 \n" // 00112233 (16) - "movdqa %%xmm2,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" // 11223344 (16) - "paddw %%xmm5,%%xmm4 \n" - "movdqa %%xmm3,%%xmm5 \n" - "paddw %%xmm6,%%xmm4 \n" - "punpcklbw %%xmm0,%%xmm5 \n" // 01122334 (16) - "paddw %%xmm5,%%xmm5 \n" - "paddw %%xmm4,%%xmm5 \n" // 3*near+far+2 (lo) - "psrlw $2,%%xmm5 \n" // 3/4*near+1/4*far (lo) - - "punpckhbw %%xmm0,%%xmm1 \n" // 44556677 (16) - "punpckhbw %%xmm0,%%xmm2 \n" // 55667788 (16) - "paddw %%xmm2,%%xmm1 \n" - "punpckhbw %%xmm0,%%xmm3 \n" // 45566778 (16) - "paddw %%xmm6,%%xmm1 \n" - "paddw %%xmm3,%%xmm3 \n" - "paddw %%xmm3,%%xmm1 \n" // 3*near+far+2 (hi) - "psrlw $2,%%xmm1 \n" // 3/4*near+1/4*far (hi) - - "packuswb %%xmm1,%%xmm5 \n" - "movdqu %%xmm5,(%1) \n" - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSE2 - -void ScaleRowUp2_Bilinear_SSE2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - LABELALIGN - "1: \n" - "pxor %%xmm0,%%xmm0 \n" // 0 - // above line - "movq (%0),%%xmm1 \n" // 01234567 - "movq 1(%0),%%xmm2 \n" // 12345678 - "movdqa %%xmm1,%%xmm3 \n" - "punpcklbw %%xmm2,%%xmm3 \n" // 0112233445566778 - "punpcklbw %%xmm1,%%xmm1 \n" // 0011223344556677 - "punpcklbw %%xmm2,%%xmm2 \n" // 1122334455667788 - - "movdqa %%xmm1,%%xmm4 \n" - "punpcklbw %%xmm0,%%xmm4 \n" // 00112233 (16) - "movdqa %%xmm2,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" // 11223344 (16) - "paddw %%xmm5,%%xmm4 \n" // near+far - "movdqa %%xmm3,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" // 01122334 (16) - "paddw %%xmm5,%%xmm5 \n" // 2*near - "paddw %%xmm5,%%xmm4 \n" // 3*near+far (1, lo) - - "punpckhbw %%xmm0,%%xmm1 \n" // 44556677 (16) - "punpckhbw %%xmm0,%%xmm2 \n" // 55667788 (16) - "paddw %%xmm2,%%xmm1 \n" - "punpckhbw %%xmm0,%%xmm3 \n" // 45566778 (16) - "paddw %%xmm3,%%xmm3 \n" // 2*near - "paddw %%xmm3,%%xmm1 \n" // 3*near+far (1, hi) - - // below line - "movq (%0,%3),%%xmm6 \n" // 01234567 - "movq 1(%0,%3),%%xmm2 \n" // 12345678 - "movdqa %%xmm6,%%xmm3 \n" - "punpcklbw %%xmm2,%%xmm3 \n" // 0112233445566778 - "punpcklbw %%xmm6,%%xmm6 \n" // 0011223344556677 - "punpcklbw %%xmm2,%%xmm2 \n" // 1122334455667788 - - "movdqa %%xmm6,%%xmm5 \n" - "punpcklbw %%xmm0,%%xmm5 \n" // 00112233 (16) - "movdqa %%xmm2,%%xmm7 \n" - "punpcklbw %%xmm0,%%xmm7 \n" // 11223344 (16) - "paddw %%xmm7,%%xmm5 \n" // near+far - "movdqa %%xmm3,%%xmm7 \n" - "punpcklbw %%xmm0,%%xmm7 \n" // 01122334 (16) - "paddw %%xmm7,%%xmm7 \n" // 2*near - "paddw %%xmm7,%%xmm5 \n" // 3*near+far (2, lo) - - "punpckhbw %%xmm0,%%xmm6 \n" // 44556677 (16) - "punpckhbw %%xmm0,%%xmm2 \n" // 55667788 (16) - "paddw %%xmm6,%%xmm2 \n" // near+far - "punpckhbw %%xmm0,%%xmm3 \n" // 45566778 (16) - "paddw %%xmm3,%%xmm3 \n" // 2*near - "paddw %%xmm3,%%xmm2 \n" // 3*near+far (2, hi) - - // xmm4 xmm1 - // xmm5 xmm2 - "pcmpeqw %%xmm0,%%xmm0 \n" - "psrlw $15,%%xmm0 \n" - "psllw $3,%%xmm0 \n" // all 8 - - "movdqa %%xmm4,%%xmm3 \n" - "movdqa %%xmm5,%%xmm6 \n" - "paddw %%xmm3,%%xmm3 \n" // 6*near+2*far (1, lo) - "paddw %%xmm0,%%xmm6 \n" // 3*near+far+8 (2, lo) - "paddw %%xmm4,%%xmm3 \n" // 9*near+3*far (1, lo) - "paddw %%xmm6,%%xmm3 \n" // 9 3 3 1 + 8 (1, lo) - "psrlw $4,%%xmm3 \n" // ^ div by 16 - - "movdqa %%xmm1,%%xmm7 \n" - "movdqa %%xmm2,%%xmm6 \n" - "paddw %%xmm7,%%xmm7 \n" // 6*near+2*far (1, hi) - "paddw %%xmm0,%%xmm6 \n" // 3*near+far+8 (2, hi) - "paddw %%xmm1,%%xmm7 \n" // 9*near+3*far (1, hi) - "paddw %%xmm6,%%xmm7 \n" // 9 3 3 1 + 8 (1, hi) - "psrlw $4,%%xmm7 \n" // ^ div by 16 - - "packuswb %%xmm7,%%xmm3 \n" - "movdqu %%xmm3,(%1) \n" // save above line - - "movdqa %%xmm5,%%xmm3 \n" - "paddw %%xmm0,%%xmm4 \n" // 3*near+far+8 (1, lo) - "paddw %%xmm3,%%xmm3 \n" // 6*near+2*far (2, lo) - "paddw %%xmm3,%%xmm5 \n" // 9*near+3*far (2, lo) - "paddw %%xmm4,%%xmm5 \n" // 9 3 3 1 + 8 (lo) - "psrlw $4,%%xmm5 \n" // ^ div by 16 - - "movdqa %%xmm2,%%xmm3 \n" - "paddw %%xmm0,%%xmm1 \n" // 3*near+far+8 (1, hi) - "paddw %%xmm3,%%xmm3 \n" // 6*near+2*far (2, hi) - "paddw %%xmm3,%%xmm2 \n" // 9*near+3*far (2, hi) - "paddw %%xmm1,%%xmm2 \n" // 9 3 3 1 + 8 (hi) - "psrlw $4,%%xmm2 \n" // ^ div by 16 - - "packuswb %%xmm2,%%xmm5 \n" - "movdqu %%xmm5,(%1,%4) \n" // save below line - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_12_SSSE3 - -void ScaleRowUp2_Linear_12_SSSE3(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "movdqa %3,%%xmm5 \n" - "pcmpeqw %%xmm4,%%xmm4 \n" - "psrlw $15,%%xmm4 \n" - "psllw $1,%%xmm4 \n" // all 2 - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" // 01234567 (16) - "movdqu 2(%0),%%xmm1 \n" // 12345678 (16) - - "movdqa %%xmm0,%%xmm2 \n" - "punpckhwd %%xmm1,%%xmm2 \n" // 45566778 (16) - "punpcklwd %%xmm1,%%xmm0 \n" // 01122334 (16) - - "movdqa %%xmm2,%%xmm3 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pshufb %%xmm5,%%xmm3 \n" // 54657687 (far) - "pshufb %%xmm5,%%xmm1 \n" // 10213243 (far) - - "paddw %%xmm4,%%xmm1 \n" // far+2 - "paddw %%xmm4,%%xmm3 \n" // far+2 - "paddw %%xmm0,%%xmm1 \n" // near+far+2 - "paddw %%xmm2,%%xmm3 \n" // near+far+2 - "paddw %%xmm0,%%xmm0 \n" // 2*near - "paddw %%xmm2,%%xmm2 \n" // 2*near - "paddw %%xmm1,%%xmm0 \n" // 3*near+far+2 (lo) - "paddw %%xmm3,%%xmm2 \n" // 3*near+far+2 (hi) - - "psrlw $2,%%xmm0 \n" // 3/4*near+1/4*far - "psrlw $2,%%xmm2 \n" // 3/4*near+1/4*far - "movdqu %%xmm0,(%1) \n" - "movdqu %%xmm2,16(%1) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kLinearShuffleFar) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_12_SSSE3 - -void ScaleRowUp2_Bilinear_12_SSSE3(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "pcmpeqw %%xmm7,%%xmm7 \n" - "psrlw $15,%%xmm7 \n" - "psllw $3,%%xmm7 \n" // all 8 - "movdqa %5,%%xmm6 \n" - - LABELALIGN - "1: \n" - // above line - "movdqu (%0),%%xmm0 \n" // 01234567 (16) - "movdqu 2(%0),%%xmm1 \n" // 12345678 (16) - "movdqa %%xmm0,%%xmm2 \n" - "punpckhwd %%xmm1,%%xmm2 \n" // 45566778 (16) - "punpcklwd %%xmm1,%%xmm0 \n" // 01122334 (16) - "movdqa %%xmm2,%%xmm3 \n" - "movdqa %%xmm0,%%xmm1 \n" - "pshufb %%xmm6,%%xmm3 \n" // 54657687 (far) - "pshufb %%xmm6,%%xmm1 \n" // 10213243 (far) - "paddw %%xmm0,%%xmm1 \n" // near+far - "paddw %%xmm2,%%xmm3 \n" // near+far - "paddw %%xmm0,%%xmm0 \n" // 2*near - "paddw %%xmm2,%%xmm2 \n" // 2*near - "paddw %%xmm1,%%xmm0 \n" // 3*near+far (1, lo) - "paddw %%xmm3,%%xmm2 \n" // 3*near+far (1, hi) - - // below line - "movdqu (%0,%3,2),%%xmm1 \n" // 01234567 (16) - "movdqu 2(%0,%3,2),%%xmm4 \n" // 12345678 (16) - "movdqa %%xmm1,%%xmm3 \n" - "punpckhwd %%xmm4,%%xmm3 \n" // 45566778 (16) - "punpcklwd %%xmm4,%%xmm1 \n" // 01122334 (16) - "movdqa %%xmm3,%%xmm5 \n" - "movdqa %%xmm1,%%xmm4 \n" - "pshufb %%xmm6,%%xmm5 \n" // 54657687 (far) - "pshufb %%xmm6,%%xmm4 \n" // 10213243 (far) - "paddw %%xmm1,%%xmm4 \n" // near+far - "paddw %%xmm3,%%xmm5 \n" // near+far - "paddw %%xmm1,%%xmm1 \n" // 2*near - "paddw %%xmm3,%%xmm3 \n" // 2*near - "paddw %%xmm4,%%xmm1 \n" // 3*near+far (2, lo) - "paddw %%xmm5,%%xmm3 \n" // 3*near+far (2, hi) - - // xmm0 xmm2 - // xmm1 xmm3 - - "movdqa %%xmm0,%%xmm4 \n" - "movdqa %%xmm1,%%xmm5 \n" - "paddw %%xmm4,%%xmm4 \n" // 6*near+2*far (1, lo) - "paddw %%xmm7,%%xmm5 \n" // 3*near+far+8 (2, lo) - "paddw %%xmm0,%%xmm4 \n" // 9*near+3*far (1, lo) - "paddw %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, lo) - "psrlw $4,%%xmm4 \n" // ^ div by 16 - "movdqu %%xmm4,(%1) \n" - - "movdqa %%xmm2,%%xmm4 \n" - "movdqa %%xmm3,%%xmm5 \n" - "paddw %%xmm4,%%xmm4 \n" // 6*near+2*far (1, hi) - "paddw %%xmm7,%%xmm5 \n" // 3*near+far+8 (2, hi) - "paddw %%xmm2,%%xmm4 \n" // 9*near+3*far (1, hi) - "paddw %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, hi) - "psrlw $4,%%xmm4 \n" // ^ div by 16 - "movdqu %%xmm4,0x10(%1) \n" - - "movdqa %%xmm1,%%xmm4 \n" - "paddw %%xmm7,%%xmm0 \n" // 3*near+far+8 (1, lo) - "paddw %%xmm4,%%xmm4 \n" // 6*near+2*far (2, lo) - "paddw %%xmm4,%%xmm1 \n" // 9*near+3*far (2, lo) - "paddw %%xmm0,%%xmm1 \n" // 9 3 3 1 + 8 (2, lo) - "psrlw $4,%%xmm1 \n" // ^ div by 16 - "movdqu %%xmm1,(%1,%4,2) \n" - - "movdqa %%xmm3,%%xmm4 \n" - "paddw %%xmm7,%%xmm2 \n" // 3*near+far+8 (1, hi) - "paddw %%xmm4,%%xmm4 \n" // 6*near+2*far (2, hi) - "paddw %%xmm4,%%xmm3 \n" // 9*near+3*far (2, hi) - "paddw %%xmm2,%%xmm3 \n" // 9 3 3 1 + 8 (2, hi) - "psrlw $4,%%xmm3 \n" // ^ div by 16 - "movdqu %%xmm3,0x10(%1,%4,2) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kLinearShuffleFar) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_16_SSE2 - -void ScaleRowUp2_Linear_16_SSE2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "pxor %%xmm5,%%xmm5 \n" - "pcmpeqd %%xmm4,%%xmm4 \n" - "psrld $31,%%xmm4 \n" - "pslld $1,%%xmm4 \n" // all 2 - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 0123 (16b) - "movq 2(%0),%%xmm1 \n" // 1234 (16b) - - "punpcklwd %%xmm5,%%xmm0 \n" // 0123 (32b) - "punpcklwd %%xmm5,%%xmm1 \n" // 1234 (32b) - - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - - "pshufd $0b10110001,%%xmm2,%%xmm2 \n" // 1032 (even, far) - "pshufd $0b10110001,%%xmm3,%%xmm3 \n" // 2143 (odd, far) - - "paddd %%xmm4,%%xmm2 \n" // far+2 (lo) - "paddd %%xmm4,%%xmm3 \n" // far+2 (hi) - "paddd %%xmm0,%%xmm2 \n" // near+far+2 (lo) - "paddd %%xmm1,%%xmm3 \n" // near+far+2 (hi) - "paddd %%xmm0,%%xmm0 \n" // 2*near (lo) - "paddd %%xmm1,%%xmm1 \n" // 2*near (hi) - "paddd %%xmm2,%%xmm0 \n" // 3*near+far+2 (lo) - "paddd %%xmm3,%%xmm1 \n" // 3*near+far+2 (hi) - - "psrld $2,%%xmm0 \n" // 3/4*near+1/4*far (lo) - "psrld $2,%%xmm1 \n" // 3/4*near+1/4*far (hi) - "packssdw %%xmm1,%%xmm0 \n" - "pshufd $0b11011000,%%xmm0,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 4 pixel to 8 pixel - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_16_SSE2 - -void ScaleRowUp2_Bilinear_16_SSE2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "pxor %%xmm7,%%xmm7 \n" - "pcmpeqd %%xmm6,%%xmm6 \n" - "psrld $31,%%xmm6 \n" - "pslld $3,%%xmm6 \n" // all 8 - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 0011 (16b, 1u1v) - "movq 4(%0),%%xmm1 \n" // 1122 (16b, 1u1v) - "punpcklwd %%xmm7,%%xmm0 \n" // 0011 (near) (32b, 1u1v) - "punpcklwd %%xmm7,%%xmm1 \n" // 1122 (near) (32b, 1u1v) - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "pshufd $0b01001110,%%xmm2,%%xmm2 \n" // 1100 (far) (1, lo) - "pshufd $0b01001110,%%xmm3,%%xmm3 \n" // 2211 (far) (1, hi) - "paddd %%xmm0,%%xmm2 \n" // near+far (1, lo) - "paddd %%xmm1,%%xmm3 \n" // near+far (1, hi) - "paddd %%xmm0,%%xmm0 \n" // 2*near (1, lo) - "paddd %%xmm1,%%xmm1 \n" // 2*near (1, hi) - "paddd %%xmm2,%%xmm0 \n" // 3*near+far (1, lo) - "paddd %%xmm3,%%xmm1 \n" // 3*near+far (1, hi) - - "movq (%0),%%xmm0 \n" // 0123 (16b) - "movq 2(%0),%%xmm1 \n" // 1234 (16b) - "punpcklwd %%xmm7,%%xmm0 \n" // 0123 (32b) - "punpcklwd %%xmm7,%%xmm1 \n" // 1234 (32b) - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "pshufd $0b10110001,%%xmm2,%%xmm2 \n" // 1032 (even, far) - "pshufd $0b10110001,%%xmm3,%%xmm3 \n" // 2143 (odd, far) - "paddd %%xmm0,%%xmm2 \n" // near+far (lo) - "paddd %%xmm1,%%xmm3 \n" // near+far (hi) - "paddd %%xmm0,%%xmm0 \n" // 2*near (lo) - "paddd %%xmm1,%%xmm1 \n" // 2*near (hi) - "paddd %%xmm2,%%xmm0 \n" // 3*near+far (1, lo) - "paddd %%xmm3,%%xmm1 \n" // 3*near+far (1, hi) - - "movq (%0,%3,2),%%xmm2 \n" - "movq 2(%0,%3,2),%%xmm3 \n" - "punpcklwd %%xmm7,%%xmm2 \n" // 0123 (32b) - "punpcklwd %%xmm7,%%xmm3 \n" // 1234 (32b) - "movdqa %%xmm2,%%xmm4 \n" - "movdqa %%xmm3,%%xmm5 \n" - "pshufd $0b10110001,%%xmm4,%%xmm4 \n" // 1032 (even, far) - "pshufd $0b10110001,%%xmm5,%%xmm5 \n" // 2143 (odd, far) - "paddd %%xmm2,%%xmm4 \n" // near+far (lo) - "paddd %%xmm3,%%xmm5 \n" // near+far (hi) - "paddd %%xmm2,%%xmm2 \n" // 2*near (lo) - "paddd %%xmm3,%%xmm3 \n" // 2*near (hi) - "paddd %%xmm4,%%xmm2 \n" // 3*near+far (2, lo) - "paddd %%xmm5,%%xmm3 \n" // 3*near+far (2, hi) - - "movdqa %%xmm0,%%xmm4 \n" - "movdqa %%xmm2,%%xmm5 \n" - "paddd %%xmm0,%%xmm4 \n" // 6*near+2*far (1, lo) - "paddd %%xmm6,%%xmm5 \n" // 3*near+far+8 (2, lo) - "paddd %%xmm0,%%xmm4 \n" // 9*near+3*far (1, lo) - "paddd %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, lo) - "psrld $4,%%xmm4 \n" // ^ div by 16 (1, lo) - - "movdqa %%xmm2,%%xmm5 \n" - "paddd %%xmm2,%%xmm5 \n" // 6*near+2*far (2, lo) - "paddd %%xmm6,%%xmm0 \n" // 3*near+far+8 (1, lo) - "paddd %%xmm2,%%xmm5 \n" // 9*near+3*far (2, lo) - "paddd %%xmm0,%%xmm5 \n" // 9 3 3 1 + 8 (2, lo) - "psrld $4,%%xmm5 \n" // ^ div by 16 (2, lo) - - "movdqa %%xmm1,%%xmm0 \n" - "movdqa %%xmm3,%%xmm2 \n" - "paddd %%xmm1,%%xmm0 \n" // 6*near+2*far (1, hi) - "paddd %%xmm6,%%xmm2 \n" // 3*near+far+8 (2, hi) - "paddd %%xmm1,%%xmm0 \n" // 9*near+3*far (1, hi) - "paddd %%xmm2,%%xmm0 \n" // 9 3 3 1 + 8 (1, hi) - "psrld $4,%%xmm0 \n" // ^ div by 16 (1, hi) - - "movdqa %%xmm3,%%xmm2 \n" - "paddd %%xmm3,%%xmm2 \n" // 6*near+2*far (2, hi) - "paddd %%xmm6,%%xmm1 \n" // 3*near+far+8 (1, hi) - "paddd %%xmm3,%%xmm2 \n" // 9*near+3*far (2, hi) - "paddd %%xmm1,%%xmm2 \n" // 9 3 3 1 + 8 (2, hi) - "psrld $4,%%xmm2 \n" // ^ div by 16 (2, hi) - - "packssdw %%xmm0,%%xmm4 \n" - "pshufd $0b11011000,%%xmm4,%%xmm4 \n" - "movdqu %%xmm4,(%1) \n" // store above - "packssdw %%xmm2,%%xmm5 \n" - "pshufd $0b11011000,%%xmm5,%%xmm5 \n" - "movdqu %%xmm5,(%1,%4,2) \n" // store below - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 4 pixel to 8 pixel - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_SSSE3 - -void ScaleRowUp2_Linear_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "pcmpeqw %%xmm4,%%xmm4 \n" - "psrlw $15,%%xmm4 \n" - "psllw $1,%%xmm4 \n" // all 2 - "movdqa %3,%%xmm3 \n" - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 01234567 - "movq 1(%0),%%xmm1 \n" // 12345678 - "punpcklwd %%xmm0,%%xmm0 \n" // 0101232345456767 - "punpcklwd %%xmm1,%%xmm1 \n" // 1212343456567878 - "movdqa %%xmm0,%%xmm2 \n" - "punpckhdq %%xmm1,%%xmm2 \n" // 4545565667677878 - "punpckldq %%xmm1,%%xmm0 \n" // 0101121223233434 - "pmaddubsw %%xmm3,%%xmm2 \n" // 3*near+far (hi) - "pmaddubsw %%xmm3,%%xmm0 \n" // 3*near+far (lo) - "paddw %%xmm4,%%xmm0 \n" // 3*near+far+2 (lo) - "paddw %%xmm4,%%xmm2 \n" // 3*near+far+2 (hi) - "psrlw $2,%%xmm0 \n" // 3/4*near+1/4*far (lo) - "psrlw $2,%%xmm2 \n" // 3/4*near+1/4*far (hi) - "packuswb %%xmm2,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kLinearMadd31) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_SSSE3 - -void ScaleRowUp2_Bilinear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "pcmpeqw %%xmm6,%%xmm6 \n" - "psrlw $15,%%xmm6 \n" - "psllw $3,%%xmm6 \n" // all 8 - "movdqa %5,%%xmm7 \n" - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 01234567 - "movq 1(%0),%%xmm1 \n" // 12345678 - "punpcklwd %%xmm0,%%xmm0 \n" // 0101232345456767 - "punpcklwd %%xmm1,%%xmm1 \n" // 1212343456567878 - "movdqa %%xmm0,%%xmm2 \n" - "punpckhdq %%xmm1,%%xmm2 \n" // 4545565667677878 - "punpckldq %%xmm1,%%xmm0 \n" // 0101121223233434 - "pmaddubsw %%xmm7,%%xmm2 \n" // 3*near+far (1, hi) - "pmaddubsw %%xmm7,%%xmm0 \n" // 3*near+far (1, lo) - - "movq (%0,%3),%%xmm1 \n" - "movq 1(%0,%3),%%xmm4 \n" - "punpcklwd %%xmm1,%%xmm1 \n" - "punpcklwd %%xmm4,%%xmm4 \n" - "movdqa %%xmm1,%%xmm3 \n" - "punpckhdq %%xmm4,%%xmm3 \n" - "punpckldq %%xmm4,%%xmm1 \n" - "pmaddubsw %%xmm7,%%xmm3 \n" // 3*near+far (2, hi) - "pmaddubsw %%xmm7,%%xmm1 \n" // 3*near+far (2, lo) - - // xmm0 xmm2 - // xmm1 xmm3 - - "movdqa %%xmm0,%%xmm4 \n" - "movdqa %%xmm1,%%xmm5 \n" - "paddw %%xmm0,%%xmm4 \n" // 6*near+2*far (1, lo) - "paddw %%xmm6,%%xmm5 \n" // 3*near+far+8 (2, lo) - "paddw %%xmm0,%%xmm4 \n" // 9*near+3*far (1, lo) - "paddw %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, lo) - "psrlw $4,%%xmm4 \n" // ^ div by 16 (1, lo) - - "movdqa %%xmm1,%%xmm5 \n" - "paddw %%xmm1,%%xmm5 \n" // 6*near+2*far (2, lo) - "paddw %%xmm6,%%xmm0 \n" // 3*near+far+8 (1, lo) - "paddw %%xmm1,%%xmm5 \n" // 9*near+3*far (2, lo) - "paddw %%xmm0,%%xmm5 \n" // 9 3 3 1 + 8 (2, lo) - "psrlw $4,%%xmm5 \n" // ^ div by 16 (2, lo) - - "movdqa %%xmm2,%%xmm0 \n" - "movdqa %%xmm3,%%xmm1 \n" - "paddw %%xmm2,%%xmm0 \n" // 6*near+2*far (1, hi) - "paddw %%xmm6,%%xmm1 \n" // 3*near+far+8 (2, hi) - "paddw %%xmm2,%%xmm0 \n" // 9*near+3*far (1, hi) - "paddw %%xmm1,%%xmm0 \n" // 9 3 3 1 + 8 (1, hi) - "psrlw $4,%%xmm0 \n" // ^ div by 16 (1, hi) - - "movdqa %%xmm3,%%xmm1 \n" - "paddw %%xmm3,%%xmm1 \n" // 6*near+2*far (2, hi) - "paddw %%xmm6,%%xmm2 \n" // 3*near+far+8 (1, hi) - "paddw %%xmm3,%%xmm1 \n" // 9*near+3*far (2, hi) - "paddw %%xmm2,%%xmm1 \n" // 9 3 3 1 + 8 (2, hi) - "psrlw $4,%%xmm1 \n" // ^ div by 16 (2, hi) - - "packuswb %%xmm0,%%xmm4 \n" - "movdqu %%xmm4,(%1) \n" // store above - "packuswb %%xmm1,%%xmm5 \n" - "movdqu %%xmm5,(%1,%4) \n" // store below - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kLinearMadd31) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_AVX2 - -void ScaleRowUp2_Linear_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqw %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $15,%%ymm4,%%ymm4 \n" - "vpsllw $1,%%ymm4,%%ymm4 \n" // all 2 - "vbroadcastf128 %3,%%ymm3 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" // 0123456789ABCDEF - "vmovdqu 1(%0),%%xmm1 \n" // 123456789ABCDEF0 - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" - "vpunpcklwd %%ymm0,%%ymm0,%%ymm0 \n" - "vpunpcklwd %%ymm1,%%ymm1,%%ymm1 \n" - "vpunpckhdq %%ymm1,%%ymm0,%%ymm2 \n" - "vpunpckldq %%ymm1,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm3,%%ymm2,%%ymm1 \n" // 3*near+far (hi) - "vpmaddubsw %%ymm3,%%ymm0,%%ymm0 \n" // 3*near+far (lo) - "vpaddw %%ymm4,%%ymm0,%%ymm0 \n" // 3*near+far+2 (lo) - "vpaddw %%ymm4,%%ymm1,%%ymm1 \n" // 3*near+far+2 (hi) - "vpsrlw $2,%%ymm0,%%ymm0 \n" // 3/4*near+1/4*far (lo) - "vpsrlw $2,%%ymm1,%%ymm1 \n" // 3/4*near+1/4*far (hi) - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 16 sample to 32 sample - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kLinearMadd31) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_AVX2 - -void ScaleRowUp2_Bilinear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "vpcmpeqw %%ymm6,%%ymm6,%%ymm6 \n" - "vpsrlw $15,%%ymm6,%%ymm6 \n" - "vpsllw $3,%%ymm6,%%ymm6 \n" // all 8 - "vbroadcastf128 %5,%%ymm7 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" // 0123456789ABCDEF - "vmovdqu 1(%0),%%xmm1 \n" // 123456789ABCDEF0 - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" - "vpunpcklwd %%ymm0,%%ymm0,%%ymm0 \n" - "vpunpcklwd %%ymm1,%%ymm1,%%ymm1 \n" - "vpunpckhdq %%ymm1,%%ymm0,%%ymm2 \n" - "vpunpckldq %%ymm1,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm7,%%ymm2,%%ymm1 \n" // 3*near+far (1, hi) - "vpmaddubsw %%ymm7,%%ymm0,%%ymm0 \n" // 3*near+far (1, lo) - - "vmovdqu (%0,%3),%%xmm2 \n" // 0123456789ABCDEF - "vmovdqu 1(%0,%3),%%xmm3 \n" // 123456789ABCDEF0 - "vpermq $0b11011000,%%ymm2,%%ymm2 \n" - "vpermq $0b11011000,%%ymm3,%%ymm3 \n" - "vpunpcklwd %%ymm2,%%ymm2,%%ymm2 \n" - "vpunpcklwd %%ymm3,%%ymm3,%%ymm3 \n" - "vpunpckhdq %%ymm3,%%ymm2,%%ymm4 \n" - "vpunpckldq %%ymm3,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm7,%%ymm4,%%ymm3 \n" // 3*near+far (2, hi) - "vpmaddubsw %%ymm7,%%ymm2,%%ymm2 \n" // 3*near+far (2, lo) - - // ymm0 ymm1 - // ymm2 ymm3 - - "vpaddw %%ymm0,%%ymm0,%%ymm4 \n" // 6*near+2*far (1, lo) - "vpaddw %%ymm6,%%ymm2,%%ymm5 \n" // 3*near+far+8 (2, lo) - "vpaddw %%ymm4,%%ymm0,%%ymm4 \n" // 9*near+3*far (1, lo) - "vpaddw %%ymm4,%%ymm5,%%ymm4 \n" // 9 3 3 1 + 8 (1, lo) - "vpsrlw $4,%%ymm4,%%ymm4 \n" // ^ div by 16 (1, lo) - - "vpaddw %%ymm2,%%ymm2,%%ymm5 \n" // 6*near+2*far (2, lo) - "vpaddw %%ymm6,%%ymm0,%%ymm0 \n" // 3*near+far+8 (1, lo) - "vpaddw %%ymm5,%%ymm2,%%ymm5 \n" // 9*near+3*far (2, lo) - "vpaddw %%ymm5,%%ymm0,%%ymm5 \n" // 9 3 3 1 + 8 (2, lo) - "vpsrlw $4,%%ymm5,%%ymm5 \n" // ^ div by 16 (2, lo) - - "vpaddw %%ymm1,%%ymm1,%%ymm0 \n" // 6*near+2*far (1, hi) - "vpaddw %%ymm6,%%ymm3,%%ymm2 \n" // 3*near+far+8 (2, hi) - "vpaddw %%ymm0,%%ymm1,%%ymm0 \n" // 9*near+3*far (1, hi) - "vpaddw %%ymm0,%%ymm2,%%ymm0 \n" // 9 3 3 1 + 8 (1, hi) - "vpsrlw $4,%%ymm0,%%ymm0 \n" // ^ div by 16 (1, hi) - - "vpaddw %%ymm3,%%ymm3,%%ymm2 \n" // 6*near+2*far (2, hi) - "vpaddw %%ymm6,%%ymm1,%%ymm1 \n" // 3*near+far+8 (1, hi) - "vpaddw %%ymm2,%%ymm3,%%ymm2 \n" // 9*near+3*far (2, hi) - "vpaddw %%ymm2,%%ymm1,%%ymm2 \n" // 9 3 3 1 + 8 (2, hi) - "vpsrlw $4,%%ymm2,%%ymm2 \n" // ^ div by 16 (2, hi) - - "vpackuswb %%ymm0,%%ymm4,%%ymm4 \n" - "vmovdqu %%ymm4,(%1) \n" // store above - "vpackuswb %%ymm2,%%ymm5,%%ymm5 \n" - "vmovdqu %%ymm5,(%1,%4) \n" // store below - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 16 sample to 32 sample - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kLinearMadd31) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_12_AVX2 - -void ScaleRowUp2_Linear_12_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "vbroadcastf128 %3,%%ymm5 \n" - "vpcmpeqw %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $15,%%ymm4,%%ymm4 \n" - "vpsllw $1,%%ymm4,%%ymm4 \n" // all 2 - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" // 0123456789ABCDEF (16b) - "vmovdqu 2(%0),%%ymm1 \n" // 123456789ABCDEF0 (16b) - - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" // 012389AB4567CDEF - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" // 12349ABC5678DEF0 - - "vpunpckhwd %%ymm1,%%ymm0,%%ymm2 \n" // 899AABBCCDDEEFF0 (near) - "vpunpcklwd %%ymm1,%%ymm0,%%ymm0 \n" // 0112233445566778 (near) - "vpshufb %%ymm5,%%ymm2,%%ymm3 \n" // 98A9BACBDCEDFE0F (far) - "vpshufb %%ymm5,%%ymm0,%%ymm1 \n" // 1021324354657687 (far) - - "vpaddw %%ymm4,%%ymm1,%%ymm1 \n" // far+2 - "vpaddw %%ymm4,%%ymm3,%%ymm3 \n" // far+2 - "vpaddw %%ymm0,%%ymm1,%%ymm1 \n" // near+far+2 - "vpaddw %%ymm2,%%ymm3,%%ymm3 \n" // near+far+2 - "vpaddw %%ymm0,%%ymm0,%%ymm0 \n" // 2*near - "vpaddw %%ymm2,%%ymm2,%%ymm2 \n" // 2*near - "vpaddw %%ymm0,%%ymm1,%%ymm0 \n" // 3*near+far+2 - "vpaddw %%ymm2,%%ymm3,%%ymm2 \n" // 3*near+far+2 - - "vpsrlw $2,%%ymm0,%%ymm0 \n" // 3/4*near+1/4*far - "vpsrlw $2,%%ymm2,%%ymm2 \n" // 3/4*near+1/4*far - "vmovdqu %%ymm0,(%1) \n" - "vmovdqu %%ymm2,32(%1) \n" - - "lea 0x20(%0),%0 \n" - "lea 0x40(%1),%1 \n" // 16 sample to 32 sample - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kLinearShuffleFar) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_12_AVX2 - -void ScaleRowUp2_Bilinear_12_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "vbroadcastf128 %5,%%ymm5 \n" - "vpcmpeqw %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $15,%%ymm4,%%ymm4 \n" - "vpsllw $3,%%ymm4,%%ymm4 \n" // all 8 - - LABELALIGN - "1: \n" - - "vmovdqu (%0),%%xmm0 \n" // 01234567 (16b) - "vmovdqu 2(%0),%%xmm1 \n" // 12345678 (16b) - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" // 0123000045670000 - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" // 1234000056780000 - "vpunpcklwd %%ymm1,%%ymm0,%%ymm0 \n" // 0112233445566778 (near) - "vpshufb %%ymm5,%%ymm0,%%ymm1 \n" // 1021324354657687 (far) - "vpaddw %%ymm0,%%ymm1,%%ymm1 \n" // near+far - "vpaddw %%ymm0,%%ymm0,%%ymm0 \n" // 2*near - "vpaddw %%ymm0,%%ymm1,%%ymm2 \n" // 3*near+far (1) - - "vmovdqu (%0,%3,2),%%xmm0 \n" // 01234567 (16b) - "vmovdqu 2(%0,%3,2),%%xmm1 \n" // 12345678 (16b) - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" // 0123000045670000 - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" // 1234000056780000 - "vpunpcklwd %%ymm1,%%ymm0,%%ymm0 \n" // 0112233445566778 (near) - "vpshufb %%ymm5,%%ymm0,%%ymm1 \n" // 1021324354657687 (far) - "vpaddw %%ymm0,%%ymm1,%%ymm1 \n" // near+far - "vpaddw %%ymm0,%%ymm0,%%ymm0 \n" // 2*near - "vpaddw %%ymm0,%%ymm1,%%ymm3 \n" // 3*near+far (2) - - "vpaddw %%ymm2,%%ymm2,%%ymm0 \n" // 6*near+2*far (1) - "vpaddw %%ymm4,%%ymm3,%%ymm1 \n" // 3*near+far+8 (2) - "vpaddw %%ymm0,%%ymm2,%%ymm0 \n" // 9*near+3*far (1) - "vpaddw %%ymm0,%%ymm1,%%ymm0 \n" // 9 3 3 1 + 8 (1) - "vpsrlw $4,%%ymm0,%%ymm0 \n" // ^ div by 16 - "vmovdqu %%ymm0,(%1) \n" // store above - - "vpaddw %%ymm3,%%ymm3,%%ymm0 \n" // 6*near+2*far (2) - "vpaddw %%ymm4,%%ymm2,%%ymm1 \n" // 3*near+far+8 (1) - "vpaddw %%ymm0,%%ymm3,%%ymm0 \n" // 9*near+3*far (2) - "vpaddw %%ymm0,%%ymm1,%%ymm0 \n" // 9 3 3 1 + 8 (2) - "vpsrlw $4,%%ymm0,%%ymm0 \n" // ^ div by 16 - "vmovdqu %%ymm0,(%1,%4,2) \n" // store below - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 sample to 16 sample - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kLinearShuffleFar) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_LINEAR_16_AVX2 - -void ScaleRowUp2_Linear_16_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqd %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrld $31,%%ymm4,%%ymm4 \n" - "vpslld $1,%%ymm4,%%ymm4 \n" // all 2 - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" // 01234567 (16b, 1u1v) - "vmovdqu 2(%0),%%xmm1 \n" // 12345678 (16b, 1u1v) - - "vpmovzxwd %%xmm0,%%ymm0 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm1,%%ymm1 \n" // 12345678 (32b, 1u1v) - - "vpshufd $0b10110001,%%ymm0,%%ymm2 \n" // 10325476 (lo, far) - "vpshufd $0b10110001,%%ymm1,%%ymm3 \n" // 21436587 (hi, far) - - "vpaddd %%ymm4,%%ymm2,%%ymm2 \n" // far+2 (lo) - "vpaddd %%ymm4,%%ymm3,%%ymm3 \n" // far+2 (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm2 \n" // near+far+2 (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm3 \n" // near+far+2 (hi) - "vpaddd %%ymm0,%%ymm0,%%ymm0 \n" // 2*near (lo) - "vpaddd %%ymm1,%%ymm1,%%ymm1 \n" // 2*near (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 3*near+far+2 (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm1 \n" // 3*near+far+2 (hi) - - "vpsrld $2,%%ymm0,%%ymm0 \n" // 3/4*near+1/4*far (lo) - "vpsrld $2,%%ymm1,%%ymm1 \n" // 3/4*near+1/4*far (hi) - "vpackusdw %%ymm1,%%ymm0,%%ymm0 \n" - "vpshufd $0b11011000,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 pixel to 16 pixel - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"); -} - -#endif - -#ifdef HAS_SCALEROWUP2_BILINEAR_16_AVX2 - -void ScaleRowUp2_Bilinear_16_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "vpcmpeqd %%ymm6,%%ymm6,%%ymm6 \n" - "vpsrld $31,%%ymm6,%%ymm6 \n" - "vpslld $3,%%ymm6,%%ymm6 \n" // all 8 - - LABELALIGN - "1: \n" - - "vmovdqu (%0),%%xmm0 \n" // 01234567 (16b, 1u1v) - "vmovdqu 2(%0),%%xmm1 \n" // 12345678 (16b, 1u1v) - "vpmovzxwd %%xmm0,%%ymm0 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm1,%%ymm1 \n" // 12345678 (32b, 1u1v) - "vpshufd $0b10110001,%%ymm0,%%ymm2 \n" // 10325476 (lo, far) - "vpshufd $0b10110001,%%ymm1,%%ymm3 \n" // 21436587 (hi, far) - "vpaddd %%ymm0,%%ymm2,%%ymm2 \n" // near+far (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm3 \n" // near+far (hi) - "vpaddd %%ymm0,%%ymm0,%%ymm0 \n" // 2*near (lo) - "vpaddd %%ymm1,%%ymm1,%%ymm1 \n" // 2*near (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 3*near+far (1, lo) - "vpaddd %%ymm1,%%ymm3,%%ymm1 \n" // 3*near+far (1, hi) - - "vmovdqu (%0,%3,2),%%xmm2 \n" // 01234567 (16b, 1u1v) - "vmovdqu 2(%0,%3,2),%%xmm3 \n" // 12345678 (16b, 1u1v) - "vpmovzxwd %%xmm2,%%ymm2 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm3,%%ymm3 \n" // 12345678 (32b, 1u1v) - "vpshufd $0b10110001,%%ymm2,%%ymm4 \n" // 10325476 (lo, far) - "vpshufd $0b10110001,%%ymm3,%%ymm5 \n" // 21436587 (hi, far) - "vpaddd %%ymm2,%%ymm4,%%ymm4 \n" // near+far (lo) - "vpaddd %%ymm3,%%ymm5,%%ymm5 \n" // near+far (hi) - "vpaddd %%ymm2,%%ymm2,%%ymm2 \n" // 2*near (lo) - "vpaddd %%ymm3,%%ymm3,%%ymm3 \n" // 2*near (hi) - "vpaddd %%ymm2,%%ymm4,%%ymm2 \n" // 3*near+far (2, lo) - "vpaddd %%ymm3,%%ymm5,%%ymm3 \n" // 3*near+far (2, hi) - - "vpaddd %%ymm0,%%ymm0,%%ymm4 \n" // 6*near+2*far (1, lo) - "vpaddd %%ymm6,%%ymm2,%%ymm5 \n" // 3*near+far+8 (2, lo) - "vpaddd %%ymm4,%%ymm0,%%ymm4 \n" // 9*near+3*far (1, lo) - "vpaddd %%ymm4,%%ymm5,%%ymm4 \n" // 9 3 3 1 + 8 (1, lo) - "vpsrld $4,%%ymm4,%%ymm4 \n" // ^ div by 16 (1, lo) - - "vpaddd %%ymm2,%%ymm2,%%ymm5 \n" // 6*near+2*far (2, lo) - "vpaddd %%ymm6,%%ymm0,%%ymm0 \n" // 3*near+far+8 (1, lo) - "vpaddd %%ymm5,%%ymm2,%%ymm5 \n" // 9*near+3*far (2, lo) - "vpaddd %%ymm5,%%ymm0,%%ymm5 \n" // 9 3 3 1 + 8 (2, lo) - "vpsrld $4,%%ymm5,%%ymm5 \n" // ^ div by 16 (2, lo) - - "vpaddd %%ymm1,%%ymm1,%%ymm0 \n" // 6*near+2*far (1, hi) - "vpaddd %%ymm6,%%ymm3,%%ymm2 \n" // 3*near+far+8 (2, hi) - "vpaddd %%ymm0,%%ymm1,%%ymm0 \n" // 9*near+3*far (1, hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 9 3 3 1 + 8 (1, hi) - "vpsrld $4,%%ymm0,%%ymm0 \n" // ^ div by 16 (1, hi) - - "vpaddd %%ymm3,%%ymm3,%%ymm2 \n" // 6*near+2*far (2, hi) - "vpaddd %%ymm6,%%ymm1,%%ymm1 \n" // 3*near+far+8 (1, hi) - "vpaddd %%ymm2,%%ymm3,%%ymm2 \n" // 9*near+3*far (2, hi) - "vpaddd %%ymm2,%%ymm1,%%ymm2 \n" // 9 3 3 1 + 8 (2, hi) - "vpsrld $4,%%ymm2,%%ymm2 \n" // ^ div by 16 (2, hi) - - "vpackusdw %%ymm0,%%ymm4,%%ymm4 \n" - "vpshufd $0b11011000,%%ymm4,%%ymm4 \n" - "vmovdqu %%ymm4,(%1) \n" // store above - "vpackusdw %%ymm2,%%ymm5,%%ymm5 \n" - "vpshufd $0b11011000,%%ymm5,%%ymm5 \n" - "vmovdqu %%ymm5,(%1,%4,2) \n" // store below - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 pixel to 16 pixel - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); -} - -#endif - -// Reads 16xN bytes and produces 16 shorts at a time. -void ScaleAddRow_SSE2(const uint8_t *src_ptr, - uint16_t *dst_ptr, - int src_width) { - asm volatile("pxor %%xmm5,%%xmm5 \n" - - // 16 pixel loop. - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm3 \n" - "lea 0x10(%0),%0 \n" // src_ptr += 16 - "movdqu (%1),%%xmm0 \n" - "movdqu 0x10(%1),%%xmm1 \n" - "movdqa %%xmm3,%%xmm2 \n" - "punpcklbw %%xmm5,%%xmm2 \n" - "punpckhbw %%xmm5,%%xmm3 \n" - "paddusw %%xmm2,%%xmm0 \n" - "paddusw %%xmm3,%%xmm1 \n" - "movdqu %%xmm0,(%1) \n" - "movdqu %%xmm1,0x10(%1) \n" - "lea 0x20(%1),%1 \n" - "sub $0x10,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(src_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); -} - -#ifdef HAS_SCALEADDROW_AVX2 - -// Reads 32 bytes and accumulates to 32 shorts at a time. -void ScaleAddRow_AVX2(const uint8_t *src_ptr, - uint16_t *dst_ptr, - int src_width) { - asm volatile("vpxor %%ymm5,%%ymm5,%%ymm5 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm3 \n" - "lea 0x20(%0),%0 \n" // src_ptr += 32 - "vpermq $0xd8,%%ymm3,%%ymm3 \n" - "vpunpcklbw %%ymm5,%%ymm3,%%ymm2 \n" - "vpunpckhbw %%ymm5,%%ymm3,%%ymm3 \n" - "vpaddusw (%1),%%ymm2,%%ymm0 \n" - "vpaddusw 0x20(%1),%%ymm3,%%ymm1 \n" - "vmovdqu %%ymm0,(%1) \n" - "vmovdqu %%ymm1,0x20(%1) \n" - "lea 0x40(%1),%1 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(src_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"); -} - -#endif // HAS_SCALEADDROW_AVX2 - -// Constant for making pixels signed to avoid pmaddubsw -// saturation. -static const uvec8 kFsub80 = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; - -// Constant for making pixels unsigned and adding .5 for rounding. -static const uvec16 kFadd40 = {0x4040, 0x4040, 0x4040, 0x4040, - 0x4040, 0x4040, 0x4040, 0x4040}; - -// Bilinear column filtering. SSSE3 version. -void ScaleFilterCols_SSSE3(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx) { - intptr_t x0, x1, temp_pixel; - asm volatile( - "movd %6,%%xmm2 \n" - "movd %7,%%xmm3 \n" - "movl $0x04040000,%k2 \n" - "movd %k2,%%xmm5 \n" - "pcmpeqb %%xmm6,%%xmm6 \n" - "psrlw $0x9,%%xmm6 \n" // 0x007f007f - "pcmpeqb %%xmm7,%%xmm7 \n" - "psrlw $15,%%xmm7 \n" // 0x00010001 - - "pextrw $0x1,%%xmm2,%k3 \n" - "subl $0x2,%5 \n" - "jl 29f \n" - "movdqa %%xmm2,%%xmm0 \n" - "paddd %%xmm3,%%xmm0 \n" - "punpckldq %%xmm0,%%xmm2 \n" - "punpckldq %%xmm3,%%xmm3 \n" - "paddd %%xmm3,%%xmm3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - - LABELALIGN - "2: \n" - "movdqa %%xmm2,%%xmm1 \n" - "paddd %%xmm3,%%xmm2 \n" - "movzwl 0x00(%1,%3,1),%k2 \n" - "movd %k2,%%xmm0 \n" - "psrlw $0x9,%%xmm1 \n" - "movzwl 0x00(%1,%4,1),%k2 \n" - "movd %k2,%%xmm4 \n" - "pshufb %%xmm5,%%xmm1 \n" - "punpcklwd %%xmm4,%%xmm0 \n" - "psubb %8,%%xmm0 \n" // make pixels signed. - "pxor %%xmm6,%%xmm1 \n" // 128 - f = (f ^ 127 ) + - // 1 - "paddusb %%xmm7,%%xmm1 \n" - "pmaddubsw %%xmm0,%%xmm1 \n" - "pextrw $0x1,%%xmm2,%k3 \n" - "pextrw $0x3,%%xmm2,%k4 \n" - "paddw %9,%%xmm1 \n" // make pixels unsigned. - "psrlw $0x7,%%xmm1 \n" - "packuswb %%xmm1,%%xmm1 \n" - "movd %%xmm1,%k2 \n" - "mov %w2,(%0) \n" - "lea 0x2(%0),%0 \n" - "subl $0x2,%5 \n" - "jge 2b \n" - - LABELALIGN - "29: \n" - "addl $0x1,%5 \n" - "jl 99f \n" - "movzwl 0x00(%1,%3,1),%k2 \n" - "movd %k2,%%xmm0 \n" - "psrlw $0x9,%%xmm2 \n" - "pshufb %%xmm5,%%xmm2 \n" - "psubb %8,%%xmm0 \n" // make pixels signed. - "pxor %%xmm6,%%xmm2 \n" - "paddusb %%xmm7,%%xmm2 \n" - "pmaddubsw %%xmm0,%%xmm2 \n" - "paddw %9,%%xmm2 \n" // make pixels unsigned. - "psrlw $0x7,%%xmm2 \n" - "packuswb %%xmm2,%%xmm2 \n" - "movd %%xmm2,%k2 \n" - "mov %b2,(%0) \n" - "99: \n" - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "=&a"(temp_pixel), // %2 - "=&r"(x0), // %3 - "=&r"(x1), // %4 -#if defined(__x86_64__) - "+rm"(dst_width) // %5 -#else - "+m"(dst_width) // %5 -#endif - : "rm"(x), // %6 - "rm"(dx), // %7 -#if defined(__x86_64__) - "x"(kFsub80), // %8 - "x"(kFadd40) // %9 -#else - "m"(kFsub80), // %8 - "m"(kFadd40) // %9 -#endif - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -// Reads 4 pixels, duplicates them and writes 8 pixels. -// Alignment requirement: src_argb 16 byte aligned, dst_argb 16 byte aligned. -void ScaleColsUp2_SSE2(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx) { - (void) x; - (void) dx; - asm volatile(LABELALIGN - "1: \n" - "movdqu (%1),%%xmm0 \n" - "lea 0x10(%1),%1 \n" - "movdqa %%xmm0,%%xmm1 \n" - "punpcklbw %%xmm0,%%xmm0 \n" - "punpckhbw %%xmm1,%%xmm1 \n" - "movdqu %%xmm0,(%0) \n" - "movdqu %%xmm1,0x10(%0) \n" - "lea 0x20(%0),%0 \n" - "sub $0x20,%2 \n" - "jg 1b \n" - - : "+r"(dst_ptr), // %0 - "+r"(src_ptr), // %1 - "+r"(dst_width) // %2 - ::"memory", - "cc", "xmm0", "xmm1"); -} - -// Divide num by div and return as 16.16 fixed point result. -int FixedDiv_X86(int num, int div) { - asm volatile( - "cdq \n" - "shld $0x10,%%eax,%%edx \n" - "shl $0x10,%%eax \n" - "idiv %1 \n" - "mov %0, %%eax \n" - : "+a"(num) // %0 - : "c"(div) // %1 - : "memory", "cc", "edx"); - return num; -} - -// Divide num - 1 by div - 1 and return as 16.16 fixed point result. -int FixedDiv1_X86(int num, int div) { - asm volatile( - "cdq \n" - "shld $0x10,%%eax,%%edx \n" - "shl $0x10,%%eax \n" - "sub $0x10001,%%eax \n" - "sbb $0x0,%%edx \n" - "sub $0x1,%1 \n" - "idiv %1 \n" - "mov %0, %%eax \n" - : "+a"(num) // %0 - : "c"(div) // %1 - : "memory", "cc", "edx"); - return num; -} - -#if defined(HAS_SCALEUVROWDOWN2BOX_SSSE3) || \ - defined(HAS_SCALEUVROWDOWN2BOX_AVX2) - -// Shuffle table for splitting UV into upper and lower part of register. -static const uvec8 kShuffleSplitUV = {0u, 2u, 4u, 6u, 8u, 10u, 12u, 14u, - 1u, 3u, 5u, 7u, 9u, 11u, 13u, 15u}; -static const uvec8 kShuffleMergeUV = {0u, 8u, 2u, 10u, 4u, 12u, - 6u, 14u, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80}; -#endif - -#ifdef HAS_SCALEUVROWDOWN2BOX_SSSE3 - -void ScaleUVRowDown2Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "pcmpeqb %%xmm4,%%xmm4 \n" // 01010101 - "psrlw $0xf,%%xmm4 \n" - "packuswb %%xmm4,%%xmm4 \n" - "pxor %%xmm5, %%xmm5 \n" // zero - "movdqa %4,%%xmm1 \n" // split shuffler - "movdqa %5,%%xmm3 \n" // merge shuffler - - LABELALIGN - "1: \n" - "movdqu (%0),%%xmm0 \n" // 8 UV row 0 - "movdqu 0x00(%0,%3,1),%%xmm2 \n" // 8 UV row 1 - "lea 0x10(%0),%0 \n" - "pshufb %%xmm1,%%xmm0 \n" // uuuuvvvv - "pshufb %%xmm1,%%xmm2 \n" - "pmaddubsw %%xmm4,%%xmm0 \n" // horizontal add - "pmaddubsw %%xmm4,%%xmm2 \n" - "paddw %%xmm2,%%xmm0 \n" // vertical add - "psrlw $0x1,%%xmm0 \n" // round - "pavgw %%xmm5,%%xmm0 \n" - "pshufb %%xmm3,%%xmm0 \n" // merge uv - "movq %%xmm0,(%1) \n" - "lea 0x8(%1),%1 \n" // 4 UV - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "m"(kShuffleSplitUV), // %4 - "m"(kShuffleMergeUV) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif // HAS_SCALEUVROWDOWN2BOX_SSSE3 - -#ifdef HAS_SCALEUVROWDOWN2BOX_AVX2 - -void ScaleUVRowDown2Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqb %%ymm4,%%ymm4,%%ymm4 \n" // 01010101 - "vpsrlw $0xf,%%ymm4,%%ymm4 \n" - "vpackuswb %%ymm4,%%ymm4,%%ymm4 \n" - "vpxor %%ymm5,%%ymm5,%%ymm5 \n" // zero - "vbroadcastf128 %4,%%ymm1 \n" // split shuffler - "vbroadcastf128 %5,%%ymm3 \n" // merge shuffler - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%ymm0 \n" // 16 UV row 0 - "vmovdqu 0x00(%0,%3,1),%%ymm2 \n" // 16 UV row 1 - "lea 0x20(%0),%0 \n" - "vpshufb %%ymm1,%%ymm0,%%ymm0 \n" // uuuuvvvv - "vpshufb %%ymm1,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm4,%%ymm0,%%ymm0 \n" // horizontal add - "vpmaddubsw %%ymm4,%%ymm2,%%ymm2 \n" - "vpaddw %%ymm2,%%ymm0,%%ymm0 \n" // vertical add - "vpsrlw $0x1,%%ymm0,%%ymm0 \n" // round - "vpavgw %%ymm5,%%ymm0,%%ymm0 \n" - "vpshufb %%ymm3,%%ymm0,%%ymm0 \n" // merge uv - "vpermq $0xd8,%%ymm0,%%ymm0 \n" // combine qwords - "vmovdqu %%xmm0,(%1) \n" - "lea 0x10(%1),%1 \n" // 8 UV - "sub $0x8,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "m"(kShuffleSplitUV), // %4 - "m"(kShuffleMergeUV) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif // HAS_SCALEUVROWDOWN2BOX_AVX2 - -static const uvec8 kUVLinearMadd31 = {3, 1, 3, 1, 1, 3, 1, 3, - 3, 1, 3, 1, 1, 3, 1, 3}; - -#ifdef HAS_SCALEUVROWUP2_LINEAR_SSSE3 - -void ScaleUVRowUp2_Linear_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "pcmpeqw %%xmm4,%%xmm4 \n" - "psrlw $15,%%xmm4 \n" - "psllw $1,%%xmm4 \n" // all 2 - "movdqa %3,%%xmm3 \n" - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 00112233 (1u1v) - "movq 2(%0),%%xmm1 \n" // 11223344 (1u1v) - "punpcklbw %%xmm1,%%xmm0 \n" // 0101121223233434 (2u2v) - "movdqa %%xmm0,%%xmm2 \n" - "punpckhdq %%xmm0,%%xmm2 \n" // 2323232334343434 (2u2v) - "punpckldq %%xmm0,%%xmm0 \n" // 0101010112121212 (2u2v) - "pmaddubsw %%xmm3,%%xmm2 \n" // 3*near+far (1u1v16, hi) - "pmaddubsw %%xmm3,%%xmm0 \n" // 3*near+far (1u1v16, lo) - "paddw %%xmm4,%%xmm0 \n" // 3*near+far+2 (lo) - "paddw %%xmm4,%%xmm2 \n" // 3*near+far+2 (hi) - "psrlw $2,%%xmm0 \n" // 3/4*near+1/4*far (lo) - "psrlw $2,%%xmm2 \n" // 3/4*near+1/4*far (hi) - "packuswb %%xmm2,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 4 uv to 8 uv - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kUVLinearMadd31) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_SSSE3 - -void ScaleUVRowUp2_Bilinear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "pcmpeqw %%xmm6,%%xmm6 \n" - "psrlw $15,%%xmm6 \n" - "psllw $3,%%xmm6 \n" // all 8 - "movdqa %5,%%xmm7 \n" - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 00112233 (1u1v) - "movq 2(%0),%%xmm1 \n" // 11223344 (1u1v) - "punpcklbw %%xmm1,%%xmm0 \n" // 0101121223233434 (2u2v) - "movdqa %%xmm0,%%xmm2 \n" - "punpckhdq %%xmm0,%%xmm2 \n" // 2323232334343434 (2u2v) - "punpckldq %%xmm0,%%xmm0 \n" // 0101010112121212 (2u2v) - "pmaddubsw %%xmm7,%%xmm2 \n" // 3*near+far (1u1v16, hi) - "pmaddubsw %%xmm7,%%xmm0 \n" // 3*near+far (1u1v16, lo) - - "movq (%0,%3),%%xmm1 \n" - "movq 2(%0,%3),%%xmm4 \n" - "punpcklbw %%xmm4,%%xmm1 \n" - "movdqa %%xmm1,%%xmm3 \n" - "punpckhdq %%xmm1,%%xmm3 \n" - "punpckldq %%xmm1,%%xmm1 \n" - "pmaddubsw %%xmm7,%%xmm3 \n" // 3*near+far (2, hi) - "pmaddubsw %%xmm7,%%xmm1 \n" // 3*near+far (2, lo) - - // xmm0 xmm2 - // xmm1 xmm3 - - "movdqa %%xmm0,%%xmm4 \n" - "movdqa %%xmm1,%%xmm5 \n" - "paddw %%xmm0,%%xmm4 \n" // 6*near+2*far (1, lo) - "paddw %%xmm6,%%xmm5 \n" // 3*near+far+8 (2, lo) - "paddw %%xmm0,%%xmm4 \n" // 9*near+3*far (1, lo) - "paddw %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, lo) - "psrlw $4,%%xmm4 \n" // ^ div by 16 (1, lo) - - "movdqa %%xmm1,%%xmm5 \n" - "paddw %%xmm1,%%xmm5 \n" // 6*near+2*far (2, lo) - "paddw %%xmm6,%%xmm0 \n" // 3*near+far+8 (1, lo) - "paddw %%xmm1,%%xmm5 \n" // 9*near+3*far (2, lo) - "paddw %%xmm0,%%xmm5 \n" // 9 3 3 1 + 8 (2, lo) - "psrlw $4,%%xmm5 \n" // ^ div by 16 (2, lo) - - "movdqa %%xmm2,%%xmm0 \n" - "movdqa %%xmm3,%%xmm1 \n" - "paddw %%xmm2,%%xmm0 \n" // 6*near+2*far (1, hi) - "paddw %%xmm6,%%xmm1 \n" // 3*near+far+8 (2, hi) - "paddw %%xmm2,%%xmm0 \n" // 9*near+3*far (1, hi) - "paddw %%xmm1,%%xmm0 \n" // 9 3 3 1 + 8 (1, hi) - "psrlw $4,%%xmm0 \n" // ^ div by 16 (1, hi) - - "movdqa %%xmm3,%%xmm1 \n" - "paddw %%xmm3,%%xmm1 \n" // 6*near+2*far (2, hi) - "paddw %%xmm6,%%xmm2 \n" // 3*near+far+8 (1, hi) - "paddw %%xmm3,%%xmm1 \n" // 9*near+3*far (2, hi) - "paddw %%xmm2,%%xmm1 \n" // 9 3 3 1 + 8 (2, hi) - "psrlw $4,%%xmm1 \n" // ^ div by 16 (2, hi) - - "packuswb %%xmm0,%%xmm4 \n" - "movdqu %%xmm4,(%1) \n" // store above - "packuswb %%xmm1,%%xmm5 \n" - "movdqu %%xmm5,(%1,%4) \n" // store below - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 4 uv to 8 uv - "sub $0x8,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kUVLinearMadd31) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_AVX2 - -void ScaleUVRowUp2_Linear_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqw %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrlw $15,%%ymm4,%%ymm4 \n" - "vpsllw $1,%%ymm4,%%ymm4 \n" // all 2 - "vbroadcastf128 %3,%%ymm3 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" - "vmovdqu 2(%0),%%xmm1 \n" - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" - "vpunpcklbw %%ymm1,%%ymm0,%%ymm0 \n" - "vpunpckhdq %%ymm0,%%ymm0,%%ymm2 \n" - "vpunpckldq %%ymm0,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm3,%%ymm2,%%ymm1 \n" // 3*near+far (hi) - "vpmaddubsw %%ymm3,%%ymm0,%%ymm0 \n" // 3*near+far (lo) - "vpaddw %%ymm4,%%ymm0,%%ymm0 \n" // 3*near+far+2 (lo) - "vpaddw %%ymm4,%%ymm1,%%ymm1 \n" // 3*near+far+2 (hi) - "vpsrlw $2,%%ymm0,%%ymm0 \n" // 3/4*near+1/4*far (lo) - "vpsrlw $2,%%ymm1,%%ymm1 \n" // 3/4*near+1/4*far (hi) - "vpackuswb %%ymm1,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 uv to 16 uv - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "m"(kUVLinearMadd31) // %3 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_AVX2 - -void ScaleUVRowUp2_Bilinear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "vpcmpeqw %%ymm6,%%ymm6,%%ymm6 \n" - "vpsrlw $15,%%ymm6,%%ymm6 \n" - "vpsllw $3,%%ymm6,%%ymm6 \n" // all 8 - "vbroadcastf128 %5,%%ymm7 \n" - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" - "vmovdqu 2(%0),%%xmm1 \n" - "vpermq $0b11011000,%%ymm0,%%ymm0 \n" - "vpermq $0b11011000,%%ymm1,%%ymm1 \n" - "vpunpcklbw %%ymm1,%%ymm0,%%ymm0 \n" - "vpunpckhdq %%ymm0,%%ymm0,%%ymm2 \n" - "vpunpckldq %%ymm0,%%ymm0,%%ymm0 \n" - "vpmaddubsw %%ymm7,%%ymm2,%%ymm1 \n" // 3*near+far (1, hi) - "vpmaddubsw %%ymm7,%%ymm0,%%ymm0 \n" // 3*near+far (1, lo) - - "vmovdqu (%0,%3),%%xmm2 \n" // 0123456789ABCDEF - "vmovdqu 2(%0,%3),%%xmm3 \n" // 123456789ABCDEF0 - "vpermq $0b11011000,%%ymm2,%%ymm2 \n" - "vpermq $0b11011000,%%ymm3,%%ymm3 \n" - "vpunpcklbw %%ymm3,%%ymm2,%%ymm2 \n" - "vpunpckhdq %%ymm2,%%ymm2,%%ymm4 \n" - "vpunpckldq %%ymm2,%%ymm2,%%ymm2 \n" - "vpmaddubsw %%ymm7,%%ymm4,%%ymm3 \n" // 3*near+far (2, hi) - "vpmaddubsw %%ymm7,%%ymm2,%%ymm2 \n" // 3*near+far (2, lo) - - // ymm0 ymm1 - // ymm2 ymm3 - - "vpaddw %%ymm0,%%ymm0,%%ymm4 \n" // 6*near+2*far (1, lo) - "vpaddw %%ymm6,%%ymm2,%%ymm5 \n" // 3*near+far+8 (2, lo) - "vpaddw %%ymm4,%%ymm0,%%ymm4 \n" // 9*near+3*far (1, lo) - "vpaddw %%ymm4,%%ymm5,%%ymm4 \n" // 9 3 3 1 + 8 (1, lo) - "vpsrlw $4,%%ymm4,%%ymm4 \n" // ^ div by 16 (1, lo) - - "vpaddw %%ymm2,%%ymm2,%%ymm5 \n" // 6*near+2*far (2, lo) - "vpaddw %%ymm6,%%ymm0,%%ymm0 \n" // 3*near+far+8 (1, lo) - "vpaddw %%ymm5,%%ymm2,%%ymm5 \n" // 9*near+3*far (2, lo) - "vpaddw %%ymm5,%%ymm0,%%ymm5 \n" // 9 3 3 1 + 8 (2, lo) - "vpsrlw $4,%%ymm5,%%ymm5 \n" // ^ div by 16 (2, lo) - - "vpaddw %%ymm1,%%ymm1,%%ymm0 \n" // 6*near+2*far (1, hi) - "vpaddw %%ymm6,%%ymm3,%%ymm2 \n" // 3*near+far+8 (2, hi) - "vpaddw %%ymm0,%%ymm1,%%ymm0 \n" // 9*near+3*far (1, hi) - "vpaddw %%ymm0,%%ymm2,%%ymm0 \n" // 9 3 3 1 + 8 (1, hi) - "vpsrlw $4,%%ymm0,%%ymm0 \n" // ^ div by 16 (1, hi) - - "vpaddw %%ymm3,%%ymm3,%%ymm2 \n" // 6*near+2*far (2, hi) - "vpaddw %%ymm6,%%ymm1,%%ymm1 \n" // 3*near+far+8 (1, hi) - "vpaddw %%ymm2,%%ymm3,%%ymm2 \n" // 9*near+3*far (2, hi) - "vpaddw %%ymm2,%%ymm1,%%ymm2 \n" // 9 3 3 1 + 8 (2, hi) - "vpsrlw $4,%%ymm2,%%ymm2 \n" // ^ div by 16 (2, hi) - - "vpackuswb %%ymm0,%%ymm4,%%ymm4 \n" - "vmovdqu %%ymm4,(%1) \n" // store above - "vpackuswb %%ymm2,%%ymm5,%%ymm5 \n" - "vmovdqu %%ymm5,(%1,%4) \n" // store below - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 8 uv to 16 uv - "sub $0x10,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)), // %4 - "m"(kUVLinearMadd31) // %5 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41 - -void ScaleUVRowUp2_Linear_16_SSE41(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "pxor %%xmm5,%%xmm5 \n" - "pcmpeqd %%xmm4,%%xmm4 \n" - "psrld $31,%%xmm4 \n" - "pslld $1,%%xmm4 \n" // all 2 - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 0011 (16b, 1u1v) - "movq 4(%0),%%xmm1 \n" // 1122 (16b, 1u1v) - - "punpcklwd %%xmm5,%%xmm0 \n" // 0011 (32b, 1u1v) - "punpcklwd %%xmm5,%%xmm1 \n" // 1122 (32b, 1u1v) - - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - - "pshufd $0b01001110,%%xmm2,%%xmm2 \n" // 1100 (lo, far) - "pshufd $0b01001110,%%xmm3,%%xmm3 \n" // 2211 (hi, far) - - "paddd %%xmm4,%%xmm2 \n" // far+2 (lo) - "paddd %%xmm4,%%xmm3 \n" // far+2 (hi) - "paddd %%xmm0,%%xmm2 \n" // near+far+2 (lo) - "paddd %%xmm1,%%xmm3 \n" // near+far+2 (hi) - "paddd %%xmm0,%%xmm0 \n" // 2*near (lo) - "paddd %%xmm1,%%xmm1 \n" // 2*near (hi) - "paddd %%xmm2,%%xmm0 \n" // 3*near+far+2 (lo) - "paddd %%xmm3,%%xmm1 \n" // 3*near+far+2 (hi) - - "psrld $2,%%xmm0 \n" // 3/4*near+1/4*far (lo) - "psrld $2,%%xmm1 \n" // 3/4*near+1/4*far (hi) - "packusdw %%xmm1,%%xmm0 \n" - "movdqu %%xmm0,(%1) \n" - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 2 uv to 4 uv - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41 - -void ScaleUVRowUp2_Bilinear_16_SSE41(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "pxor %%xmm7,%%xmm7 \n" - "pcmpeqd %%xmm6,%%xmm6 \n" - "psrld $31,%%xmm6 \n" - "pslld $3,%%xmm6 \n" // all 8 - - LABELALIGN - "1: \n" - "movq (%0),%%xmm0 \n" // 0011 (16b, 1u1v) - "movq 4(%0),%%xmm1 \n" // 1122 (16b, 1u1v) - "punpcklwd %%xmm7,%%xmm0 \n" // 0011 (near) (32b, 1u1v) - "punpcklwd %%xmm7,%%xmm1 \n" // 1122 (near) (32b, 1u1v) - "movdqa %%xmm0,%%xmm2 \n" - "movdqa %%xmm1,%%xmm3 \n" - "pshufd $0b01001110,%%xmm2,%%xmm2 \n" // 1100 (far) (1, lo) - "pshufd $0b01001110,%%xmm3,%%xmm3 \n" // 2211 (far) (1, hi) - "paddd %%xmm0,%%xmm2 \n" // near+far (1, lo) - "paddd %%xmm1,%%xmm3 \n" // near+far (1, hi) - "paddd %%xmm0,%%xmm0 \n" // 2*near (1, lo) - "paddd %%xmm1,%%xmm1 \n" // 2*near (1, hi) - "paddd %%xmm2,%%xmm0 \n" // 3*near+far (1, lo) - "paddd %%xmm3,%%xmm1 \n" // 3*near+far (1, hi) - - "movq (%0,%3,2),%%xmm2 \n" - "movq 4(%0,%3,2),%%xmm3 \n" - "punpcklwd %%xmm7,%%xmm2 \n" - "punpcklwd %%xmm7,%%xmm3 \n" - "movdqa %%xmm2,%%xmm4 \n" - "movdqa %%xmm3,%%xmm5 \n" - "pshufd $0b01001110,%%xmm4,%%xmm4 \n" // 1100 (far) (2, lo) - "pshufd $0b01001110,%%xmm5,%%xmm5 \n" // 2211 (far) (2, hi) - "paddd %%xmm2,%%xmm4 \n" // near+far (2, lo) - "paddd %%xmm3,%%xmm5 \n" // near+far (2, hi) - "paddd %%xmm2,%%xmm2 \n" // 2*near (2, lo) - "paddd %%xmm3,%%xmm3 \n" // 2*near (2, hi) - "paddd %%xmm4,%%xmm2 \n" // 3*near+far (2, lo) - "paddd %%xmm5,%%xmm3 \n" // 3*near+far (2, hi) - - "movdqa %%xmm0,%%xmm4 \n" - "movdqa %%xmm2,%%xmm5 \n" - "paddd %%xmm0,%%xmm4 \n" // 6*near+2*far (1, lo) - "paddd %%xmm6,%%xmm5 \n" // 3*near+far+8 (2, lo) - "paddd %%xmm0,%%xmm4 \n" // 9*near+3*far (1, lo) - "paddd %%xmm5,%%xmm4 \n" // 9 3 3 1 + 8 (1, lo) - "psrld $4,%%xmm4 \n" // ^ div by 16 (1, lo) - - "movdqa %%xmm2,%%xmm5 \n" - "paddd %%xmm2,%%xmm5 \n" // 6*near+2*far (2, lo) - "paddd %%xmm6,%%xmm0 \n" // 3*near+far+8 (1, lo) - "paddd %%xmm2,%%xmm5 \n" // 9*near+3*far (2, lo) - "paddd %%xmm0,%%xmm5 \n" // 9 3 3 1 + 8 (2, lo) - "psrld $4,%%xmm5 \n" // ^ div by 16 (2, lo) - - "movdqa %%xmm1,%%xmm0 \n" - "movdqa %%xmm3,%%xmm2 \n" - "paddd %%xmm1,%%xmm0 \n" // 6*near+2*far (1, hi) - "paddd %%xmm6,%%xmm2 \n" // 3*near+far+8 (2, hi) - "paddd %%xmm1,%%xmm0 \n" // 9*near+3*far (1, hi) - "paddd %%xmm2,%%xmm0 \n" // 9 3 3 1 + 8 (1, hi) - "psrld $4,%%xmm0 \n" // ^ div by 16 (1, hi) - - "movdqa %%xmm3,%%xmm2 \n" - "paddd %%xmm3,%%xmm2 \n" // 6*near+2*far (2, hi) - "paddd %%xmm6,%%xmm1 \n" // 3*near+far+8 (1, hi) - "paddd %%xmm3,%%xmm2 \n" // 9*near+3*far (2, hi) - "paddd %%xmm1,%%xmm2 \n" // 9 3 3 1 + 8 (2, hi) - "psrld $4,%%xmm2 \n" // ^ div by 16 (2, hi) - - "packusdw %%xmm0,%%xmm4 \n" - "movdqu %%xmm4,(%1) \n" // store above - "packusdw %%xmm2,%%xmm5 \n" - "movdqu %%xmm5,(%1,%4,2) \n" // store below - - "lea 0x8(%0),%0 \n" - "lea 0x10(%1),%1 \n" // 2 uv to 4 uv - "sub $0x4,%2 \n" - "jg 1b \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", - "xmm7"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2 - -void ScaleUVRowUp2_Linear_16_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width) { - asm volatile( - "vpcmpeqd %%ymm4,%%ymm4,%%ymm4 \n" - "vpsrld $31,%%ymm4,%%ymm4 \n" - "vpslld $1,%%ymm4,%%ymm4 \n" // all 2 - - LABELALIGN - "1: \n" - "vmovdqu (%0),%%xmm0 \n" // 00112233 (16b, 1u1v) - "vmovdqu 4(%0),%%xmm1 \n" // 11223344 (16b, 1u1v) - - "vpmovzxwd %%xmm0,%%ymm0 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm1,%%ymm1 \n" // 12345678 (32b, 1u1v) - - "vpshufd $0b01001110,%%ymm0,%%ymm2 \n" // 11003322 (lo, far) - "vpshufd $0b01001110,%%ymm1,%%ymm3 \n" // 22114433 (hi, far) - - "vpaddd %%ymm4,%%ymm2,%%ymm2 \n" // far+2 (lo) - "vpaddd %%ymm4,%%ymm3,%%ymm3 \n" // far+2 (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm2 \n" // near+far+2 (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm3 \n" // near+far+2 (hi) - "vpaddd %%ymm0,%%ymm0,%%ymm0 \n" // 2*near (lo) - "vpaddd %%ymm1,%%ymm1,%%ymm1 \n" // 2*near (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 3*near+far+2 (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm1 \n" // 3*near+far+2 (hi) - - "vpsrld $2,%%ymm0,%%ymm0 \n" // 3/4*near+1/4*far (lo) - "vpsrld $2,%%ymm1,%%ymm1 \n" // 3/4*near+1/4*far (hi) - "vpackusdw %%ymm1,%%ymm0,%%ymm0 \n" - "vmovdqu %%ymm0,(%1) \n" - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 4 uv to 8 uv - "sub $0x8,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4"); -} - -#endif - -#ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2 - -void ScaleUVRowUp2_Bilinear_16_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width) { - asm volatile( - "vpcmpeqd %%ymm6,%%ymm6,%%ymm6 \n" - "vpsrld $31,%%ymm6,%%ymm6 \n" - "vpslld $3,%%ymm6,%%ymm6 \n" // all 8 - - LABELALIGN - "1: \n" - - "vmovdqu (%0),%%xmm0 \n" // 00112233 (16b, 1u1v) - "vmovdqu 4(%0),%%xmm1 \n" // 11223344 (16b, 1u1v) - "vpmovzxwd %%xmm0,%%ymm0 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm1,%%ymm1 \n" // 12345678 (32b, 1u1v) - "vpshufd $0b01001110,%%ymm0,%%ymm2 \n" // 11003322 (lo, far) - "vpshufd $0b01001110,%%ymm1,%%ymm3 \n" // 22114433 (hi, far) - "vpaddd %%ymm0,%%ymm2,%%ymm2 \n" // near+far (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm3 \n" // near+far (hi) - "vpaddd %%ymm0,%%ymm0,%%ymm0 \n" // 2*near (lo) - "vpaddd %%ymm1,%%ymm1,%%ymm1 \n" // 2*near (hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 3*near+far (lo) - "vpaddd %%ymm1,%%ymm3,%%ymm1 \n" // 3*near+far (hi) - - "vmovdqu (%0,%3,2),%%xmm2 \n" // 00112233 (16b, 1u1v) - "vmovdqu 4(%0,%3,2),%%xmm3 \n" // 11223344 (16b, 1u1v) - "vpmovzxwd %%xmm2,%%ymm2 \n" // 01234567 (32b, 1u1v) - "vpmovzxwd %%xmm3,%%ymm3 \n" // 12345678 (32b, 1u1v) - "vpshufd $0b01001110,%%ymm2,%%ymm4 \n" // 11003322 (lo, far) - "vpshufd $0b01001110,%%ymm3,%%ymm5 \n" // 22114433 (hi, far) - "vpaddd %%ymm2,%%ymm4,%%ymm4 \n" // near+far (lo) - "vpaddd %%ymm3,%%ymm5,%%ymm5 \n" // near+far (hi) - "vpaddd %%ymm2,%%ymm2,%%ymm2 \n" // 2*near (lo) - "vpaddd %%ymm3,%%ymm3,%%ymm3 \n" // 2*near (hi) - "vpaddd %%ymm2,%%ymm4,%%ymm2 \n" // 3*near+far (lo) - "vpaddd %%ymm3,%%ymm5,%%ymm3 \n" // 3*near+far (hi) - - "vpaddd %%ymm0,%%ymm0,%%ymm4 \n" // 6*near+2*far (1, lo) - "vpaddd %%ymm6,%%ymm2,%%ymm5 \n" // 3*near+far+8 (2, lo) - "vpaddd %%ymm4,%%ymm0,%%ymm4 \n" // 9*near+3*far (1, lo) - "vpaddd %%ymm4,%%ymm5,%%ymm4 \n" // 9 3 3 1 + 8 (1, lo) - "vpsrld $4,%%ymm4,%%ymm4 \n" // ^ div by 16 (1, lo) - - "vpaddd %%ymm2,%%ymm2,%%ymm5 \n" // 6*near+2*far (2, lo) - "vpaddd %%ymm6,%%ymm0,%%ymm0 \n" // 3*near+far+8 (1, lo) - "vpaddd %%ymm5,%%ymm2,%%ymm5 \n" // 9*near+3*far (2, lo) - "vpaddd %%ymm5,%%ymm0,%%ymm5 \n" // 9 3 3 1 + 8 (2, lo) - "vpsrld $4,%%ymm5,%%ymm5 \n" // ^ div by 16 (2, lo) - - "vpaddd %%ymm1,%%ymm1,%%ymm0 \n" // 6*near+2*far (1, hi) - "vpaddd %%ymm6,%%ymm3,%%ymm2 \n" // 3*near+far+8 (2, hi) - "vpaddd %%ymm0,%%ymm1,%%ymm0 \n" // 9*near+3*far (1, hi) - "vpaddd %%ymm0,%%ymm2,%%ymm0 \n" // 9 3 3 1 + 8 (1, hi) - "vpsrld $4,%%ymm0,%%ymm0 \n" // ^ div by 16 (1, hi) - - "vpaddd %%ymm3,%%ymm3,%%ymm2 \n" // 6*near+2*far (2, hi) - "vpaddd %%ymm6,%%ymm1,%%ymm1 \n" // 3*near+far+8 (1, hi) - "vpaddd %%ymm2,%%ymm3,%%ymm2 \n" // 9*near+3*far (2, hi) - "vpaddd %%ymm2,%%ymm1,%%ymm2 \n" // 9 3 3 1 + 8 (2, hi) - "vpsrld $4,%%ymm2,%%ymm2 \n" // ^ div by 16 (2, hi) - - "vpackusdw %%ymm0,%%ymm4,%%ymm4 \n" - "vmovdqu %%ymm4,(%1) \n" // store above - "vpackusdw %%ymm2,%%ymm5,%%ymm5 \n" - "vmovdqu %%ymm5,(%1,%4,2) \n" // store below - - "lea 0x10(%0),%0 \n" - "lea 0x20(%1),%1 \n" // 4 uv to 8 uv - "sub $0x8,%2 \n" - "jg 1b \n" - "vzeroupper \n" - : "+r"(src_ptr), // %0 - "+r"(dst_ptr), // %1 - "+r"(dst_width) // %2 - : "r"((intptr_t) (src_stride)), // %3 - "r"((intptr_t) (dst_stride)) // %4 - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6"); -} - -#endif - -#endif // defined(__x86_64__) || defined(__i386__) diff --git a/pkg/encoder/yuv/libyuv/scale_row.h b/pkg/encoder/yuv/libyuv/scale_row.h deleted file mode 100644 index 16389cdcf..000000000 --- a/pkg/encoder/yuv/libyuv/scale_row.h +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright 2013 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. - */ - -#ifndef INCLUDE_LIBYUV_SCALE_ROW_H_ -#define INCLUDE_LIBYUV_SCALE_ROW_H_ - -#include "basic_types.h" -#include "scale.h" - -#if defined(__pnacl__) || defined(__CLR_VER) || \ - (defined(__native_client__) && defined(__x86_64__)) || \ - (defined(__i386__) && !defined(__SSE__) && !defined(__clang__)) -#define LIBYUV_DISABLE_X86 -#endif -#if defined(__native_client__) -#define LIBYUV_DISABLE_NEON -#endif -// MemorySanitizer does not support assembly code yet. http://crbug.com/344505 -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_NEON) -#define LIBYUV_DISABLE_NEON -#endif -#if __has_feature(memory_sanitizer) && !defined(LIBYUV_DISABLE_X86) -#define LIBYUV_DISABLE_X86 -#endif -#endif -// GCC >= 4.7.0 required for AVX2. -#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) -#if (__GNUC__ > 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) -#define GCC_HAS_AVX2 1 -#endif // GNUC >= 4.7 -#endif // __GNUC__ - -// The following are available on all x86 platforms: -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) -#define HAS_FIXEDDIV1_X86 -#define HAS_FIXEDDIV_X86 -#define HAS_SCALEADDROW_SSE2 -#define HAS_SCALECOLSUP2_SSE2 -#define HAS_SCALEFILTERCOLS_SSSE3 -#define HAS_SCALEROWDOWN2_SSSE3 -#define HAS_SCALEROWDOWN34_SSSE3 -#define HAS_SCALEROWDOWN38_SSSE3 -#define HAS_SCALEROWDOWN4_SSSE3 -#endif - -// The following are available for gcc/clang x86 platforms: -// TODO(fbarchard): Port to Visual C -#if !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__)) -#define HAS_SCALEUVROWDOWN2BOX_SSSE3 -#define HAS_SCALEROWUP2_LINEAR_SSE2 -#define HAS_SCALEROWUP2_LINEAR_SSSE3 -#define HAS_SCALEROWUP2_BILINEAR_SSE2 -#define HAS_SCALEROWUP2_BILINEAR_SSSE3 -#define HAS_SCALEROWUP2_LINEAR_12_SSSE3 -#define HAS_SCALEROWUP2_BILINEAR_12_SSSE3 -#define HAS_SCALEROWUP2_LINEAR_16_SSE2 -#define HAS_SCALEROWUP2_BILINEAR_16_SSE2 -#define HAS_SCALEUVROWUP2_LINEAR_SSSE3 -#define HAS_SCALEUVROWUP2_BILINEAR_SSSE3 -#define HAS_SCALEUVROWUP2_LINEAR_16_SSE41 -#define HAS_SCALEUVROWUP2_BILINEAR_16_SSE41 -#endif - -// The following are available for gcc/clang x86 platforms, but -// require clang 3.4 or gcc 4.7. -// TODO(fbarchard): Port to Visual C -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(__x86_64__) || defined(__i386__)) && \ - (defined(CLANG_HAS_AVX2) || defined(GCC_HAS_AVX2)) -#define HAS_SCALEUVROWDOWN2BOX_AVX2 -#define HAS_SCALEROWUP2_LINEAR_AVX2 -#define HAS_SCALEROWUP2_BILINEAR_AVX2 -#define HAS_SCALEROWUP2_LINEAR_12_AVX2 -#define HAS_SCALEROWUP2_BILINEAR_12_AVX2 -#define HAS_SCALEROWUP2_LINEAR_16_AVX2 -#define HAS_SCALEROWUP2_BILINEAR_16_AVX2 -#define HAS_SCALEUVROWUP2_LINEAR_AVX2 -#define HAS_SCALEUVROWUP2_BILINEAR_AVX2 -#define HAS_SCALEUVROWUP2_LINEAR_16_AVX2 -#define HAS_SCALEUVROWUP2_BILINEAR_16_AVX2 -#endif - -// The following are available on all x86 platforms, but -// require VS2012, clang 3.4 or gcc 4.7. -// The code supports NaCL but requires a new compiler and validator. -#if !defined(LIBYUV_DISABLE_X86) && \ - (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2) || \ - defined(GCC_HAS_AVX2)) -#define HAS_SCALEADDROW_AVX2 -#define HAS_SCALEROWDOWN2_AVX2 -#define HAS_SCALEROWDOWN4_AVX2 -#endif - -// Scale ARGB vertically with bilinear interpolation. -void ScalePlaneVertical(int src_height, - int dst_width, - int dst_height, - int src_stride, - int dst_stride, - const uint8_t *src_argb, - uint8_t *dst_argb, - int x, - int y, - int dy, - int bpp, - enum FilterMode filtering); - -// Simplify the filtering based on scale factors. -enum FilterMode ScaleFilterReduce(int src_width, - int src_height, - int dst_width, - int dst_height, - enum FilterMode filtering); - -// Divide num by div and return as 16.16 fixed point result. -int FixedDiv_X86(int num, int div); - -int FixedDiv1_X86(int num, int div); - -#ifdef HAS_FIXEDDIV_X86 -#define FixedDiv FixedDiv_X86 -#define FixedDiv1 FixedDiv1_X86 -#endif - -// Compute slope values for stepping. -void ScaleSlope(int src_width, - int src_height, - int dst_width, - int dst_height, - enum FilterMode filtering, - int *x, - int *y, - int *dx, - int *dy); - -void ScaleRowDown2_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown2Linear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown2Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown2Box_Odd_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown4_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown4Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown34_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown34_0_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *d, - int dst_width); - -void ScaleRowDown34_1_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *d, - int dst_width); - -void ScaleRowUp2_Linear_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_Any_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_Any_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_Any_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_Any_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleCols_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx); - -void ScaleColsUp2_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int, - int); - -void ScaleFilterCols_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx); - -void ScaleFilterCols64_C(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x32, - int dx); - -void ScaleRowDown38_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst, - int dst_width); - -void ScaleRowDown38_3_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_2_Box_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleAddRow_C(const uint8_t *src_ptr, uint16_t *dst_ptr, int src_width); - -void ScaleUVRowDown2_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowDown2Linear_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowDown2Box_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowDownEven_C(const uint8_t *src_uv, - ptrdiff_t src_stride, - int src_stepx, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowUp2_Linear_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_Any_C(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_Any_C(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_Any_C(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_Any_C(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -// Specialized scalers for x86. -void ScaleRowDown2_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Linear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Linear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_1_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_0_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_3_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_2_Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Linear_SSE2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_SSE2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_12_SSSE3(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_12_SSSE3(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_SSE2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_SSE2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_12_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_12_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_Any_SSE2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_Any_SSE2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_12_Any_SSSE3(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_12_Any_SSSE3(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_Any_SSE2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_Any_SSE2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_Any_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_Any_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_12_Any_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_12_Any_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowUp2_Linear_16_Any_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleRowUp2_Bilinear_16_Any_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleRowDown2_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Linear_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_Odd_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Linear_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown2Box_Odd_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown4Box_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_1_Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown34_0_Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_3_Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleRowDown38_2_Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleAddRow_SSE2(const uint8_t *src_ptr, uint16_t *dst_ptr, int src_width); - -void ScaleAddRow_AVX2(const uint8_t *src_ptr, uint16_t *dst_ptr, int src_width); - -void ScaleAddRow_Any_SSE2(const uint8_t *src_ptr, - uint16_t *dst_ptr, - int src_width); - -void ScaleAddRow_Any_AVX2(const uint8_t *src_ptr, - uint16_t *dst_ptr, - int src_width); - -void ScaleFilterCols_SSSE3(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx); - -void ScaleColsUp2_SSE2(uint8_t *dst_ptr, - const uint8_t *src_ptr, - int dst_width, - int x, - int dx); - -// UV Row functions -void ScaleUVRowDown2Box_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowDown2Box_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_uv, - int dst_width); - -void ScaleUVRowDown2Box_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowDown2Box_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Linear_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_Any_SSSE3(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_Any_SSSE3(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_Any_AVX2(const uint8_t *src_ptr, - uint8_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_Any_AVX2(const uint8_t *src_ptr, - ptrdiff_t src_stride, - uint8_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_SSE41(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_SSE41(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_Any_SSE41(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_Any_SSE41(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -void ScaleUVRowUp2_Linear_16_Any_AVX2(const uint16_t *src_ptr, - uint16_t *dst_ptr, - int dst_width); - -void ScaleUVRowUp2_Bilinear_16_Any_AVX2(const uint16_t *src_ptr, - ptrdiff_t src_stride, - uint16_t *dst_ptr, - ptrdiff_t dst_stride, - int dst_width); - -#endif // INCLUDE_LIBYUV_SCALE_ROW_H_ \ No newline at end of file diff --git a/pkg/encoder/yuv/libyuv/version.h b/pkg/encoder/yuv/libyuv/version.h deleted file mode 100644 index d45ef09d6..000000000 --- a/pkg/encoder/yuv/libyuv/version.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2012 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. - */ - -#ifndef INCLUDE_LIBYUV_VERSION_H_ -#define INCLUDE_LIBYUV_VERSION_H_ - -#define LIBYUV_VERSION 1875 - -#endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/pkg/encoder/yuv/libyuv/video_common.c b/pkg/encoder/yuv/libyuv/video_common.c deleted file mode 100644 index e492402e8..000000000 --- a/pkg/encoder/yuv/libyuv/video_common.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 "video_common.h" - -struct FourCCAliasEntry { - uint32_t alias; - uint32_t canonical; -}; - -#define NUM_ALIASES 18 -static const struct FourCCAliasEntry kFourCCAliases[NUM_ALIASES] = { - {FOURCC_IYUV, FOURCC_I420}, - {FOURCC_YU12, FOURCC_I420}, - {FOURCC_YU16, FOURCC_I422}, - {FOURCC_YU24, FOURCC_I444}, - {FOURCC_YUYV, FOURCC_YUY2}, - {FOURCC_YUVS, FOURCC_YUY2}, // kCMPixelFormat_422YpCbCr8_yuvs - {FOURCC_HDYC, FOURCC_UYVY}, - {FOURCC_2VUY, FOURCC_UYVY}, // kCMPixelFormat_422YpCbCr8 - {FOURCC_JPEG, FOURCC_MJPG}, // Note: JPEG has DHT while MJPG does not. - {FOURCC_DMB1, FOURCC_MJPG}, - {FOURCC_BA81, FOURCC_BGGR}, // deprecated. - {FOURCC_RGB3, FOURCC_RAW}, - {FOURCC_BGR3, FOURCC_24BG}, - {FOURCC_CM32, FOURCC_BGRA}, // kCMPixelFormat_32ARGB - {FOURCC_CM24, FOURCC_RAW}, // kCMPixelFormat_24RGB - {FOURCC_L555, FOURCC_RGBO}, // kCMPixelFormat_16LE555 - {FOURCC_L565, FOURCC_RGBP}, // kCMPixelFormat_16LE565 - {FOURCC_5551, FOURCC_RGBO}, // kCMPixelFormat_16LE5551 -}; - -LIBYUV_API -uint32_t CanonicalFourCC(uint32_t fourcc) { - int i; - for (i = 0; i < NUM_ALIASES; ++i) { - if (kFourCCAliases[i].alias == fourcc) { - return kFourCCAliases[i].canonical; - } - } - // Not an alias, so return it as-is. - return fourcc; -} diff --git a/pkg/encoder/yuv/libyuv/video_common.h b/pkg/encoder/yuv/libyuv/video_common.h deleted file mode 100644 index e2aacf44c..000000000 --- a/pkg/encoder/yuv/libyuv/video_common.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - */ - -// Common definitions for video, including fourcc and VideoFormat. - -#ifndef INCLUDE_LIBYUV_VIDEO_COMMON_H_ -#define INCLUDE_LIBYUV_VIDEO_COMMON_H_ - -#include "basic_types.h" - -////////////////////////////////////////////////////////////////////////////// -// Definition of FourCC codes -////////////////////////////////////////////////////////////////////////////// - -// Convert four characters to a FourCC code. -// Needs to be a macro otherwise the OS X compiler complains when the kFormat* -// constants are used in a switch. -#ifdef __cplusplus -#define FOURCC(a, b, c, d) \ - ((static_cast(a)) | (static_cast(b) << 8) | \ - (static_cast(c) << 16) | /* NOLINT */ \ - (static_cast(d) << 24)) /* NOLINT */ -#else -#define FOURCC(a, b, c, d) \ - (((uint32_t)(a)) | ((uint32_t)(b) << 8) | /* NOLINT */ \ - ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) /* NOLINT */ -#endif - -// Some pages discussing FourCC codes: -// http://www.fourcc.org/yuv.php -// http://v4l2spec.bytesex.org/spec/book1.htm -// http://developer.apple.com/quicktime/icefloe/dispatch020.html -// http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12 -// http://people.xiph.org/~xiphmont/containers/nut/nut4cc.txt - -// FourCC codes grouped according to implementation efficiency. -// Primary formats should convert in 1 efficient step. -// Secondary formats are converted in 2 steps. -// Auxilliary formats call primary converters. -enum FourCC { - // 10 Primary YUV formats: 5 planar, 2 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_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 - FOURCC_I210 = FOURCC('I', '2', '1', '0'), // bt.601 10 bit 422 - - // 1 Secondary YUV format: row biplanar. deprecated. - FOURCC_M420 = FOURCC('M', '4', '2', '0'), - - // 13 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc 2 64 bpp - FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), - FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'), - FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'), - FOURCC_AR30 = FOURCC('A', 'R', '3', '0'), // 10 bit per channel. 2101010. - FOURCC_AB30 = FOURCC('A', 'B', '3', '0'), // ABGR version of 10 bit - FOURCC_AR64 = FOURCC('A', 'R', '6', '4'), // 16 bit per channel. - FOURCC_AB64 = FOURCC('A', 'B', '6', '4'), // ABGR version of 16 bit - FOURCC_24BG = FOURCC('2', '4', 'B', 'G'), - FOURCC_RAW = FOURCC('r', 'a', 'w', ' '), - FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'), - FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE. - FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE. - FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE. - - // 1 Primary Compressed YUV format. - FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'), - - // 14 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias. - FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'), - FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), - FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), - FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. - FOURCC_J420 = - FOURCC('J', '4', '2', '0'), // jpeg (bt.601 full), unofficial fourcc - FOURCC_J422 = - FOURCC('J', '4', '2', '2'), // jpeg (bt.601 full), unofficial fourcc - FOURCC_J444 = - FOURCC('J', '4', '4', '4'), // jpeg (bt.601 full), unofficial fourcc - FOURCC_J400 = - FOURCC('J', '4', '0', '0'), // jpeg (bt.601 full), unofficial fourcc - FOURCC_F420 = FOURCC('F', '4', '2', '0'), // bt.709 full, unofficial fourcc - FOURCC_F422 = FOURCC('F', '4', '2', '2'), // bt.709 full, unofficial fourcc - FOURCC_F444 = FOURCC('F', '4', '4', '4'), // bt.709 full, unofficial fourcc - FOURCC_H420 = FOURCC('H', '4', '2', '0'), // bt.709, unofficial fourcc - FOURCC_H422 = FOURCC('H', '4', '2', '2'), // bt.709, unofficial fourcc - FOURCC_H444 = FOURCC('H', '4', '4', '4'), // bt.709, unofficial fourcc - FOURCC_U420 = FOURCC('U', '4', '2', '0'), // bt.2020, unofficial fourcc - FOURCC_U422 = FOURCC('U', '4', '2', '2'), // bt.2020, unofficial fourcc - FOURCC_U444 = FOURCC('U', '4', '4', '4'), // bt.2020, unofficial fourcc - FOURCC_F010 = FOURCC('F', '0', '1', '0'), // bt.709 full range 10 bit 420 - FOURCC_H010 = FOURCC('H', '0', '1', '0'), // bt.709 10 bit 420 - FOURCC_U010 = FOURCC('U', '0', '1', '0'), // bt.2020 10 bit 420 - FOURCC_F210 = FOURCC('F', '2', '1', '0'), // bt.709 full range 10 bit 422 - FOURCC_H210 = FOURCC('H', '2', '1', '0'), // bt.709 10 bit 422 - FOURCC_U210 = FOURCC('U', '2', '1', '0'), // bt.2020 10 bit 422 - FOURCC_P010 = FOURCC('P', '0', '1', '0'), - FOURCC_P210 = FOURCC('P', '2', '1', '0'), - - // 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc. - FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420. - FOURCC_YU16 = FOURCC('Y', 'U', '1', '6'), // Alias for I422. - FOURCC_YU24 = FOURCC('Y', 'U', '2', '4'), // Alias for I444. - FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2. - FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac. - FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY. - FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY on Mac. - FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG. - FOURCC_DMB1 = FOURCC('d', 'm', 'b', '1'), // Alias for MJPG on Mac. - FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR. - FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW. - FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG. - FOURCC_CM32 = FOURCC(0, 0, 0, 32), // Alias for BGRA kCMPixelFormat_32ARGB - FOURCC_CM24 = FOURCC(0, 0, 0, 24), // Alias for RAW kCMPixelFormat_24RGB - FOURCC_L555 = FOURCC('L', '5', '5', '5'), // Alias for RGBO. - FOURCC_L565 = FOURCC('L', '5', '6', '5'), // Alias for RGBP. - FOURCC_5551 = FOURCC('5', '5', '5', '1'), // Alias for RGBO. - - // deprecated formats. Not supported, but defined for backward compatibility. - FOURCC_I411 = FOURCC('I', '4', '1', '1'), - FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), - FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'), - FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'), - FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'), - FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'), - FOURCC_H264 = FOURCC('H', '2', '6', '4'), - - // Match any fourcc. - FOURCC_ANY = -1, -}; - -enum FourCCBpp { - // Canonical fourcc codes used in our code. - FOURCC_BPP_I420 = 12, - FOURCC_BPP_I422 = 16, - FOURCC_BPP_I444 = 24, - FOURCC_BPP_I411 = 12, - FOURCC_BPP_I400 = 8, - FOURCC_BPP_NV21 = 12, - FOURCC_BPP_NV12 = 12, - FOURCC_BPP_YUY2 = 16, - FOURCC_BPP_UYVY = 16, - FOURCC_BPP_M420 = 12, // deprecated - FOURCC_BPP_Q420 = 12, - FOURCC_BPP_ARGB = 32, - FOURCC_BPP_BGRA = 32, - FOURCC_BPP_ABGR = 32, - FOURCC_BPP_RGBA = 32, - FOURCC_BPP_AR30 = 32, - FOURCC_BPP_AB30 = 32, - FOURCC_BPP_AR64 = 64, - FOURCC_BPP_AB64 = 64, - FOURCC_BPP_24BG = 24, - FOURCC_BPP_RAW = 24, - FOURCC_BPP_RGBP = 16, - FOURCC_BPP_RGBO = 16, - FOURCC_BPP_R444 = 16, - FOURCC_BPP_RGGB = 8, - FOURCC_BPP_BGGR = 8, - FOURCC_BPP_GRBG = 8, - FOURCC_BPP_GBRG = 8, - FOURCC_BPP_YV12 = 12, - FOURCC_BPP_YV16 = 16, - FOURCC_BPP_YV24 = 24, - FOURCC_BPP_YU12 = 12, - FOURCC_BPP_J420 = 12, - FOURCC_BPP_J400 = 8, - FOURCC_BPP_H420 = 12, - FOURCC_BPP_H422 = 16, - FOURCC_BPP_I010 = 15, - FOURCC_BPP_I210 = 20, - FOURCC_BPP_H010 = 15, - FOURCC_BPP_H210 = 20, - FOURCC_BPP_P010 = 15, - FOURCC_BPP_P210 = 20, - FOURCC_BPP_MJPG = 0, // 0 means unknown. - FOURCC_BPP_H264 = 0, - FOURCC_BPP_IYUV = 12, - FOURCC_BPP_YU16 = 16, - FOURCC_BPP_YU24 = 24, - FOURCC_BPP_YUYV = 16, - FOURCC_BPP_YUVS = 16, - FOURCC_BPP_HDYC = 16, - FOURCC_BPP_2VUY = 16, - FOURCC_BPP_JPEG = 1, - FOURCC_BPP_DMB1 = 1, - FOURCC_BPP_BA81 = 8, - FOURCC_BPP_RGB3 = 24, - FOURCC_BPP_BGR3 = 24, - FOURCC_BPP_CM32 = 32, - FOURCC_BPP_CM24 = 24, - - // Match any fourcc. - FOURCC_BPP_ANY = 0, // 0 means unknown. -}; - -// Converts fourcc aliases into canonical ones. -LIBYUV_API uint32_t CanonicalFourCC(uint32_t fourcc); - -#endif // INCLUDE_LIBYUV_VIDEO_COMMON_H_ \ No newline at end of file diff --git a/pkg/encoder/yuv/yuv_test.go b/pkg/encoder/yuv/yuv_test.go index 6b67c29f0..3f07aa69d 100644 --- a/pkg/encoder/yuv/yuv_test.go +++ b/pkg/encoder/yuv/yuv_test.go @@ -115,6 +115,9 @@ func TestYuvPredefined(t *testing.T) { frame := RawFrame{Data: im, Stride: 32, W: 32, H: 32} a := pc.Process(frame, 0, PixFmt(libyuv.FourccAbgr)) + v := libyuv.Version() + t.Logf("%v", v) + if len(a) != len(should) { t.Fatalf("diffrent size a: %v, o: %v", len(a), len(should)) }