diff options
author | Thomas Hellström <totte67@users.sourceforge.net> | 2004-10-12 07:40:07 +0000 |
---|---|---|
committer | Thomas Hellström <totte67@users.sourceforge.net> | 2004-10-12 07:40:07 +0000 |
commit | 937f0bc598b5b91cc0a8368d6007467d0925d5f6 (patch) | |
tree | f695bc88cbbdfc8b0ea98314735b112d28c520fb | |
parent | 77b3e88fe2cf735c457756c8fdbe3f1c78d5ef85 (diff) | |
download | xine-lib-937f0bc598b5b91cc0a8368d6007467d0925d5f6.tar.gz xine-lib-937f0bc598b5b91cc0a8368d6007467d0925d5f6.tar.bz2 |
xxmc driver updates:
Updated software fallback mechanism to be compatible with post plugin
deinterlacing. A decoder using the plugin can now request a software
fallback format to be used if acceleration fails.
Removed the software deinterlacer that was inherited from the xv plugin.
Made idct/mocomp fall back to software decoding for interlaced streams, since
these are not rendered correctly either with the xvmc or the xxmc plugin.
CVS patchset: 7029
CVS date: 2004/10/12 07:40:07
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | src/libmpeg2/decode.c | 10 | ||||
-rw-r--r-- | src/libmpeg2/slice_xvmc_vld.c | 26 | ||||
-rw-r--r-- | src/libmpeg2/xxmc.h | 3 | ||||
-rw-r--r-- | src/video_out/video_out_xxmc.c | 604 | ||||
-rw-r--r-- | src/video_out/xxmc.h | 7 | ||||
-rw-r--r-- | src/xine-engine/accel_xvmc.h | 10 |
7 files changed, 246 insertions, 415 deletions
@@ -25,6 +25,7 @@ menu and feature with the Escape key [bug #1025469] * video image scaling can now be disabled for more video output plugins than XShm [feature requests #987635, #856408] + * Updated the xxmc driver with a better software fallback mechanism xine-lib (1-rc6) * Moved win32 frontend into separate module. diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 114e8bc11..c4ac7c9ba 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -285,7 +285,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, if (mpeg2dec->frame_format == XINE_IMGFMT_XXMC) { xine_xxmc_t *xxmc = (xine_xxmc_t *) picture->current_frame->accel_data; - switch(xxmc->format) { + switch(picture->current_frame->format) { case XINE_IMGFMT_XXMC: switch(xxmc->acceleration) { case XINE_XVMC_ACCEL_VLD: @@ -533,7 +533,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, * Move to libmpeg2_accel.c * int libmpeg2_accel_new_frame(mpeg2dec_t *, picture_t *) */ - mpeg2_xxmc_choose_coding(mpeg2dec->frame_format, picture); + mpeg2_xxmc_choose_coding(mpeg2dec, picture, get_aspect_ratio(mpeg2dec), + flags); /* * End of new frame accel code. */ @@ -549,7 +550,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, * Move to libmpeg2_accel.c * int libmpeg2_accel_new_frame(mpeg2dec_t *, picture_t *) */ - mpeg2_xxmc_choose_coding(mpeg2dec->frame_format, picture); + mpeg2_xxmc_choose_coding(mpeg2dec, picture, + get_aspect_ratio(mpeg2dec), flags); /* * End of new frame accel code. */ @@ -632,7 +634,7 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, { xine_xxmc_t *xxmc = (xine_xxmc_t *) picture->current_frame->accel_data; - switch(xxmc->format) { + switch(picture->current_frame->format) { case XINE_IMGFMT_XXMC: switch(xxmc->acceleration) { case XINE_XVMC_ACCEL_VLD: diff --git a/src/libmpeg2/slice_xvmc_vld.c b/src/libmpeg2/slice_xvmc_vld.c index 950ec1f63..3da94237b 100644 --- a/src/libmpeg2/slice_xvmc_vld.c +++ b/src/libmpeg2/slice_xvmc_vld.c @@ -48,8 +48,12 @@ static uint8_t alternate_scan [64] ATTR_ALIGN(16) = -void mpeg2_xxmc_choose_coding(int decoder_format, picture_t *picture) +void mpeg2_xxmc_choose_coding(mpeg2dec_t *mpeg2dec, picture_t *picture, + double aspect_ratio, int flags) { + int + decoder_format = mpeg2dec->frame_format; + if (picture->current_frame) { if (XINE_IMGFMT_XXMC == decoder_format) { xine_xxmc_t *xxmc = (xine_xxmc_t *) @@ -60,11 +64,27 @@ void mpeg2_xxmc_choose_coding(int decoder_format, picture_t *picture) * the output plugin. */ - xxmc->format = XINE_IMGFMT_XXMC; + xxmc->fallback_format = XINE_IMGFMT_YV12; xxmc->acceleration = XINE_XVMC_ACCEL_VLD| XINE_XVMC_ACCEL_IDCT | XINE_XVMC_ACCEL_MOCOMP ; + + /* + * Standard MOCOMP / IDCT XvMC implementation for interlaced streams + * is buggy. The bug is inherited from the old XvMC driver. Don't use it until + * it has been fixed. (A volunteer ?) + */ + + if ( picture->picture_structure != 3 ) { + xxmc->acceleration &= ~( XINE_XVMC_ACCEL_IDCT | XINE_XVMC_ACCEL_MOCOMP ); + } + xxmc->mpeg = (picture->mpeg1) ? XINE_XVMC_MPEG_1:XINE_XVMC_MPEG_2; - xxmc->proc_xxmc_frame(picture->current_frame); + xxmc->proc_xxmc_update_frame (picture->current_frame->driver, + picture->current_frame, + picture->coded_picture_width, + picture->coded_picture_height, + aspect_ratio, + XINE_IMGFMT_XXMC,flags); } } } diff --git a/src/libmpeg2/xxmc.h b/src/libmpeg2/xxmc.h index c4221200b..222ead11b 100644 --- a/src/libmpeg2/xxmc.h +++ b/src/libmpeg2/xxmc.h @@ -5,7 +5,8 @@ extern void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture, int code, uint8_t *buffer); -extern void mpeg2_xxmc_choose_coding(int decoder_format, picture_t *picture); +extern void mpeg2_xxmc_choose_coding(mpeg2dec_t *mpeg2dec, picture_t *picture, + double aspect_ratio, int flags); extern void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code); diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index e358ae1c0..305ca73fc 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -18,7 +18,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: video_out_xxmc.c,v 1.3 2004/10/04 08:57:55 totte67 Exp $ + * $Id: video_out_xxmc.c,v 1.4 2004/10/12 07:40:23 totte67 Exp $ * * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine * @@ -31,11 +31,9 @@ * * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001 * X11 unscaled overlay support by Miguel Freitas - Nov 2003 - * XvMC VLD implementation by Thomas Hellström - August-Sep 2004 + * XvMC VLD implementation by Thomas Hellström - August-Oct 2004 * XvMC merge by Thomas Hellström - Sep 2004 * - * Test IDCT - * Test VLD */ @@ -43,7 +41,7 @@ #include "xxmc.h" static int gX11Fail; -static int xxmc_xvmc_update_context(xxmc_driver_t *driver,xxmc_frame_t *frame); +static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame); static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage); @@ -382,6 +380,7 @@ static void xvmc_flush(vo_frame_t *this_gen) /* * Callback function for the VO-loop to duplicate frame data. + * YV12 and YUY2 formats are taken care of in the xine-engine. */ @@ -396,79 +395,51 @@ static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, XvMCSubpicture *tmp; int need_dummy; - if (original->format == XINE_IMGFMT_XXMC) { - xxmc = &orig->xxmc_data; - switch(xxmc->format) { - case XINE_IMGFMT_YV12: - yv12_to_yv12( original->base[0], original->pitches[0], - this_gen->base[0], this_gen->pitches[0], - original->base[1], original->pitches[1], - this_gen->base[1], this_gen->pitches[1], - original->base[2], original->pitches[2], - this_gen->base[2], this_gen->pitches[2], - this_gen->width, this_gen->height); - xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicate Frame YV12.\n"); - break; - case XINE_IMGFMT_XXMC: - xvmc_context_writer_lock( &driver->xvmc_lock); - if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf)) { - xvmc_context_writer_unlock( &driver->xvmc_lock ); - return; - } - this->xxmc_data = *xxmc; - this->width = original->width; - this->height = original->height; - if (! xxmc_xvmc_update_context(driver,this) ) { - xvmc_context_writer_unlock( &driver->xvmc_lock ); - return; - } - xvmc_context_writer_unlock( &driver->xvmc_lock ); - xvmc_context_reader_lock( &driver->xvmc_lock ); - if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf) || - !xxmc_xvmc_surface_valid(driver,this->xvmc_surf)) { - xvmc_context_reader_unlock( &driver->xvmc_lock ); - return; - } - - /* - * Allocate a dummy subpicture and copy using - * XvMCBlendsubpicture2. VLD implementations can do blending with a - * NULL subpicture. Use that if possible. - */ - - need_dummy = (xxmc->acceleration != XINE_XVMC_ACCEL_VLD); - tmp = NULL; - if (need_dummy) { - tmp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, - this->width, this->height, - driver->xvmc_cap - [driver->xvmc_cur_cap].subPicType.id); - } - if (tmp || !need_dummy) { - XVMCLOCKDISPLAY( driver->display ); - if (tmp) XvMCClearSubpicture(driver->display, tmp , 0,0, this->width, - this->height, 0); - if (Success == XvMCBlendSubpicture2( driver->display, orig->xvmc_surf, - this->xvmc_surf, tmp, - 0,0,this->width, this->height, - 0,0,this->width, this->height)) { - this->xxmc_data.decoded = 1; - } - XVMCUNLOCKDISPLAY( driver->display ); - if (tmp) xxmc_xvmc_free_subpicture( driver, tmp); - } - - xvmc_context_reader_unlock( &driver->xvmc_lock ); - xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicated XvMC frame %d %d.\n", - this->width,this->height); - break; - default: - break; - } - } -} + xxmc = &orig->xxmc_data; + xvmc_context_writer_lock( &driver->xvmc_lock); + if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf)) { + xvmc_context_reader_unlock( &driver->xvmc_lock ); + return; + } + this->xxmc_data = *xxmc; + this->width = original->width; + this->height = original->height; + this->format = original->format; + + xxmc_frame_updates(driver,this); + /* + * Allocate a dummy subpicture and copy using + * XvMCBlendsubpicture2. VLD implementations can do blending with a + * NULL subpicture. Use that if possible. + */ + need_dummy = (xxmc->acceleration != XINE_XVMC_ACCEL_VLD); + tmp = NULL; + if (need_dummy) { + tmp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, + this->width, this->height, + driver->xvmc_cap + [driver->xvmc_cur_cap].subPicType.id); + } + if (tmp || !need_dummy) { + XVMCLOCKDISPLAY( driver->display ); + if (tmp) XvMCClearSubpicture(driver->display, tmp , 0,0, this->width, + this->height, 0); + if (Success == XvMCBlendSubpicture2( driver->display, orig->xvmc_surf, + this->xvmc_surf, tmp, + 0,0,this->width, this->height, + 0,0,this->width, this->height)) { + this->xxmc_data.decoded = 1; + } + XVMCUNLOCKDISPLAY( driver->display ); + if (tmp) xxmc_xvmc_free_subpicture( driver, tmp); + } + + xvmc_context_reader_unlock( &driver->xvmc_lock ); + xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicated XvMC frame %d %d.\n", + this->width,this->height); +} static uint32_t xxmc_get_capabilities (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; @@ -550,6 +521,9 @@ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) { frame->vo_frame.field = xxmc_frame_field; frame->vo_frame.dispose = xxmc_frame_dispose; frame->vo_frame.driver = this_gen; + frame->last_sw_format = 0; + frame->vo_frame.accel_data = &frame->xxmc_data; + frame->image = NULL; xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Allocating frame\n"); @@ -591,7 +565,6 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, switch (format) { case XINE_IMGFMT_YV12: - case XINE_IMGFMT_XXMC: xv_format = this->xv_format_yv12; break; case XINE_IMGFMT_YUY2: @@ -702,7 +675,6 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, switch (format) { case XINE_IMGFMT_YV12: - case XINE_IMGFMT_XXMC: data = malloc (width * height * 3/2); break; case XINE_IMGFMT_YUY2: @@ -758,6 +730,7 @@ static void xxmc_dispose_context(xxmc_driver_t *driver) XVMCUNLOCKDISPLAY( driver->display ); driver->contextActive = 0; driver->hwSubpictures = 0; + driver->xvmc_accel = 0; } } @@ -938,8 +911,8 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) XVMCUNLOCKDISPLAY( driver->display ); /* - * If we have a shape overlay, switch to colorkey since we have a - * colorkey overlay. + * If we have a shape X11OSD, switch to colorkey X11OSD since we have a + * colorkey XvMC surface. */ if ( driver->xoverlay ) { @@ -958,7 +931,7 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) } else { /* - * Not a colorkey overlay. Swith to shape. + * Not a colorkey XvMC surface. Switch to shape X11OSD */ if ( driver->xoverlay ) { @@ -975,7 +948,8 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) } -static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame) +static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame, + uint32_t width, uint32_t height) { xine_xxmc_t *xxmc = &frame->xxmc_data; @@ -983,50 +957,52 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame) * Are we at all capable of doing XvMC ? */ - if (driver->xvmc_cap == 0 || frame->format != XINE_IMGFMT_XXMC) + + if (driver->xvmc_cap == 0) return 0; - /* - * Determine if we have to change context. - */ - - if (((frame->width != driver->xvmc_width) || - (frame->height != driver->xvmc_height) || - (xxmc->mpeg != driver->xvmc_mpeg))) { - - - xprintf(driver->xine, XINE_VERBOSITY_LOG, - "video_out_xxmc: New format. Need to change XvMC Context.\n" - "width: %d height: %d mpeg: %d acceleration: %d\n", frame->width, frame->height, + xprintf(driver->xine, XINE_VERBOSITY_LOG, + "video_out_xxmc: New format. Need to change XvMC Context.\n" + "width: %d height: %d mpeg: %d acceleration: %d\n", width, height, xxmc->mpeg, xxmc->acceleration); + + if (frame->xvmc_surf) + xxmc_xvmc_free_surface( driver , frame->xvmc_surf); + frame->xvmc_surf = NULL; - if (frame->xvmc_surf) - xxmc_xvmc_free_surface( driver , frame->xvmc_surf); - frame->xvmc_surf = NULL; - - - xxmc_dispose_context( driver ); - - if (xxmc_find_context( driver, xxmc, frame->width, frame->height )) { - xxmc_create_context( driver, frame->width, frame->height); - xvmc_check_colorkey_properties( driver ); - xxmc_setup_subpictures(driver, frame->width, frame->height); - if ((driver->xvmc_accel & (XINE_XVMC_ACCEL_MOCOMP | XINE_XVMC_ACCEL_IDCT))) { - if (!xxmc_mocomp_create_macroblocks(driver, frame, 1)) { - lprintf("video_out_xxmc: ERROR: Macroblock allocation failed\n"); - xxmc_dispose_context( driver ); - } + xxmc_dispose_context( driver ); + + if (xxmc_find_context( driver, xxmc, width, height )) { + xxmc_create_context( driver, width, height); + xvmc_check_colorkey_properties( driver ); + xxmc_setup_subpictures(driver, width, height); + if ((driver->xvmc_accel & + (XINE_XVMC_ACCEL_MOCOMP | XINE_XVMC_ACCEL_IDCT))) { + if (!xxmc_mocomp_create_macroblocks(driver, frame, 1)) { + lprintf("video_out_xxmc: ERROR: Macroblock allocation failed\n"); + xxmc_dispose_context( driver ); } } + } - if (!driver->contextActive) { - printf("video_out_xxmc: Using software decoding for this stream.\n"); - driver->xvmc_accel = 0; - } else { - printf("video_out_xxmc: Using hardware decoding for this stream.\n"); - } - } + if (!driver->contextActive) { + printf("video_out_xxmc: Using software decoding for this stream.\n"); + driver->xvmc_accel = 0; + } else { + printf("video_out_xxmc: Using hardware decoding for this stream.\n"); + } + driver->xvmc_mpeg = xxmc->mpeg; + driver->xvmc_width = width; + driver->xvmc_height = height; + return driver->contextActive; +} + +static void xxmc_frame_updates(xxmc_driver_t *driver, + xxmc_frame_t *frame) +{ + xine_xxmc_t *xxmc = &frame->xxmc_data; + /* * If we have changed context since the surface was updated, xvmc_surf * is either NULL or invalid. If it is invalid. Set it to NULL. @@ -1042,93 +1018,55 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame) } /* - * If it is NULL, check that we have a valid XvMC context, and in that case, - * create a new surface. + * If it is NULL create a new surface. */ - if ((frame->xvmc_surf == NULL) && (driver->contextActive) ) { + if (frame->xvmc_surf == NULL) { if (NULL == (frame->xvmc_surf = xxmc_xvmc_alloc_surface( driver, &driver->context))) { printf("video_out_xxmc: ERROR: Accelerated surface allocation failed.\n" "video_out_xxmc: You are probably out of framebuffer memory.\n" "video_out_xxmc: Falling back to software decoding.\n"); - driver->xvmc_accel = 0; xxmc_dispose_context( driver ); + return; } } - - - driver->xvmc_mpeg = xxmc->mpeg; - driver->xvmc_width = frame->width; - driver->xvmc_height = frame->height; - return driver->contextActive; -} - - -/* - * This one is called by the decoder to tell us what type of - * XxMC image format it really want to use. It could be either an - * XvMC format or an Xv format. This allows us to handle different - * stream format accelerations such as mpeg2, mpeg4, mpeg1 etc. at - * the same time as we can handle IDCT, MOCOMP, VLD. etc. For un- - * supported XvMC formats, we just fall back to YV12. - */ -static void xxmc_update_xxmc(vo_frame_t *vo_img) { - - xxmc_frame_t *frame = (xxmc_frame_t *) vo_img; - xxmc_driver_t *driver = (xxmc_driver_t *) frame->vo_frame.driver; - xine_xxmc_t *xxmc = &frame->xxmc_data; - - xvmc_context_writer_lock( &driver->xvmc_lock); - if (xxmc->format == XINE_IMGFMT_XXMC) { - - /* - * Check if we can find a suitable context for what the - * decoder plugin wants! Otherwise, fall back to YV12. - */ - - if (! xxmc_xvmc_update_context(driver, frame)) { - - /* - * Either no suitable context was found or an XvMC error occured. - */ + xxmc->acceleration = driver->xvmc_accel; + xxmc->xvmc.macroblocks = (xine_macroblocks_t *) &driver->macroblocks; + xxmc->xvmc.macroblocks->xvmc_accel = (driver->unsigned_intra) ? + 0 : XINE_VO_SIGNED_INTRA; + switch(driver->xvmc_accel) { + case XINE_XVMC_ACCEL_IDCT: + xxmc->xvmc.macroblocks->xvmc_accel |= XINE_VO_IDCT_ACCEL; + break; + case XINE_XVMC_ACCEL_MOCOMP: + xxmc->xvmc.macroblocks->xvmc_accel |= XINE_VO_MOTION_ACCEL; + break; + default: + xxmc->xvmc.macroblocks->xvmc_accel = 0; + } + driver->macroblocks.num_blocks = 0; + driver->macroblocks.macroblockptr = driver->macroblocks.macroblockbaseptr; + driver->macroblocks.xine_mc.blockptr = + driver->macroblocks.xine_mc.blockbaseptr; - xxmc->format = XINE_IMGFMT_YV12; - xxmc->acceleration = 0; - xxmc->xvmc.macroblocks = 0; - } else { - - /* - * We're running accelerated. - */ + /* + * Accelerated callbacks. + */ - xxmc->format = XINE_IMGFMT_XXMC; - xxmc->acceleration = driver->xvmc_accel; - xxmc->xvmc.macroblocks = (xine_macroblocks_t *) &driver->macroblocks; - xxmc->xvmc.macroblocks->xvmc_accel = (driver->unsigned_intra) ? - 0 : XINE_VO_SIGNED_INTRA; - switch(driver->xvmc_accel) { - case XINE_XVMC_ACCEL_IDCT: - xxmc->xvmc.macroblocks->xvmc_accel |= XINE_VO_IDCT_ACCEL; - break; - case XINE_XVMC_ACCEL_MOCOMP: - xxmc->xvmc.macroblocks->xvmc_accel |= XINE_VO_MOTION_ACCEL; - break; - default: - xxmc->xvmc.macroblocks->xvmc_accel = 0; - } - } - driver->macroblocks.num_blocks = 0; - driver->macroblocks.macroblockptr = driver->macroblocks.macroblockbaseptr; - driver->macroblocks.xine_mc.blockptr = driver->macroblocks.xine_mc.blockbaseptr; + xxmc->proc_xxmc_flush = xvmc_flush; + xxmc->xvmc.proc_macro_block = xxmc_xvmc_proc_macro_block; + frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data; +#ifdef HAVE_VLDXVMC + xxmc->proc_xxmc_begin = xvmc_vld_frame; + xxmc->proc_xxmc_slice = xvmc_vld_slice; +#endif - xxmc->decoded = 0; - } - xvmc_context_writer_unlock( &driver->xvmc_lock); } + /* called xlocked */ static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, @@ -1152,54 +1090,69 @@ static void dispose_ximage (xxmc_driver_t *this, } -/* - * Just fills in functions. Surface and context updates are not done here. - */ - -static void xxmc_update_frame_format (vo_driver_t *this_gen, - vo_frame_t *frame_gen, - uint32_t width, uint32_t height, - double ratio, int format, int flags) { +static void xxmc_do_update_frame(vo_driver_t *this_gen, + vo_frame_t *frame_gen, + uint32_t width, uint32_t height, + double ratio, int format, int flags) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; - frame->vo_frame.accel_data = &frame->xxmc_data; if ( XINE_IMGFMT_XXMC == format ) { - frame->xxmc_data.proc_xxmc_frame = xxmc_update_xxmc; - frame->xxmc_data.proc_xxmc_flush = xvmc_flush; -#ifdef HAVE_VLDXVMC - frame->xxmc_data.proc_xxmc_begin = xvmc_vld_frame; - frame->xxmc_data.proc_xxmc_slice = xvmc_vld_slice; -#endif - frame->xxmc_data.xvmc.proc_macro_block = xxmc_xvmc_proc_macro_block; - frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data; + xine_xxmc_t *xxmc = &frame->xxmc_data; + + xvmc_context_writer_lock( &this->xvmc_lock); + if ((this->last_accel_request != xxmc->acceleration) || + (this->xvmc_mpeg != xxmc->mpeg) || + (this->xvmc_width != width) || + (this->xvmc_height != height)) { + this->last_accel_request = xxmc->acceleration; + xxmc_xvmc_update_context(this, frame, width, height); + this->fallback_used = 0; + } + + if (this->contextActive) + xxmc_frame_updates(this, frame); + + format = xxmc->fallback_format; + + if (!this->contextActive) { + this->fallback_used = 1; + xxmc->acceleration = 0; + xxmc->xvmc.macroblocks = 0; + frame->vo_frame.proc_duplicate_frame_data = NULL; + } + xvmc_context_writer_unlock( &this->xvmc_lock); + } else { - frame->xxmc_data.format = format; + frame->vo_frame.proc_duplicate_frame_data = NULL; + if (!this->fallback_used) this->last_accel_request = 0; + xxmc_dispose_context( this ); } if (this->use_pitch_alignment) { width = (width + 7) & ~0x7; } - + if ((frame->width != width) || (frame->height != height) - || (frame->format != format)) { - + || (frame->last_sw_format != format)) { + + frame->last_sw_format = format; XLockDisplay (this->display); - + /* * (re-) allocate xvimage */ - + if (frame->image) { dispose_ximage (this, &frame->shminfo, frame->image); frame->image = NULL; } - + frame->image = create_ximage (this, &frame->shminfo, width, height, format); - + if(format == XINE_IMGFMT_YUY2) { frame->vo_frame.pitches[0] = frame->image->pitches[0]; frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0]; @@ -1212,135 +1165,45 @@ static void xxmc_update_frame_format (vo_driver_t *this_gen, frame->vo_frame.base[1] = frame->image->data + frame->image->offsets[2]; frame->vo_frame.base[2] = frame->image->data + frame->image->offsets[1]; } - - frame->width = width; - frame->height = height; - frame->format = format; XUnlockDisplay (this->display); } frame->ratio = ratio; + frame->width = width; + frame->height = height; + frame->format = (this->contextActive) ? XINE_IMGFMT_XXMC : format; + frame->vo_frame.format = frame->format; } -/* - * From Xv. - */ - - -#define DEINTERLACE_CROMA -static void xxmc_deinterlace_frame (xxmc_driver_t *this) { - uint8_t *recent_bitmaps[VO_NUM_RECENT_FRAMES]; - xxmc_frame_t *frame = this->recent_frames[0]; - int i; - int xvscaling; - - xvscaling = (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) ? 2 : 1; - - if (!this->deinterlace_frame.image - || (frame->width != this->deinterlace_frame.width) - || (frame->height != this->deinterlace_frame.height ) - || (frame->format != this->deinterlace_frame.format) - || (frame->ratio != this->deinterlace_frame.ratio)) { - 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 / xvscaling, - frame->format); - this->deinterlace_frame.width = frame->width; - this->deinterlace_frame.height = frame->height; - this->deinterlace_frame.format = frame->format; - this->deinterlace_frame.ratio = frame->ratio; - - XUnlockDisplay (this->display); - } - - - if ( this->deinterlace_method != DEINTERLACE_ONEFIELDXV ) { -#ifdef DEINTERLACE_CROMA - - /* I don't think this is the right way to do it (deinterlacing croma by croma info). - DScaler deinterlaces croma together with luma, but it's easier for them because - they have that components 1:1 at the same table. - */ - for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) - if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && - this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height; - else - recent_bitmaps[i] = NULL; - - deinterlace_yuv( this->deinterlace_frame.image->data+frame->width*frame->height, - recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method ); - for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) - if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && - this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height*5/4; - else - recent_bitmaps[i] = NULL; - - deinterlace_yuv( this->deinterlace_frame.image->data+frame->width*frame->height*5/4, - recent_bitmaps, frame->width/2, frame->height/2, this->deinterlace_method ); - -#else - - /* know bug: we are not deinterlacing Cb and Cr */ - xine_fast_memcpy(this->deinterlace_frame.image->data + frame->width*frame->height, - frame->image->data + frame->width*frame->height, - frame->width*frame->height*1/2); - -#endif +static void xxmc_update_frame_format(vo_driver_t *this_gen, + vo_frame_t *frame_gen, + uint32_t width, uint32_t height, + double ratio, int format, int flags) +{ - for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) - if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && - this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image->data; - else - recent_bitmaps[i] = NULL; + if (format != XINE_IMGFMT_XXMC) { + xxmc_do_update_frame(this_gen, frame_gen, width, height, + ratio, format, flags); + } else { - deinterlace_yuv( this->deinterlace_frame.image->data, recent_bitmaps, - frame->width, frame->height, this->deinterlace_method ); - } - else { /* - dirty and cheap deinterlace method: we give half of the lines to xv - driver and let it scale for us. - note that memcpy's below don't seem to impact much on performance, - specially when fast memcpys are available. - */ - uint8_t *dst, *src; - - dst = this->deinterlace_frame.image->data; - src = this->recent_frames[0]->image->data; - for( i = 0; i < frame->height; i+=2 ) { - xine_fast_memcpy(dst,src,frame->width); - dst += frame->width; - src += 2 * frame->width; - } - - dst = this->deinterlace_frame.image->data + frame->width * frame->height / 2; - src = this->recent_frames[0]->image->data + frame->width * frame->height; - for( i = 0; i < frame->height; i+=4 ) { - xine_fast_memcpy(dst,src,frame->width / 2); - dst += frame->width / 2; - src += frame->width; - } + * More parameters are needed to xxmc_do_update_frame(). + * Register the function as a callback and return. + * The decoder needs to call the callback with more parameters + * in the xine_xxmc_t structure. + */ - dst = this->deinterlace_frame.image->data + frame->width * frame->height * 5 / 8; - src = this->recent_frames[0]->image->data + frame->width * frame->height * 5 / 4; - for( i = 0; i < frame->height; i+=4 ) { - xine_fast_memcpy(dst,src,frame->width / 2); - dst += frame->width / 2; - src += frame->width; - } + xine_xxmc_t *xxmc = (xine_xxmc_t *)frame_gen->accel_data; + xxmc->decoded = 0; + xxmc->proc_xxmc_update_frame = xxmc_do_update_frame; + frame_gen->proc_duplicate_frame_data = xxmc_duplicate_frame_data; } - - this->cur_frame = &this->deinterlace_frame; } +/* + * From Xv. + */ + static void xxmc_clean_output_area (xxmc_driver_t *this) { int i, autopainting; @@ -1358,9 +1221,9 @@ static void xxmc_clean_output_area (xxmc_driver_t *this) { /* * XvMC does not support autopainting regardless of whether there's an - * Xv attribute for this. If there is an XvMC attribute for autopainting, - * we ca assume it is supported. This is checked whenever a context is - * changed. + * Xv attribute for it. However, if there is an XvMC attribute for + * autopainting, we should be able to assume it is supported. + * That support is checked whenever a context is changed. */ autopainting = (this->props[VO_PROP_AUTOPAINT_COLORKEY].value == 1); @@ -1401,14 +1264,6 @@ static void xxmc_compute_output_size (xxmc_driver_t *this) { _x_vo_scale_compute_output_size( &this->sc ); - /* onefield_xv divide by 2 the number of lines */ - if (this->deinterlace_enabled - && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) - && ((this->cur_frame->format == XINE_IMGFMT_YV12) - || this->cur_frame->format == XINE_IMGFMT_XXMC)) { - this->sc.displayed_height = this->sc.displayed_height / 2 - 1; - this->sc.displayed_yoffset = this->sc.displayed_yoffset / 2; - } } static void xxmc_overlay_begin (vo_driver_t *this_gen, @@ -1536,8 +1391,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, } } } else { - if ((frame->format == XINE_IMGFMT_YV12) || - (frame->format == XINE_IMGFMT_XXMC)) { + if (frame->format == XINE_IMGFMT_YV12) { blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches); } else { @@ -1622,29 +1476,13 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->sc.force_redraw = 1; /* trigger re-calc of output size */ } - - /* - * deinterlace frame if necessary - * (currently only working for YUV images) - */ - - if (this->deinterlace_enabled && this->deinterlace_method - && ((frame->format == XINE_IMGFMT_YV12) || - (frame->format == XINE_IMGFMT_XXMC)) - && deinterlace_yuv_supported( this->deinterlace_method ) == 1) { - if (frame->format != XINE_IMGFMT_XXMC) - xxmc_deinterlace_frame (this); - else if (xxmc->format != XINE_IMGFMT_XXMC) - xxmc_deinterlace_frame (this); - } - /* * tell gui that we are about to display a frame, * ask for offset and output size */ xxmc_redraw_needed (this_gen); - if (frame->xvmc_surf && (xxmc->format == XINE_IMGFMT_XXMC)) { + if (frame->format == XINE_IMGFMT_XXMC) { if (xxmc->decoded && xxmc_xvmc_surface_valid(this, frame->xvmc_surf)) { XVMCLOCKDISPLAY( this->display ); XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable, @@ -1760,12 +1598,8 @@ static int xxmc_set_property (vo_driver_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: VO_PROP_INTERLACED(%d)\n", this->props[property].value); this->deinterlace_enabled = value; - if (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) { - xxmc_compute_ideal_size (this); - xxmc_compute_output_size (this); - } break; - + case VO_PROP_ASPECT_RATIO: if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; @@ -1847,7 +1681,7 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, xxmc_clean_output_area (this); xvmc_context_reader_lock( &this->xvmc_lock ); - if (frame->xvmc_surf && (xxmc->format == XINE_IMGFMT_XXMC)) { + if (frame->format == XINE_IMGFMT_XXMC) { if (xxmc->decoded && xxmc_xvmc_surface_valid(this, frame->xvmc_surf)) { XVMCLOCKDISPLAY( this->display ); XvMCPutSurface( this->display, frame->xvmc_surf, this->drawable, @@ -1912,15 +1746,6 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, rect->w = x2-x1; rect->h = y2-y1; - /* onefield_xv divide by 2 the number of lines */ - if (this->deinterlace_enabled - && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) - && ((this->cur_frame->format == XINE_IMGFMT_YV12) || - (this->cur_frame->format == XINE_IMGFMT_XXMC))) { - rect->y = rect->y * 2; - rect->h = rect->h * 2; - } - } break; @@ -1951,14 +1776,6 @@ static void xxmc_dispose (vo_driver_t *this_gen) { } - if (this->deinterlace_frame.image) { - XLockDisplay (this->display); - dispose_ximage (this, &this->deinterlace_frame.shminfo, - this->deinterlace_frame.image); - XUnlockDisplay (this->display); - this->deinterlace_frame.image = NULL; - } - XLockDisplay (this->display); if(XvUngrabPort (this->display, this->xv_port, CurrentTime) != Success) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: xxmc_exit: XvUngrabPort() failed.\n"); @@ -2122,12 +1939,6 @@ static void xxmc_update_nvidia_fix(void *this_gen, xine_cfg_entry_t *entry) { this->reverse_nvidia_palette = entry->num_value; } -static void xxmc_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - - this->deinterlace_method = entry->num_value; -} - static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) { @@ -2183,11 +1994,11 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) curCap->mpeg_flags = 0; curCap->accel_flags = 0; if (curInfo->chroma_format == XVMC_CHROMA_FORMAT_420) { - curCap->mpeg_flags |= ((curInfo->mc_type & XINE_XVMC_MPEG_1) ? + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ? XINE_XVMC_MPEG_1 : 0); - curCap->mpeg_flags |= ((curInfo->mc_type & XINE_XVMC_MPEG_2) ? + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ? XINE_XVMC_MPEG_2 : 0); - curCap->mpeg_flags |= ((curInfo->mc_type & XINE_XVMC_MPEG_4) ? + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ? XINE_XVMC_MPEG_4 : 0); curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ? XINE_XVMC_ACCEL_VLD : 0); @@ -2270,6 +2081,8 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) this->capabilities |= VO_CAP_XXMC; XVMCUNLOCKDISPLAY( this->display ); init_xx44_palette( &this->palette , 0); + this->last_accel_request = 0xFFFFFFFF; + this->fallback_used = 0; xvmc_context_writer_unlock( &this->xvmc_lock ); return; @@ -2377,8 +2190,6 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi XUnlockDisplay (this->display); this->capabilities = VO_CAP_CROP; this->use_shm = 1; - this->deinterlace_method = 0; - this->deinterlace_frame.image = NULL; this->use_colorkey = 0; this->colorkey = 0; this->xoverlay = NULL; @@ -2583,13 +2394,6 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi "Only for Linux kernel 2.6 series or 2.4 with multimedia patch.\n" "Experimental.\n"), 10, xxmc_update_cpu_save, this); - this->deinterlace_method = - config->register_enum (config, "video.deinterlace_method", 0, - deinterlace_methods, - _("deinterlace_methods"), - _("This config setting is deprecated. You should use the new " - "deinterlacing post processing settings instead.\n"), - 10, xxmc_update_deinterlace, this); this->reverse_nvidia_palette = config->register_bool (config, "video.xvmc_nvidia_color_fix", 0, _("Fix buggy NVIDIA XvMC subpicture colors"), diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index 74825add4..568cc761e 100644 --- a/src/video_out/xxmc.h +++ b/src/video_out/xxmc.h @@ -18,7 +18,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: xxmc.h,v 1.2 2004/10/03 12:36:15 totte67 Exp $ + * $Id: xxmc.h,v 1.3 2004/10/12 07:40:23 totte67 Exp $ * * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine * @@ -136,6 +136,7 @@ typedef struct { XvMCSurface *xvmc_surf; xine_xxmc_t xxmc_data; + int last_sw_format; } xxmc_frame_t; typedef struct{ @@ -208,8 +209,6 @@ struct xxmc_driver_s { /* all scaling information goes here */ vo_scale_t sc; - xxmc_frame_t deinterlace_frame; - int deinterlace_method; int deinterlace_enabled; int use_colorkey; uint32_t colorkey; @@ -244,6 +243,8 @@ struct xxmc_driver_s { xvmc_surface_handler_t xvmc_surf_handler; unsigned xvmc_mpeg; unsigned xvmc_accel; + unsigned last_accel_request; + unsigned fallback_used; unsigned xvmc_width; unsigned xvmc_height; int have_xvmc_autopaint; diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h index ea10a40ff..bccbf9475 100644 --- a/src/xine-engine/accel_xvmc.h +++ b/src/xine-engine/accel_xvmc.h @@ -18,7 +18,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: accel_xvmc.h,v 1.1 2004/09/28 18:49:40 miguelfreitas Exp $ + * $Id: accel_xvmc.h,v 1.2 2004/10/12 07:40:23 totte67 Exp $ * * * Common acceleration definitions for XvMC. @@ -83,10 +83,10 @@ typedef struct xine_xxmc_s { */ xine_xvmc_t xvmc; - - unsigned format; + unsigned mpeg; unsigned acceleration; + int fallback_format; xine_vld_frame_t vld_frame; uint8_t *slice_data; unsigned slice_data_size; @@ -94,7 +94,9 @@ typedef struct xine_xxmc_s { int result; int decoded; float sleep; - void (*proc_xxmc_frame) (vo_frame_t *vo_img); + void (*proc_xxmc_update_frame) (vo_driver_t *this_gen, vo_frame_t *frame_gen, + uint32_t width, uint32_t height, double ratio, + int format, int flags); void (*proc_xxmc_begin) (vo_frame_t *vo_img); void (*proc_xxmc_slice) (vo_frame_t *vo_img); void (*proc_xxmc_flush) (vo_frame_t *vo_img); |