1 /*****************************************************************************
2 * jpeg.c: jpeg decoder module making use of libjpeg.
3 *****************************************************************************
4 * Copyright (C) 2013 VLC authors and VideoLAN
6 * Authors: Maxim Bublis <b@codemonkey.ru>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_codec.h>
34 * jpeg decoder descriptor
38 /* libjpeg error handler manager */
39 struct jpeg_error_mgr err;
41 /* setjmp buffer for internal libjpeg error handling */
42 jmp_buf setjmp_buffer;
49 static int OpenDecoder(vlc_object_t *);
50 static void CloseDecoder(vlc_object_t *);
52 static picture_t *DecodeBlock(decoder_t *, block_t **);
58 set_category(CAT_INPUT)
59 set_subcategory(SUBCAT_INPUT_VCODEC)
60 set_description(N_("JPEG image decoder"))
61 set_capability("decoder", 1000)
62 set_callbacks(OpenDecoder, CloseDecoder)
67 * Probe the decoder and return score
69 static int OpenDecoder(vlc_object_t *p_this)
71 decoder_t *p_dec = (decoder_t *)p_this;
73 if (p_dec->fmt_in.i_codec != VLC_CODEC_JPEG)
78 /* Allocate the memory needed to store the decoder's structure */
79 p_dec->p_sys = malloc(sizeof(decoder_sys_t));
80 if (p_dec->p_sys == NULL)
85 p_dec->p_sys->p_dec = p_dec;
87 /* Set output properties */
88 p_dec->fmt_out.i_cat = VIDEO_ES;
91 p_dec->pf_decode_video = DecodeBlock;
97 * Exit error handler for libjpeg
99 static void user_error_exit(j_common_ptr p_jpeg)
101 decoder_sys_t *p_sys = (decoder_sys_t *)p_jpeg->err;
102 p_sys->b_error = true;
103 p_sys->err.output_message(p_jpeg);
104 longjmp(p_sys->setjmp_buffer, 1);
108 * Emit message error handler for libjpeg
110 static void user_error_message(j_common_ptr p_jpeg)
112 char error_msg[JMSG_LENGTH_MAX];
114 decoder_sys_t *p_sys = (decoder_sys_t *)p_jpeg->err;
115 p_sys->err.format_message(p_jpeg, error_msg);
116 msg_Err(p_sys->p_dec, "%s", error_msg);
120 * This function must be fed with a complete compressed frame.
122 static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
124 decoder_sys_t *p_sys = p_dec->p_sys;
126 picture_t *p_pic = 0;
128 struct jpeg_decompress_struct p_jpeg;
129 JSAMPARRAY p_row_pointers = NULL;
131 if (!pp_block || !*pp_block)
137 p_sys->b_error = false;
139 if (p_block->i_flags & BLOCK_FLAG_DISCONTINUITY)
141 block_Release(p_block);
146 p_jpeg.err = jpeg_std_error(&p_sys->err);
147 p_sys->err.error_exit = user_error_exit;
148 p_sys->err.output_message = user_error_message;
150 /* libjpeg longjmp's there in case of error */
151 if (setjmp(p_sys->setjmp_buffer))
156 jpeg_create_decompress(&p_jpeg);
162 jpeg_mem_src(&p_jpeg, p_block->p_buffer, p_block->i_buffer);
168 jpeg_read_header(&p_jpeg, TRUE);
174 p_jpeg.out_color_space = JCS_RGB;
176 jpeg_start_decompress(&p_jpeg);
182 /* Set output properties */
183 p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
184 p_dec->fmt_out.video.i_width = p_jpeg.output_width;
185 p_dec->fmt_out.video.i_height = p_jpeg.output_height;
186 p_dec->fmt_out.video.i_sar_num = 1;
187 p_dec->fmt_out.video.i_sar_den = 1;
188 p_dec->fmt_out.video.i_rmask = 0x000000ff;
189 p_dec->fmt_out.video.i_gmask = 0x0000ff00;
190 p_dec->fmt_out.video.i_bmask = 0x00ff0000;
192 /* Get a new picture */
193 p_pic = decoder_NewPicture(p_dec);
200 p_row_pointers = malloc(sizeof(JSAMPROW) * p_jpeg.output_height);
205 for (int i = 0; i < (int)p_jpeg.output_height; i++) {
206 p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i;
209 while (p_jpeg.output_scanline < p_jpeg.output_height)
211 jpeg_read_scanlines(&p_jpeg, p_row_pointers + p_jpeg.output_scanline,
212 p_jpeg.output_height - p_jpeg.output_scanline);
219 jpeg_finish_decompress(&p_jpeg);
220 jpeg_destroy_decompress(&p_jpeg);
221 free(p_row_pointers);
223 p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;
225 block_Release(p_block);
232 jpeg_destroy_decompress(&p_jpeg);
233 free(p_row_pointers);
235 block_Release(p_block);
242 * jpeg decoder destruction
244 static void CloseDecoder(vlc_object_t *p_this)
246 decoder_t *p_dec = (decoder_t *)p_this;
247 decoder_sys_t *p_sys = p_dec->p_sys;