summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuenter Bartsch <guenter@users.sourceforge.net>2001-10-14 00:43:06 +0000
committerGuenter Bartsch <guenter@users.sourceforge.net>2001-10-14 00:43:06 +0000
commit1d935a2e2b0709ea276d0f312c2a7218ab6928c3 (patch)
treec9178fecb5c63d89c88c28ee074f6b716142bf41 /src
parent58fc755d454c2c277f3fb6f2a37203553a06049a (diff)
downloadxine-lib-1d935a2e2b0709ea276d0f312c2a7218ab6928c3.tar.gz
xine-lib-1d935a2e2b0709ea276d0f312c2a7218ab6928c3.tar.bz2
libdivx4 updates from Harm van der Heijden <harm@etpmod.phys.tue.nl>
CVS patchset: 794 CVS date: 2001/10/14 00:43:06
Diffstat (limited to 'src')
-rw-r--r--src/libdivx4/Makefile.am9
-rw-r--r--src/libdivx4/decore-if.h177
-rw-r--r--src/libdivx4/xine_decoder.c164
3 files changed, 328 insertions, 22 deletions
diff --git a/src/libdivx4/Makefile.am b/src/libdivx4/Makefile.am
index cebb2ab86..a4a2595dc 100644
--- a/src/libdivx4/Makefile.am
+++ b/src/libdivx4/Makefile.am
@@ -8,14 +8,17 @@ LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic
libdir = $(XINE_PLUGINDIR)
-if HAVE_DIVX4
+#
+# use HAVE_DIVX4 to make compilation optional;
+# not really needed because the divx4 plugin sources are self-contained.
+#
+#if HAVE_DIVX4
divx4_module = xineplug_decode_divx4.la
-endif
+#endif
lib_LTLIBRARIES = $(divx4_module)
xineplug_decode_divx4_la_SOURCES = xine_decoder.c
-xineplug_decode_divx4_la_LIBADD = @DIVX4_LIBS@
xineplug_decode_divx4_la_LDFLAGS = -avoid-version -module
debug:
diff --git a/src/libdivx4/decore-if.h b/src/libdivx4/decore-if.h
new file mode 100644
index 000000000..72e34521a
--- /dev/null
+++ b/src/libdivx4/decore-if.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2001 the xine project
+ *
+ * This file is part of xine, a unix 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: decore-if.h,v 1.1 2001/10/14 00:43:06 guenter Exp $
+ *
+ * This file documents the interface for the decore() function
+ * in libdivxdecore. In case of problems, it is recommended you compare
+ * the definitions in this file with the header file that came with your
+ * divx4 library (see below).
+ *
+ * The divxdecore library can be found as part of the divx4linux package at
+ * http://www.divx.com or http://avifile.sourceforge.net The package also
+ * contains a text file documenting the decore/encore API.
+ *
+ * Alternatively, the open source OpenDivx project (http://www.projectmayo.com)
+ * also provides a divxdecore library with the same interface. There is
+ * a project called XviD at http://www.videocoding.de that extends the
+ * opendivx project.
+ *
+ * THIS FILE AND THE XINE DECORE PLUGIN ARE INTENDED FOR THE BINARY DIVX4LINUX
+ * PACKAGE. OPENDIVX DECORE LIBRARIES ARE CURRENTLY NOT SUPPORTED AND MAY OR
+ * MAY NOT WORK.
+ *
+ * Harm van der Heijden <hrm@users.sourceforge.net>
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _DECORE_IF_H_
+#define _DECORE_IF_H_
+
+/* decore commands (2nd parameter in decore()) */
+#define DEC_OPT_MEMORY_REQS 0
+#define DEC_OPT_INIT 1
+#define DEC_OPT_RELEASE 2
+#define DEC_OPT_SETPP 3
+#define DEC_OPT_SETOUT 4
+#define DEC_OPT_FRAME 5
+#define DEC_OPT_FRAME_311 6
+#define DEC_OPT_SETPP2 7
+
+/* decore() return values. */
+#define DEC_OK 0
+#define DEC_MEMORY 1
+#define DEC_BAD_FORMAT 2
+#define DEC_EXIT 3
+
+/* colour formats -- yuv */
+#define DEC_YUY2 1
+#define DEC_YUV2 DEC_YUY2
+#define DEC_UYVY 2
+#define DEC_420 3
+#define DEC_YV12 13 /* looks like an afterthought, eh? */
+
+/* colour formats -- rgb
+ not yet used by xine, but perhaps in the future.
+ (decore yuv->rgb conversion may be better than libsdl/Xshm) */
+#define DEC_RGB32 4
+#define DEC_RGB24 5
+#define DEC_RGB555 6
+#define DEC_RGB565 7
+
+#define DEC_RGB32_INV 8
+#define DEC_RGB24_INV 9
+#define DEC_RGB555_INV 10
+#define DEC_RGB565_INV 11
+
+/* pseudo colour format; makes decore() return pointers to internal
+ yuv buffers for manual conversion, see DEC_PICTURE */
+#define DEC_USER 12
+
+/* memory requirement structure; the officical codec spec calls for
+ a DEC_OPT_MEMORY_REQ call prior to DEC_OPT_INIT, but it does not
+ actually seem to be used */
+typedef struct
+{
+ unsigned long mp4_edged_ref_buffers_size;
+ unsigned long mp4_edged_for_buffers_size;
+ unsigned long mp4_edged_back_buffers_size;
+ unsigned long mp4_display_buffers_size;
+ unsigned long mp4_state_size;
+ unsigned long mp4_tables_size;
+ unsigned long mp4_stream_size;
+ unsigned long mp4_reference_size;
+} DEC_MEM_REQS;
+
+/* included in DEC_PARAM for init, not really used otherwise. */
+typedef struct
+{
+ void * mp4_edged_ref_buffers;
+ void * mp4_edged_for_buffers;
+ void * mp4_edged_back_buffers;
+ void * mp4_display_buffers;
+ void * mp4_state;
+ void * mp4_tables;
+ void * mp4_stream;
+ void * mp4_reference;
+} DEC_BUFFERS;
+
+/* struct for DEC_OPT_INIT */
+typedef struct
+{
+ int x_dim; /* frame width */
+ int y_dim; /* frame height */
+ int output_format; /* refers to colour formats defined above */
+ int time_incr; /* mystery parameter, use 15 */
+ DEC_BUFFERS buffers; /* memcpy 0's in this struct before init */
+} DEC_PARAM;
+
+/* struct for DEC_OPT_DECODE */
+typedef struct
+{
+ void *bmp; /* pointer to rgb, yuv or DEC_PICTURE buffer */
+ void *bitstream; /* input bit stream */
+ long length; /* length of input */
+ int render_flag; /* 1 to actually render the frame */
+ unsigned int stride; /* bmp stride; should be width */
+} DEC_FRAME;
+
+/* decode frame information. not yet used by xine */
+typedef struct
+{
+ int intra;
+ int *quant_store;
+ int quant_stride;
+} DEC_FRAME_INFO;
+
+/* structure for DEC_OPT_SETPP, for setting the postprocessing level */
+typedef struct
+{
+ int postproc_level; /* between 0-100, actually used 0-60 */
+} DEC_SET;
+
+/* structure for DEC_USER output format, should be used instead of bmp ptr */
+typedef struct
+{
+ void *y;
+ void *u;
+ void *v;
+ int stride_y;
+ int stride_uv;
+} DEC_PICTURE;
+
+/* Finally, decore() itself. Refer to the official codec interface text for
+ a complete description. */
+int decore( unsigned long handle, unsigned long dec_opt, void* param1, void* param2);
+/* handle: unique caller handle. xine uses the video_decoder_t ptr.
+ dec_opt: decore command id
+ param1: depends on command. Usually ptr to struct with input values.
+ param2: depends on command. Usually ptr to struct with output values. */
+
+/* typedef for pointer to decore function */
+typedef int (*decoreFunc)(unsigned long, unsigned long, void*, void*);
+
+#endif // _DECORE_IF_H_
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/libdivx4/xine_decoder.c b/src/libdivx4/xine_decoder.c
index 9052a30a5..752c9beef 100644
--- a/src/libdivx4/xine_decoder.c
+++ b/src/libdivx4/xine_decoder.c
@@ -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: xine_decoder.c,v 1.1 2001/10/07 18:06:00 guenter Exp $
+ * $Id: xine_decoder.c,v 1.2 2001/10/14 00:43:06 guenter Exp $
*
* xine decoder plugin using divx4
*
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
+#include <dlfcn.h>
#include "xine_internal.h"
#include "cpu_accel.h"
@@ -48,7 +49,7 @@
#include "buffer.h"
#include "metronom.h"
-#include <decore.h>
+#include "decore-if.h"
/* now this is ripped of wine's vfw.h */
typedef struct {
@@ -77,6 +78,7 @@ typedef struct divx4_decoder_s {
long biHeight;
unsigned char buf[128*1024];
int size;
+ decoreFunc decore; /* ptr to decore function in libdivxdecore */
/* whether to decode MSMPEG4_V3 format
(aka divx ;-) and divx 3.11-- thank god they dropped the smileys
with divx4)
@@ -85,6 +87,18 @@ typedef struct divx4_decoder_s {
/* postprocessing level; currently valid values 0-6 (internally 0-100)
set by divx4_postproc in .xinerc */
int postproc;
+ /* what output format we ask of decore()
+ supported at the moment:
+ DEC_YV12, copied straight into image buffer by decore(),
+ fast but perhaps risky.
+ DEC_USER, decore() returns pointers to internal y,u,v buffers,
+ and we copy the data ourselves. Not optimised, so probably slower.
+ It seems that OpenDivx likes this better. */
+ int decore_format;
+ /* can we handle 311 format? No easy way to find out (divx4linux can,
+ OpenDivx cannot, so the user can set it in .xinerc. If 0, can_handle
+ only returns MPEG4, yielding 311 to ffmpeg */
+ int can_handle_311;
} divx4_decoder_t;
static unsigned long str2ulong(void *data) {
@@ -93,11 +107,23 @@ static unsigned long str2ulong(void *data) {
return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );
}
+static char* decore_retval(int ret)
+{
+ switch (ret) {
+ case DEC_OK: return "DEC_OK";
+ case DEC_MEMORY: return "DEC_MEMORY";
+ case DEC_BAD_FORMAT: return "DEC_BAD_FORMAT";
+ case DEC_EXIT: return "DEC_EXIT";
+ }
+ return "[Unknown code]";
+}
+
static int divx4_can_handle (video_decoder_t *this_gen, int buf_type) {
+ divx4_decoder_t *this = (divx4_decoder_t *) this_gen;
buf_type &= 0xFFFF0000;
/* divx4 currently does not support MSMPEG4 v1/v2 */
- return ( buf_type == BUF_VIDEO_MSMPEG4_V3 ||
+ return ( (buf_type == BUF_VIDEO_MSMPEG4_V3 && this->can_handle_311) ||
/* buf_type == BUF_VIDEO_MSMPEG4_V12 || */
buf_type == BUF_VIDEO_MPEG4);
}
@@ -116,6 +142,8 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
DEC_PARAM param; /* for init */
DEC_SET setpp; /* for setting postproc level */
DEC_FRAME frame; /* for getting a frame */
+ DEC_PICTURE pict;/* contains ptrs to the decoders internal yuv buffers */
+ int ret;
divx4_decoder_t *this = (divx4_decoder_t *) this_gen;
@@ -151,17 +179,27 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
/* FIXME: the decoder can also supply RGB data, and my avifile experience
is that it's far preferable over generic yuv conversion. Would this
be interesting for the XShm crowd, lacking a YUV overlay? */
- param.output_format=DEC_YV12;
+ param.output_format=this->decore_format;
memset(&param.buffers, 0, sizeof(param.buffers));
- /* FIXME: check return value: */
- decore((unsigned long)this, DEC_OPT_INIT, &param, &this->bih);
+
+ ret = this->decore((unsigned long)this, DEC_OPT_INIT, &param, &this->bih);
+ if (ret != DEC_OK) {
+ printf("divx4: decore DEC_OPT_INIT command returned %s.\n", decore_retval(ret));
+ return;
+ }
/* multiply postproc level by 10 for internal consumption */
- printf("Divx4: Setting post processing level to %d (see ~/.xinerc)\n"
- "Divx4: Valid range 0-6, reduce if you get frame drop\n",
+ printf("divx4: Setting post processing level to %d (see ~/.xinerc)\n"
+ "divx4: Valid range 0-6, reduce if you get frame drop\n",
this->postproc);
setpp.postproc_level=this->postproc*10;
- decore((unsigned long)this, DEC_OPT_SETPP, &setpp, 0);
+
+ ret = this->decore((unsigned long)this, DEC_OPT_SETPP, &setpp, 0);
+ if (ret != DEC_OK)
+ {
+ printf("divx4: decore DEC_OPT_SETPP command returned %s.\n", decore_retval(ret));
+ /* perhaps not fatal, so we'll continue */
+ }
this->decoder_ok = 1;
this->video_out->open (this->video_out);
@@ -172,8 +210,8 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
this->size += buf->size;
- if (buf->decoder_info[0] == 2) { // what does this mean?
- // allocate image (taken from ffmpeg plugin)
+ if (buf->decoder_info[0] == 2) { /* what does this mean? */
+ /* allocate image (taken from ffmpeg plugin) */
vo_frame_t *img;
img = this->video_out->get_frame (this->video_out,
/* this->av_picture.linesize[0], */
@@ -186,21 +224,68 @@ static void divx4_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
/*
setup the decode frame parameters, as demonstrated by avifile.
- FIXME: I assume here that the layout of base[] is flat,
- i.e. that base[0], [1] and [2] all point inside the same
+ If decore format is DEC_YV12, I assume here that the layout of
+ base[] is flat, i.e. that base[0], [1] and [2] all point inside the same
contiguous bit of memory. It seems to work for the Xv driver
- but I don not know if this is always acceptable.
+ but I don't not know if this is always acceptable. Use DEC_USER if this
+ causes problems (configurable via .xinerc). Also, OpenDivx seems to
+ prefer DEC_USER.
*/
frame.bitstream= (void*)this->buf;
- frame.bmp=img->base[0]; // can I do this?
+
+ if (this->decore_format == DEC_USER)
+ frame.bmp=&pict; /* decore will set ptrs to internal y,u&v buffers */
+ else
+ frame.bmp=img->base[0]; /* YV12: assume y,u & v buffers are contiguous */
+
frame.length=this->size;
frame.render_flag=1;
frame.stride=this->biWidth;
if(this->use_311_compat)
- decore((unsigned long)this, DEC_OPT_FRAME_311, &frame, 0);
+ ret = this->decore((unsigned long)this, DEC_OPT_FRAME_311, &frame, 0);
else
- decore((unsigned long)this, DEC_OPT_FRAME, &frame, 0);
+ ret = this->decore((unsigned long)this, DEC_OPT_FRAME, &frame, 0);
+
+ if (ret != DEC_OK) {
+ printf("divx4: decore DEC_OPT_FRAME command returned %s.\n", decore_retval(ret));
+ img->bad_frame = 1; /* better skip this one */
+ }
+ else if (this->decore_format == DEC_USER)
+ {
+ /* We need to copy the yuv data from the decoder's internal buffers.
+ Y size is width*height, U and V width*height/4 */
+ int i;
+ int src_offset,dst_offset;
+ /* shortcut if stride_y equals width */
+ if (pict.stride_y == img->width) {
+ memcpy(img->base[0], pict.y, img->width*img->height);
+ }
+ else { /* copy line by line */
+ src_offset=dst_offset = 0;
+ for (i=0; i<img->height; i++) {
+ memcpy(img->base[0]+dst_offset, pict.y+src_offset, img->width);
+ src_offset += pict.stride_y;
+ dst_offset += img->width;
+ }
+ }
+ /* same for u,v data, but at 1/4 resolution.
+ FIXME: Weird... I thought YV12 means order y-v-u, yet base[1]
+ seems to be u and base[2] is v. */
+ if (pict.stride_uv == img->width>>1) {
+ memcpy(img->base[1], pict.u, (img->width*img->height)>>2);
+ memcpy(img->base[2], pict.v, (img->width*img->height)>>2);
+ }
+ else {
+ src_offset=dst_offset = 0;
+ for (i=0; i<img->height>>1; i++) {
+ memcpy(img->base[1]+dst_offset, pict.u+src_offset, img->width>>1);
+ memcpy(img->base[2]+dst_offset, pict.v+src_offset, img->width>>1);
+ src_offset += pict.stride_uv;
+ dst_offset += img->width>>1;
+ }
+ }
+ }
/* this again from ffmpeg plugin */
img->PTS = buf->PTS;
@@ -218,7 +303,9 @@ static void divx4_close (video_decoder_t *this_gen) {
if (this->decoder_ok) {
/* FIXME: this segfaults here
- decore((unsigned long)this, DEC_OPT_RELEASE, 0, 0);*/
+ (note: avifile also has the release command commented out;
+ probably a known 'feature')
+ this->decore((unsigned long)this, DEC_OPT_RELEASE, 0, 0);*/
this->video_out->close(this->video_out);
this->decoder_ok = 0;
@@ -234,6 +321,9 @@ static char *divx4_get_id(void) {
video_decoder_t *init_video_decoder_plugin (int iface_version, config_values_t *cfg) {
divx4_decoder_t *this ;
+ char *libdecore_name;
+ void *libdecore_handle;
+ decoreFunc libdecore_func = 0;
if (iface_version != 2) {
printf( "divx4: plugin doesn't support plugin API version %d.\n"
@@ -244,6 +334,22 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, config_values_t *
return NULL;
}
+ /* Try to dlopen libdivxdecore, then look for decore function
+ if it fails, print a message and return 0 so that xine ignores
+ us from then on. */
+ libdecore_name = cfg->lookup_str(cfg, "divx4_libdivxdecore", "libdivxdecore.so");
+ libdecore_handle = dlopen(libdecore_name, RTLD_LAZY);
+ if (libdecore_handle)
+ libdecore_func = dlsym(libdecore_handle, "decore");
+ if (! libdecore_func) {
+ printf("divx4: could not find decore function in library \"%s\"\n"
+ "divx4: system returned \"%s\"\n"
+ "divx4: libdivxdecore unavailable; this plugin will be disabled.\n",
+ libdecore_name, dlerror());
+ return NULL;
+ }
+ printf("divx4: successfully opened \"%s\"\n", libdecore_name);
+
this = (divx4_decoder_t *) malloc (sizeof (divx4_decoder_t));
this->video_decoder.interface_version = 2;
@@ -253,9 +359,29 @@ video_decoder_t *init_video_decoder_plugin (int iface_version, config_values_t *
this->video_decoder.close = divx4_close;
this->video_decoder.get_identifier = divx4_get_id;
this->video_decoder.priority = cfg->lookup_int(cfg, "divx4_priority", 6);
- this->postproc = cfg->lookup_int(cfg, "divx4_postproc", 3);
+ this->decore = libdecore_func;
+ this->postproc = cfg->lookup_int(cfg, "divx4_postproc", 3);
+ this->decore_format = cfg->lookup_int(cfg, "divx4_decoreformat", 1);
+ this->can_handle_311 = cfg->lookup_int(cfg, "divx4_msmpeg4v3", 1);
this->size = 0;
+ /* at the moment availabe values are 0-6, but future versions may support
+ higher levels. Internally, postproc is multiplied by 10 and values
+ between 0 and 100 are valid */
+ if (this->postproc > 10) this->postproc=10;
+ if (this->postproc < 0) this->postproc=0;
+
+ /* translate the decore_format value to the internal constant, correct if
+ an illegal value was given.
+ This might someday be extended to allow for RGB output from the decoder */
+ if (this->decore_format == 0) this->decore_format = DEC_YV12;
+ else if (this->decore_format == 1) this->decore_format = DEC_USER;
+ else {
+ printf("divx4: Illegal value %d for divx4_decoreformat, using 1.\n"
+ "divx4: Valid are 0 (YV12, faster) and 1 (USER, safer). No quality difference.\n",
+ this->decore_format);
+ this->decore_format = DEC_USER;
+ }
return (video_decoder_t *) this;
}