1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (C) 2014 Robert Xiao
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
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.
20 *
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 *********************************************************************/
34
35 /**
36 * @defgroup frame Frame processing
37 */
38 #include "libuvc/libuvc.h"
39 #include "libuvc/libuvc_internal.h"
40 #include <jpeglib.h>
41 #include <setjmp.h>
42
43 extern uvc_error_t uvc_ensure_frame_size(uvc_frame_t *frame, size_t need_bytes);
44
45 struct error_mgr {
46 struct jpeg_error_mgr super;
47 jmp_buf jmp;
48 };
49
_error_exit(j_common_ptr dinfo)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);
54 }
55
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};
62
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};
67
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};
110
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)); \
116 } while(0)
117
insert_huff_tables(j_decompress_ptr dinfo)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);
123 }
124
uvc_mjpeg_convert(uvc_frame_t * in,uvc_frame_t * out)125 static uvc_error_t uvc_mjpeg_convert(uvc_frame_t *in, uvc_frame_t *out) {
126 struct jpeg_decompress_struct dinfo;
127 struct error_mgr jerr;
128 size_t lines_read;
129 dinfo.err = jpeg_std_error(&jerr.super);
130 jerr.super.error_exit = _error_exit;
131
132 if (setjmp(jerr.jmp)) {
133 goto fail;
134 }
135
136 jpeg_create_decompress(&dinfo);
137 jpeg_mem_src(&dinfo, in->data, in->data_bytes);
138 jpeg_read_header(&dinfo, TRUE);
139
140 if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
141 /* This frame is missing the Huffman tables: fill in the standard ones */
142 insert_huff_tables(&dinfo);
143 }
144
145 if (out->frame_format == UVC_FRAME_FORMAT_RGB)
146 dinfo.out_color_space = JCS_RGB;
147 else if (out->frame_format == UVC_FRAME_FORMAT_GRAY8)
148 dinfo.out_color_space = JCS_GRAYSCALE;
149 else
150 goto fail;
151
152 dinfo.dct_method = JDCT_IFAST;
153
154 jpeg_start_decompress(&dinfo);
155
156 lines_read = 0;
157 while (dinfo.output_scanline < dinfo.output_height) {
158 unsigned char *buffer[1] = {( unsigned char*) out->data + lines_read * out->step };
159 int num_scanlines;
160
161 num_scanlines = jpeg_read_scanlines(&dinfo, buffer, 1);
162 lines_read += num_scanlines;
163 }
164
165 jpeg_finish_decompress(&dinfo);
166 jpeg_destroy_decompress(&dinfo);
167 return 0;
168
169 fail:
170 jpeg_destroy_decompress(&dinfo);
171 return UVC_ERROR_OTHER;
172 }
173
174 /** @brief Convert an MJPEG frame to RGB
175 * @ingroup frame
176 *
177 * @param in MJPEG frame
178 * @param out RGB frame
179 */
uvc_mjpeg2rgb(uvc_frame_t * in,uvc_frame_t * out)180 uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
181 if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
182 return UVC_ERROR_INVALID_PARAM;
183
184 if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
185 return UVC_ERROR_NO_MEM;
186
187 out->width = in->width;
188 out->height = in->height;
189 out->frame_format = UVC_FRAME_FORMAT_RGB;
190 out->step = in->width * 3;
191 out->sequence = in->sequence;
192 out->capture_time = in->capture_time;
193 out->capture_time_finished = in->capture_time_finished;
194 out->source = in->source;
195
196 return uvc_mjpeg_convert(in, out);
197 }
198
199 /** @brief Convert an MJPEG frame to GRAY8
200 * @ingroup frame
201 *
202 * @param in MJPEG frame
203 * @param out GRAY8 frame
204 */
uvc_mjpeg2gray(uvc_frame_t * in,uvc_frame_t * out)205 uvc_error_t uvc_mjpeg2gray(uvc_frame_t *in, uvc_frame_t *out) {
206 if (in->frame_format != UVC_FRAME_FORMAT_MJPEG)
207 return UVC_ERROR_INVALID_PARAM;
208
209 if (uvc_ensure_frame_size(out, in->width * in->height) < 0)
210 return UVC_ERROR_NO_MEM;
211
212 out->width = in->width;
213 out->height = in->height;
214 out->frame_format = UVC_FRAME_FORMAT_GRAY8;
215 out->step = in->width;
216 out->sequence = in->sequence;
217 out->capture_time = in->capture_time;
218 out->capture_time_finished = in->capture_time_finished;
219 out->source = in->source;
220
221 return uvc_mjpeg_convert(in, out);
222 }
223