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
11492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#include "libyuv/convert.h"
12492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
13492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef HAVE_JPEG
14492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#include "libyuv/mjpeg_decoder.h"
15492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
16492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
17492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef __cplusplus
18492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comnamespace libyuv {
19492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comextern "C" {
20492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
21492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
22492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef HAVE_JPEG
23492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstruct I420Buffers {
24492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* y;
25492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int y_stride;
26492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* u;
27492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int u_stride;
28492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  uint8* v;
29492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int v_stride;
30492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int w;
31492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  int h;
32492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com};
33492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
34492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstatic void JpegCopyI420(void* opaque,
35492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         const uint8* const* data,
36492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         const int* strides,
37492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                         int rows) {
38a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  I420Buffers* dest = (I420Buffers*)(opaque);
39492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  I420Copy(data[0], strides[0],
40492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           data[1], strides[1],
41492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           data[2], strides[2],
42492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           dest->y, dest->y_stride,
43492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           dest->u, dest->u_stride,
44492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           dest->v, dest->v_stride,
45492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com           dest->w, rows);
46492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->y += rows * dest->y_stride;
47492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->u += ((rows + 1) >> 1) * dest->u_stride;
48492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->v += ((rows + 1) >> 1) * dest->v_stride;
49492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->h -= rows;
50492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
51492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
52492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstatic void JpegI422ToI420(void* opaque,
53492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const uint8* const* data,
54492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const int* strides,
55492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           int rows) {
56a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  I420Buffers* dest = (I420Buffers*)(opaque);
57492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  I422ToI420(data[0], strides[0],
58492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[1], strides[1],
59492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[2], strides[2],
60492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->y, dest->y_stride,
61492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->u, dest->u_stride,
62492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->v, dest->v_stride,
63492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->w, rows);
64492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->y += rows * dest->y_stride;
65492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->u += ((rows + 1) >> 1) * dest->u_stride;
66492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->v += ((rows + 1) >> 1) * dest->v_stride;
67492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->h -= rows;
68492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
69492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
70492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstatic void JpegI444ToI420(void* opaque,
71492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const uint8* const* data,
72492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const int* strides,
73492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           int rows) {
74a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  I420Buffers* dest = (I420Buffers*)(opaque);
75492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  I444ToI420(data[0], strides[0],
76492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[1], strides[1],
77492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[2], strides[2],
78492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->y, dest->y_stride,
79492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->u, dest->u_stride,
80492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->v, dest->v_stride,
81492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->w, rows);
82492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->y += rows * dest->y_stride;
83492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->u += ((rows + 1) >> 1) * dest->u_stride;
84492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->v += ((rows + 1) >> 1) * dest->v_stride;
85492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->h -= rows;
86492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
87492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
88492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstatic void JpegI411ToI420(void* opaque,
89492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const uint8* const* data,
90492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const int* strides,
91492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           int rows) {
92a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  I420Buffers* dest = (I420Buffers*)(opaque);
93492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  I411ToI420(data[0], strides[0],
94492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[1], strides[1],
95492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             data[2], strides[2],
96492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->y, dest->y_stride,
97492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->u, dest->u_stride,
98492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->v, dest->v_stride,
99492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->w, rows);
100492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->y += rows * dest->y_stride;
101492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->u += ((rows + 1) >> 1) * dest->u_stride;
102492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->v += ((rows + 1) >> 1) * dest->v_stride;
103492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->h -= rows;
104492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
105492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
106492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comstatic void JpegI400ToI420(void* opaque,
107492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const uint8* const* data,
108492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           const int* strides,
109492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                           int rows) {
110a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  I420Buffers* dest = (I420Buffers*)(opaque);
111492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  I400ToI420(data[0], strides[0],
112492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->y, dest->y_stride,
113492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->u, dest->u_stride,
114492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->v, dest->v_stride,
115492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             dest->w, rows);
116492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->y += rows * dest->y_stride;
117492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->u += ((rows + 1) >> 1) * dest->u_stride;
118492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->v += ((rows + 1) >> 1) * dest->v_stride;
119492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  dest->h -= rows;
120492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
121492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
122492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// Query size of MJPG in pixels.
123492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comLIBYUV_API
124492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comint MJPGSize(const uint8* sample, size_t sample_size,
125492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com             int* width, int* height) {
126492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  MJpegDecoder mjpeg_decoder;
127db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com  LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
128492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (ret) {
129492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    *width = mjpeg_decoder.GetWidth();
130492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    *height = mjpeg_decoder.GetHeight();
131492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
132492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  mjpeg_decoder.UnloadFrame();
133492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  return ret ? 0 : -1;  // -1 for runtime failure.
134492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
135492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
136492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// MJPG (Motion JPeg) to I420
137492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com// TODO(fbarchard): review w and h requirement. dw and dh may be enough.
138492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comLIBYUV_API
139492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.comint MJPGToI420(const uint8* sample,
140492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               size_t sample_size,
141492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               uint8* y, int y_stride,
142492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               uint8* u, int u_stride,
143492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               uint8* v, int v_stride,
144492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               int w, int h,
145492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               int dw, int dh) {
146492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (sample_size == kUnknownDataSize) {
147492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // ERROR: MJPEG frame size unknown
148492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    return -1;
149492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
150492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
151492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  // TODO(fbarchard): Port MJpeg to C.
152492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  MJpegDecoder mjpeg_decoder;
153db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com  LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
154492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (ret && (mjpeg_decoder.GetWidth() != w ||
155492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com              mjpeg_decoder.GetHeight() != h)) {
156492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // ERROR: MJPEG frame has unexpected dimensions
157492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    mjpeg_decoder.UnloadFrame();
158492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    return 1;  // runtime failure
159492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
160492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  if (ret) {
161492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    I420Buffers bufs = { y, y_stride, u, u_stride, v, v_stride, dw, dh };
162492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // YUV420
163492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    if (mjpeg_decoder.GetColorSpace() ==
164492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com            MJpegDecoder::kColorSpaceYCbCr &&
165492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetNumComponents() == 3 &&
166492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(0) == 2 &&
167492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
168492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(1) == 1 &&
169492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
170492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(2) == 1 &&
171492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(2) == 1) {
172492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegCopyI420, &bufs, dw, dh);
173492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // YUV422
174492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
175492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
176492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
177492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
178492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
179492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
180492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
181492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
182492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
183492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI422ToI420, &bufs, dw, dh);
184492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // YUV444
185492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
186492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
187492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
188492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
189492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 1 &&
190492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
191492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
192492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
193492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
194492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI444ToI420, &bufs, dw, dh);
195492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // YUV411
196492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
197492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
198492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
199492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
200492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 4 &&
201492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
202492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
203492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
204492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
205492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI411ToI420, &bufs, dw, dh);
206492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    // YUV400
207492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
208492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com                   MJpegDecoder::kColorSpaceGrayscale &&
209492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 1 &&
210492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
211492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 1) {
212492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI400ToI420, &bufs, dw, dh);
213492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    } else {
214492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      // TODO(fbarchard): Implement conversion for any other colorspace/sample
215492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      // factors that occur in practice. 411 is supported by libjpeg
216492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      // ERROR: Unable to convert MJPEG frame because format is not supported
217492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      mjpeg_decoder.UnloadFrame();
218492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com      return 1;
219492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com    }
220492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com  }
22116ea9c816b5468f7651336b9ead21041fa3e5a6efbarchard@google.com  return ret ? 0 : 1;
222492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}
2238c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2248c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com#ifdef HAVE_JPEG
2258c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstruct ARGBBuffers {
2268c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  uint8* argb;
2278c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  int argb_stride;
2288c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  int w;
2298c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  int h;
2308c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com};
2318c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2328c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstatic void JpegI420ToARGB(void* opaque,
2338c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                         const uint8* const* data,
2348c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                         const int* strides,
2358c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                         int rows) {
236a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  ARGBBuffers* dest = (ARGBBuffers*)(opaque);
2378c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  I420ToARGB(data[0], strides[0],
2388c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[1], strides[1],
2398c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[2], strides[2],
2408c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->argb, dest->argb_stride,
2418c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->w, rows);
2428c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->argb += rows * dest->argb_stride;
2438c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->h -= rows;
2448c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
2458c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2468c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstatic void JpegI422ToARGB(void* opaque,
2478c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const uint8* const* data,
2488c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const int* strides,
2498c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           int rows) {
250a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  ARGBBuffers* dest = (ARGBBuffers*)(opaque);
2518c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  I422ToARGB(data[0], strides[0],
2528c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[1], strides[1],
2538c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[2], strides[2],
2548c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->argb, dest->argb_stride,
2558c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->w, rows);
2568c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->argb += rows * dest->argb_stride;
2578c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->h -= rows;
2588c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
2598c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2608c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstatic void JpegI444ToARGB(void* opaque,
2618c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const uint8* const* data,
2628c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const int* strides,
2638c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           int rows) {
264a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  ARGBBuffers* dest = (ARGBBuffers*)(opaque);
2658c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  I444ToARGB(data[0], strides[0],
2668c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[1], strides[1],
2678c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[2], strides[2],
2688c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->argb, dest->argb_stride,
2698c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->w, rows);
2708c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->argb += rows * dest->argb_stride;
2718c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->h -= rows;
2728c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
2738c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2748c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstatic void JpegI411ToARGB(void* opaque,
2758c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const uint8* const* data,
2768c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const int* strides,
2778c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           int rows) {
278a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  ARGBBuffers* dest = (ARGBBuffers*)(opaque);
2798c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  I411ToARGB(data[0], strides[0],
2808c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[1], strides[1],
2818c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             data[2], strides[2],
2828c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->argb, dest->argb_stride,
2838c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->w, rows);
2848c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->argb += rows * dest->argb_stride;
2858c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->h -= rows;
2868c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
2878c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
2888c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comstatic void JpegI400ToARGB(void* opaque,
2898c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const uint8* const* data,
2908c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           const int* strides,
2918c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                           int rows) {
292a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com  ARGBBuffers* dest = (ARGBBuffers*)(opaque);
2938c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  I400ToARGB(data[0], strides[0],
2948c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->argb, dest->argb_stride,
2958c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com             dest->w, rows);
2968c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->argb += rows * dest->argb_stride;
2978c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  dest->h -= rows;
2988c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
2998c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
3008c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com// MJPG (Motion JPeg) to ARGB
3018c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com// TODO(fbarchard): review w and h requirement. dw and dh may be enough.
3028c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comLIBYUV_API
3038c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.comint MJPGToARGB(const uint8* sample,
3048c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               size_t sample_size,
3058c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               uint8* argb, int argb_stride,
3068c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               int w, int h,
3078c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               int dw, int dh) {
3088c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  if (sample_size == kUnknownDataSize) {
3098c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // ERROR: MJPEG frame size unknown
3108c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    return -1;
3118c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  }
3128c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
3138c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  // TODO(fbarchard): Port MJpeg to C.
3148c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  MJpegDecoder mjpeg_decoder;
315db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com  LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
3168c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  if (ret && (mjpeg_decoder.GetWidth() != w ||
3178c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com              mjpeg_decoder.GetHeight() != h)) {
3188c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // ERROR: MJPEG frame has unexpected dimensions
3198c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    mjpeg_decoder.UnloadFrame();
3208c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    return 1;  // runtime failure
3218c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  }
3228c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  if (ret) {
3238c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    ARGBBuffers bufs = { argb, argb_stride, dw, dh };
3248c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // YUV420
3258c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    if (mjpeg_decoder.GetColorSpace() ==
3268c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com            MJpegDecoder::kColorSpaceYCbCr &&
3278c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetNumComponents() == 3 &&
3288c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(0) == 2 &&
3298c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
3308c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(1) == 1 &&
3318c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
3328c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetVertSampFactor(2) == 1 &&
3338c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com        mjpeg_decoder.GetHorizSampFactor(2) == 1) {
3348c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI420ToARGB, &bufs, dw, dh);
3358c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // YUV422
3368c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
3378c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
3388c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
3398c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
3408c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
3418c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
3428c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
3438c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
3448c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
3458c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI422ToARGB, &bufs, dw, dh);
3468c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // YUV444
3478c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
3488c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
3498c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
3508c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
3518c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 1 &&
3528c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
3538c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
3548c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
3558c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
3568c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI444ToARGB, &bufs, dw, dh);
3578c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // YUV411
3588c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
3598c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                   MJpegDecoder::kColorSpaceYCbCr &&
3608c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 3 &&
3618c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
3628c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 4 &&
3638c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(1) == 1 &&
3648c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
3658c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(2) == 1 &&
3668c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(2) == 1) {
3678c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI411ToARGB, &bufs, dw, dh);
3688c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    // YUV400
3698c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    } else if (mjpeg_decoder.GetColorSpace() ==
3708c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com                   MJpegDecoder::kColorSpaceGrayscale &&
3718c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetNumComponents() == 1 &&
3728c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetVertSampFactor(0) == 1 &&
3738c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com               mjpeg_decoder.GetHorizSampFactor(0) == 1) {
3748c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      ret = mjpeg_decoder.DecodeToCallback(&JpegI400ToARGB, &bufs, dw, dh);
3758c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    } else {
3768c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      // TODO(fbarchard): Implement conversion for any other colorspace/sample
3778c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      // factors that occur in practice. 411 is supported by libjpeg
3788c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      // ERROR: Unable to convert MJPEG frame because format is not supported
3798c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      mjpeg_decoder.UnloadFrame();
3808c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com      return 1;
3818c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com    }
3828c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com  }
38316ea9c816b5468f7651336b9ead21041fa3e5a6efbarchard@google.com  return ret ? 0 : 1;
3848c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com}
3858c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com#endif
3868c8cf8d70718f9ac0647a2d0fcbd2b19f5b366e1fbarchard@google.com
387492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
388492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com
389492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#ifdef __cplusplus
390492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}  // extern "C"
391492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com}  // namespace libyuv
392492768cbca51a0ea8a00faaf572fa02b1d6b1934fbarchard@google.com#endif
393