141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org/*
241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *
441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  Use of this source code is governed by a BSD-style license
541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  that can be found in the LICENSE file in the root of the source
641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  tree. An additional intellectual property rights grant can be found
741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  in the file PATENTS. All contributing project authors may
841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org *  be found in the AUTHORS file in the root of the source tree.
941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org */
1041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
1141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/convert_argb.h"
1241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
1341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/cpu_id.h"
1441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/format_conversion.h"
1541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#ifdef HAVE_JPEG
1641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/mjpeg_decoder.h"
1741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#endif
1841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/rotate_argb.h"
1941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/row.h"
2041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#include "libyuv/video_common.h"
2141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
2241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#ifdef __cplusplus
2341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgnamespace libyuv {
2441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgextern "C" {
2541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#endif
2641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
2741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org// Convert camera sample to I420 with cropping, rotation and vertical flip.
2841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org// src_width is used for source stride computation
2941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org// src_height is used to compute location of planes, and indicate inversion
3041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org// sample_size is measured in bytes and is the size of the frame.
3141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//   With MJPEG it is the compressed size of the frame.
3241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgLIBYUV_API
3341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.orgint ConvertToARGB(const uint8* sample, size_t sample_size,
3441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  uint8* crop_argb, int argb_stride,
3541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  int crop_x, int crop_y,
3641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  int src_width, int src_height,
3741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  int crop_width, int crop_height,
3841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  enum RotationMode rotation,
3941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                  uint32 fourcc) {
4041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  uint32 format = CanonicalFourCC(fourcc);
4141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int aligned_src_width = (src_width + 1) & ~1;
4241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  const uint8* src;
4341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  const uint8* src_uv;
4441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int abs_src_height = (src_height < 0) ? -src_height : src_height;
4541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int inv_crop_height = (crop_height < 0) ? -crop_height : crop_height;
4641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int r = 0;
4741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
4841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // One pass rotation is available for some formats. For the rest, convert
4941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // to I420 (with optional vertical flipping) into a temporary I420 buffer,
5041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // and then rotate the I420 to the final destination buffer.
5141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // For in-place conversion, if destination crop_argb is same as source sample,
5241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  // also enable temporary buffer.
5341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  LIBYUV_BOOL need_buf = (rotation && format != FOURCC_ARGB) ||
5441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      crop_argb == sample;
5541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  uint8* tmp_argb = crop_argb;
5641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int tmp_argb_stride = argb_stride;
5741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  uint8* rotate_buffer = NULL;
5841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height;
5941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
6041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  if (crop_argb == NULL || sample == NULL ||
6141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src_width <= 0 || crop_width <= 0 ||
6241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src_height == 0 || crop_height == 0) {
6341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    return -1;
6441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
6541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  if (src_height < 0) {
6641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    inv_crop_height = -inv_crop_height;
6741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
6841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
6941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  if (need_buf) {
7041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    int argb_size = crop_width * abs_crop_height * 4;
7141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    rotate_buffer = (uint8*)malloc(argb_size);
7241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    if (!rotate_buffer) {
7341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      return 1;  // Out of memory runtime error.
7441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
7541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    crop_argb = rotate_buffer;
7641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    argb_stride = crop_width;
7741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
7841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
7941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  switch (format) {
8041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    // Single plane formats
8141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_YUY2:
8241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
8341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = YUY2ToARGB(src, aligned_src_width * 2,
8441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
8541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
8641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
8741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_UYVY:
8841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
8941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = UYVYToARGB(src, aligned_src_width * 2,
9041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
9141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
9241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
9341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_24BG:
9441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 3;
9541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = RGB24ToARGB(src, src_width * 3,
9641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                      crop_argb, argb_stride,
9741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                      crop_width, inv_crop_height);
9841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
9941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_RAW:
10041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 3;
10141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = RAWToARGB(src, src_width * 3,
10241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                    crop_argb, argb_stride,
10341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                    crop_width, inv_crop_height);
10441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
10541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_ARGB:
10641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 4;
10741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = ARGBToARGB(src, src_width * 4,
10841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
10941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
11041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
11141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_BGRA:
11241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 4;
11341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = BGRAToARGB(src, src_width * 4,
11441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
11541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
11641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
11741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_ABGR:
11841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 4;
11941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = ABGRToARGB(src, src_width * 4,
12041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
12141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
12241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
12341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_RGBA:
12441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 4;
12541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = RGBAToARGB(src, src_width * 4,
12641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
12741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
12841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
12941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_RGBP:
13041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 2;
13141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = RGB565ToARGB(src, src_width * 2,
13241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                       crop_argb, argb_stride,
13341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                       crop_width, inv_crop_height);
13441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
13541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_RGBO:
13641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 2;
13741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = ARGB1555ToARGB(src, src_width * 2,
13841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                         crop_argb, argb_stride,
13941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                         crop_width, inv_crop_height);
14041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
14141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_R444:
14241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x) * 2;
14341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = ARGB4444ToARGB(src, src_width * 2,
14441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                         crop_argb, argb_stride,
14541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                         crop_width, inv_crop_height);
14641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
14741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    // TODO(fbarchard): Support cropping Bayer by odd numbers
14841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    // by adjusting fourcc.
14941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_BGGR:
15041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
15141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = BayerBGGRToARGB(src, src_width,
15241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_argb, argb_stride,
15341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_width, inv_crop_height);
15441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
15541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
15641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_GBRG:
15741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
15841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = BayerGBRGToARGB(src, src_width,
15941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_argb, argb_stride,
16041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_width, inv_crop_height);
16141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
16241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
16341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_GRBG:
16441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
16541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = BayerGRBGToARGB(src, src_width,
16641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_argb, argb_stride,
16741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_width, inv_crop_height);
16841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
16941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
17041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_RGGB:
17141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
17241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = BayerRGGBToARGB(src, src_width,
17341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_argb, argb_stride,
17441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                          crop_width, inv_crop_height);
17541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
17641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
17741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_I400:
17841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + src_width * crop_y + crop_x;
17941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = I400ToARGB(src, src_width,
18041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
18141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
18241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
18341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
18441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    // Biplanar formats
18541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_NV12:
18641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
18741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
18841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = NV12ToARGB(src, src_width,
18941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_uv, aligned_src_width,
19041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
19141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
19241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
19341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_NV21:
19441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y + crop_x);
19541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
19641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      // Call NV12 but with u and v parameters swapped.
19741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = NV21ToARGB(src, src_width,
19841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_uv, aligned_src_width,
19941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
20041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
20141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
20241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_M420:
20341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
20441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = M420ToARGB(src, src_width,
20541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
20641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
20741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
20841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//    case FOURCC_Q420:
20941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//      src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x;
21041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//      src_uv = sample + (src_width + aligned_src_width * 2) * crop_y +
21141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//               src_width + crop_x * 2;
21241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//      r = Q420ToARGB(src, src_width * 3,
21341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//                    src_uv, src_width * 3,
21441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//                    crop_argb, argb_stride,
21541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//                    crop_width, inv_crop_height);
21641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org//      break;
21741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    // Triplanar formats
21841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_I420:
21941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_YU12:
22041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_YV12: {
22141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_y = sample + (src_width * crop_y + crop_x);
22241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_u;
22341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_v;
22441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      int halfwidth = (src_width + 1) / 2;
22541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      int halfheight = (abs_src_height + 1) / 2;
22641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      if (format == FOURCC_YV12) {
22741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * abs_src_height +
22841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            (halfwidth * crop_y + crop_x) / 2;
22941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * abs_src_height +
23041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
23141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      } else {
23241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * abs_src_height +
23341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            (halfwidth * crop_y + crop_x) / 2;
23441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * abs_src_height +
23541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
23641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      }
23741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = I420ToARGB(src_y, src_width,
23841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_u, halfwidth,
23941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_v, halfwidth,
24041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
24141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
24241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
24341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
24441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_I422:
24541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_YV16: {
24641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_y = sample + src_width * crop_y + crop_x;
24741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_u;
24841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_v;
24941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      int halfwidth = (src_width + 1) / 2;
25041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      if (format == FOURCC_YV16) {
25141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * abs_src_height +
25241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * crop_y + crop_x / 2;
25341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * abs_src_height +
25441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
25541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      } else {
25641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * abs_src_height +
25741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * crop_y + crop_x / 2;
25841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * abs_src_height +
25941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
26041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      }
26141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = I422ToARGB(src_y, src_width,
26241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_u, halfwidth,
26341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_v, halfwidth,
26441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
26541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
26641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
26741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
26841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_I444:
26941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_YV24: {
27041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_y = sample + src_width * crop_y + crop_x;
27141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_u;
27241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_v;
27341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      if (format == FOURCC_YV24) {
27441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * (abs_src_height + crop_y) + crop_x;
27541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
27641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      } else {
27741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_u = sample + src_width * (abs_src_height + crop_y) + crop_x;
27841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org        src_v = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
27941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      }
28041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = I444ToARGB(src_y, src_width,
28141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_u, src_width,
28241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_v, src_width,
28341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
28441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
28541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
28641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
28741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_I411: {
28841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      int quarterwidth = (src_width + 3) / 4;
28941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_y = sample + src_width * crop_y + crop_x;
29041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_u = sample + src_width * abs_src_height +
29141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org          quarterwidth * crop_y + crop_x / 4;
29241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      const uint8* src_v = sample + src_width * abs_src_height +
29341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org          quarterwidth * (abs_src_height + crop_y) + crop_x / 4;
29441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = I411ToARGB(src_y, src_width,
29541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_u, quarterwidth,
29641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_v, quarterwidth,
29741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
29841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, inv_crop_height);
29941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
30041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
30141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#ifdef HAVE_JPEG
30241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    case FOURCC_MJPG:
30341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = MJPGToARGB(sample, sample_size,
30441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_argb, argb_stride,
30541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     src_width, abs_src_height, crop_width, inv_crop_height);
30641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      break;
30741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#endif
30841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    default:
30941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = -1;  // unknown fourcc - return failure code.
31041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
31141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
31241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  if (need_buf) {
31341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    if (!r) {
31441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org      r = ARGBRotate(crop_argb, argb_stride,
31541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     tmp_argb, tmp_argb_stride,
31641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org                     crop_width, abs_crop_height, rotation);
31741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    }
31841294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org    free(rotate_buffer);
31941294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  }
32041294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
32141294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org  return r;
32241294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org}
32341294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org
32441294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#ifdef __cplusplus
32541294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org}  // extern "C"
32641294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org}  // namespace libyuv
32741294d96d7dbf9bc215b09832a8336c5fb158f0bjohannkoenig@chromium.org#endif
328