1740 lines · 53.6 KB · C++
RawDownload
/* *  Copyright 2011 The LibYuv Project Authors. All rights reserved. * *  Use of this source code is governed by a BSD-style license *  that can be found in the LICENSE file in the root of the source *  tree. An additional intellectual property rights grant can be found *  in the file PATENTS. All contributing project authors may *  be found in the AUTHORS file in the root of the source tree. */ #include "libyuv/convert.h" #include "libyuv/basic_types.h"#include "libyuv/cpu_id.h"#include "libyuv/planar_functions.h"#include "libyuv/rotate.h"#include "libyuv/row.h"#include "libyuv/scale.h"  // For ScalePlane() #ifdef __cplusplusnamespace libyuv {extern "C" {#endif #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)static __inline int Abs(int v) {  return v >= 0 ? v : -v;} // Any I4xx To I420 format with mirroring.static int I4xxToI420(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 src_y_width,                      int src_y_height,                      int src_uv_width,                      int src_uv_height) {  const int dst_y_width = Abs(src_y_width);  const int dst_y_height = Abs(src_y_height);  const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);  const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);  if (src_uv_width == 0 || src_uv_height == 0) {    return -1;  }  if (dst_y) {    ScalePlane(src_y, src_stride_y, src_y_width, src_y_height, dst_y,               dst_stride_y, dst_y_width, dst_y_height, kFilterBilinear);  }  ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height, dst_u,             dst_stride_u, dst_uv_width, dst_uv_height, kFilterBilinear);  ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height, dst_v,             dst_stride_v, dst_uv_width, dst_uv_height, kFilterBilinear);  return 0;} // Copy I420 with optional flipping.// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure// is does row coalescing.LIBYUV_APIint 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_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;} // Copy I010 with optional flipping.LIBYUV_APIint I010Copy(const uint16_t* src_y,             int src_stride_y,             const uint16_t* src_u,             int src_stride_u,             const uint16_t* src_v,             int src_stride_v,             uint16_t* dst_y,             int dst_stride_y,             uint16_t* dst_u,             int dst_stride_u,             uint16_t* dst_v,             int dst_stride_v,             int width,             int height) {  int halfwidth = (width + 1) >> 1;  int halfheight = (height + 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;    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_16(src_y, src_stride_y, dst_y, dst_stride_y, width, height);  }  // Copy UV planes.  CopyPlane_16(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);  CopyPlane_16(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);  return 0;} // Convert 10 bit YUV to 8 bit.LIBYUV_APIint I010ToI420(const uint16_t* src_y,               int src_stride_y,               const uint16_t* src_u,               int src_stride_u,               const uint16_t* src_v,               int src_stride_v,               uint8_t* dst_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_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;  }   // Convert Y plane.  Convert16To8Plane(src_y, src_stride_y, dst_y, dst_stride_y, 16384, width,                    height);  // Convert UV planes.  Convert16To8Plane(src_u, src_stride_u, dst_u, dst_stride_u, 16384, halfwidth,                    halfheight);  Convert16To8Plane(src_v, src_stride_v, dst_v, dst_stride_v, 16384, halfwidth,                    halfheight);  return 0;} // 422 chroma is 1/2 width, 1x height// 420 chroma is 1/2 width, 1/2 heightLIBYUV_APIint I422ToI420(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) {  const int src_uv_width = SUBSAMPLE(width, 1, 1);  return I4xxToI420(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, src_uv_width, height);} // 444 chroma is 1x width, 1x height// 420 chroma is 1/2 width, 1/2 heightLIBYUV_APIint I444ToI420(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) {  return I4xxToI420(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, width, height);} // I400 is greyscale typically used in MJPGLIBYUV_APIint I400ToI420(const uint8_t* src_y,               int src_stride_y,               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 (!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_stride_y = -src_stride_y;  }  if (dst_y) {    CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);  }  SetPlane(dst_u, dst_stride_u, halfwidth, halfheight, 128);  SetPlane(dst_v, dst_stride_v, halfwidth, halfheight, 128);  return 0;} static void CopyPlane2(const uint8_t* src,                       int src_stride_0,                       int src_stride_1,                       uint8_t* dst,                       int dst_stride,                       int width,                       int height) {  int y;  void (*CopyRow)(const uint8_t* src, uint8_t* dst, int width) = CopyRow_C;#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 - 1; y += 2) {    CopyRow(src, dst, width);    CopyRow(src + src_stride_0, dst + dst_stride, width);    src += src_stride_0 + src_stride_1;    dst += dst_stride * 2;  }  if (height & 1) {    CopyRow(src, dst, width);  }} // Support converting from FOURCC_M420// Useful for bandwidth constrained transports like USB 1.0 and 2.0 and for// easy conversion to I420.// M420 format description:// M420 is row biplanar 420: 2 rows of Y and 1 row of UV.// Chroma is half width / half height. (420)// src_stride_m420 is row planar. Normally this will be the width in pixels.//   The UV plane is half width, but 2 values, so src_stride_m420 applies to//   this as well as the two Y planes.static int X420ToI420(const uint8_t* src_y,                      int src_stride_y0,                      int src_stride_y1,                      const uint8_t* src_uv,                      int src_stride_uv,                      uint8_t* dst_y,                      int dst_stride_y,                      uint8_t* dst_u,                      int dst_stride_u,                      uint8_t* dst_v,                      int dst_stride_v,                      int width,                      int height) {  int halfwidth = (width + 1) >> 1;  int halfheight = (height + 1) >> 1;  if (!src_uv || !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;    if (dst_y) {      dst_y = dst_y + (height - 1) * dst_stride_y;    }    dst_u = dst_u + (halfheight - 1) * dst_stride_u;    dst_v = dst_v + (halfheight - 1) * dst_stride_v;    dst_stride_y = -dst_stride_y;    dst_stride_u = -dst_stride_u;    dst_stride_v = -dst_stride_v;  }  // Coalesce rows.  if (src_stride_y0 == width && src_stride_y1 == width &&      dst_stride_y == width) {    width *= height;    height = 1;    src_stride_y0 = src_stride_y1 = dst_stride_y = 0;  }  // Coalesce rows.  if (src_stride_uv == halfwidth * 2 && dst_stride_u == halfwidth &&      dst_stride_v == halfwidth) {    halfwidth *= halfheight;    halfheight = 1;    src_stride_uv = dst_stride_u = dst_stride_v = 0;  }   if (dst_y) {    if (src_stride_y0 == src_stride_y1) {      CopyPlane(src_y, src_stride_y0, dst_y, dst_stride_y, width, height);    } else {      CopyPlane2(src_y, src_stride_y0, src_stride_y1, dst_y, dst_stride_y,                 width, height);    }  }   // Split UV plane - NV12 / NV21  SplitUVPlane(src_uv, src_stride_uv, dst_u, dst_stride_u, dst_v, dst_stride_v,               halfwidth, halfheight);   return 0;} // Convert NV12 to I420.LIBYUV_APIint NV12ToI420(const uint8_t* src_y,               int src_stride_y,               const uint8_t* src_uv,               int src_stride_uv,               uint8_t* dst_y,               int dst_stride_y,               uint8_t* dst_u,               int dst_stride_u,               uint8_t* dst_v,               int dst_stride_v,               int width,               int height) {  return X420ToI420(src_y, src_stride_y, src_stride_y, src_uv, src_stride_uv,                    dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v,                    dst_stride_v, width, height);} // Convert NV21 to I420.  Same as NV12 but u and v pointers swapped.LIBYUV_APIint NV21ToI420(const uint8_t* src_y,               int src_stride_y,               const uint8_t* src_vu,               int src_stride_vu,               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) {  return X420ToI420(src_y, src_stride_y, src_stride_y, src_vu, src_stride_vu,                    dst_y, dst_stride_y, dst_v, dst_stride_v, dst_u,                    dst_stride_u, width, height);} // Convert M420 to I420.LIBYUV_APIint M420ToI420(const uint8_t* src_m420,               int src_stride_m420,               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) {  return X420ToI420(src_m420, src_stride_m420, src_stride_m420 * 2,                    src_m420 + src_stride_m420 * 2, src_stride_m420 * 3, dst_y,                    dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v,                    width, height);} // Convert YUY2 to I420.LIBYUV_APIint YUY2ToI420(const uint8_t* src_yuy2,               int src_stride_yuy2,               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 (*YUY2ToUVRow)(const uint8_t* src_yuy2, int src_stride_yuy2,                      uint8_t* dst_u, uint8_t* dst_v, int width) =      YUY2ToUVRow_C;  void (*YUY2ToYRow)(const uint8_t* src_yuy2, uint8_t* dst_y, int width) =      YUY2ToYRow_C;  // Negative height means invert the image.  if (height < 0) {    height = -height;    src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;    src_stride_yuy2 = -src_stride_yuy2;  }#if defined(HAS_YUY2TOYROW_SSE2)  if (TestCpuFlag(kCpuHasSSE2)) {    YUY2ToUVRow = YUY2ToUVRow_Any_SSE2;    YUY2ToYRow = YUY2ToYRow_Any_SSE2;    if (IS_ALIGNED(width, 16)) {      YUY2ToUVRow = YUY2ToUVRow_SSE2;      YUY2ToYRow = YUY2ToYRow_SSE2;    }  }#endif#if defined(HAS_YUY2TOYROW_AVX2)  if (TestCpuFlag(kCpuHasAVX2)) {    YUY2ToUVRow = YUY2ToUVRow_Any_AVX2;    YUY2ToYRow = YUY2ToYRow_Any_AVX2;    if (IS_ALIGNED(width, 32)) {      YUY2ToUVRow = YUY2ToUVRow_AVX2;      YUY2ToYRow = YUY2ToYRow_AVX2;    }  }#endif#if defined(HAS_YUY2TOYROW_NEON)  if (TestCpuFlag(kCpuHasNEON)) {    YUY2ToYRow = YUY2ToYRow_Any_NEON;    YUY2ToUVRow = YUY2ToUVRow_Any_NEON;    if (IS_ALIGNED(width, 16)) {      YUY2ToYRow = YUY2ToYRow_NEON;      YUY2ToUVRow = YUY2ToUVRow_NEON;    }  }#endif#if defined(HAS_YUY2TOYROW_MSA)  if (TestCpuFlag(kCpuHasMSA)) {    YUY2ToYRow = YUY2ToYRow_Any_MSA;    YUY2ToUVRow = YUY2ToUVRow_Any_MSA;    if (IS_ALIGNED(width, 32)) {      YUY2ToYRow = YUY2ToYRow_MSA;

Lines 1–500 of 1740.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t