diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2001-09-16 15:14:30 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2001-09-16 15:14:30 +0000 |
commit | ce153b6b3b234f8cbc5c48119b4a3c2538e1fd17 (patch) | |
tree | 844d932da7964901f0b4a3c8b1407a00735472b2 | |
parent | 849562a897431915fd760f83524de0ac8e81c548 (diff) | |
download | xine-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.am | 4 | ||||
-rw-r--r-- | src/video_out/deinterlace.c | 217 | ||||
-rw-r--r-- | src/video_out/deinterlace.h | 39 | ||||
-rw-r--r-- | src/video_out/video_out_xv.c | 249 |
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 */ |