summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-09-16 15:14:30 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2001-09-16 15:14:30 +0000
commitce153b6b3b234f8cbc5c48119b4a3c2538e1fd17 (patch)
tree844d932da7964901f0b4a3c8b1407a00735472b2
parent849562a897431915fd760f83524de0ac8e81c548 (diff)
downloadxine-lib-ce153b6b3b234f8cbc5c48119b4a3c2538e1fd17.tar.gz
xine-lib-ce153b6b3b234f8cbc5c48119b4a3c2538e1fd17.tar.bz2
software deinterlacer filter (BOB)
currently only working with Xv and MMX CVS patchset: 641 CVS date: 2001/09/16 15:14:30
-rw-r--r--src/video_out/Makefile.am4
-rw-r--r--src/video_out/deinterlace.c217
-rw-r--r--src/video_out/deinterlace.h39
-rw-r--r--src/video_out/video_out_xv.c249
4 files changed, 415 insertions, 94 deletions
diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am
index 22c6efc7e..908d9d1e5 100644
--- a/src/video_out/Makefile.am
+++ b/src/video_out/Makefile.am
@@ -25,7 +25,7 @@ endif
#
lib_LTLIBRARIES = $(xv_module) $(syncfb_module) $(xshm_module) $(aa_module)
-xineplug_vo_out_xv_la_SOURCES = alphablend.c video_out_xv.c
+xineplug_vo_out_xv_la_SOURCES = deinterlace.c alphablend.c video_out_xv.c
xineplug_vo_out_xv_la_LIBADD = $(XV_LIB) $(X_LIBS) -lXext
xineplug_vo_out_xv_la_LDFLAGS = -avoid-version -module
@@ -41,7 +41,7 @@ xineplug_vo_out_aa_la_SOURCES = video_out_aa.c
xineplug_vo_out_aa_la_LIBADD = $(AALIB_LIBS)
xineplug_vo_out_aa_la_LDFLAGS = -avoid-version -module
-noinst_HEADERS = yuv2rgb.h video_out_syncfb.h alphablend.h
+noinst_HEADERS = yuv2rgb.h video_out_syncfb.h alphablend.h deinterlace.h
include_HEADERS = video_out_x11.h
diff --git a/src/video_out/deinterlace.c b/src/video_out/deinterlace.c
new file mode 100644
index 000000000..13217b111
--- /dev/null
+++ b/src/video_out/deinterlace.c
@@ -0,0 +1,217 @@
+ /*
+ * 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
+ *
+ * Deinterlace routines by Miguel Freitas
+ * based of DScaler project sources (deinterlace.sourceforge.net)
+ *
+ * Currently only available for Xv driver and MMX extensions
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "xine_internal.h"
+#include "cpu_accel.h"
+#include "deinterlace.h"
+
+/*
+ DeinterlaceFieldBob algorithm
+ Based on Virtual Dub plugin by Gunnar Thalin
+ MMX asm version from dscaler project (deinterlace.sourceforge.net)
+ Linux version for Xine player by Miguel Freitas
+ Todo: use a MMX optimized memcpy
+*/
+static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc,
+ int width, int height )
+{
+#ifdef ARCH_X86
+
+ int Line;
+ long long* YVal1;
+ long long* YVal2;
+ long long* YVal3;
+ long long* Dest;
+ uint8_t* pEvenLines = psrc;
+ uint8_t* pOddLines = psrc+width;
+ int LineLength = width;
+ int Pitch = width * 2;
+ int IsOdd = 1;
+ long EdgeDetect = 625;
+ long JaggieThreshold = 73;
+
+ int n;
+
+ unsigned long long qwEdgeDetect;
+ unsigned long long qwThreshold;
+ const unsigned long long Mask = 0xfefefefefefefefe;
+ const unsigned long long YMask = 0x00ff00ff00ff00ff;
+
+ qwEdgeDetect = EdgeDetect;
+ qwEdgeDetect += (qwEdgeDetect << 48) + (qwEdgeDetect << 32) + (qwEdgeDetect << 16);
+ qwThreshold = JaggieThreshold;
+ qwThreshold += (qwThreshold << 48) + (qwThreshold << 32) + (qwThreshold << 16);
+
+
+ // copy first even line no matter what, and the first odd line if we're
+ // processing an odd field.
+ memcpy(pdst, pEvenLines, LineLength);
+ if (IsOdd)
+ memcpy(pdst + LineLength, pOddLines, LineLength);
+
+ height = height / 2;
+ for (Line = 0; Line < height - 1; ++Line)
+ {
+ if (IsOdd)
+ {
+ YVal1 = (long long *)(pOddLines + Line * Pitch);
+ YVal2 = (long long *)(pEvenLines + (Line + 1) * Pitch);
+ YVal3 = (long long *)(pOddLines + (Line + 1) * Pitch);
+ Dest = (long long *)(pdst + (Line * 2 + 2) * LineLength);
+ }
+ else
+ {
+ YVal1 = (long long *)(pEvenLines + Line * Pitch);
+ YVal2 = (long long *)(pOddLines + Line * Pitch);
+ YVal3 = (long long *)(pEvenLines + (Line + 1) * Pitch);
+ Dest = (long long *)(pdst + (Line * 2 + 1) * LineLength);
+ }
+
+ // For ease of reading, the comments below assume that we're operating on an odd
+ // field (i.e., that bIsOdd is true). The exact same processing is done when we
+ // operate on an even field, but the roles of the odd and even fields are reversed.
+ // It's just too cumbersome to explain the algorithm in terms of "the next odd
+ // line if we're doing an odd field, or the next even line if we're doing an
+ // even field" etc. So wherever you see "odd" or "even" below, keep in mind that
+ // half the time this function is called, those words' meanings will invert.
+
+ // Copy the odd line to the overlay verbatim.
+ memcpy((char *)Dest + LineLength, YVal3, LineLength);
+
+ n = LineLength >> 3;
+ while( n-- )
+ {
+ movq_m2r (*YVal1++, mm0);
+ movq_m2r (*YVal2++, mm1);
+ movq_m2r (*YVal3++, mm2);
+
+ // get intensities in mm3 - 4
+ movq_r2r ( mm0, mm3 );
+ movq_r2r ( mm1, mm4 );
+ movq_r2r ( mm2, mm5 );
+
+ pand_m2r ( *&YMask, mm3 );
+ pand_m2r ( *&YMask, mm4 );
+ pand_m2r ( *&YMask, mm5 );
+
+ // get average in mm0
+ pand_m2r ( *&Mask, mm0 );
+ pand_m2r ( *&Mask, mm2 );
+ psrlw_i2r ( 01, mm0 );
+ psrlw_i2r ( 01, mm2 );
+ paddw_r2r ( mm2, mm0 );
+
+ // work out (O1 - E) * (O2 - E) / 2 - EdgeDetect * (O1 - O2) ^ 2 >> 12
+ // result will be in mm6
+
+ psrlw_i2r ( 01, mm3 );
+ psrlw_i2r ( 01, mm4 );
+ psrlw_i2r ( 01, mm5 );
+
+ movq_r2r ( mm3, mm6 );
+ psubw_r2r ( mm4, mm6 ); //mm6 = O1 - E
+
+ movq_r2r ( mm5, mm7 );
+ psubw_r2r ( mm4, mm7 ); //mm7 = O2 - E
+
+ pmullw_r2r ( mm7, mm6 ); // mm6 = (O1 - E) * (O2 - E)
+
+ movq_r2r ( mm3, mm7 );
+ psubw_r2r ( mm5, mm7 ); // mm7 = (O1 - O2)
+ pmullw_r2r ( mm7, mm7 ); // mm7 = (O1 - O2) ^ 2
+ psrlw_i2r ( 12, mm7 ); // mm7 = (O1 - O2) ^ 2 >> 12
+ pmullw_m2r ( *&qwEdgeDetect, mm7 );// mm7 = EdgeDetect * (O1 - O2) ^ 2 >> 12
+
+ psubw_r2r ( mm7, mm6 ); // mm6 is what we want
+
+ pcmpgtw_m2r ( *&qwThreshold, mm6 );
+
+ movq_r2r ( mm6, mm7 );
+
+ pand_r2r ( mm6, mm0 );
+
+ pandn_r2r ( mm1, mm7 );
+
+ por_r2r ( mm0, mm7 );
+
+ movq_r2m ( mm7, *Dest++ );
+ }
+ }
+
+ // Copy last odd line if we're processing an even field.
+ if (! IsOdd)
+ {
+ memcpy(pdst + (height * 2 - 1) * LineLength,
+ pOddLines + (height - 1) * Pitch,
+ LineLength);
+ }
+
+ // clear out the MMX registers ready for doing floating point
+ // again
+ emms();
+#endif
+}
+
+
+static int check_for_mmx(void)
+{
+#ifdef ARCH_X86
+static int config_flags = -1;
+
+ if ( config_flags == -1 )
+ config_flags = mm_accel();
+ if (config_flags & MM_ACCEL_X86_MMX)
+ return 1;
+ return 0;
+#elif
+ return 0;
+#endif
+}
+
+static void abort_mmx_missing(void)
+{
+ printf("deinterlace: Fatal error, MMX instruction set needed!\n");
+ /* FIXME: is it possible to call some "nicer" xine exit function? */
+ exit(1);
+}
+
+void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc,
+ int width, int height, int method )
+{
+ switch( method ) {
+ case DEINTERLACE_NONE:
+ memcpy(pdst,psrc,width*height);
+ break;
+ case DEINTERLACE_BOB:
+ if( check_for_mmx() )
+ deinterlace_bob_yuv_mmx(pdst,psrc,width,height);
+ else /* FIXME: provide an alternative? */
+ abort_mmx_missing();
+ break;
+ }
+}
diff --git a/src/video_out/deinterlace.h b/src/video_out/deinterlace.h
new file mode 100644
index 000000000..fc9e69bd4
--- /dev/null
+++ b/src/video_out/deinterlace.h
@@ -0,0 +1,39 @@
+ /*
+ * 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
+ *
+ * Deinterlace routines by Miguel Freitas
+ * based of DScaler project sources (deinterlace.sourceforge.net)
+ *
+ * Currently only available for Xv driver and MMX extensions
+ *
+ */
+
+#ifndef __DEINTERLACE_H__
+#define __DEINTERLACE_H__
+
+#include "video_out.h"
+
+void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc,
+ int width, int height, int method );
+
+
+#define DEINTERLACE_NONE 0
+#define DEINTERLACE_BOB 1
+
+#endif
diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c
index 201dc7f10..25b8f6aa1 100644
--- a/src/video_out/video_out_xv.c
+++ b/src/video_out/video_out_xv.c
@@ -1,8 +1,8 @@
-/*
+/*
* Copyright (C) 2000, 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
@@ -12,12 +12,12 @@
* 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: video_out_xv.c,v 1.58 2001/09/10 14:18:47 guenter Exp $
+ * $Id: video_out_xv.c,v 1.59 2001/09/16 15:14:30 miguelfreitas Exp $
*
* video_out_xv.c, X11 video extension interface for xine
*
@@ -57,6 +57,7 @@
#include "xine_internal.h"
/* #include "overlay.h" */
#include "alphablend.h"
+#include "deinterlace.h"
uint32_t xine_debug;
@@ -108,27 +109,30 @@ typedef struct {
vo_overlay_t *overlay;
/* size / aspect ratio calculations */
- int delivered_width; /* everything is set up for
+ int delivered_width; /* everything is set up for
these frame dimensions */
- int delivered_height; /* the dimension as they come
+ int delivered_height; /* the dimension as they come
from the decoder */
int delivered_ratio_code;
- double ratio_factor; /* output frame must fullfill:
+ double ratio_factor; /* output frame must fullfill:
height = width * ratio_factor */
- int output_width; /* frames will appear in this
+ int output_width; /* frames will appear in this
size (pixels) on screen */
int output_height;
int output_xoffset;
int output_yoffset;
+ xv_frame_t deinterlace_frame;
+ int deinterlace_method;
+
/* display anatomy */
- double display_ratio; /* given by visual parameter
+ double display_ratio; /* given by visual parameter
from init function */
/* gui callback */
void (*request_dest_size) (int video_width, int video_height,
- int *dest_x, int *dest_y,
+ int *dest_x, int *dest_y,
int *dest_height, int *dest_width);
} xv_driver_t;
@@ -152,10 +156,10 @@ static void xv_frame_dispose (vo_frame_t *vo_img) {
xv_driver_t *this = (xv_driver_t *) vo_img->instance->driver;
if (frame->image) {
- XLockDisplay (this->display);
+ XLockDisplay (this->display);
XShmDetach (this->display, &frame->shminfo);
XFree (frame->image);
- XUnlockDisplay (this->display);
+ XUnlockDisplay (this->display);
shmdt (frame->shminfo.shmaddr);
shmctl (frame->shminfo.shmid, IPC_RMID,NULL);
@@ -181,16 +185,16 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) {
/*
* supply required functions
*/
-
+
frame->vo_frame.copy = NULL;
- frame->vo_frame.field = xv_frame_field;
+ frame->vo_frame.field = xv_frame_field;
frame->vo_frame.dispose = xv_frame_dispose;
-
+
return (vo_frame_t *) frame;
}
int HandleXError (Display *display, XErrorEvent *xevent) {
-
+
char str [1024];
XGetErrorText (display, xevent->error_code, str, 1024);
@@ -214,7 +218,7 @@ static void x11_DeInstallXErrorHandler (xv_driver_t *this)
XFlush (this->display);
}
-static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
+static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
int width, int height, int format) {
unsigned int xv_format;
@@ -234,58 +238,58 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
fprintf (stderr, "create_ximage: unknown format %08x\n",format);
exit (1);
}
-
+
if (this->use_shm) {
/*
* try shm
*/
-
+
gX11Fail = 0;
x11_InstallXErrorHandler (this);
image = XvShmCreateImage(this->display, this->xv_port, xv_format, 0,
width, height, shminfo);
-
+
if (image == NULL ) {
printf("video_out_xv: XvShmCreateImage failed\n");
printf("video_out_xv: => not using MIT Shared Memory extension.\n");
this->use_shm = 0;
goto finishShmTesting;
}
-
- shminfo->shmid=shmget(IPC_PRIVATE,
- image->data_size,
+
+ shminfo->shmid=shmget(IPC_PRIVATE,
+ image->data_size,
IPC_CREAT | 0777);
-
- if (image->data_size==0) {
+
+ if (image->data_size==0) {
printf("video_out_xv: XvShmCreateImage returned a zero size\n");
printf("video_out_xv: => not using MIT Shared Memory extension.\n");
this->use_shm = 0;
goto finishShmTesting;
- }
-
+ }
+
if (shminfo->shmid < 0 ) {
- perror("video_out_xv: shared memory error in shmget: ");
+ perror("video_out_xv: shared memory error in shmget: ");
printf("video_out_xv: => not using MIT Shared Memory extension.\n");
this->use_shm = 0;
goto finishShmTesting;
}
-
+
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
-
+
if (shminfo->shmaddr == NULL) {
printf("video_out_xv: shared memory error (address error NULL)\n");
this->use_shm = 0;
goto finishShmTesting;
}
-
+
if (shminfo->shmaddr == ((char *) -1)) {
printf("video_out_xv: shared memory error (address error)\n");
this->use_shm = 0;
goto finishShmTesting;
}
-
+
shminfo->readOnly = False;
image->data = shminfo->shmaddr;
@@ -293,7 +297,7 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
XSync(this->display, False);
shmctl(shminfo->shmid, IPC_RMID, 0);
-
+
if (gX11Fail) {
printf ("video_out_xv: x11 error during shared memory XImage creation\n");
printf ("video_out_xv: => not using MIT Shared Memory extension.\n");
@@ -304,7 +308,7 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
goto finishShmTesting;
}
- /*
+ /*
* Now that the Xserver has learned about and attached to the
* shared memory segment, delete it. It's actually deleted by
* the kernel when all users of that segment have detached from
@@ -330,14 +334,14 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo,
image = XvCreateImage (this->display, this->xv_port,
xv_format, data, width, height);
-
+
}
return image;
}
-static void dispose_ximage (xv_driver_t *this,
- XShmSegmentInfo *shminfo,
+static void dispose_ximage (xv_driver_t *this,
+ XShmSegmentInfo *shminfo,
XvImage *myimage) {
if (this->use_shm) {
@@ -365,13 +369,13 @@ static void xv_update_frame_format (vo_driver_t *this_gen,
xv_driver_t *this = (xv_driver_t *) this_gen;
xv_frame_t *frame = (xv_frame_t *) frame_gen;
- if ((frame->width != width)
+ if ((frame->width != width)
|| (frame->height != height)
|| (frame->format != format)) {
/* printf ("video_out_xv: updating frame to %d x %d (ratio=%d, format=%08x)\n",width,height,ratio_code,format); */
- XLockDisplay (this->display);
+ XLockDisplay (this->display);
/*
* (re-) allocate xvimage
@@ -391,15 +395,58 @@ static void xv_update_frame_format (vo_driver_t *this_gen,
frame->width = width;
frame->height = height;
frame->format = format;
-
- XUnlockDisplay (this->display);
+
+ XUnlockDisplay (this->display);
}
frame->ratio_code = ratio_code;
}
-static void xv_adapt_to_output_area (xv_driver_t *this,
- int dest_x, int dest_y,
+static void xv_deinterlace_frame (vo_driver_t *this_gen,
+ vo_frame_t *frame_gen ) {
+
+ xv_driver_t *this = (xv_driver_t *) this_gen;
+ xv_frame_t *frame = (xv_frame_t *) frame_gen;
+ XvImage *imgtmp;
+
+ if ( !this->deinterlace_frame.image
+ || (frame->width != this->deinterlace_frame.width)
+ || (frame->height != this->deinterlace_frame.height)
+ || (frame->format != this->deinterlace_frame.format)) {
+ XLockDisplay (this->display);
+
+ if( this->deinterlace_frame.image )
+ dispose_ximage (this, &this->deinterlace_frame.shminfo,
+ this->deinterlace_frame.image);
+
+ this->deinterlace_frame.image = create_ximage (this, &this->deinterlace_frame.shminfo,
+ frame->width,frame->height, frame->format);
+ this->deinterlace_frame.width = frame->width;
+ this->deinterlace_frame.height = frame->height;
+ this->deinterlace_frame.format = frame->format;
+
+ XUnlockDisplay (this->display);
+ }
+
+ memcpy(this->deinterlace_frame.image->data + frame->width*frame->height,
+ frame->image->data + frame->width*frame->height,
+ frame->width*frame->height*1/2);
+
+ imgtmp = this->deinterlace_frame.image;
+ this->deinterlace_frame.image = frame->image;
+ frame->image = imgtmp;
+ frame->vo_frame.base[0] = frame->image->data;
+ frame->vo_frame.base[1] = frame->image->data + frame->width * frame->height * 5 / 4;
+ frame->vo_frame.base[2] = frame->image->data + frame->width * frame->height;
+
+
+ deinterlace_yuv( frame->image->data, this->deinterlace_frame.image->data,
+ frame->width, frame->height, this->deinterlace_method );
+}
+
+
+static void xv_adapt_to_output_area (xv_driver_t *this,
+ int dest_x, int dest_y,
int dest_width, int dest_height) {
/*
@@ -419,29 +466,29 @@ static void xv_adapt_to_output_area (xv_driver_t *this,
this->output_height = dest_height;
this->output_xoffset = dest_x + (dest_width - this->output_width) / 2;
this->output_yoffset = dest_y;
- }
+ }
/*
* clear unused output area
*/
- XLockDisplay (this->display);
+ XLockDisplay (this->display);
XSetForeground (this->display, this->gc, this->black.pixel);
- XFillRectangle(this->display, this->drawable, this->gc,
+ XFillRectangle(this->display, this->drawable, this->gc,
dest_x, dest_y, dest_width, this->output_yoffset - dest_y);
XFillRectangle(this->display, this->drawable, this->gc,
dest_x, dest_y, this->output_xoffset-dest_x, dest_height);
- XFillRectangle(this->display, this->drawable, this->gc,
- dest_x, this->output_yoffset+this->output_height,
- dest_width,
+ XFillRectangle(this->display, this->drawable, this->gc,
+ dest_x, this->output_yoffset+this->output_height,
+ dest_width,
dest_height - this->output_yoffset - this->output_height);
XFillRectangle(this->display, this->drawable, this->gc,
this->output_xoffset+this->output_width, dest_y,
- dest_width - this->output_xoffset - this->output_width,
+ dest_width - this->output_xoffset - this->output_width,
dest_height);
XUnlockDisplay (this->display);
}
@@ -465,15 +512,15 @@ static void xv_calc_format (xv_driver_t *this,
* aspect ratio calculation
*/
- image_ratio =
+ image_ratio =
(double) this->delivered_width / (double) this->delivered_height;
xprintf (VERBOSE | VIDEO, "display_ratio : %f\n", this->display_ratio);
- xprintf (VERBOSE | VIDEO, "stream aspect ratio : %f , code : %d\n",
+ xprintf (VERBOSE | VIDEO, "stream aspect ratio : %f , code : %d\n",
image_ratio, ratio_code);
switch (this->props[VO_PROP_ASPECT_RATIO].value) {
- case ASPECT_AUTO:
+ case ASPECT_AUTO:
switch (ratio_code) {
case 3: /* anamorphic */
desired_ratio = 16.0 /9.0;
@@ -486,7 +533,7 @@ static void xv_calc_format (xv_driver_t *this,
case 1: /* "square" => 4:3 */
case 2: /* 4:3 */
default:
- xprintf (VIDEO, "unknown aspect ratio (%d) in stream => using 4:3\n",
+ xprintf (VIDEO, "unknown aspect ratio (%d) in stream => using 4:3\n",
ratio_code);
desired_ratio = 4.0 / 3.0;
break;
@@ -509,7 +556,7 @@ static void xv_calc_format (xv_driver_t *this,
* calc ideal output frame size
*/
- corr_factor = this->ratio_factor / image_ratio ;
+ corr_factor = this->ratio_factor / image_ratio ;
if (corr_factor >= 1.0) {
ideal_width = this->delivered_width * corr_factor;
@@ -574,9 +621,9 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
if ( (frame->width != this->delivered_width)
- || (frame->height != this->delivered_height)
+ || (frame->height != this->delivered_height)
|| (frame->ratio_code != this->delivered_ratio_code) ) {
-
+
xv_calc_format (this, frame->width, frame->height, frame->ratio_code);
}
// Alpha Blend here
@@ -584,53 +631,56 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
// blend_yuv( frame->image->data, this->overlay, frame->width, frame->height);
// }
+ if( this->deinterlace_method )
+ xv_deinterlace_frame (this_gen, frame_gen );
+
XLockDisplay (this->display);
-
+
this->cur_frame = frame;
if (this->use_shm) {
- XvShmPutImage(this->display, this->xv_port,
+ XvShmPutImage(this->display, this->xv_port,
this->drawable, this->gc, frame->image,
0, 0, frame->width, frame->height-5,
this->output_xoffset, this->output_yoffset,
this->output_width, this->output_height, True);
-
+
this->expecting_event = 10;
} else {
- XvPutImage(this->display, this->xv_port,
+ XvPutImage(this->display, this->xv_port,
this->drawable, this->gc, frame->image,
0, 0, frame->width, frame->height-5,
this->output_xoffset, this->output_yoffset,
this->output_width, this->output_height);
}
-
- XFlush(this->display);
-
+
+ XFlush(this->display);
+
XUnlockDisplay (this->display);
-
+
}
}
static int xv_get_property (vo_driver_t *this_gen, int property) {
-
+
xv_driver_t *this = (xv_driver_t *) this_gen;
return this->props[property].value;
}
-static int xv_set_property (vo_driver_t *this_gen,
+static int xv_set_property (vo_driver_t *this_gen,
int property, int value) {
xv_driver_t *this = (xv_driver_t *) this_gen;
if (this->props[property].atom != None) {
- XvSetPortAttribute (this->display, this->xv_port,
+ XvSetPortAttribute (this->display, this->xv_port,
this->props[property].atom, value);
- XvGetPortAttribute (this->display, this->xv_port,
+ XvGetPortAttribute (this->display, this->xv_port,
this->props[property].atom,
&this->props[property].value);
- this->config->set_int (this->config, this->props[property].key,
+ this->config->set_int (this->config, this->props[property].key,
this->props[property].value);
return this->props[property].value;
@@ -638,28 +688,34 @@ static int xv_set_property (vo_driver_t *this_gen,
switch (property) {
case VO_PROP_INTERLACED:
this->props[property].value = value;
- printf("video_out_xv: VO_PROP_INTERLACED(%d)\n",
+ printf("video_out_xv: VO_PROP_INTERLACED(%d)\n",
this->props[property].value);
break;
case VO_PROP_ASPECT_RATIO:
-
+
if (value>ASPECT_DVB)
value = ASPECT_AUTO;
-
+
this->props[property].value = value;
- printf("video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n",
+ printf("video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n",
this->props[property].value);
- xv_calc_format (this, this->delivered_width, this->delivered_height,
+ xv_calc_format (this, this->delivered_width, this->delivered_height,
this->delivered_ratio_code) ;
break;
+ case VO_PROP_SOFT_DEINTERLACE:
+ this->props[property].value = value;
+ printf("video_out_xv: VO_PROP_SOFT_DEINTERLACE (%d)\n",
+ this->props[property].value);
+ this->deinterlace_method = value;
+ break;
}
}
-
+
return value;
}
-static void xv_get_property_min_max (vo_driver_t *this_gen,
+static void xv_get_property_min_max (vo_driver_t *this_gen,
int property, int *min, int *max) {
xv_driver_t *this = (xv_driver_t *) this_gen;
@@ -705,7 +761,7 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen,
XLockDisplay (this->display);
if (this->use_shm) {
- XvShmPutImage(this->display, this->xv_port,
+ XvShmPutImage(this->display, this->xv_port,
this->drawable, this->gc, this->cur_frame->image,
0, 0, this->cur_frame->width, this->cur_frame->height-5,
this->output_xoffset, this->output_yoffset,
@@ -717,8 +773,8 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen,
this->output_xoffset, this->output_yoffset,
this->output_width, this->output_height);
}
- XFlush(this->display);
-
+ XFlush(this->display);
+
XUnlockDisplay (this->display);
}
}
@@ -738,6 +794,13 @@ static void xv_exit (vo_driver_t *this_gen) {
xv_driver_t *this = (xv_driver_t *) this_gen;
+ if( this->deinterlace_frame.image )
+ {
+ dispose_ximage (this, &this->deinterlace_frame.shminfo,
+ this->deinterlace_frame.image);
+ this->deinterlace_frame.image = NULL;
+ }
+
XLockDisplay (this->display);
if(XvUngrabPort (this->display, this->xv_port, CurrentTime) != Success) {
fprintf(stderr, "xv_exit: XvUngrabPort() failed.\n");
@@ -762,10 +825,10 @@ static int xv_check_yv12 (Display *display, XvPortID port) {
}
static void xv_check_capability (xv_driver_t *this,
- uint32_t capability,
+ uint32_t capability,
int property, XvAttribute attr,
int base_id, char *str_prop) {
-
+
int nDefault;
this->capabilities |= capability;
@@ -777,7 +840,7 @@ static void xv_check_capability (xv_driver_t *this,
XvGetPortAttribute (this->display, this->xv_port,
this->props[property].atom, &nDefault);
- xv_set_property (&this->vo_driver, property,
+ xv_set_property (&this->vo_driver, property,
this->config->lookup_int (this->config, str_prop, nDefault));
}
@@ -796,7 +859,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
XColor dummy;
XvImage *myimage;
XShmSegmentInfo myshminfo;
-
+
display = visual->display;
xine_debug = config->lookup_int (config, "xine_debug", 0);
@@ -813,7 +876,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
* check adaptors, search for one that supports (at least) yuv12
*/
- if (Success != XvQueryAdaptors(display,DefaultRootWindow(display),
+ if (Success != XvQueryAdaptors(display,DefaultRootWindow(display),
&adaptors,&adaptor_info)) {
printf("video_out_xv: XvQueryAdaptors failed.\n");
return NULL;
@@ -837,7 +900,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
}
}
-
+
adaptor_num++;
}
@@ -881,9 +944,11 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
this->capabilities = 0;
this->expecting_event = 0;
this->use_shm = 1;
+ this->deinterlace_method = 0;
+ this->deinterlace_frame.image = NULL;
- XAllocNamedColor(this->display,
- DefaultColormap(this->display, this->screen),
+ XAllocNamedColor(this->display,
+ DefaultColormap(this->display, this->screen),
"black", &this->black, &dummy);
this->vo_driver.get_capabilities = xv_get_capabilities;
@@ -912,7 +977,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
this->props[VO_PROP_INTERLACED].value = 0;
this->props[VO_PROP_ASPECT_RATIO].value = ASPECT_AUTO;
- /*
+ /*
* check this adaptor's capabilities
*/
@@ -963,7 +1028,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
XvFreeAdaptorInfo (adaptor_info);
- /*
+ /*
* check supported image formats
*/
@@ -993,7 +1058,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) {
}
/*
- * try to create a shared image
+ * try to create a shared image
* to find out if MIT shm really works
*/