1 /*********************************************************************
2 * Software License Agreement (BSD License)
4 * Copyright (C) 2014 Robert Xiao
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the author nor other contributors may be
18 * used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
36 * @defgroup frame Frame processing
38 #include "libuvc/libuvc.h"
39 #include "libuvc/libuvc_internal.h"
43 extern uvc_error_t uvc_ensure_frame_size(uvc_frame_t *frame, size_t need_bytes);
46 struct jpeg_error_mgr super;
50 static void _error_exit(j_common_ptr dinfo) {
51 struct error_mgr *myerr = (struct error_mgr *)dinfo->err;
52 (*dinfo->err->output_message)(dinfo);
53 longjmp(myerr->jmp, 1);
56 /* ISO/IEC 10918-1:1993(E) K.3.3. Default Huffman tables used by MJPEG UVC devices
57 which don't specify a Huffman table in the JPEG stream. */
58 static const unsigned char dc_lumi_len[] =
59 {0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0};
60 static const unsigned char dc_lumi_val[] =
61 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
63 static const unsigned char dc_chromi_len[] =
64 {0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
65 static const unsigned char dc_chromi_val[] =
66 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
68 static const unsigned char ac_lumi_len[] =
69 {0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d};
70 static const unsigned char ac_lumi_val[] =
71 {0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21,
72 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71,
73 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
74 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,
75 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
76 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37,
77 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
78 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
79 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
80 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
81 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
82 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
83 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
84 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
85 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
86 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
87 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
88 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
89 static const unsigned char ac_chromi_len[] =
90 {0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77};
91 static const unsigned char ac_chromi_val[] =
92 {0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31,
93 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
94 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
95 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
96 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18,
97 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36,
98 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
99 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
100 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
101 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
102 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
103 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
104 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
105 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
106 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
107 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
108 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
109 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa};
111 #define COPY_HUFF_TABLE(dinfo,tbl,name) do { \
112 if(dinfo->tbl == NULL) dinfo->tbl = jpeg_alloc_huff_table((j_common_ptr)dinfo); \
113 memcpy(dinfo->tbl->bits, name##_len, sizeof(name##_len)); \
114 memset(dinfo->tbl->huffval, 0, sizeof(dinfo->tbl->huffval)); \
115 memcpy(dinfo->tbl->huffval, name##_val, sizeof(name##_val)); \
118 static void insert_huff_tables(j_decompress_ptr dinfo) {
119 COPY_HUFF_TABLE(dinfo, dc_huff_tbl_ptrs[0], dc_lumi);
120 COPY_HUFF_TABLE(dinfo, dc_huff_tbl_ptrs[1], dc_chromi);
121 COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[0], ac_lumi);
122 COPY_HUFF_TABLE(dinfo, ac_huff_tbl_ptrs[1], ac_chromi);
125 /** @brief Convert an MJPEG frame to RGB
128 * @param in MJPEG frame
129 * @param out RGB frame
131 uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
132 struct jpeg_decompress_struct dinfo;
133 struct error_mgr jerr;
136 if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
137 return UVC_ERROR_INVALID_PARAM;
139 if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
140 return UVC_ERROR_NO_MEM;
142 out->width = in->width;
143 out->height = in->height;
144 out->frame_format = UVC_FRAME_FORMAT_RGB;
145 out->step = in->width * 3;
146 out->sequence = in->sequence;
147 out->capture_time = in->capture_time;
148 out->source = in->source;
150 dinfo.err = jpeg_std_error(&jerr.super);
151 jerr.super.error_exit = _error_exit;
153 if (setjmp(jerr.jmp)) {
157 jpeg_create_decompress(&dinfo);
158 jpeg_mem_src(&dinfo, in->data, in->data_bytes);
159 jpeg_read_header(&dinfo, TRUE);
161 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
162 /* This frame is missing the Huffman tables: fill in the standard ones */
163 insert_huff_tables(&dinfo);
166 dinfo.out_color_space = JCS_RGB;
167 dinfo.dct_method = JDCT_IFAST;
169 jpeg_start_decompress(&dinfo);
172 while (dinfo.output_scanline < dinfo.output_height) {
173 unsigned char *buffer[1] = { out->data + lines_read * out->step };
176 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, 1);
177 lines_read += num_scanlines;
180 jpeg_finish_decompress(&dinfo);
181 jpeg_destroy_decompress(&dinfo);
185 jpeg_destroy_decompress(&dinfo);
186 return UVC_ERROR_OTHER;