1492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com/*
2492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *
4492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  Use of this source code is governed by a BSD-style license
5492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  that can be found in the LICENSE file in the root of the source
6492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  tree. An additional intellectual property rights grant can be found
7492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  in the file PATENTS. All contributing project authors may
8492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com *  be found in the AUTHORS file in the root of the source tree.
9492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com */
10492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
111f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com#include <stdlib.h>
121f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com
13492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#include "libyuv/convert.h"
14492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
15492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#include "libyuv/format_conversion.h"
16492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#include "libyuv/video_common.h"
17492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
18492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef __cplusplus
19492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comnamespace libyuv {
20492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comextern "C" {
21492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
22492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
23492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// Convert camera sample to I420 with cropping, rotation and vertical flip.
24492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// src_width is used for source stride computation
25492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// src_height is used to compute location of planes, and indicate inversion
26492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// sample_size is measured in bytes and is the size of the frame.
27492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com//   With MJPEG it is the compressed size of the frame.
28492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comLIBYUV_API
29492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comint ConvertToI420(const uint8* sample,
30492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  size_t sample_size,
31492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  uint8* y, int y_stride,
32492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  uint8* u, int u_stride,
33492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  uint8* v, int v_stride,
34492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  int crop_x, int crop_y,
35492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  int src_width, int src_height,
36f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                  int crop_width, int crop_height,
37db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com                  enum RotationMode rotation,
38492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                  uint32 fourcc) {
39492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint32 format = CanonicalFourCC(fourcc);
40492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int aligned_src_width = (src_width + 1) & ~1;
41492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  const uint8* src;
42492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  const uint8* src_uv;
43492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int abs_src_height = (src_height < 0) ? -src_height : src_height;
44f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com  int inv_crop_height = (crop_height < 0) ? -crop_height : crop_height;
45492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int r = 0;
46db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com  LIBYUV_BOOL need_buf = (rotation && format != FOURCC_I420 &&
47492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      format != FOURCC_NV12 && format != FOURCC_NV21 &&
48492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      format != FOURCC_YU12 && format != FOURCC_YV12) || y == sample;
49492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* tmp_y = y;
50492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* tmp_u = u;
51492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* tmp_v = v;
52492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int tmp_y_stride = y_stride;
53492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int tmp_u_stride = u_stride;
54492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int tmp_v_stride = v_stride;
552d8824079a1460b8b42faa93753f09ef8375a084fbarchard@google.com  uint8* rotate_buffer = NULL;
56f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com  int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height;
576d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com
586d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  if (!y || !u || !v || !sample ||
596d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com      src_width <= 0 || crop_width <= 0  ||
606d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com      src_height == 0 || crop_height == 0) {
616d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com    return -1;
626d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  }
636d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  if (src_height < 0) {
646d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com    inv_crop_height = -inv_crop_height;
656d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  }
666d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com
676d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  // One pass rotation is available for some formats. For the rest, convert
686d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  // to I420 (with optional vertical flipping) into a temporary I420 buffer,
696d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  // and then rotate the I420 to the final destination buffer.
706d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  // For in-place conversion, if destination y is same as source sample,
716d82347dda1b90d7b2c4ee8c110089c78777c738fbarchard@google.com  // also enable temporary buffer.
72492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (need_buf) {
73f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com    int y_size = crop_width * abs_crop_height;
74f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com    int uv_size = ((crop_width + 1) / 2) * ((abs_crop_height + 1) / 2);
7553a7923b159626a6a598a7856a9830df4bbb560cfbarchard@google.com    rotate_buffer = (uint8*)malloc(y_size + uv_size * 2);
762d8824079a1460b8b42faa93753f09ef8375a084fbarchard@google.com    if (!rotate_buffer) {
77492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      return 1;  // Out of memory runtime error.
78492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
792d8824079a1460b8b42faa93753f09ef8375a084fbarchard@google.com    y = rotate_buffer;
80492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    u = y + y_size;
81492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    v = u + uv_size;
82f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com    y_stride = crop_width;
83f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com    u_stride = v_stride = ((crop_width + 1) / 2);
84492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
85492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
86492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  switch (format) {
87492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // Single plane formats
88492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_YUY2:
89492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
90492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = YUY2ToI420(src, aligned_src_width * 2,
91492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
92492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
93492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
94f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
95492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
96492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_UYVY:
97492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
98492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = UYVYToI420(src, aligned_src_width * 2,
99492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
100492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
101492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
102f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
103492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
104492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_RGBP:
105492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 2;
106492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = RGB565ToI420(src, src_width * 2,
107492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                       y, y_stride,
108492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                       u, u_stride,
109492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                       v, v_stride,
110f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                       crop_width, inv_crop_height);
111492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
112492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_RGBO:
113492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 2;
114492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = ARGB1555ToI420(src, src_width * 2,
115492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         y, y_stride,
116492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         u, u_stride,
117492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         v, v_stride,
118f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                         crop_width, inv_crop_height);
119492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
120492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_R444:
121492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 2;
122492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = ARGB4444ToI420(src, src_width * 2,
123492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         y, y_stride,
124492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         u, u_stride,
125492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         v, v_stride,
126f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                         crop_width, inv_crop_height);
127492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
128492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_24BG:
129492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 3;
130492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = RGB24ToI420(src, src_width * 3,
131492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                      y, y_stride,
132492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                      u, u_stride,
133492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                      v, v_stride,
134f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                      crop_width, inv_crop_height);
135492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
136492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_RAW:
137492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 3;
138492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = RAWToI420(src, src_width * 3,
139492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    y, y_stride,
140492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    u, u_stride,
141492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    v, v_stride,
142f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                    crop_width, inv_crop_height);
143492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
144492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_ARGB:
145492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 4;
146492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = ARGBToI420(src, src_width * 4,
147492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
148492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
149492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
150f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
151492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
152492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_BGRA:
153492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 4;
154492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = BGRAToI420(src, src_width * 4,
155492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
156492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
157492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
158f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
159492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
160492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_ABGR:
161492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 4;
162492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = ABGRToI420(src, src_width * 4,
163492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
164492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
165492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
166f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
167492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
168492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_RGBA:
169492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x) * 4;
170492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = RGBAToI420(src, src_width * 4,
171492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
172492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
173492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
174f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
175492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
176492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // TODO(fbarchard): Support cropping Bayer by odd numbers
177492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // by adjusting fourcc.
178492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_BGGR:
179492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
180492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = BayerBGGRToI420(src, src_width,
181492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          y, y_stride,
182492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          u, u_stride,
183492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          v, v_stride,
184f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                          crop_width, inv_crop_height);
185492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
186492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_GBRG:
187492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
188492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = BayerGBRGToI420(src, src_width,
189492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          y, y_stride,
190492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          u, u_stride,
191492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          v, v_stride,
192f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                          crop_width, inv_crop_height);
193492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
194492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_GRBG:
195492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
196492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = BayerGRBGToI420(src, src_width,
197492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          y, y_stride,
198492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          u, u_stride,
199492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          v, v_stride,
200f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                          crop_width, inv_crop_height);
201492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
202492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_RGGB:
203492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
204492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = BayerRGGBToI420(src, src_width,
205492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          y, y_stride,
206492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          u, u_stride,
207492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                          v, v_stride,
208f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                          crop_width, inv_crop_height);
209492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
210492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_I400:
211492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + src_width * crop_y + crop_x;
212492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I400ToI420(src, src_width,
213492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
214492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
215492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
216f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
217492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
218492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // Biplanar formats
219492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_NV12:
220492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
221492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
222492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = NV12ToI420Rotate(src, src_width,
223492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           src_uv, aligned_src_width,
224492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           y, y_stride,
225492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           u, u_stride,
226492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           v, v_stride,
227f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                           crop_width, inv_crop_height, rotation);
228492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
229492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_NV21:
230492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y + crop_x);
231492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
232492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      // Call NV12 but with u and v parameters swapped.
233492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = NV12ToI420Rotate(src, src_width,
234492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           src_uv, aligned_src_width,
235492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           y, y_stride,
236492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           v, v_stride,
237492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           u, u_stride,
238f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                           crop_width, inv_crop_height, rotation);
239492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
240492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_M420:
241492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
242492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = M420ToI420(src, src_width,
243492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
244492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
245492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
246f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
247492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
248492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_Q420:
249492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x;
250492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      src_uv = sample + (src_width + aligned_src_width * 2) * crop_y +
251492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               src_width + crop_x * 2;
252492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = Q420ToI420(src, src_width * 3,
253492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    src_uv, src_width * 3,
254492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    y, y_stride,
255492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    u, u_stride,
256492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                    v, v_stride,
257f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                    crop_width, inv_crop_height);
258492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
259492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // Triplanar formats
260492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_I420:
261492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_YU12:
262492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_YV12: {
263492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_y = sample + (src_width * crop_y + crop_x);
264492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_u;
265492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_v;
266492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      int halfwidth = (src_width + 1) / 2;
267492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      int halfheight = (abs_src_height + 1) / 2;
268492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      if (format == FOURCC_YV12) {
269492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * abs_src_height +
270492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            (halfwidth * crop_y + crop_x) / 2;
271492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * abs_src_height +
272492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
273492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      } else {
274492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * abs_src_height +
275492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            (halfwidth * crop_y + crop_x) / 2;
276492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * abs_src_height +
277492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
278492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      }
279492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I420Rotate(src_y, src_width,
280492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_u, halfwidth,
281492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_v, halfwidth,
282492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
283492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
284492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
285f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height, rotation);
286492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
287492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
288492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_I422:
289492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_YV16: {
290492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_y = sample + src_width * crop_y + crop_x;
291492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_u;
292492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_v;
293492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      int halfwidth = (src_width + 1) / 2;
294492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      if (format == FOURCC_YV16) {
295492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * abs_src_height +
296492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * crop_y + crop_x / 2;
297492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * abs_src_height +
298492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
299492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      } else {
300492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * abs_src_height +
301492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * crop_y + crop_x / 2;
302492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * abs_src_height +
303492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
304492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      }
305492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I422ToI420(src_y, src_width,
306492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_u, halfwidth,
307492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_v, halfwidth,
308492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
309492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
310492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
311f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
312492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
313492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
314492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_I444:
315492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_YV24: {
316492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_y = sample + src_width * crop_y + crop_x;
317492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_u;
318492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_v;
319492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      if (format == FOURCC_YV24) {
320492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * (abs_src_height + crop_y) + crop_x;
321492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
322492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      } else {
323492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_u = sample + src_width * (abs_src_height + crop_y) + crop_x;
324492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        src_v = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
325492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      }
326492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I444ToI420(src_y, src_width,
327492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_u, src_width,
328492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_v, src_width,
329492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
330492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
331492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
332f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
333492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
334492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
335492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_I411: {
336492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      int quarterwidth = (src_width + 3) / 4;
337492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_y = sample + src_width * crop_y + crop_x;
338492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_u = sample + src_width * abs_src_height +
339492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com          quarterwidth * crop_y + crop_x / 4;
340492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      const uint8* src_v = sample + src_width * abs_src_height +
341492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com          quarterwidth * (abs_src_height + crop_y) + crop_x / 4;
342492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I411ToI420(src_y, src_width,
343492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_u, quarterwidth,
344492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     src_v, quarterwidth,
345492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
346492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
347492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
348f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, inv_crop_height);
349492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
350492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
351492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef HAVE_JPEG
352492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    case FOURCC_MJPG:
353492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = MJPGToI420(sample, sample_size,
354492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     y, y_stride,
355492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
356492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
357f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     src_width, abs_src_height, crop_width, inv_crop_height);
358492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      break;
359492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
360492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    default:
361492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = -1;  // unknown fourcc - return failure code.
362492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
363492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
364492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (need_buf) {
365492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    if (!r) {
366492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      r = I420Rotate(y, y_stride,
367492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     u, u_stride,
368492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     v, v_stride,
369492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     tmp_y, tmp_y_stride,
370492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     tmp_u, tmp_u_stride,
371492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                     tmp_v, tmp_v_stride,
372f2bd31538e43abaefc51d2a07b7a9f9e5f9911a0fbarchard@google.com                     crop_width, abs_crop_height, rotation);
373492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
3741f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com    free(rotate_buffer);
375492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
376492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
377492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  return r;
378492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
379492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
380492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef __cplusplus
381492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}  // extern "C"
382492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}  // namespace libyuv
383492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
384