/* * Copyright 2011 The LibYuv Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/planar_functions.h" #include <string.h> // for memset() #include "libyuv/cpu_id.h"#ifdef HAVE_JPEG#include "libyuv/mjpeg_decoder.h"#endif#include "libyuv/row.h"#include "libyuv/scale_row.h" // for ScaleRowDown2 #ifdef __cplusplusnamespace libyuv {extern "C" {#endif // Copy a plane of dataLIBYUV_APIvoid CopyPlane(const uint8_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int width, int height) { int y; void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; } // Nothing to do. if (src_y == dst_y && src_stride_y == dst_stride_y) { return; } #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) if (TestCpuFlag(kCpuHasNEON)) { CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON; }#endif // Copy plane for (y = 0; y < height; ++y) { CopyRow(src_y, dst_y, width); src_y += src_stride_y; dst_y += dst_stride_y; }} // TODO(fbarchard): Consider support for negative height.// TODO(fbarchard): Consider stride measured in bytes.LIBYUV_APIvoid CopyPlane_16(const uint16_t* src_y, int src_stride_y, uint16_t* dst_y, int dst_stride_y, int width, int height) { int y; void (*CopyRow)(const uint16_t* src, uint16_t* dst, int width) = CopyRow_16_C; // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; }#if defined(HAS_COPYROW_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32)) { CopyRow = CopyRow_16_SSE2; }#endif#if defined(HAS_COPYROW_16_ERMS) if (TestCpuFlag(kCpuHasERMS)) { CopyRow = CopyRow_16_ERMS; }#endif#if defined(HAS_COPYROW_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { CopyRow = CopyRow_16_NEON; }#endif // Copy plane for (y = 0; y < height; ++y) { CopyRow(src_y, dst_y, width); src_y += src_stride_y; dst_y += dst_stride_y; }} // Convert a plane of 16 bit data to 8 bitLIBYUV_APIvoid Convert16To8Plane(const uint16_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int scale, // 16384 for 10 bits int width, int height) { int y; void (*Convert16To8Row)(const uint16_t* src_y, uint8_t* dst_y, int scale, int width) = Convert16To8Row_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; }#if defined(HAS_CONVERT16TO8ROW_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { Convert16To8Row = Convert16To8Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { Convert16To8Row = Convert16To8Row_SSSE3; } }#endif#if defined(HAS_CONVERT16TO8ROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { Convert16To8Row = Convert16To8Row_Any_AVX2; if (IS_ALIGNED(width, 32)) { Convert16To8Row = Convert16To8Row_AVX2; } }#endif // Convert plane for (y = 0; y < height; ++y) { Convert16To8Row(src_y, dst_y, scale, width); src_y += src_stride_y; dst_y += dst_stride_y; }} // Convert a plane of 8 bit data to 16 bitLIBYUV_APIvoid Convert8To16Plane(const uint8_t* src_y, int src_stride_y, uint16_t* dst_y, int dst_stride_y, int scale, // 16384 for 10 bits int width, int height) { int y; void (*Convert8To16Row)(const uint8_t* src_y, uint16_t* dst_y, int scale, int width) = Convert8To16Row_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; }#if defined(HAS_CONVERT8TO16ROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { Convert8To16Row = Convert8To16Row_Any_SSE2; if (IS_ALIGNED(width, 16)) { Convert8To16Row = Convert8To16Row_SSE2; } }#endif#if defined(HAS_CONVERT8TO16ROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { Convert8To16Row = Convert8To16Row_Any_AVX2; if (IS_ALIGNED(width, 32)) { Convert8To16Row = Convert8To16Row_AVX2; } }#endif // Convert plane for (y = 0; y < height; ++y) { Convert8To16Row(src_y, dst_y, scale, width); src_y += src_stride_y; dst_y += dst_stride_y; }} // Copy I422.LIBYUV_APIint I422Copy(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; if (!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; src_y = src_y + (height - 1) * src_stride_y; src_u = src_u + (height - 1) * src_stride_u; src_v = src_v + (height - 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); } CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height); CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height); return 0;} // Copy I444.LIBYUV_APIint I444Copy(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) { if (!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; src_y = src_y + (height - 1) * src_stride_y; src_u = src_u + (height - 1) * src_stride_u; src_v = src_v + (height - 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); } CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height); CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height); return 0;} // Copy I400.LIBYUV_APIint I400ToI400(const uint8_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int width, int height) { if (!src_y || !dst_y || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; src_y = src_y + (height - 1) * src_stride_y; src_stride_y = -src_stride_y; } CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); return 0;} // Convert I420 to I400.LIBYUV_APIint I420ToI400(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, int width, int height) { (void)src_u; (void)src_stride_u; (void)src_v; (void)src_stride_v; if (!src_y || !dst_y || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; src_y = src_y + (height - 1) * src_stride_y; src_stride_y = -src_stride_y; } CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); return 0;} // Support function for NV12 etc UV channels.// Width and height are plane sizes (typically half pixel width).LIBYUV_APIvoid SplitUVPlane(const uint8_t* src_uv, int src_stride_uv, uint8_t* dst_u, int dst_stride_u, uint8_t* dst_v, int dst_stride_v, int width, int height) { int y; void (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, int width) = SplitUVRow_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_u = dst_u + (height - 1) * dst_stride_u; dst_v = dst_v + (height - 1) * dst_stride_v; dst_stride_u = -dst_stride_u; dst_stride_v = -dst_stride_v; } // Coalesce rows. if (src_stride_uv == width * 2 && dst_stride_u == width && dst_stride_v == width) { width *= height; height = 1; src_stride_uv = dst_stride_u = dst_stride_v = 0; }#if defined(HAS_SPLITUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { SplitUVRow = SplitUVRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { SplitUVRow = SplitUVRow_SSE2; } }#endif#if defined(HAS_SPLITUVROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { SplitUVRow = SplitUVRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { SplitUVRow = SplitUVRow_AVX2; } }#endif#if defined(HAS_SPLITUVROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { SplitUVRow = SplitUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { SplitUVRow = SplitUVRow_NEON; } }#endif#if defined(HAS_SPLITUVROW_MSA) if (TestCpuFlag(kCpuHasMSA)) { SplitUVRow = SplitUVRow_Any_MSA; if (IS_ALIGNED(width, 32)) { SplitUVRow = SplitUVRow_MSA; } }#endif for (y = 0; y < height; ++y) { // Copy a row of UV. SplitUVRow(src_uv, dst_u, dst_v, width); dst_u += dst_stride_u; dst_v += dst_stride_v; src_uv += src_stride_uv; }} LIBYUV_APIvoid MergeUVPlane(const uint8_t* src_u, int src_stride_u, const uint8_t* src_v, int src_stride_v, uint8_t* dst_uv, int dst_stride_uv, int width, int height) { int y; void (*MergeUVRow)(const uint8_t* src_u, const uint8_t* src_v, uint8_t* dst_uv, int width) = MergeUVRow_C; // Coalesce rows. // Negative height means invert the image. if (height < 0) { height = -height; dst_uv = dst_uv + (height - 1) * dst_stride_uv; dst_stride_uv = -dst_stride_uv; } // Coalesce rows. if (src_stride_u == width && src_stride_v == width && dst_stride_uv == width * 2) { width *= height; height = 1; src_stride_u = src_stride_v = dst_stride_uv = 0; }#if defined(HAS_MERGEUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow = MergeUVRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_SSE2; } }#endif#if defined(HAS_MERGEUVROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { MergeUVRow = MergeUVRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { MergeUVRow = MergeUVRow_AVX2; } }#endif#if defined(HAS_MERGEUVROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { MergeUVRow = MergeUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_NEON; } }#endif#if defined(HAS_MERGEUVROW_MSA) if (TestCpuFlag(kCpuHasMSA)) { MergeUVRow = MergeUVRow_Any_MSA; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_MSA; } }#endif for (y = 0; y < height; ++y) { // Merge a row of U and V into a row of UV. MergeUVRow(src_u, src_v, dst_uv, width); src_u += src_stride_u; src_v += src_stride_v; dst_uv += dst_stride_uv; }} // Support function for NV12 etc RGB channels.// Width and height are plane sizes (typically half pixel width).LIBYUV_APIvoid SplitRGBPlane(const uint8_t* src_rgb, int src_stride_rgb, uint8_t* dst_r, int dst_stride_r, uint8_t* dst_g, int dst_stride_g, uint8_t* dst_b,Lines 1–500 of 3587. Load more
/* * Copyright 2011 The LibYuv Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/planar_functions.h" #include <string.h> // for memset() #include "libyuv/cpu_id.h" #ifdef HAVE_JPEG #include "libyuv/mjpeg_decoder.h" #endif #include "libyuv/row.h" #include "libyuv/scale_row.h" // for ScaleRowDown2 #ifdef __cplusplus namespace libyuv { extern "C" { #endif // Copy a plane of data LIBYUV_API void CopyPlane(const uint8_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int width, int height) { int y; void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; } // Nothing to do. if (src_y == dst_y && src_stride_y == dst_stride_y) { return; } #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) if (TestCpuFlag(kCpuHasNEON)) { CopyRow = IS_ALIGNED(width, 32) ? CopyRow_NEON : CopyRow_Any_NEON; } #endif // Copy plane for (y = 0; y < height; ++y) { CopyRow(src_y, dst_y, width); src_y += src_stride_y; dst_y += dst_stride_y; } } // TODO(fbarchard): Consider support for negative height. // TODO(fbarchard): Consider stride measured in bytes. LIBYUV_API void CopyPlane_16(const uint16_t* src_y, int src_stride_y, uint16_t* dst_y, int dst_stride_y, int width, int height) { int y; void (*CopyRow)(const uint16_t* src, uint16_t* dst, int width) = CopyRow_16_C; // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; } #if defined(HAS_COPYROW_16_SSE2) if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32)) { CopyRow = CopyRow_16_SSE2; } #endif #if defined(HAS_COPYROW_16_ERMS) if (TestCpuFlag(kCpuHasERMS)) { CopyRow = CopyRow_16_ERMS; } #endif #if defined(HAS_COPYROW_16_NEON) if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { CopyRow = CopyRow_16_NEON; } #endif // Copy plane for (y = 0; y < height; ++y) { CopyRow(src_y, dst_y, width); src_y += src_stride_y; dst_y += dst_stride_y; } } // Convert a plane of 16 bit data to 8 bit LIBYUV_API void Convert16To8Plane(const uint16_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int scale, // 16384 for 10 bits int width, int height) { int y; void (*Convert16To8Row)(const uint16_t* src_y, uint8_t* dst_y, int scale, int width) = Convert16To8Row_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; } #if defined(HAS_CONVERT16TO8ROW_SSSE3) if (TestCpuFlag(kCpuHasSSSE3)) { Convert16To8Row = Convert16To8Row_Any_SSSE3; if (IS_ALIGNED(width, 16)) { Convert16To8Row = Convert16To8Row_SSSE3; } } #endif #if defined(HAS_CONVERT16TO8ROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { Convert16To8Row = Convert16To8Row_Any_AVX2; if (IS_ALIGNED(width, 32)) { Convert16To8Row = Convert16To8Row_AVX2; } } #endif // Convert plane for (y = 0; y < height; ++y) { Convert16To8Row(src_y, dst_y, scale, width); src_y += src_stride_y; dst_y += dst_stride_y; } } // Convert a plane of 8 bit data to 16 bit LIBYUV_API void Convert8To16Plane(const uint8_t* src_y, int src_stride_y, uint16_t* dst_y, int dst_stride_y, int scale, // 16384 for 10 bits int width, int height) { int y; void (*Convert8To16Row)(const uint8_t* src_y, uint16_t* dst_y, int scale, int width) = Convert8To16Row_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_y = dst_y + (height - 1) * dst_stride_y; dst_stride_y = -dst_stride_y; } // Coalesce rows. if (src_stride_y == width && dst_stride_y == width) { width *= height; height = 1; src_stride_y = dst_stride_y = 0; } #if defined(HAS_CONVERT8TO16ROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { Convert8To16Row = Convert8To16Row_Any_SSE2; if (IS_ALIGNED(width, 16)) { Convert8To16Row = Convert8To16Row_SSE2; } } #endif #if defined(HAS_CONVERT8TO16ROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { Convert8To16Row = Convert8To16Row_Any_AVX2; if (IS_ALIGNED(width, 32)) { Convert8To16Row = Convert8To16Row_AVX2; } } #endif // Convert plane for (y = 0; y < height; ++y) { Convert8To16Row(src_y, dst_y, scale, width); src_y += src_stride_y; dst_y += dst_stride_y; } } // Copy I422. LIBYUV_API int I422Copy(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; if (!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; src_y = src_y + (height - 1) * src_stride_y; src_u = src_u + (height - 1) * src_stride_u; src_v = src_v + (height - 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); } CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height); CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height); return 0; } // Copy I444. LIBYUV_API int I444Copy(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) { if (!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; src_y = src_y + (height - 1) * src_stride_y; src_u = src_u + (height - 1) * src_stride_u; src_v = src_v + (height - 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); } CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height); CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height); return 0; } // Copy I400. LIBYUV_API int I400ToI400(const uint8_t* src_y, int src_stride_y, uint8_t* dst_y, int dst_stride_y, int width, int height) { if (!src_y || !dst_y || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; src_y = src_y + (height - 1) * src_stride_y; src_stride_y = -src_stride_y; } CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); return 0; } // Convert I420 to I400. LIBYUV_API int I420ToI400(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, int width, int height) { (void)src_u; (void)src_stride_u; (void)src_v; (void)src_stride_v; if (!src_y || !dst_y || width <= 0 || height == 0) { return -1; } // Negative height means invert the image. if (height < 0) { height = -height; src_y = src_y + (height - 1) * src_stride_y; src_stride_y = -src_stride_y; } CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); return 0; } // Support function for NV12 etc UV channels. // Width and height are plane sizes (typically half pixel width). LIBYUV_API void SplitUVPlane(const uint8_t* src_uv, int src_stride_uv, uint8_t* dst_u, int dst_stride_u, uint8_t* dst_v, int dst_stride_v, int width, int height) { int y; void (*SplitUVRow)(const uint8_t* src_uv, uint8_t* dst_u, uint8_t* dst_v, int width) = SplitUVRow_C; // Negative height means invert the image. if (height < 0) { height = -height; dst_u = dst_u + (height - 1) * dst_stride_u; dst_v = dst_v + (height - 1) * dst_stride_v; dst_stride_u = -dst_stride_u; dst_stride_v = -dst_stride_v; } // Coalesce rows. if (src_stride_uv == width * 2 && dst_stride_u == width && dst_stride_v == width) { width *= height; height = 1; src_stride_uv = dst_stride_u = dst_stride_v = 0; } #if defined(HAS_SPLITUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { SplitUVRow = SplitUVRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { SplitUVRow = SplitUVRow_SSE2; } } #endif #if defined(HAS_SPLITUVROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { SplitUVRow = SplitUVRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { SplitUVRow = SplitUVRow_AVX2; } } #endif #if defined(HAS_SPLITUVROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { SplitUVRow = SplitUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { SplitUVRow = SplitUVRow_NEON; } } #endif #if defined(HAS_SPLITUVROW_MSA) if (TestCpuFlag(kCpuHasMSA)) { SplitUVRow = SplitUVRow_Any_MSA; if (IS_ALIGNED(width, 32)) { SplitUVRow = SplitUVRow_MSA; } } #endif for (y = 0; y < height; ++y) { // Copy a row of UV. SplitUVRow(src_uv, dst_u, dst_v, width); dst_u += dst_stride_u; dst_v += dst_stride_v; src_uv += src_stride_uv; } } LIBYUV_API void MergeUVPlane(const uint8_t* src_u, int src_stride_u, const uint8_t* src_v, int src_stride_v, uint8_t* dst_uv, int dst_stride_uv, int width, int height) { int y; void (*MergeUVRow)(const uint8_t* src_u, const uint8_t* src_v, uint8_t* dst_uv, int width) = MergeUVRow_C; // Coalesce rows. // Negative height means invert the image. if (height < 0) { height = -height; dst_uv = dst_uv + (height - 1) * dst_stride_uv; dst_stride_uv = -dst_stride_uv; } // Coalesce rows. if (src_stride_u == width && src_stride_v == width && dst_stride_uv == width * 2) { width *= height; height = 1; src_stride_u = src_stride_v = dst_stride_uv = 0; } #if defined(HAS_MERGEUVROW_SSE2) if (TestCpuFlag(kCpuHasSSE2)) { MergeUVRow = MergeUVRow_Any_SSE2; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_SSE2; } } #endif #if defined(HAS_MERGEUVROW_AVX2) if (TestCpuFlag(kCpuHasAVX2)) { MergeUVRow = MergeUVRow_Any_AVX2; if (IS_ALIGNED(width, 32)) { MergeUVRow = MergeUVRow_AVX2; } } #endif #if defined(HAS_MERGEUVROW_NEON) if (TestCpuFlag(kCpuHasNEON)) { MergeUVRow = MergeUVRow_Any_NEON; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_NEON; } } #endif #if defined(HAS_MERGEUVROW_MSA) if (TestCpuFlag(kCpuHasMSA)) { MergeUVRow = MergeUVRow_Any_MSA; if (IS_ALIGNED(width, 16)) { MergeUVRow = MergeUVRow_MSA; } } #endif for (y = 0; y < height; ++y) { // Merge a row of U and V into a row of UV. MergeUVRow(src_u, src_v, dst_uv, width); src_u += src_stride_u; src_v += src_stride_v; dst_uv += dst_stride_uv; } } // Support function for NV12 etc RGB channels. // Width and height are plane sizes (typically half pixel width). LIBYUV_API void SplitRGBPlane(const uint8_t* src_rgb, int src_stride_rgb, uint8_t* dst_r, int dst_stride_r, uint8_t* dst_g, int dst_stride_g, uint8_t* dst_b,