Commit 6a06a82a authored by Maxim Bublis's avatar Maxim Bublis Committed by Jean-Baptiste Kempf

codec: implemented libjpeg module

Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 6ba7773c
...@@ -2693,6 +2693,17 @@ AC_CHECK_HEADERS(png.h, [ ...@@ -2693,6 +2693,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
dnl H262 encoder plugin (lib262) dnl H262 encoder plugin (lib262)
dnl dnl
......
...@@ -103,6 +103,12 @@ libpng_plugin_la_LIBADD = -lpng -lz $(LIBM) ...@@ -103,6 +103,12 @@ libpng_plugin_la_LIBADD = -lpng -lz $(LIBM)
EXTRA_LTLIBRARIES += libpng_plugin.la EXTRA_LTLIBRARIES += libpng_plugin.la
codec_LTLIBRARIES += $(LTLIBpng) 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_SOURCES = codec/sdl_image.c
libsdl_image_plugin_la_CFLAGS = $(AM_CFLAGS) $(SDL_IMAGE_CFLAGS) libsdl_image_plugin_la_CFLAGS = $(AM_CFLAGS) $(SDL_IMAGE_CFLAGS)
libsdl_image_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)' libsdl_image_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
......
/*****************************************************************************
* jpeg.c: jpeg decoder module making use of libjpeg.
*****************************************************************************
* Copyright (C) 2013 VLC authors and VideoLAN
*
* Authors: Maxim Bublis <b@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;
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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment