1 /*********************************************************************
2 * add and modified some function to avoid crash
3 * Copyright (C) 2014-2015 saki@serenegiant All rights reserved.
4 *********************************************************************/
5 /*********************************************************************
6 * Software License Agreement (BSD License)
8 * Copyright (C) 2014 Robert Xiao
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
21 * * Neither the name of the author nor other contributors may be
22 * used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *********************************************************************/
40 * @defgroup frame Frame processing
42 #include "libuvc/libuvc.h"
43 #include "libuvc/libuvc_internal.h"
47 extern uvc_error_t uvc_ensure_frame_size(uvc_frame_t *frame, size_t need_bytes);
50 struct jpeg_error_mgr super;
54 static void _error_exit(j_common_ptr dinfo) {
55 struct error_mgr *myerr = (struct error_mgr *) dinfo->err;
57 #if (defined(ANDROID) || defined(__ANDROID__))
59 (*dinfo->err->format_message)(dinfo, err_msg);
61 LOGW("err=%s", err_msg);
63 (*dinfo->err->output_message)(dinfo);
66 longjmp(myerr->jmp, 1);
69 /* ISO/IEC 10918-1:1993(E) K.3.3. Default Huffman tables used by MJPEG UVC devices
70 which don't specify a Huffman table in the JPEG stream. */
71 static const unsigned char dc_lumi_len[] = {
72 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
73 static const unsigned char dc_lumi_val[] = {
74 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
76 static const unsigned char dc_chromi_len[] = {
77 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
78 static const unsigned char dc_chromi_val[] = {
79 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
81 static const unsigned char ac_lumi_len[] = {
82 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
83 static const unsigned char ac_lumi_val[] = {
84 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
85 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
86 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
87 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
88 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
89 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
90 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
91 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
92 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
93 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
94 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
95 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
96 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
97 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
98 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
99 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
100 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
101 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
102 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
103 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
106 static const unsigned char ac_chromi_len[] = {
107 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
108 static const unsigned char ac_chromi_val[] = {
109 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
110 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
111 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
112 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
113 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
114 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
115 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
116 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
117 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
118 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
119 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
120 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
121 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
122 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
123 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
124 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
125 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
126 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
127 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
128 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
132 #define COPY_HUFF_TABLE(dinfo,tbl,name) do { \
133 if (dinfo->tbl == NULL) dinfo->tbl = jpeg_alloc_huff_table((j_common_ptr)dinfo); \
134 memcpy(dinfo->tbl->bits, name##_len, sizeof(name##_len)); \
135 memset(dinfo->tbl->huffval, 0, sizeof(dinfo->tbl->huffval)); \
136 memcpy(dinfo->tbl->huffval, name##_val, sizeof(name##_val)); \
139 static inline void insert_huff_tables(j_decompress_ptr dinfo) {
140 COPY_HUFF_TABLE(dinfo, dc_huff_tbl_ptrs[0], dc_lumi);
141 COPY_HUFF_TABLE(dinfo, dc_huff_tbl_ptrs[1], dc_chromi);
142 COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[0], ac_lumi);
143 COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[1], ac_chromi);
146 // XXX added to improve the performance of decoding
147 // maximun reading lines for each call of jpeg_read_scanlines
148 // when defined this macro, it's value should be common factor
149 // of all available frame height.
150 // (1, 2, 4, 5, 6, 8, 10, 12, 20, 40...for 720p&1080p)
151 #define MAX_READLINE 8
154 #define MAX_READLINE 1
158 #define MAX_READLINE 1
161 /** @brief Convert an MJPEG frame to RGB
164 * @param in MJPEG frame
165 * @param out RGB frame
167 uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
168 struct jpeg_decompress_struct dinfo;
169 struct error_mgr jerr;
172 uint8_t *data = out->data;
173 const int out_step = out->step;
175 int num_scanlines, i;
177 unsigned char *buffer[MAX_READLINE];
179 out->actual_bytes = 0; // XXX
180 if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
181 return UVC_ERROR_INVALID_PARAM;
183 if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
184 return UVC_ERROR_NO_MEM;
186 out->width = in->width;
187 out->height = in->height;
188 out->frame_format = UVC_FRAME_FORMAT_RGB;
189 out->step = in->width * 3;
190 out->sequence = in->sequence;
191 out->capture_time = in->capture_time;
192 out->source = in->source;
194 dinfo.err = jpeg_std_error(&jerr.super);
195 jerr.super.error_exit = _error_exit;
197 if (setjmp(jerr.jmp)) {
201 jpeg_create_decompress(&dinfo);
202 jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);
203 jpeg_read_header(&dinfo, TRUE);
205 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
206 /* This frame is missing the Huffman tables: fill in the standard ones */
207 insert_huff_tables(&dinfo);
210 dinfo.out_color_space = JCS_RGB;
211 dinfo.dct_method = JDCT_IFAST;
213 jpeg_start_decompress(&dinfo);
215 if (LIKELY(dinfo.output_height == out->height)) {
216 for (; dinfo.output_scanline < dinfo.output_height ;) {
217 buffer[0] = data + (lines_read) * out_step;
218 for (i = 1; i < MAX_READLINE; i++)
219 buffer[i] = buffer[i-1] + out_step;
220 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
221 lines_read += num_scanlines;
223 out->actual_bytes = in->width * in->height * 3; // XXX
225 jpeg_finish_decompress(&dinfo);
226 jpeg_destroy_decompress(&dinfo);
227 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX
230 jpeg_destroy_decompress(&dinfo);
231 return UVC_ERROR_OTHER+1;
234 /** @brief Convert an MJPEG frame to BGR
237 * @param in MJPEG frame
238 * @param out BGR frame
240 uvc_error_t uvc_mjpeg2bgr(uvc_frame_t *in, uvc_frame_t *out) {
241 struct jpeg_decompress_struct dinfo;
242 struct error_mgr jerr;
245 int num_scanlines, i;
247 unsigned char *buffer[MAX_READLINE];
249 out->actual_bytes = 0; // XXX
250 if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
251 return UVC_ERROR_INVALID_PARAM;
253 if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
254 return UVC_ERROR_NO_MEM;
256 out->width = in->width;
257 out->height = in->height;
258 out->frame_format = UVC_FRAME_FORMAT_BGR;
259 out->step = in->width * 3;
260 out->sequence = in->sequence;
261 out->capture_time = in->capture_time;
262 out->source = in->source;
264 dinfo.err = jpeg_std_error(&jerr.super);
265 jerr.super.error_exit = _error_exit;
267 if (setjmp(jerr.jmp)) {
271 jpeg_create_decompress(&dinfo);
272 jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);
273 jpeg_read_header(&dinfo, TRUE);
275 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
276 /* This frame is missing the Huffman tables: fill in the standard ones */
277 insert_huff_tables(&dinfo);
280 dinfo.out_color_space = JCS_EXT_BGR;
281 dinfo.dct_method = JDCT_IFAST;
283 jpeg_start_decompress(&dinfo);
286 uint8_t *data = out->data;
287 const int out_step = out->step;
289 if (LIKELY(dinfo.output_height == out->height)) {
290 for (; dinfo.output_scanline < dinfo.output_height ;) {
291 buffer[0] = data + (lines_read) * out_step;
292 for (i = 1; i < MAX_READLINE; i++)
293 buffer[i] = buffer[i-1] + out_step;
294 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
295 lines_read += num_scanlines;
297 out->actual_bytes = in->width * in->height * 3; // XXX
299 jpeg_finish_decompress(&dinfo);
300 jpeg_destroy_decompress(&dinfo);
301 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX
304 jpeg_destroy_decompress(&dinfo);
305 return UVC_ERROR_OTHER+1;
308 /** @brief Convert an MJPEG frame to RGB565
311 * @param in MJPEG frame
312 * @param out RGB frame
314 uvc_error_t uvc_mjpeg2rgb565(uvc_frame_t *in, uvc_frame_t *out) {
315 struct jpeg_decompress_struct dinfo;
316 struct error_mgr jerr;
319 int num_scanlines, i;
321 unsigned char *buffer[MAX_READLINE];
323 out->actual_bytes = 0; // XXX
324 if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
325 return UVC_ERROR_INVALID_PARAM;
327 if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0)
328 return UVC_ERROR_NO_MEM;
330 out->width = in->width;
331 out->height = in->height;
332 out->frame_format = UVC_FRAME_FORMAT_RGB565;
333 out->step = in->width * 2;
334 out->sequence = in->sequence;
335 out->capture_time = in->capture_time;
336 out->source = in->source;
338 dinfo.err = jpeg_std_error(&jerr.super);
339 jerr.super.error_exit = _error_exit;
341 if (setjmp(jerr.jmp)) {
345 jpeg_create_decompress(&dinfo);
346 jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);
347 jpeg_read_header(&dinfo, TRUE);
349 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
350 /* This frame is missing the Huffman tables: fill in the standard ones */
351 insert_huff_tables(&dinfo);
354 dinfo.out_color_space = JCS_RGB565;
355 dinfo.dct_method = JDCT_IFAST;
357 jpeg_start_decompress(&dinfo);
360 uint8_t *data = out->data;
361 const int out_step = out->step;
363 if (LIKELY(dinfo.output_height == out->height)) {
364 for (; dinfo.output_scanline < dinfo.output_height ;) {
365 buffer[0] = data + (lines_read) * out_step;
366 for (i = 1; i < MAX_READLINE; i++)
367 buffer[i] = buffer[i-1] + out_step;
368 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
369 lines_read += num_scanlines;
371 out->actual_bytes = in->width * in->height * 2; // XXX
373 jpeg_finish_decompress(&dinfo);
374 jpeg_destroy_decompress(&dinfo);
375 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX
378 jpeg_destroy_decompress(&dinfo);
379 return UVC_ERROR_OTHER+1;
382 /** @brief Convert an MJPEG frame to RGBX
385 * @param in MJPEG frame
386 * @param out RGBX frame
388 uvc_error_t uvc_mjpeg2rgbx(uvc_frame_t *in, uvc_frame_t *out) {
389 struct jpeg_decompress_struct dinfo;
390 struct error_mgr jerr;
393 uint8_t *data = out->data;
394 const int out_step = out->step;
396 int num_scanlines, i;
398 unsigned char *buffer[MAX_READLINE];
400 out->actual_bytes = 0; // XXX
401 if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
402 return UVC_ERROR_INVALID_PARAM;
404 if (uvc_ensure_frame_size(out, in->width * in->height * 4) < 0)
405 return UVC_ERROR_NO_MEM;
407 out->width = in->width;
408 out->height = in->height;
409 out->frame_format = UVC_FRAME_FORMAT_RGBX; // XXX
410 out->step = in->width * 4;
411 out->sequence = in->sequence;
412 out->capture_time = in->capture_time;
413 out->source = in->source;
415 dinfo.err = jpeg_std_error(&jerr.super);
416 jerr.super.error_exit = _error_exit;
418 if (setjmp(jerr.jmp)) {
422 jpeg_create_decompress(&dinfo);
423 jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); // XXX
424 jpeg_read_header(&dinfo, TRUE);
426 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
427 /* This frame is missing the Huffman tables: fill in the standard ones */
428 insert_huff_tables(&dinfo);
431 dinfo.out_color_space = JCS_EXT_RGBA;
432 dinfo.dct_method = JDCT_IFAST;
434 jpeg_start_decompress(&dinfo);
436 if (LIKELY(dinfo.output_height == out->height)) {
437 for (; dinfo.output_scanline < dinfo.output_height ;) {
438 buffer[0] = data + (lines_read) * out_step;
439 for (i = 1; i < MAX_READLINE; i++)
440 buffer[i] = buffer[i-1] + out_step;
441 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
442 lines_read += num_scanlines;
444 out->actual_bytes = in->width * in->height * 4; // XXX
446 jpeg_finish_decompress(&dinfo);
447 jpeg_destroy_decompress(&dinfo);
448 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER; // XXX
451 jpeg_destroy_decompress(&dinfo);
452 return UVC_ERROR_OTHER+1;
455 static inline unsigned char sat(int i) {
456 return (unsigned char) (i >= 255 ? 255 : (i < 0 ? 0 : i));
459 #define YCbCr_YUYV_2(YCbCr, yuyv) \
461 *(yuyv++) = *(YCbCr+0); \
462 *(yuyv++) = (*(YCbCr+1) + *(YCbCr+4)) >> 1; \
463 *(yuyv++) = *(YCbCr+3); \
464 *(yuyv++) = (*(YCbCr+2) + *(YCbCr+5)) >> 1; \
467 uvc_error_t uvc_mjpeg2yuyv(uvc_frame_t *in, uvc_frame_t *out) {
469 out->actual_bytes = 0; // XXX
470 if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
471 return UVC_ERROR_INVALID_PARAM;
473 if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0)
474 return UVC_ERROR_NO_MEM;
476 size_t lines_read = 0;
479 register uint8_t *yuyv, *ycbcr;
481 out->width = in->width;
482 out->height = in->height;
483 out->frame_format = UVC_FRAME_FORMAT_YUYV;
484 out->step = in->width * 2;
485 out->sequence = in->sequence;
486 out->capture_time = in->capture_time;
487 out->source = in->source;
489 struct jpeg_decompress_struct dinfo;
490 struct error_mgr jerr;
491 dinfo.err = jpeg_std_error(&jerr.super);
492 jerr.super.error_exit = _error_exit;
494 if (setjmp(jerr.jmp)) {
498 jpeg_create_decompress(&dinfo);
499 jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/); // XXX
500 jpeg_read_header(&dinfo, TRUE);
502 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
503 /* This frame is missing the Huffman tables: fill in the standard ones */
504 insert_huff_tables(&dinfo);
507 dinfo.out_color_space = JCS_YCbCr;
508 dinfo.dct_method = JDCT_IFAST;
510 // start decompressor
511 jpeg_start_decompress(&dinfo);
513 // these dinfo.xxx valiables are only valid after jpeg_start_decompress
514 const int row_stride = dinfo.output_width * dinfo.output_components;
517 register JSAMPARRAY buffer = (*dinfo.mem->alloc_sarray)
518 ((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, MAX_READLINE);
521 uint8_t *data = out->data;
522 const int out_step = out->step;
524 if (LIKELY(dinfo.output_height == out->height)) {
525 for (; dinfo.output_scanline < dinfo.output_height ;) {
526 // convert lines of mjpeg data to YCbCr
527 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
528 // convert YCbCr to yuyv(YUV422)
529 for (j = 0; j < num_scanlines; j++) {
530 yuyv = data + (lines_read + j) * out_step;
532 for (i = 0; i < row_stride; i += 24) { // step by YCbCr x 8 pixels = 3 x 8 bytes
533 YCbCr_YUYV_2(ycbcr + i, yuyv);
534 YCbCr_YUYV_2(ycbcr + i + 6, yuyv);
535 YCbCr_YUYV_2(ycbcr + i + 12, yuyv);
536 YCbCr_YUYV_2(ycbcr + i + 18, yuyv);
539 lines_read += num_scanlines;
541 out->actual_bytes = in->width * in->height * 2; // XXX
544 jpeg_finish_decompress(&dinfo);
545 jpeg_destroy_decompress(&dinfo);
546 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER;
549 jpeg_destroy_decompress(&dinfo);
550 return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER+1;