1ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian/*
2ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *
4ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  in the file PATENTS. All contributing project authors may
8ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian */
10ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
11ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/convert_argb.h"
12ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
13ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/cpu_id.h"
14ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef HAVE_JPEG
15ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/mjpeg_decoder.h"
16ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
17ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/rotate_argb.h"
18ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/row.h"
19ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "libyuv/video_common.h"
20ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
21ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
22ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramaniannamespace libyuv {
23ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianextern "C" {
24ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
25ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
267bc9febe8749e98a3812a0dc4380ceae75c29450Johann// Convert camera sample to ARGB with cropping, rotation and vertical flip.
27ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// src_width is used for source stride computation
28ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// src_height is used to compute location of planes, and indicate inversion
29ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian// sample_size is measured in bytes and is the size of the frame.
30ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian//   With MJPEG it is the compressed size of the frame.
31ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh VenkatasubramanianLIBYUV_API
32ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianint ConvertToARGB(const uint8* sample, size_t sample_size,
33ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint8* crop_argb, int argb_stride,
34ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int crop_x, int crop_y,
35ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int src_width, int src_height,
36ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  int crop_width, int crop_height,
37ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  enum RotationMode rotation,
38ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                  uint32 fourcc) {
39ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint32 format = CanonicalFourCC(fourcc);
40ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int aligned_src_width = (src_width + 1) & ~1;
41ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8* src;
42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8* src_uv;
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int abs_src_height = (src_height < 0) ? -src_height : src_height;
44ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int inv_crop_height = (crop_height < 0) ? -crop_height : crop_height;
45ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int r = 0;
46ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
47ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // One pass rotation is available for some formats. For the rest, convert
48ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // to I420 (with optional vertical flipping) into a temporary I420 buffer,
49ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // and then rotate the I420 to the final destination buffer.
50ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // For in-place conversion, if destination crop_argb is same as source sample,
51ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // also enable temporary buffer.
52ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  LIBYUV_BOOL need_buf = (rotation && format != FOURCC_ARGB) ||
53ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      crop_argb == sample;
547bc9febe8749e98a3812a0dc4380ceae75c29450Johann  uint8* dest_argb = crop_argb;
557bc9febe8749e98a3812a0dc4380ceae75c29450Johann  int dest_argb_stride = argb_stride;
56ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8* rotate_buffer = NULL;
57ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height;
58ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
59ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (crop_argb == NULL || sample == NULL ||
60ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_width <= 0 || crop_width <= 0 ||
61ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_height == 0 || crop_height == 0) {
62ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return -1;
63ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
64ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (src_height < 0) {
65ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    inv_crop_height = -inv_crop_height;
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
67ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
68ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (need_buf) {
697bc9febe8749e98a3812a0dc4380ceae75c29450Johann    int argb_size = crop_width * 4 * abs_crop_height;
70ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    rotate_buffer = (uint8*)malloc(argb_size);
71ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!rotate_buffer) {
72ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      return 1;  // Out of memory runtime error.
73ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
74ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    crop_argb = rotate_buffer;
757bc9febe8749e98a3812a0dc4380ceae75c29450Johann    argb_stride = crop_width * 4;
76ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
77ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
78ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  switch (format) {
79ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Single plane formats
80ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_YUY2:
81ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
82ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = YUY2ToARGB(src, aligned_src_width * 2,
83ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
84ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
85ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
86ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_UYVY:
87ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (aligned_src_width * crop_y + crop_x) * 2;
88ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = UYVYToARGB(src, aligned_src_width * 2,
89ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
90ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
91ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
92ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_24BG:
93ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 3;
94ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = RGB24ToARGB(src, src_width * 3,
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      crop_argb, argb_stride,
96ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                      crop_width, inv_crop_height);
97ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_RAW:
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 3;
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = RAWToARGB(src, src_width * 3,
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    crop_argb, argb_stride,
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                    crop_width, inv_crop_height);
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_ARGB:
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 4;
106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = ARGBToARGB(src, src_width * 4,
107ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
108ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
109ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
110ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_BGRA:
111ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 4;
112ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = BGRAToARGB(src, src_width * 4,
113ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
114ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
115ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
116ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_ABGR:
117ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 4;
118ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = ABGRToARGB(src, src_width * 4,
119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
121ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_RGBA:
123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 4;
124ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = RGBAToARGB(src, src_width * 4,
125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_RGBP:
129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 2;
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = RGB565ToARGB(src, src_width * 2,
131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       crop_argb, argb_stride,
132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                       crop_width, inv_crop_height);
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_RGBO:
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 2;
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = ARGB1555ToARGB(src, src_width * 2,
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         crop_argb, argb_stride,
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         crop_width, inv_crop_height);
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_R444:
141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x) * 2;
142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = ARGB4444ToARGB(src, src_width * 2,
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         crop_argb, argb_stride,
144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                         crop_width, inv_crop_height);
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_I400:
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + src_width * crop_y + crop_x;
148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = I400ToARGB(src, src_width,
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
151ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Biplanar formats
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_NV12:
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x);
156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = NV12ToARGB(src, src_width,
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_uv, aligned_src_width,
159ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
160ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
161ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
162ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_NV21:
163ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y + crop_x);
164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x;
165ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      // Call NV12 but with u and v parameters swapped.
166ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = NV21ToARGB(src, src_width,
167ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_uv, aligned_src_width,
168ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
169ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_M420:
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      src = sample + (src_width * crop_y) * 12 / 8 + crop_x;
173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = M420ToARGB(src, src_width,
174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Triplanar formats
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_I420:
179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_YV12: {
180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_y = sample + (src_width * crop_y + crop_x);
181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_u;
182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_v;
183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int halfwidth = (src_width + 1) / 2;
184ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int halfheight = (abs_src_height + 1) / 2;
185ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (format == FOURCC_YV12) {
186ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * abs_src_height +
187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            (halfwidth * crop_y + crop_x) / 2;
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * abs_src_height +
189ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
190ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
191ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * abs_src_height +
192ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            (halfwidth * crop_y + crop_x) / 2;
193ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * abs_src_height +
194ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
195ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
196ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = I420ToARGB(src_y, src_width,
197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_u, halfwidth,
198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_v, halfwidth,
199ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
200ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
201ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
203da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
204da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    case FOURCC_J420: {
205da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      const uint8* src_y = sample + (src_width * crop_y + crop_x);
206da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      const uint8* src_u;
207da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      const uint8* src_v;
208da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      int halfwidth = (src_width + 1) / 2;
209da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      int halfheight = (abs_src_height + 1) / 2;
210da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src_u = sample + src_width * abs_src_height +
211da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian          (halfwidth * crop_y + crop_x) / 2;
212da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src_v = sample + src_width * abs_src_height +
213da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian          halfwidth * (halfheight + crop_y / 2) + crop_x / 2;
214da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      r = J420ToARGB(src_y, src_width,
215da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     src_u, halfwidth,
216da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     src_v, halfwidth,
217da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     crop_argb, argb_stride,
218da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
219da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      break;
220da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
221da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
222ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_I422:
223ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_YV16: {
224ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_y = sample + src_width * crop_y + crop_x;
225ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_u;
226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_v;
227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int halfwidth = (src_width + 1) / 2;
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (format == FOURCC_YV16) {
229ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * abs_src_height +
230ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * crop_y + crop_x / 2;
231ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * abs_src_height +
232ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
233ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
234ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * abs_src_height +
235ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * crop_y + crop_x / 2;
236ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * abs_src_height +
237ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian            halfwidth * (abs_src_height + crop_y) + crop_x / 2;
238ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
239ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = I422ToARGB(src_y, src_width,
240ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_u, halfwidth,
241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_v, halfwidth,
242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
243ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
244ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
245ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
246ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_I444:
247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_YV24: {
248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_y = sample + src_width * crop_y + crop_x;
249ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_u;
250ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_v;
251ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (format == FOURCC_YV24) {
252ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * (abs_src_height + crop_y) + crop_x;
253ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
254ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
255ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_u = sample + src_width * (abs_src_height + crop_y) + crop_x;
256ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        src_v = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x;
257ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
258ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = I444ToARGB(src_y, src_width,
259ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_u, src_width,
260ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_v, src_width,
261ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
262ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
263ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
264ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
265ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_I411: {
266ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      int quarterwidth = (src_width + 3) / 4;
267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_y = sample + src_width * crop_y + crop_x;
268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_u = sample + src_width * abs_src_height +
269ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          quarterwidth * crop_y + crop_x / 4;
270ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      const uint8* src_v = sample + src_width * abs_src_height +
271ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          quarterwidth * (abs_src_height + crop_y) + crop_x / 4;
272ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = I411ToARGB(src_y, src_width,
273ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_u, quarterwidth,
274ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_v, quarterwidth,
275ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
276ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, inv_crop_height);
277ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
278ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
279ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef HAVE_JPEG
280ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case FOURCC_MJPG:
281ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = MJPGToARGB(sample, sample_size,
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_argb, argb_stride,
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     src_width, abs_src_height, crop_width, inv_crop_height);
284ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    default:
287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = -1;  // unknown fourcc - return failure code.
288ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (need_buf) {
291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (!r) {
292ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      r = ARGBRotate(crop_argb, argb_stride,
2937bc9febe8749e98a3812a0dc4380ceae75c29450Johann                     dest_argb, dest_argb_stride,
294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                     crop_width, abs_crop_height, rotation);
295ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
296ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    free(rotate_buffer);
297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
299ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return r;
300ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
302ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef __cplusplus
303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // extern "C"
304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}  // namespace libyuv
305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
306