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