From 143e6ca14ef8d043cc01e922ac6ed03e20b71606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 6 May 2005 07:42:20 +0000 Subject: **BUGFIX** improve xxmc cpu-usage for IDCT / MOCOMP acceleration through better locking [bug #1195282] CVS patchset: 7524 CVS date: 2005/05/06 07:42:20 --- ChangeLog | 2 + src/libmpeg2/decode.c | 4 +- src/libmpeg2/libmpeg2_accel.c | 17 +++++- src/libmpeg2/libmpeg2_accel.h | 4 +- src/libmpeg2/slice_xvmc_vld.c | 12 ++-- src/video_out/video_out_xxmc.c | 126 ++++++++++++++++++++++++++++++----------- src/video_out/xvmc_mocomp.c | 6 +- src/video_out/xvmc_vld.c | 23 +------- src/video_out/xxmc.h | 6 +- src/xine-engine/accel_xvmc.h | 12 +++- 10 files changed, 136 insertions(+), 76 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0030b9f6..abcd28e5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ xine-lib (1.0.2) * speed up xx44 alphablending of large transparent areas * stop libmpeg2 XvMC IDCT / MOCOMP attempting software motion compensation [bug #1194754] + * improve xxmc cpu-usage for IDCT / MOCOMP acceleration through better locking + [bug #1195282] xine-lib (1.0.1) * Big XvMC quality / correctness / cpu-usage fix. [bug #1114517] diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 5d3f78ec5..c4b980f79 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -573,8 +573,8 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, printf("slice target %08x past %08x future %08x\n",picture->current_frame,picture->forward_reference_frame,picture->backward_reference_frame); fflush(stdout); #endif - libmpeg2_accel_slice(&mpeg2dec->accel, mpeg2dec->frame_format, picture, code, buffer, - mpeg2dec->chunk_size, mpeg2dec->chunk_buffer); + libmpeg2_accel_slice(&mpeg2dec->accel, picture, code, buffer, mpeg2dec->chunk_size, + mpeg2dec->chunk_buffer); if( picture->v_offset > picture->limit_y ) { picture->current_frame->bad_frame = 0; } diff --git a/src/libmpeg2/libmpeg2_accel.c b/src/libmpeg2/libmpeg2_accel.c index 376ae3979..54bdee549 100644 --- a/src/libmpeg2/libmpeg2_accel.c +++ b/src/libmpeg2/libmpeg2_accel.c @@ -147,8 +147,8 @@ libmpeg2_accel_frame_completion(mpeg2dec_accel_t * accel, uint32_t frame_format, int -libmpeg2_accel_slice(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t *picture, - int code, char * buffer, uint32_t chunk_size, uint8_t *chunk_buffer) +libmpeg2_accel_slice(mpeg2dec_accel_t *accel, picture_t *picture, int code, char * buffer, + uint32_t chunk_size, uint8_t *chunk_buffer) { /* * Don't reference frames of other formats. They are invalid. This may happen if the @@ -172,13 +172,21 @@ libmpeg2_accel_slice(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t * } } + switch( picture->current_frame->format ) { - switch( frame_format ) { case XINE_IMGFMT_XXMC: { xine_xxmc_t *xxmc = (xine_xxmc_t *) picture->current_frame->accel_data; + if ( xxmc->proc_xxmc_lock_valid( picture->current_frame, + picture->forward_reference_frame, + picture->backward_reference_frame, + picture->current_frame->picture_coding_type)) { + picture->v_offset = 0; + return 1; + } + switch(picture->current_frame->format) { case XINE_IMGFMT_XXMC: switch(xxmc->acceleration) { @@ -198,11 +206,14 @@ libmpeg2_accel_slice(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t * mpeg2_slice (picture, code, buffer); break; } + xxmc->proc_xxmc_unlock(picture->current_frame->driver); break; } + case XINE_IMGFMT_XVMC: mpeg2_xvmc_slice (accel, picture, code, buffer); break; + default: mpeg2_slice (picture, code, buffer); break; diff --git a/src/libmpeg2/libmpeg2_accel.h b/src/libmpeg2/libmpeg2_accel.h index 41b081cc5..5d0b37a78 100644 --- a/src/libmpeg2/libmpeg2_accel.h +++ b/src/libmpeg2/libmpeg2_accel.h @@ -41,8 +41,8 @@ extern int libmpeg2_accel_new_sequence(mpeg2dec_accel_t *accel, uint32_t frame_f extern int libmpeg2_accel_new_frame(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t *picture, double ratio, uint32_t flags); extern void libmpeg2_accel_frame_completion(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t *picture, int code); -extern int libmpeg2_accel_slice(mpeg2dec_accel_t *accel, uint32_t frame_format, picture_t *picture, - int code, char * buffer, uint32_t chunk_size, uint8_t *chunk_buffer); +extern int libmpeg2_accel_slice(mpeg2dec_accel_t *accel, picture_t *picture, int code, + char * buffer, uint32_t chunk_size, uint8_t *chunk_buffer); extern void libmpeg2_accel_scan( mpeg2dec_accel_t *accel, uint8_t *scan_norm, uint8_t *scan_alt); #endif diff --git a/src/libmpeg2/slice_xvmc_vld.c b/src/libmpeg2/slice_xvmc_vld.c index 3c177d97a..3647c7386 100644 --- a/src/libmpeg2/slice_xvmc_vld.c +++ b/src/libmpeg2/slice_xvmc_vld.c @@ -146,7 +146,6 @@ void mpeg2_xxmc_slice( mpeg2dec_accel_t *accel, picture_t *picture, vft->backward_reference_frame = picture->backward_reference_frame; xxmc->proc_xxmc_begin( frame ); if (xxmc->result != 0) { - xxmc->proc_xxmc_flush( frame ); accel->xvmc_last_slice_code=-1; } } @@ -164,9 +163,9 @@ void mpeg2_xxmc_slice( mpeg2dec_accel_t *accel, picture_t *picture, xxmc->slice_data = chunk_buffer; xxmc->slice_code = code; - xxmc->proc_xxmc_slice( frame ); + xxmc->proc_xxmc_slice( frame ); + if (xxmc->result != 0) { - xxmc->proc_xxmc_flush( frame ); accel->xvmc_last_slice_code=-1; return; } @@ -188,7 +187,6 @@ void mpeg2_xxmc_slice( mpeg2dec_accel_t *accel, picture_t *picture, lprintf("libmpeg2: VLD XvMC: Slice error.\n"); accel->xvmc_last_slice_code = -1; - xxmc->proc_xxmc_flush( frame ); return; } } @@ -200,7 +198,11 @@ void mpeg2_xxmc_vld_frame_complete(mpeg2dec_accel_t *accel, picture_t *picture, xine_xxmc_t *xxmc = (xine_xxmc_t *) frame->accel_data; - if (xxmc->decoded || (accel->xvmc_last_slice_code == -1)) return; + if (xxmc->decoded) return; + if (accel->xvmc_last_slice_code == -1) { + xxmc->proc_xxmc_flush( frame ); + return; + } if ((code != 0xff) || ((accel->xvmc_last_slice_code == accel->xxmc_mb_pic_height) && diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index d22d80623..ffdba63d9 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.15 2005/05/04 04:27:20 totte67 Exp $ + * $Id: video_out_xxmc.c,v 1.16 2005/05/06 07:42:21 totte67 Exp $ * * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine * @@ -31,7 +31,7 @@ * * overlay support by James Courtier-Dutton - July 2001 * X11 unscaled overlay support by Miguel Freitas - Nov 2003 - * XvMC VLD implementation by Thomas Hellström - August-Oct 2004 + * XvMC VLD implementation by Thomas Hellström - 2004, 2005. * XvMC merge by Thomas Hellström - Sep 2004 * */ @@ -41,6 +41,7 @@ #include "xxmc.h" #include + static int gX11Fail; static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, int init_macroblocks); @@ -349,10 +350,60 @@ static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub) } +/* + * Callback used by decoder to check that surfaces are still valid, + * and to lock the context so that it won't get destroyed during + * decoding. + */ + + +static int xxmc_lock_and_validate_surfaces(vo_frame_t *cur_frame, + vo_frame_t *fw_frame, + vo_frame_t *bw_frame, + unsigned pc_type) +{ + xxmc_driver_t + *driver = (xxmc_driver_t *) cur_frame->driver; + xxmc_frame_t + *frame; + xvmc_context_reader_lock( &driver->xvmc_lock ); + + switch(pc_type) { + case XINE_PICT_B_TYPE: + frame = (xxmc_frame_t *) bw_frame; + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + /* fall through */ + case XINE_PICT_P_TYPE: + frame = (xxmc_frame_t *) fw_frame; + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + /* fall through */ + default: + frame = (xxmc_frame_t *) cur_frame; + if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; + return 0; + } + + xvmc_context_reader_unlock( &driver->xvmc_lock ); + return -1; +} /* - * Here follows a number of callback function. + * Callback for decoder. Decoding temporarily halted. Release the context. + */ + +static void xxmc_unlock_surfaces(vo_driver_t *this_gen) +{ + xxmc_driver_t + *driver = (xxmc_driver_t *) this_gen; + + xvmc_context_reader_unlock( &driver->xvmc_lock ); +} + +/* + * Callback for decoder. + * Check that the surface is vaid and + * flush outstanding rendering requests on this surface. */ static void xvmc_flush(vo_frame_t *this_gen) @@ -380,13 +431,13 @@ 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. + * This one only deals with hardware surfaces and duplicates them + * using a call to XvMCBlendSubpicture2 with a blank subpicture. */ - static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, vo_frame_t *original) { @@ -731,6 +782,13 @@ static void xxmc_dispose_context(xxmc_driver_t *driver) } } +/* + * Find a suitable XvMC Context according to the acceleration request + * passed to us in the xxmc variable, and to the acceleration type + * priority set up in this plugin. Result is returned in + * driver->xvmc_cur_cap. + */ + static int xxmc_find_context(xxmc_driver_t *driver, xine_xxmc_t *xxmc, unsigned width, unsigned height) { @@ -990,28 +1048,38 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, 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"); + fprintf(stderr, "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; } - } + 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; + } - 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; + + xxmc->proc_xxmc_flush = xvmc_flush; + xxmc->proc_xxmc_lock_valid = xxmc_lock_and_validate_surfaces; + xxmc->proc_xxmc_unlock = xxmc_unlock_surfaces; + + 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 } if (init_macroblocks) { @@ -1020,15 +1088,7 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, 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->acceleration = driver->xvmc_accel; } @@ -1110,7 +1170,7 @@ static void xxmc_do_update_frame_xv(vo_driver_t *this_gen, } /* - * Check if we need to change XvMC context due to a + * Check if we need to change XvMC context due to an * acceleration request change. */ @@ -1133,7 +1193,7 @@ static int xxmc_accel_update(xxmc_driver_t *driver, if ((driver->xvmc_accel & new_request) == 0) return 1; /* - * Test for a higher acceleration level. + * Test for possible use of a higher acceleration level. */ for (k = 0; k < NUM_ACCEL_PRIORITY; ++k) { diff --git a/src/video_out/xvmc_mocomp.c b/src/video_out/xvmc_mocomp.c index 75a1aa4d9..970c243dd 100644 --- a/src/video_out/xvmc_mocomp.c +++ b/src/video_out/xvmc_mocomp.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: xvmc_mocomp.c,v 1.3 2005/02/22 18:31:59 totte67 Exp $ + * $Id: xvmc_mocomp.c,v 1.4 2005/05/06 07:42:21 totte67 Exp $ * * XvMC image support by Jack Kelliher */ @@ -110,7 +110,6 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, int top_field_first = current_frame->top_field_first; int picture_coding_type = current_frame->picture_coding_type; - xvmc_context_reader_lock( &this->xvmc_lock ); mbs->macroblockptr->x = x; mbs->macroblockptr->y = y; @@ -253,9 +252,6 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, mbs->macroblockptr = mbs->macroblockbaseptr; mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr; } - - xvmc_context_reader_unlock( &this->xvmc_lock ); - } diff --git a/src/video_out/xvmc_vld.c b/src/video_out/xvmc_vld.c index 93c5f00bd..ba1b51795 100644 --- a/src/video_out/xvmc_vld.c +++ b/src/video_out/xvmc_vld.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: xvmc_vld.c,v 1.3 2005/05/04 04:27:20 totte67 Exp $ + * $Id: xvmc_vld.c,v 1.4 2005/05/06 07:42:21 totte67 Exp $ * * xvmc_vld.c, X11 decoding accelerated video extension interface for xine * @@ -92,24 +92,14 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) } qmx.load_chroma_intra_quantiser_matrix = 0; qmx.load_chroma_non_intra_quantiser_matrix = 0; - xvmc_context_reader_lock( &driver->xvmc_lock ); - if ( (!xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) || - ((ctl.picture_coding_type == XVMC_P_PICTURE || - ctl.picture_coding_type == XVMC_B_PICTURE) && - !xxmc_xvmc_surface_valid( driver, fs )) || - ((ctl.picture_coding_type == XVMC_B_PICTURE) && - !xxmc_xvmc_surface_valid( driver, bs )) ) { - cf->xxmc_data.result = 128; - xvmc_context_reader_unlock( &driver->xvmc_lock ); - return; - } + XVMCLOCKDISPLAY( driver->display ); XvMCLoadQMatrix(driver->display, &driver->context, &qmx); + while((cf->xxmc_data.result = XvMCBeginSurface(driver->display, &driver->context, cf->xvmc_surf, fs, bs, &ctl))); XVMCUNLOCKDISPLAY( driver->display ); - xvmc_context_reader_unlock( &driver->xvmc_lock ); driver->cpu_saver = 0.; } @@ -120,12 +110,6 @@ void xvmc_vld_slice(vo_frame_t *this_gen) xxmc_driver_t *driver = (xxmc_driver_t *) cf->vo_frame.driver; - xvmc_context_reader_lock( &driver->xvmc_lock ); - if ( ! xxmc_xvmc_surface_valid( driver, cf->xvmc_surf)) { - cf->xxmc_data.result = 128; - xvmc_context_reader_unlock( &driver->xvmc_lock ); - return; - } XVMCLOCKDISPLAY( driver->display ); cf->xxmc_data.result = XvMCPutSlice2(driver->display,&driver->context,cf->xxmc_data.slice_data, @@ -138,7 +122,6 @@ void xvmc_vld_slice(vo_frame_t *this_gen) */ XVMCUNLOCKDISPLAY( driver->display ); - xvmc_context_reader_unlock( &driver->xvmc_lock ); if (driver->cpu_save_enabled) { driver->cpu_saver += 1.; if (driver->cpu_saver >= cf->xxmc_data.sleep) { diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index 27103dea7..fcbd082e3 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.7 2005/04/09 11:47:43 totte67 Exp $ + * $Id: xxmc.h,v 1.8 2005/05/06 07:42:21 totte67 Exp $ * * video_out_xxmc.c, X11 decoding accelerated video extension interface for xine * @@ -178,8 +178,8 @@ typedef struct context_lock_s { #define XVMCLOCKDISPLAY(display) #define XVMCUNLOCKDISPLAY(display) #else -#define XVMCLOCKDISPLAY(display) XLockDisplay(display); -#define XVMCUNLOCKDISPLAY(display) XUnlockDisplay(display); +#define XVMCLOCKDISPLAY(display) XLockDisplay(display) +#define XVMCUNLOCKDISPLAY(display) XUnlockDisplay(display) #endif struct xxmc_driver_s { diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h index bccbf9475..46cbfba22 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.2 2004/10/12 07:40:23 totte67 Exp $ + * $Id: accel_xvmc.h,v 1.3 2005/05/06 07:42:21 totte67 Exp $ * * * Common acceleration definitions for XvMC. @@ -100,6 +100,14 @@ typedef struct xine_xxmc_s { 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); + + /* + * For thread-safety only. + */ + + int (*proc_xxmc_lock_valid) (vo_frame_t *cur_frame, vo_frame_t *fw_frame, + vo_frame_t *bw_frame,unsigned pc_type); + void (*proc_xxmc_unlock) (vo_driver_t *this_gen); } xine_xxmc_t; /* @@ -144,8 +152,6 @@ typedef struct xine_xxmc_s { #define XINE_MACROBLOCK_QUANT 16 #define XINE_MACROBLOCK_DCT_TYPE_INTERLACED 32 - - #ifdef __cplusplus } #endif -- cgit v1.2.3