From 484a83b43658b3b0a6e06bc97eec9395e8917322 Mon Sep 17 00:00:00 2001 From: Stefan Holst Date: Thu, 3 Feb 2005 23:18:33 +0000 Subject: make the image decoder use imagemagick to decode images. slight improvements of image dummy demuxer which now sends proper end-of-frame flags CVS patchset: 7381 CVS date: 2005/02/03 23:18:33 --- src/demuxers/Makefile.am | 2 +- src/demuxers/demux_image.c | 17 +-- src/libxinevdec/Makefile.am | 8 +- src/libxinevdec/image.c | 309 ++++++++++++-------------------------------- 4 files changed, 94 insertions(+), 242 deletions(-) (limited to 'src') diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index eff9538b2..043efe6ca 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -18,7 +18,7 @@ if HAVE_LIBMNG mng_module = xineplug_dmx_mng.la endif -if HAVE_LIBPNG +if HAVE_WAND image_module = xineplug_dmx_image.la endif diff --git a/src/demuxers/demux_image.c b/src/demuxers/demux_image.c index 5c2a860c2..c7c869c9d 100644 --- a/src/demuxers/demux_image.c +++ b/src/demuxers/demux_image.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 the xine project + * Copyright (C) 2003-2005 the xine project * * This file is part of xine, a free video player. * @@ -19,7 +19,7 @@ */ /* - * $Id: demux_image.c,v 1.15 2004/06/13 21:28:53 miguelfreitas Exp $ + * $Id: demux_image.c,v 1.16 2005/02/03 23:18:34 holstsn Exp $ * * image dummy demultiplexer */ @@ -74,13 +74,14 @@ static int demux_image_send_chunk (demux_plugin_t *this_gen) { buf->size = this->input->read (this->input, buf->mem, buf->max_size-1); if (buf->size <= 0) { - buf->free_buffer(buf); - xine_usec_sleep(250000); + buf->size = 0; + buf->decoder_flags |= BUF_FLAG_FRAME_END; + this->status = DEMUX_FINISHED; } else { - lprintf("got %i bytes\n", buf->size); - this->video_fifo->put (this->video_fifo, buf); + this->status = DEMUX_OK; } - this->status = DEMUX_OK; + this->video_fifo->put (this->video_fifo, buf); + return this->status; } @@ -196,7 +197,7 @@ static char *get_identifier (demux_class_t *this_gen) { } static char *get_extensions (demux_class_t *this_gen) { - return "png"; + return "png gif jpg jpeg"; } static char *get_mimetypes (demux_class_t *this_gen) { diff --git a/src/libxinevdec/Makefile.am b/src/libxinevdec/Makefile.am index e612dc89c..e0d4acf2b 100644 --- a/src/libxinevdec/Makefile.am +++ b/src/libxinevdec/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = foovideo.c -if HAVE_LIBPNG +if HAVE_WAND image_module = xineplug_decode_image.la endif @@ -26,6 +26,6 @@ xineplug_decode_yuv_la_LIBADD = $(XINE_LIB) xineplug_decode_yuv_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ xineplug_decode_image_la_SOURCES = image.c -xineplug_decode_image_la_CFLAGS = $(PNG_CFLAGS) -xineplug_decode_image_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(PNG_LIBS) -xineplug_decode_image_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_decode_image_la_CFLAGS = $(WAND_CFLAGS) +xineplug_decode_image_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(WAND_LIBS) +xineplug_decode_image_la_LDFLAGS = $(WAND_LDFLAGS) -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ diff --git a/src/libxinevdec/image.c b/src/libxinevdec/image.c index 413aee26f..407a9f3b6 100644 --- a/src/libxinevdec/image.c +++ b/src/libxinevdec/image.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 the xine project + * Copyright (C) 2003-2005 the xine project * * This file is part of xine, a free video player. * @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: image.c,v 1.16 2004/12/03 15:46:42 mroi Exp $ + * $Id: image.c,v 1.17 2005/02/03 23:18:34 holstsn Exp $ * * a image video decoder */ @@ -29,8 +29,7 @@ #include #include #include - -#include +#include #define LOG_MODULE "image_video_decoder" #define LOG_VERBOSE @@ -39,9 +38,12 @@ */ #include "xine_internal.h" -#include "bswap.h" #include "video_out.h" #include "buffer.h" +#include "xineutils.h" +#include "bswap.h" + +#include typedef struct { video_decoder_class_t decoder_class; @@ -60,248 +62,96 @@ typedef struct image_decoder_s { xine_stream_t *stream; int video_open; - int pts; - - /* png */ - png_structp png_ptr; - png_infop info_ptr; - char *user_error_ptr; - png_uint_32 width, height; - int bit_depth, - color_type, - interlace_type, - compression_type, - filter_type; - png_bytep *rows; - jmp_buf jmpbuf; - int passes, rowbytes; - int rows_valid; - -} image_decoder_t; - -/* - * png stuff - */ - -static void info_callback(png_structp png_ptr, png_infop info); -static void row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass); -static void end_callback(png_structp png_ptr, png_infop info); - -static int initialize_png_reader(image_decoder_t *this) { - - this->png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)this, - NULL, NULL); - if (!this->png_ptr) - return -1; - - this->info_ptr = png_create_info_struct(this->png_ptr); - if (!this->info_ptr) { - png_destroy_read_struct(&this->png_ptr, NULL, NULL); - return -1; - } - - if (setjmp(this->jmpbuf)) { - png_destroy_read_struct(&this->png_ptr, &this->info_ptr, - (png_infopp)NULL); - return -1; - } - - png_set_progressive_read_fn(this->png_ptr, (void *)this, - info_callback, row_callback, end_callback); + unsigned char *image; + int index; - return 0; -} - -static void finalize_png_reader(image_decoder_t *this) { - - png_destroy_read_struct(&this->png_ptr, &this->info_ptr, - (png_infopp)NULL); - this->png_ptr = NULL; - this->info_ptr = NULL; - -} - -static int process_data(image_decoder_t *this, - png_bytep buffer, png_uint_32 length) { - - if (setjmp(this->jmpbuf)) { - png_destroy_read_struct(&this->png_ptr, &this->info_ptr, (png_infopp)NULL); - return -1; - } - png_process_data(this->png_ptr, this->info_ptr, buffer, length); - return 0; -} - - /* - * process png header (do some conversions if necessary) - */ - -static void info_callback(png_structp png_ptr, png_infop info_ptr) { - int i; - image_decoder_t *this = png_get_progressive_ptr(png_ptr); - - lprintf("png info cb\n"); - png_get_IHDR(png_ptr, info_ptr, &this->width, &this->height, - &this->bit_depth, &this->color_type, &this->interlace_type, - &this->compression_type, &this->filter_type); - - - /* expand palette images to RGB, low-bit-depth - * grayscale images to 8 bits, transparency chunks to full alpha channel; - * strip 16-bit-per-sample images to 8 bits per sample; and convert - * grayscale to RGB[A] */ - - if (this->color_type == PNG_COLOR_TYPE_PALETTE) - png_set_expand(png_ptr); - if (this->color_type == PNG_COLOR_TYPE_GRAY && this->bit_depth < 8) - png_set_expand(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand(png_ptr); - if (this->bit_depth == 16) - png_set_strip_16(png_ptr); - if (this->color_type == PNG_COLOR_TYPE_GRAY || - this->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - if (this->color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - - - /* we'll let libpng expand interlaced images, too */ - - this->passes = png_set_interlace_handling(png_ptr); - - /* all transformations have been registered; now update info_ptr data and - * then get rowbytes */ - - png_read_update_info(png_ptr, info_ptr); +} image_decoder_t; - this->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); - this->rows = xine_xmalloc(sizeof(png_bytep)*this->height); +static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { + image_decoder_t *this = (image_decoder_t *) this_gen; - for (i=0; iheight; i++) { - this->rows[i] = xine_xmalloc(this->rowbytes); + if (!this->video_open) { + lprintf("opening video\n"); + this->stream->video_out->open(this->stream->video_out, this->stream); + this->video_open = 1; } - this->rows_valid = 1; -} - -static void row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) { - image_decoder_t *this = png_get_progressive_ptr(png_ptr); - - if (!new_row) return; - - /* - * copy new row to this->rows - */ + xine_buffer_copyin(this->image, this->index, buf->mem, buf->size); + this->index += buf->size; - png_progressive_combine_row(png_ptr, this->rows[row_num], new_row); -} + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + int width, height, i; + MagickBooleanType status; + MagickWand *wand; + uint8_t *img_buf, *img_buf_ptr; + yuv_planes_t yuv_planes; + vo_frame_t *img; + + /* + * this->image -> rgb data + */ + wand = NewMagickWand(); + status = MagickReadImageBlob(wand, this->image, this->index); + this->index = 0; + + if (status == MagickFalse) { + DestroyMagickWand(wand); + lprintf("error loading image\n"); + return; + } -/* for rgb2yuv */ -#define CENTERSAMPLE 128 -#define SCALEBITS 16 -#define FIX(x) ( (int32_t) ( (x) * (1<stream, XINE_STREAM_INFO_VIDEO_WIDTH, width); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height); - vo_frame_t *img; /* video out frame */ - int row, col; + lprintf("image loaded successfully\n"); - /* - * libpng has read end of image, now convert rows into a video frame - */ - - image_decoder_t *this = png_get_progressive_ptr(png_ptr); - finalize_png_reader(this); - lprintf("png end cb\n"); - - if (this->rows_valid) { - img = this->stream->video_out->get_frame (this->stream->video_out, this->width, - this->height, (double)this->width/(double)this->height, - XINE_IMGFMT_YUY2, - VO_BOTH_FIELDS); + /* + * rgb data -> yuv_planes + */ + init_yuv_planes(&yuv_planes, width, height); + + img_buf_ptr = img_buf; + for (i=0; i < width*height; i++) { + uint8_t r = *(img_buf_ptr++); + uint8_t g = *(img_buf_ptr++); + uint8_t b = *(img_buf_ptr++); - img->pts = this->pts; + yuv_planes.y[i] = COMPUTE_Y(r, g, b); + yuv_planes.u[i] = COMPUTE_U(r, g, b); + yuv_planes.v[i] = COMPUTE_V(r, g, b); + } + free(img_buf); + + /* + * alloc and draw video frame + */ + img = this->stream->video_out->get_frame (this->stream->video_out, width, + height, (double)width/(double)height, + XINE_IMGFMT_YUY2, + VO_BOTH_FIELDS); + img->pts = buf->pts; img->duration = 3600; img->bad_frame = 0; + + yuv444_to_yuy2(&yuv_planes, img->base[0], img->pitches[0]); + free_yuv_planes(&yuv_planes); - for (row=0; rowheight; row++) { - - uint16_t *out; - - out = (uint16_t *) (img->base[0] + row * img->pitches[0] ); - - for (col=0; colwidth; col++, out++) { - - uint8_t r,g,b; - uint8_t y,u,v; - - r = *(this->rows[row]+col*3); - g = *(this->rows[row]+col*3+1); - b = *(this->rows[row]+col*3+2); - y = (FIX(0.257) * r + FIX(0.504) * g + FIX(0.098) * b + ONE_HALF + FOOTROOM) - >> SCALEBITS; - if (!(col & 0x0001)) { - /* even pixel, do u */ - u = (- FIX(0.148) * r - FIX(0.291) * g + FIX(0.439) * b - + CBCR_OFFSET + ONE_HALF-1) >> SCALEBITS; - *out = ( (uint16_t) u << 8) | (uint16_t) y; - } else { - /* odd pixel, do v */ - v = (FIX(0.439) * r - FIX(0.368) * g - FIX(0.071) * b - + CBCR_OFFSET + ONE_HALF-1) >> SCALEBITS; - *out = ( (uint16_t) v << 8) | (uint16_t) y; - } - - *out = le2me_16(*out); - } - - free(this->rows[row]); - } - free(this->rows); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, img->duration); + img->draw(img, this->stream); img->free(img); } } -/* - * png stuff end - */ - -static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { - image_decoder_t *this = (image_decoder_t *) this_gen; - - if (!this->png_ptr) { - if (initialize_png_reader(this) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "image: failed to init png reader\n"); - } - } - if (!this->video_open) { - lprintf("opening video\n"); - this->stream->video_out->open(this->stream->video_out, this->stream); - this->video_open = 1; - } - - lprintf("have to decode data\n"); - - this->pts = buf->pts; - if (process_data(this, buf->content, buf->size) < 0) - { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "image: error processing data\n"); - } -} - - static void image_flush (video_decoder_t *this_gen) { /* image_decoder_t *this = (image_decoder_t *) this_gen; */ @@ -312,12 +162,14 @@ static void image_flush (video_decoder_t *this_gen) { static void image_reset (video_decoder_t *this_gen) { - /* image_decoder_t *this = (image_decoder_t *) this_gen; */ + image_decoder_t *this = (image_decoder_t *) this_gen; /* * reset decoder after engine flush (prepare for new * video data not related to recently decoded data) */ + + this->index = 0; } @@ -340,6 +192,8 @@ static void image_dispose (video_decoder_t *this_gen) { this->video_open = 0; } + xine_buffer_free(this->image); + lprintf("closed\n"); free (this); } @@ -367,9 +221,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, * initialisation of privates */ - if (initialize_png_reader(this) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "image: failed to init png reader\n"); - } + this->image = xine_buffer_init(10240); return &this->video_decoder; } @@ -397,7 +249,6 @@ static void dispose_class (video_decoder_class_t *this_gen) { static void *init_class (xine_t *xine, void *data) { image_class_t *this; - /* config_values_t *config = xine->config; */ this = (image_class_t *) xine_xmalloc (sizeof (image_class_t)); -- cgit v1.2.3