[vlc-devel] [PATCH] codec: implemented libjpeg module

Jean-Baptiste Kempf jb at videolan.org
Wed Dec 25 20:20:59 CET 2013


Applied.
Thanks.

On 19 Dec, Maxim Bublis wrote :
> ---
>  configure.ac              |  11 ++
>  modules/codec/Makefile.am |   6 ++
>  modules/codec/jpeg.c      | 250 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 267 insertions(+)
>  create mode 100644 modules/codec/jpeg.c
> 
> 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..3283574
> --- /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 <b at codemonkey.ru>
> + *
> + * 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;
> +
> +    bool b_error;
> +
> +    decoder_t *p_dec;
> +};
> +
> +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);
> +}
> -- 
> 1.8.3.4 (Apple Git-47)
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel

-- 
With my kindest regards,

-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/ - +33 672 704 734
Sent from my Electronic Device



More information about the vlc-devel mailing list