vlc | branch: master | Maxim Bublis <[email protected]> | Thu Dec 19 10:45:55 2013 +0000| [6a06a82aa27617efb5a24d34680f8d823585d4cd] | committer: Jean-Baptiste Kempf
codec: implemented libjpeg module Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6a06a82aa27617efb5a24d34680f8d823585d4cd --- configure.ac | 11 ++ modules/codec/Makefile.am | 6 ++ modules/codec/jpeg.c | 250 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+) diff --git a/configure.ac b/configure.ac index 08fb0eb..d60eae3 100644 --- a/configure.ac +++ b/configure.ac @@ -2694,6 +2694,17 @@ AC_CHECK_HEADERS(png.h, [ ]) dnl +dnl JPEG decoder module +dnl +AC_ARG_ENABLE(jpeg, + [ --enable-jpeg JPEG support (default enabled)]) +AS_IF([test "${enable_jpeg}" != "no"], [ +AC_CHECK_HEADERS(jpeglib.h, [ + VLC_ADD_PLUGIN([jpeg]) + ]) +]) + +dnl dnl H262 encoder plugin (lib262) dnl AC_ARG_ENABLE(x262, diff --git a/modules/codec/Makefile.am b/modules/codec/Makefile.am index 05a0b00..9673d04 100644 --- a/modules/codec/Makefile.am +++ b/modules/codec/Makefile.am @@ -103,6 +103,12 @@ libpng_plugin_la_LIBADD = -lpng -lz $(LIBM) EXTRA_LTLIBRARIES += libpng_plugin.la codec_LTLIBRARIES += $(LTLIBpng) +libjpeg_plugin_la_SOURCES = codec/jpeg.c +libjpeg_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)' +libjpeg_plugin_la_LIBADD = -ljpeg +EXTRA_LTLIBRARIES += libjpeg_plugin.la +codec_LTLIBRARIES += $(LTLIBjpeg) + libsdl_image_plugin_la_SOURCES = codec/sdl_image.c libsdl_image_plugin_la_CFLAGS = $(AM_CFLAGS) $(SDL_IMAGE_CFLAGS) libsdl_image_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)' diff --git a/modules/codec/jpeg.c b/modules/codec/jpeg.c new file mode 100644 index 0000000..d65ebed --- /dev/null +++ b/modules/codec/jpeg.c @@ -0,0 +1,250 @@ +/***************************************************************************** + * jpeg.c: jpeg decoder module making use of libjpeg. + ***************************************************************************** + * Copyright (C) 2013 VLC authors and VideoLAN + * + * Authors: Maxim Bublis <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_plugin.h> +#include <vlc_codec.h> +#include <jpeglib.h> +#include <setjmp.h> + +/* + * jpeg decoder descriptor + */ +struct decoder_sys_t +{ + /* libjpeg error handler manager */ + struct jpeg_error_mgr err; + + /* setjmp buffer for internal libjpeg error handling */ + jmp_buf setjmp_buffer; + + decoder_t *p_dec; + + bool b_error; +}; + +static int OpenDecoder(vlc_object_t *); +static void CloseDecoder(vlc_object_t *); + +static picture_t *DecodeBlock(decoder_t *, block_t **); + +/* + * Module descriptor + */ +vlc_module_begin() + set_category(CAT_INPUT) + set_subcategory(SUBCAT_INPUT_VCODEC) + set_description(N_("JPEG image decoder")) + set_capability("decoder", 1000) + set_callbacks(OpenDecoder, CloseDecoder) + add_shortcut("jpeg") +vlc_module_end() + +/* + * Probe the decoder and return score + */ +static int OpenDecoder(vlc_object_t *p_this) +{ + decoder_t *p_dec = (decoder_t *)p_this; + + if (p_dec->fmt_in.i_codec != VLC_CODEC_JPEG) + { + return VLC_EGENERIC; + } + + /* Allocate the memory needed to store the decoder's structure */ + p_dec->p_sys = malloc(sizeof(decoder_sys_t)); + if (p_dec->p_sys == NULL) + { + return VLC_ENOMEM; + } + + p_dec->p_sys->p_dec = p_dec; + + /* Set output properties */ + p_dec->fmt_out.i_cat = VIDEO_ES; + + /* Set callbacks */ + p_dec->pf_decode_video = DecodeBlock; + + return VLC_SUCCESS; +} + +/* + * Exit error handler for libjpeg + */ +static void user_error_exit(j_common_ptr p_jpeg) +{ + decoder_sys_t *p_sys = (decoder_sys_t *)p_jpeg->err; + p_sys->b_error = true; + p_sys->err.output_message(p_jpeg); + longjmp(p_sys->setjmp_buffer, 1); +} + +/* + * Emit message error handler for libjpeg + */ +static void user_error_message(j_common_ptr p_jpeg) +{ + char error_msg[JMSG_LENGTH_MAX]; + + decoder_sys_t *p_sys = (decoder_sys_t *)p_jpeg->err; + p_sys->err.format_message(p_jpeg, error_msg); + msg_Err(p_sys->p_dec, "%s", error_msg); +} + +/* + * This function must be fed with a complete compressed frame. + */ +static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_block; + picture_t *p_pic = 0; + + struct jpeg_decompress_struct p_jpeg; + JSAMPARRAY p_row_pointers = NULL; + + if (!pp_block || !*pp_block) + { + return NULL; + } + + p_block = *pp_block; + p_sys->b_error = false; + + if (p_block->i_flags & BLOCK_FLAG_DISCONTINUITY) + { + block_Release(p_block); + *pp_block = NULL; + return NULL; + } + + p_jpeg.err = jpeg_std_error(&p_sys->err); + p_sys->err.error_exit = user_error_exit; + p_sys->err.output_message = user_error_message; + + /* libjpeg longjmp's there in case of error */ + if (setjmp(p_sys->setjmp_buffer)) + { + goto error; + } + + jpeg_create_decompress(&p_jpeg); + if (p_sys->b_error) + { + goto error; + } + + jpeg_mem_src(&p_jpeg, p_block->p_buffer, p_block->i_buffer); + if (p_sys->b_error) + { + goto error; + } + + jpeg_read_header(&p_jpeg, TRUE); + if (p_sys->b_error) + { + goto error; + } + + p_jpeg.out_color_space = JCS_RGB; + + jpeg_start_decompress(&p_jpeg); + if (p_sys->b_error) + { + goto error; + } + + /* Set output properties */ + p_dec->fmt_out.i_codec = VLC_CODEC_RGB24; + p_dec->fmt_out.video.i_width = p_jpeg.output_width; + p_dec->fmt_out.video.i_height = p_jpeg.output_height; + p_dec->fmt_out.video.i_sar_num = 1; + p_dec->fmt_out.video.i_sar_den = 1; + p_dec->fmt_out.video.i_rmask = 0x000000ff; + p_dec->fmt_out.video.i_gmask = 0x0000ff00; + p_dec->fmt_out.video.i_bmask = 0x00ff0000; + + /* Get a new picture */ + p_pic = decoder_NewPicture(p_dec); + if (!p_pic) + { + goto error; + } + + /* Decode picture */ + p_row_pointers = malloc(sizeof(JSAMPROW) * p_jpeg.output_height); + if (!p_row_pointers) + { + goto error; + } + for (int i = 0; i < (int)p_jpeg.output_height; i++) { + p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i; + } + + while (p_jpeg.output_scanline < p_jpeg.output_height) + { + jpeg_read_scanlines(&p_jpeg, p_row_pointers + p_jpeg.output_scanline, + p_jpeg.output_height - p_jpeg.output_scanline); + if (p_sys->b_error) + { + goto error; + } + } + + jpeg_finish_decompress(&p_jpeg); + jpeg_destroy_decompress(&p_jpeg); + free(p_row_pointers); + + p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts; + + block_Release(p_block); + *pp_block = NULL; + + return p_pic; + +error: + + jpeg_destroy_decompress(&p_jpeg); + free(p_row_pointers); + + block_Release(p_block); + *pp_block = NULL; + + return NULL; +} + +/* + * jpeg decoder destruction + */ +static void CloseDecoder(vlc_object_t *p_this) +{ + decoder_t *p_dec = (decoder_t *)p_this; + decoder_sys_t *p_sys = p_dec->p_sys; + + free(p_sys); +} _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
