diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | configure.ac | 34 | ||||
-rw-r--r-- | src/libxinevdec/Makefile.am | 11 | ||||
-rw-r--r-- | src/libxinevdec/gdkpixbuf.c | 300 |
4 files changed, 342 insertions, 4 deletions
@@ -9,6 +9,7 @@ xine-lib (1.1.2) * Fix the ./configure --enable-static-xv parameter * Really fix the speed changing race that was mentioned in 1.1.1 * Send events for tvtime filmmode changes + * Add an image decoder based on gdk-pixbuf xine-lib (1.1.1) * Improve sound quality when using alsa 1.0.9 or above. diff --git a/configure.ac b/configure.ac index 77fadf58d..26dd1bfd0 100644 --- a/configure.ac +++ b/configure.ac @@ -1369,11 +1369,11 @@ dnl --------------------------------------------- dnl gnome-vfs support dnl --------------------------------------------- -AC_ARG_ENABLE([gnome], - AC_HELP_STRING([--disable-gnome], [do not build gnome-vfs support]), - [with_gnome=$enableval], [with_gnome=yes]) +AC_ARG_ENABLE([gnomevfs], + AC_HELP_STRING([--disable-gnomevfs], [do not build gnome-vfs support]), + [with_gnome_vfs=$enableval], [with_gnome_vfs=yes]) -if test "x$with_gnome" = "xyes"; then +if test "x$with_gnome_vfs" = "xyes"; then PKG_CHECK_MODULES(GNOME_VFS, gnome-vfs-2.0, no_gnome_vfs=no, no_gnome_vfs=yes) @@ -1389,6 +1389,29 @@ else fi AM_CONDITIONAL(HAVE_GNOME_VFS, test x"$no_gnome_vfs" != "xyes") +dnl --------------------------------------------- +dnl gdk-pixbuf support +dnl --------------------------------------------- + +AC_ARG_ENABLE([gdkpixbuf], + AC_HELP_STRING([--disable-gdkpixbuf], [do not build gdk-pixbuf support]), + [with_gdkpixbuf=$enableval], [with_gdkpixbuf=yes]) + +if test "x$with_gdkpixbuf" = "xyes"; then + PKG_CHECK_MODULES(GDK_PIXBUF, gdk-pixbuf-2.0, + no_gdkpixbuf=no, + no_gdkpixbuf=yes) + AC_SUBST(GDK_PIXBUF_CFLAGS) + AC_SUBST(GDK_PIXBUF_LIBS) + if test x"$no_gdkpixbuf" != "xyes"; then + AC_DEFINE(HAVE_GDK_PIXBUF,1,[Define this if you have gdk-pixbuf installed]) + else + AC_MSG_RESULT(*** All of the gdk-pixbuf dependent parts will be disabled ***) + fi +else + no_gdkpixbuf=yes +fi +AM_CONDITIONAL(HAVE_GDK_PIXBUF, test x"$no_gdkpixbuf" != "xyes") dnl --------------------------------------------- dnl libsmbclient support @@ -2489,6 +2512,9 @@ fi if test x"$have_imagemagick" = "xyes"; then echo " - image" fi +if test x"no_gdkpixbuf" != "xyes"; then + echo " - gdk-pixbuf" +fi if test x"$no_theora" != "xyes"; then echo " - theora" fi diff --git a/src/libxinevdec/Makefile.am b/src/libxinevdec/Makefile.am index e0d4acf2b..bf1ae1d68 100644 --- a/src/libxinevdec/Makefile.am +++ b/src/libxinevdec/Makefile.am @@ -6,9 +6,14 @@ if HAVE_WAND image_module = xineplug_decode_image.la endif +if HAVE_GDK_PIXBUF +gdkpixbuf_module = xineplug_decode_gdk_pixbuf.la +endif + libdir = $(XINE_PLUGINDIR) lib_LTLIBRARIES = $(image_module) \ + $(gdkpixbuf_module) \ xineplug_decode_bitplane.la \ xineplug_decode_rgb.la \ xineplug_decode_yuv.la @@ -29,3 +34,9 @@ xineplug_decode_image_la_SOURCES = image.c 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@ + +xineplug_decode_gdk_pixbuf_la_SOURCES = gdkpixbuf.c +xineplug_decode_gdk_pixbuf_la_CFLAGS = $(GDK_PIXBUF_CFLAGS) +xineplug_decode_gdk_pixbuf_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(GDK_PIXBUF_LIBS) +xineplug_decode_gdk_pixbuf_la_LDFLAGS = $(GDK_PIXBUF_LDFLAGS) -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + diff --git a/src/libxinevdec/gdkpixbuf.c b/src/libxinevdec/gdkpixbuf.c new file mode 100644 index 000000000..a40568fc8 --- /dev/null +++ b/src/libxinevdec/gdkpixbuf.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2006 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: gdkpixbuf.c,v 1.1 2006/02/02 20:39:32 hadess Exp $ + * + * a gdk-pixbuf-based image video decoder + */ + + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> + +#define LOG_MODULE "gdkpixbuf_video_decoder" +#define LOG_VERBOSE +/* +#define LOG +*/ + +#include "xine_internal.h" +#include "video_out.h" +#include "buffer.h" +#include "xineutils.h" +#include "bswap.h" + +#include <gdk-pixbuf/gdk-pixbuf.h> + +typedef struct { + video_decoder_class_t decoder_class; + + /* + * private variables + */ + +} image_class_t; + + +typedef struct image_decoder_s { + video_decoder_t video_decoder; + + image_class_t *cls; + + xine_stream_t *stream; + int video_open; + + unsigned char *image; + int index; + +} image_decoder_t; + + +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->video_open) { + lprintf("opening video\n"); + this->stream->video_out->open(this->stream->video_out, this->stream); + this->video_open = 1; + } + + xine_buffer_copyin(this->image, this->index, buf->mem, buf->size); + this->index += buf->size; + + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + GdkPixbufLoader *loader; + GdkPixbuf *pixbuf; + int width, height, x, y, rowstride, n_channels, i; + guchar *img_buf; + yuv_planes_t yuv_planes; + vo_frame_t *img; + + /* + * this->image -> rgb data + */ + loader = gdk_pixbuf_loader_new (); + if (gdk_pixbuf_loader_write (loader, this->image, this->index, NULL) == FALSE) { + lprintf("error loading image\n"); + return; + } + + if (gdk_pixbuf_loader_close (loader, NULL) == FALSE) { + lprintf("error loading image\n"); + return; + } + + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + this->index = 0; + + if (pixbuf == NULL) { + g_object_unref (loader); + lprintf("error loading image\n"); + return; + } + + width = gdk_pixbuf_get_width (pixbuf) & ~1; /* must be even for init_yuv_planes */ + height = gdk_pixbuf_get_height (pixbuf); + img_buf = gdk_pixbuf_get_pixels (pixbuf); + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height); + + lprintf("image loaded successfully\n"); + + /* + * rgb data -> yuv_planes + */ + init_yuv_planes(&yuv_planes, width, height); + + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + i = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + guchar *p; + p = img_buf + y * rowstride + x * n_channels; + + yuv_planes.y[i] = COMPUTE_Y (p[0], p[1], p[2]); + yuv_planes.u[i] = COMPUTE_U (p[0], p[1], p[2]); + yuv_planes.v[i] = COMPUTE_V (p[0], p[1], p[2]); + + i++; + } + } + gdk_pixbuf_unref (pixbuf); + + /* + * 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); + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, img->duration); + + img->draw(img, this->stream); + img->free(img); + } +} + + +static void image_flush (video_decoder_t *this_gen) { + /* image_decoder_t *this = (image_decoder_t *) this_gen; */ + + /* + * flush out any frames that are still stored in the decoder + */ +} + + +static void image_reset (video_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; +} + + +static void image_discontinuity (video_decoder_t *this_gen) { + /* image_decoder_t *this = (image_decoder_t *) this_gen; */ + + /* + * a time reference discontinuity has happened. + * that is, it must forget any currently held pts value + */ +} + +static void image_dispose (video_decoder_t *this_gen) { + image_decoder_t *this = (image_decoder_t *) this_gen; + + if (this->video_open) { + lprintf("closing video\n"); + + this->stream->video_out->close(this->stream->video_out, this->stream); + this->video_open = 0; + } + + xine_buffer_free(this->image); + + lprintf("closed\n"); + free (this); +} + + +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, + xine_stream_t *stream) { + + image_class_t *cls = (image_class_t *) class_gen; + image_decoder_t *this; + + lprintf("opened\n"); + + g_type_init (); + + this = (image_decoder_t *) xine_xmalloc (sizeof (image_decoder_t)); + + this->video_decoder.decode_data = image_decode_data; + this->video_decoder.flush = image_flush; + this->video_decoder.reset = image_reset; + this->video_decoder.discontinuity = image_discontinuity; + this->video_decoder.dispose = image_dispose; + this->cls = cls; + this->stream = stream; + + /* + * initialisation of privates + */ + + this->image = xine_buffer_init(10240); + + return &this->video_decoder; +} + +/* + * image plugin class + */ + +static char *get_identifier (video_decoder_class_t *this) { + return "gdkpixbuf"; +} + +static char *get_description (video_decoder_class_t *this) { + return "gdk-pixbuf image video decoder plugin"; +} + +static void dispose_class (video_decoder_class_t *this_gen) { + image_class_t *this = (image_class_t *) this_gen; + + lprintf("class closed\n"); + + free (this); +} + +static void *init_class (xine_t *xine, void *data) { + + image_class_t *this; + + this = (image_class_t *) xine_xmalloc (sizeof (image_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + /* + * initialisation of privates + */ + + lprintf("class opened\n"); + + return this; +} + +/* + * exported plugin catalog entry + */ + +static uint32_t supported_types[] = { BUF_VIDEO_IMAGE, + 0 }; + +static decoder_info_t dec_info_image = { + supported_types, /* supported types */ + 6 /* priority */ +}; + +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_VIDEO_DECODER, 18, "gdkpixbuf", XINE_VERSION_CODE, &dec_info_image, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; |