summaryrefslogtreecommitdiff
path: root/src/video_out/video_out_xxmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_out/video_out_xxmc.c')
-rw-r--r--src/video_out/video_out_xxmc.c419
1 files changed, 278 insertions, 141 deletions
diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c
index 0abe2f0fc..98ce99f1f 100644
--- a/src/video_out/video_out_xxmc.c
+++ b/src/video_out/video_out_xxmc.c
@@ -16,9 +16,7 @@
*
* 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_xxmc.c,v 1.23 2007/03/25 23:13:53 dgp85 Exp $
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* video_out_xxmc.c, X11 decoding accelerated video extension interface for xine
*
@@ -31,9 +29,8 @@
*
* 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 - 2004, 2005.
- * XvMC merge by Thomas Hellström - Sep 2004
- *
+ * XvMC VLD implementation by Thomas Hellström - 2004, 2005.
+ * XvMC merge by Thomas Hellström - Sep 2004
*/
@@ -54,7 +51,7 @@ static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
* is more efficient than VLD.
*/
-static unsigned accel_priority[] = {
+static const unsigned int accel_priority[] = {
#ifdef HAVE_VLDXVMC
XINE_XVMC_ACCEL_VLD,
#endif
@@ -165,14 +162,10 @@ static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this)
xvmc_surface_handler_t *handler = &this->xvmc_surf_handler;
pthread_mutex_init(&handler->mutex,NULL);
- for (i=0; i<XVMC_MAX_SURFACES; ++i) {
- handler->surfInUse[i] = 0;
- handler->surfValid[i] = 0;
- }
- for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) {
- handler->subInUse[i] = 0;
- handler->subValid[i] = 0;
- }
+ memset(handler->surfInUse, 0, sizeof(*handler->surfInUse)*XVMC_MAX_SURFACES);
+ memset(handler->surfValid, 0, sizeof(*handler->surfValid)*XVMC_MAX_SURFACES);
+ memset(handler->subInUse, 0, sizeof(*handler->subInUse)*XVMC_MAX_SUBPICTURES);
+ memset(handler->subValid, 0, sizeof(*handler->subValid)*XVMC_MAX_SUBPICTURES);
}
static void xxmc_xvmc_destroy_surfaces(xxmc_driver_t *this)
@@ -242,7 +235,7 @@ static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this,
}
XVMCUNLOCKDISPLAY( this->display );
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Created surface %d\n",i);
+ LOG_MODULE ": Created surface %d\n",i);
handler->surfInUse[i] = 1;
handler->surfValid[i] = 1;
pthread_mutex_unlock(&handler->mutex);
@@ -262,7 +255,7 @@ static void xxmc_xvmc_free_surface(xxmc_driver_t *this, XvMCSurface *surf)
if (index >= XVMC_MAX_SURFACES) return;
pthread_mutex_lock(&handler->mutex);
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Disposing of surface %d\n",index);
+ LOG_MODULE ": Disposing of surface %d\n",index);
handler->surfInUse[index]--;
xxmc_xvmc_dump_surfaces(this);
pthread_mutex_unlock(&handler->mutex);
@@ -322,7 +315,7 @@ static XvMCSubpicture *xxmc_xvmc_alloc_subpicture
}
XVMCUNLOCKDISPLAY( this->display );
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Created subpicture %d\n",i);
+ LOG_MODULE ": Created subpicture %d\n",i);
handler->subInUse[i] = 1;
handler->subValid[i] = 1;
pthread_mutex_unlock(&handler->mutex);
@@ -343,7 +336,7 @@ static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub)
if (index >= XVMC_MAX_SUBPICTURES) return;
pthread_mutex_lock(&handler->mutex);
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Disposing of subpicture %d\n",index);
+ LOG_MODULE ": Disposing of subpicture %d\n",index);
handler->subInUse[index] = 0;
xxmc_xvmc_dump_subpictures(this);
pthread_mutex_unlock(&handler->mutex);
@@ -371,15 +364,15 @@ static int xxmc_lock_and_validate_surfaces(vo_frame_t *cur_frame,
switch(pc_type) {
case XINE_PICT_B_TYPE:
- frame = (xxmc_frame_t *) bw_frame;
+ frame = XXMC_FRAME(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;
+ frame = XXMC_FRAME(fw_frame);
if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break;
/* fall through */
default:
- frame = (xxmc_frame_t *) cur_frame;
+ frame = XXMC_FRAME(cur_frame);
if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break;
return 0;
}
@@ -410,7 +403,7 @@ static void xvmc_flush(vo_frame_t *this_gen)
{
xxmc_frame_t
- *frame = (xxmc_frame_t *) this_gen;
+ *frame = XXMC_FRAME(this_gen);
xxmc_driver_t
*driver = (xxmc_driver_t *) this_gen->driver;
@@ -458,6 +451,7 @@ static void xxmc_duplicate_frame_data(vo_frame_t *this_gen,
return;
}
this->xxmc_data = *xxmc;
+ this->xxmc_data.xvmc.vo_frame = &this->vo_frame;
this->width = original->width;
this->height = original->height;
this->format = original->format;
@@ -572,6 +566,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) {
frame->vo_frame.driver = this_gen;
frame->last_sw_format = 0;
frame->vo_frame.accel_data = &frame->xxmc_data;
+ frame->xxmc_data.xvmc.vo_frame = &frame->vo_frame;
frame->image = NULL;
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "Allocating frame\n");
@@ -608,11 +603,6 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
unsigned int xv_format;
XvImage *image = NULL;
- if (width <= 0)
- width = 1;
- if (height <= 0)
- height = 1;
-
if (this->use_pitch_alignment) {
width = (width + 7) & ~0x7;
}
@@ -647,8 +637,9 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
if (image == NULL ) {
xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: XvShmCreateImage failed\n"
- "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
+ _("%s: XvShmCreateImage failed\n"), LOG_MODULE);
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE);
this->use_shm = 0;
goto finishShmTesting;
}
@@ -657,16 +648,18 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
if (image->data_size==0) {
xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: XvShmCreateImage returned a zero size\n"
- "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
+ _("%s: XvShmCreateImage returned a zero size\n"), LOG_MODULE);
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE);
this->use_shm = 0;
goto finishShmTesting;
}
if (shminfo->shmid < 0 ) {
xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: shared memory error in shmget: %s\n"
- "video_out_xxmc: => not using MIT Shared Memory extension.\n"), strerror(errno));
+ _("%s: shared memory error in shmget: %s\n"), LOG_MODULE, strerror(errno));
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE);
this->use_shm = 0;
goto finishShmTesting;
}
@@ -675,14 +668,14 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
if (shminfo->shmaddr == NULL) {
xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: shared memory error (address error NULL)\n");
+ LOG_MODULE ": shared memory error (address error NULL)\n");
this->use_shm = 0;
goto finishShmTesting;
}
if (shminfo->shmaddr == ((char *) -1)) {
xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: shared memory error (address error)\n");
+ LOG_MODULE ": shared memory error (address error)\n");
this->use_shm = 0;
goto finishShmTesting;
}
@@ -696,12 +689,13 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo,
shmctl(shminfo->shmid, IPC_RMID, 0);
if (gX11Fail) {
- xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: x11 error during shared memory XImage creation\n"
- "video_out_xxmc: => not using MIT Shared Memory extension.\n"));
shmdt (shminfo->shmaddr);
shmctl (shminfo->shmid, IPC_RMID, 0);
shminfo->shmid = -1;
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("%s: x11 error during shared memory XImage creation\n"), LOG_MODULE);
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE);
this->use_shm = 0;
goto finishShmTesting;
}
@@ -766,13 +760,13 @@ static void xxmc_dispose_context(xxmc_driver_t *driver)
}
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Freeing up XvMC Surfaces and subpictures.\n");
+ LOG_MODULE ": Freeing up XvMC Surfaces and subpictures.\n");
if (driver->xvmc_palette) free(driver->xvmc_palette);
_x_dispose_xx44_palette( &driver->palette );
xxmc_xvmc_destroy_subpictures( driver );
xxmc_xvmc_destroy_surfaces( driver );
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Freeing up XvMC Context.\n");
+ LOG_MODULE ": Freeing up XvMC Context.\n");
XLockDisplay (driver->display);
if (driver->subImage)
dispose_ximage(driver, &driver->subShmInfo, driver->subImage);
@@ -812,10 +806,10 @@ static int xxmc_find_context(xxmc_driver_t *driver, xine_xxmc_t *xxmc,
curCap = driver->xvmc_cap;
for (i =0; i < driver->xvmc_num_cap; ++i) {
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Surface type %d. Capabilities 0x%8x 0x%8x\n",i,
+ LOG_MODULE ": Surface type %d. Capabilities 0x%8x 0x%8x\n",i,
curCap->mpeg_flags,curCap->accel_flags);
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Requests: 0x%8x 0x%8x\n",
+ LOG_MODULE ": Requests: 0x%8x 0x%8x\n",
request_mpeg_flags,request_accel_flags);
if (((curCap->mpeg_flags & request_mpeg_flags) == request_mpeg_flags) &&
((curCap->accel_flags & request_accel_flags)) &&
@@ -846,7 +840,7 @@ static int xxmc_create_context(xxmc_driver_t *driver, unsigned width, unsigned h
curCap = driver->xvmc_cap + driver->xvmc_cur_cap;
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Creating new XvMC Context %d\n",curCap->type_id);
+ LOG_MODULE ": Creating new XvMC Context %d\n",curCap->type_id);
XVMCLOCKDISPLAY( driver->display );
if (Success == XvMCCreateContext( driver->display, driver->xv_port,
curCap->type_id, width,
@@ -879,7 +873,7 @@ static void xxmc_setup_subpictures(xxmc_driver_t *driver, unsigned width, unsign
if ((driver->xvmc_backend_subpic = (curCap->flags & XVMC_BACKEND_SUBPICTURE)))
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Using Backend subpictures.\n");
+ LOG_MODULE ": Using Backend subpictures.\n");
if (!driver->subImage) {
/*
@@ -895,7 +889,7 @@ static void xxmc_setup_subpictures(xxmc_driver_t *driver, unsigned width, unsign
XUnlockDisplay (driver->display);
if (NULL == driver->subImage) {
xprintf(driver->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: Failed allocating XvImage for supbictures.\n");
+ LOG_MODULE ": Failed allocating XvImage for supbictures.\n");
return;
}
}
@@ -977,7 +971,7 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver)
static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame,
- uint32_t width, uint32_t height)
+ uint32_t width, uint32_t height, int frame_format_xxmc)
{
xine_xxmc_t *xxmc = &frame->xxmc_data;
@@ -990,9 +984,13 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame,
return 0;
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);
+ LOG_MODULE ": New format. Need to change XvMC Context.\n"
+ LOG_MODULE ": width: %d height: %d", width, height);
+ if (frame_format_xxmc) {
+ xprintf(driver->xine, XINE_VERBOSITY_LOG,
+ " mpeg: %d acceleration: %d", xxmc->mpeg, xxmc->acceleration);
+ }
+ xprintf(driver->xine, XINE_VERBOSITY_LOG, "\n");
if (frame->xvmc_surf)
xxmc_xvmc_free_surface( driver , frame->xvmc_surf);
@@ -1000,24 +998,24 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame,
xxmc_dispose_context( driver );
- if (xxmc_find_context( driver, xxmc, width, height )) {
+ if (frame_format_xxmc && 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");
+ printf(LOG_MODULE ": ERROR: Macroblock allocation failed\n");
xxmc_dispose_context( driver );
}
}
}
if (!driver->contextActive) {
- printf("video_out_xxmc: Using software decoding for this stream.\n");
+ printf(LOG_MODULE ": Using software decoding for this stream.\n");
driver->xvmc_accel = 0;
} else {
- printf("video_out_xxmc: Using hardware decoding for this stream.\n");
+ printf(LOG_MODULE ": Using hardware decoding for this stream.\n");
}
driver->xvmc_mpeg = xxmc->mpeg;
@@ -1053,9 +1051,9 @@ 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))) {
- 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");
+ fprintf(stderr, LOG_MODULE ": ERROR: Accelerated surface allocation failed.\n"
+ LOG_MODULE ": You are probably out of framebuffer memory.\n"
+ LOG_MODULE ": Falling back to software decoding.\n");
driver->xvmc_accel = 0;
xxmc_dispose_context( driver );
return;
@@ -1220,10 +1218,17 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen,
double ratio, int format, int flags) {
xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
- xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
+ xxmc_frame_t *frame = XXMC_FRAME(frame_gen);
if ( XINE_IMGFMT_XXMC == format ) {
xine_xxmc_t *xxmc = &frame->xxmc_data;
+ vo_frame_t orig_frame_content;
+
+ if (frame_gen != &frame->vo_frame) {
+ /* this is an intercepted frame, so we need to detect and propagate any
+ * changes on the original vo_frame to all the intercepted frames */
+ xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t));
+ }
xvmc_context_writer_lock( &this->xvmc_lock);
if (xxmc_accel_update(this, this->last_accel_request, xxmc->acceleration) ||
@@ -1231,7 +1236,7 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen,
(this->xvmc_width != width) ||
(this->xvmc_height != height)) {
this->last_accel_request = xxmc->acceleration;
- xxmc_xvmc_update_context(this, frame, width, height);
+ xxmc_xvmc_update_context(this, frame, width, height, 1);
} else {
this->last_accel_request = xxmc->acceleration;
}
@@ -1239,7 +1244,7 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen,
if (this->contextActive)
xxmc_frame_updates(this, frame, 1);
- xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio,
+ xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio,
xxmc->fallback_format, flags);
if (!this->contextActive) {
@@ -1253,9 +1258,41 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen,
xvmc_context_writer_unlock( &this->xvmc_lock);
+ if (frame_gen != &frame->vo_frame) {
+ /* this is an intercepted frame, so we need to detect and propagate any
+ * changes on the original vo_frame to all the intercepted frames */
+ unsigned char *p0 = (unsigned char *)&orig_frame_content;
+ unsigned char *p1 = (unsigned char *)&frame->vo_frame;
+ int i;
+ for (i = 0; i < sizeof (vo_frame_t); i++) {
+ if (*p0 != *p1) {
+ /* propagate the change */
+ vo_frame_t *f = frame_gen;
+ while (f->next) {
+ /* serveral restrictions apply when intercepting XXMC frames. So let's check
+ * the intercepted frames before modifing them and fail otherwise. */
+ unsigned char *p = (unsigned char *)f + i;
+ if (*p != *p0) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "xxmc_do_update_frame: a post plugin violates the restrictions on intercepting XXMC frames\n");
+ _x_abort();
+ }
+
+ *p = *p1;
+ f = f->next;
+ }
+ }
+ p0++;
+ p1++;
+ }
+ }
} else {
+ /* switch back to an unaccelerated context */
+ if (this->last_accel_request != 0xFFFFFFFF) {
+ this->last_accel_request = 0xFFFFFFFF;
+ xxmc_xvmc_update_context(this, frame, width, height, 0);
+ }
frame->vo_frame.proc_duplicate_frame_data = NULL;
- xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio,
+ xxmc_do_update_frame_xv(this_gen, &frame->vo_frame, width, height, ratio,
format, flags);
}
}
@@ -1482,6 +1519,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
if (overlay->rle) {
+ this->scaled_osd_active = !overlay->unscaled;
if( overlay->unscaled ) {
if( this->ovl_changed && this->xoverlay ) {
XLockDisplay (this->display);
@@ -1491,6 +1529,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
} else if (frame->format == XINE_IMGFMT_XXMC) {
if (this->ovl_changed && this->hwSubpictures) {
if (this->new_subpic) {
+ int x0, y0, x1, y1, w, h;
LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf );
if (this->first_overlay) {
memset(this->subImage->data,0,this->subImage->width*
@@ -1501,13 +1540,29 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen,
this->subImage->height, this->subImage->width,
&this->alphablend_extra_data,
&this->palette, (this->subImage->id == FOURCC_IA44));
- XVMCLOCKDISPLAY( this->display );
- XvMCCompositeSubpicture( this->display, this->new_subpic,
- this->subImage,
- overlay->x, overlay->y,overlay->width,
- overlay->height,
- overlay->x, overlay->y);
- XVMCUNLOCKDISPLAY( this->display );
+
+ /* clip overlay against sub image like in _x_blend_xx44() */
+ x0 = overlay->x;
+ y0 = overlay->y;
+ x1 = x0 + overlay->width;
+ y1 = y0 + overlay->height;
+ w = this->subImage->width;
+ h = this->subImage->height;
+
+ x0 = (x0 < 0) ? 0 : ((x0 > w) ? w : x0);
+ y0 = (y0 < 0) ? 0 : ((y0 > h) ? h : y0);
+ x1 = (x1 < 0) ? 0 : ((x1 > w) ? w : x1);
+ y1 = (y1 < 0) ? 0 : ((y1 > h) ? h : y1);
+
+ /* anything left after clipping? */
+ if (x0 != x1 && y0 != y1) {
+ XVMCLOCKDISPLAY( this->display );
+ XvMCCompositeSubpicture( this->display, this->new_subpic,
+ this->subImage,
+ x0, y0, x1 - x0, y1 - y0,
+ x0, y0);
+ XVMCUNLOCKDISPLAY( this->display );
+ }
xvmc_context_reader_unlock( &this->xvmc_lock );
}
}
@@ -1579,6 +1634,35 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen;
xine_xxmc_t *xxmc = &frame->xxmc_data;
int first_field;
+ int disable_deinterlace = 0;
+ struct timeval tv_top;
+
+ /*
+ * take time to calculate the time to sleep for the bottom field
+ */
+ gettimeofday(&tv_top, 0);
+
+ /*
+ * bob deinterlacing doesn't make much sense for still images or at replay speeds
+ * other than 100 %, so let's disable deinterlacing at all for this frame
+ */
+ if (this->deinterlace_enabled && this->bob) {
+ disable_deinterlace = this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame
+ || this->disable_bob_for_scaled_osd && this->scaled_osd_active
+ || !frame->vo_frame.stream
+ || xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) != XINE_FINE_SPEED_NORMAL;
+ if (!disable_deinterlace) {
+ int vo_bufs_in_fifo = 0;
+ _x_query_buffer_usage(frame->vo_frame.stream, NULL, NULL, &vo_bufs_in_fifo, NULL);
+ disable_deinterlace = (vo_bufs_in_fifo <= 0);
+ }
+ }
+
+ /*
+ * reset this flag now -- it will be set again before the next call to
+ * xxmc_display_frame() as long as there is a scaled OSD active on screen.
+ */
+ this->scaled_osd_active = 0;
/*
* queue frames (deinterlacing)
@@ -1587,6 +1671,15 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
xvmc_context_reader_lock( &this->xvmc_lock );
+ /*
+ * the current implementation doesn't need recent frames for deinterlacing,
+ * but we need to hold references on the frame we are about to show and to
+ * the previous frame which is currently shown on screen. Otherwise, the
+ * frame on screen will be immediately reused for decoding which will then
+ * most often result in mixed images on screen, especially when decoding
+ * is faster than sending the image to the monitor, and/or when exchanging
+ * the overlay image is synced to retrace.
+ */
xxmc_add_recent_frame (this, frame); /* deinterlacing */
if ((frame->format == XINE_IMGFMT_XXMC) &&
@@ -1616,34 +1709,58 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
first_field = (frame->vo_frame.top_field_first) ? XVMC_TOP_FIELD : XVMC_BOTTOM_FIELD;
first_field = (this->bob) ? first_field : XVMC_TOP_FIELD;
- this->cur_field = (this->deinterlace_enabled) ? first_field : XVMC_FRAME_PICTURE;
+ this->cur_field = (this->deinterlace_enabled && !disable_deinterlace) ? first_field : XVMC_FRAME_PICTURE;
xxmc_redraw_needed (this_gen);
if (frame->format == XINE_IMGFMT_XXMC) {
XVMCLOCKDISPLAY( this->display );
XvMCSyncSurface( this->display, frame->xvmc_surf );
+ XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */
XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable,
this->sc.displayed_xoffset, this->sc.displayed_yoffset,
this->sc.displayed_width, this->sc.displayed_height,
this->sc.output_xoffset, this->sc.output_yoffset,
this->sc.output_width, this->sc.output_height,
this->cur_field);
+ XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */
XVMCUNLOCKDISPLAY( this->display );
- if (this->deinterlace_enabled && this->bob) {
- unsigned
- ms_per_field = 500 * frame->vo_frame.duration / 90000 - 2;
-
- usleep(ms_per_field*1000);
- this->cur_field = (frame->vo_frame.top_field_first) ? XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD;
+ if (this->deinterlace_enabled && !disable_deinterlace && this->bob) {
+ struct timeval tv_middle;
+ long us_spent_so_far, us_per_field = frame->vo_frame.duration * 50 / 9;
- XVMCLOCKDISPLAY( this->display );
- XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable,
- this->sc.displayed_xoffset, this->sc.displayed_yoffset,
- this->sc.displayed_width, this->sc.displayed_height,
- this->sc.output_xoffset, this->sc.output_yoffset,
- this->sc.output_width, this->sc.output_height,
- this->cur_field);
- XVMCUNLOCKDISPLAY( this->display );
+ gettimeofday(&tv_middle, 0);
+ us_spent_so_far = (tv_middle.tv_sec - tv_top.tv_sec) * 1000000 + (tv_middle.tv_usec - tv_top.tv_usec);
+ if (us_spent_so_far < 0)
+ us_spent_so_far = 0;
+
+ /*
+ * typically, the operations above take just a few milliseconds, but when the
+ * driver actively waits to sync on the next field, we better skip showing the
+ * other field as it would lead to further busy waiting
+ * so display the other field only if we've spent less than 75 % of the per
+ * field time so far
+ */
+ if (4 * us_spent_so_far < 3 * us_per_field) {
+ long us_delay = (us_per_field - 2000) - us_spent_so_far;
+ if (us_delay > 0) {
+ xvmc_context_reader_unlock( &this->xvmc_lock );
+ xine_usec_sleep(us_delay);
+ LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf );
+ }
+
+ this->cur_field = (frame->vo_frame.top_field_first) ? XVMC_BOTTOM_FIELD : XVMC_TOP_FIELD;
+
+ XVMCLOCKDISPLAY( this->display );
+ XLockDisplay( this->display ); /* blocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */
+ XvMCPutSurface( this->display, frame->xvmc_surf , this->drawable,
+ this->sc.displayed_xoffset, this->sc.displayed_yoffset,
+ this->sc.displayed_width, this->sc.displayed_height,
+ this->sc.output_xoffset, this->sc.output_yoffset,
+ this->sc.output_width, this->sc.output_height,
+ this->cur_field);
+ XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */
+ XVMCUNLOCKDISPLAY( this->display );
+ }
}
} else {
XLockDisplay (this->display);
@@ -1679,9 +1796,21 @@ static int xxmc_get_property (vo_driver_t *this_gen, int property) {
case VO_PROP_WINDOW_HEIGHT:
this->props[property].value = this->sc.gui_height;
break;
+ case VO_PROP_OUTPUT_WIDTH:
+ this->props[property].value = this->sc.output_width;
+ break;
+ case VO_PROP_OUTPUT_HEIGHT:
+ this->props[property].value = this->sc.output_height;
+ break;
+ case VO_PROP_OUTPUT_XOFFSET:
+ this->props[property].value = this->sc.output_xoffset;
+ break;
+ case VO_PROP_OUTPUT_YOFFSET:
+ this->props[property].value = this->sc.output_yoffset;
+ break;
}
- lprintf("video_out_xxmc: property #%d = %d\n", property, this->props[property].value);
+ lprintf("%s: property #%d = %d\n", LOG_MODULE, property, this->props[property].value);
return this->props[property].value;
}
@@ -1744,7 +1873,7 @@ static int xxmc_set_property (vo_driver_t *this_gen,
case VO_PROP_INTERLACED:
this->props[property].value = value;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: VO_PROP_INTERLACED(%d)\n", this->props[property].value);
+ LOG_MODULE ": VO_PROP_INTERLACED(%d)\n", this->props[property].value);
this->deinterlace_enabled = value;
break;
@@ -1754,7 +1883,7 @@ static int xxmc_set_property (vo_driver_t *this_gen,
this->props[property].value = value;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value);
+ LOG_MODULE ": VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value);
this->sc.user_ratio = value;
xxmc_compute_ideal_size (this);
@@ -1766,7 +1895,7 @@ static int xxmc_set_property (vo_driver_t *this_gen,
if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
this->props[property].value = value;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: VO_PROP_ZOOM_X = %d\n", this->props[property].value);
+ LOG_MODULE ": VO_PROP_ZOOM_X = %d\n", this->props[property].value);
this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP;
@@ -1780,7 +1909,7 @@ static int xxmc_set_property (vo_driver_t *this_gen,
if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) {
this->props[property].value = value;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- "video_out_xxmc: VO_PROP_ZOOM_Y = %d\n", this->props[property].value);
+ LOG_MODULE ": VO_PROP_ZOOM_Y = %d\n", this->props[property].value);
this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP;
@@ -1927,14 +2056,14 @@ static void xxmc_dispose (vo_driver_t *this_gen) {
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");
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": xxmc_exit: XvUngrabPort() failed.\n");
}
XFreeGC(this->display, this->gc);
XUnlockDisplay (this->display);
for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) {
if( this->recent_frames[i] )
- this->recent_frames[i]->vo_frame.dispose
+ this->recent_frames[i]->vo_frame.free
(&this->recent_frames[i]->vo_frame);
this->recent_frames[i] = NULL;
}
@@ -1991,7 +2120,7 @@ static void xxmc_check_capability (xxmc_driver_t *this,
this->props[property].atom, &int_default);
xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: port attribute %s (%d) value is %d\n", str_prop, property, int_default);
+ LOG_MODULE ": port attribute %s (%d) value is %d\n", str_prop, property, int_default);
/*
* We enable autopaint by default.
@@ -2053,7 +2182,7 @@ static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) {
XUnlockDisplay(this->display);
xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter);
+ LOG_MODULE ": bilinear scaling mode (XV_FILTER) = %d\n",xv_filter);
}
static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) {
@@ -2069,7 +2198,7 @@ static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry
XUnlockDisplay(this->display);
xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer);
+ LOG_MODULE ": double buffering mode = %d\n", xv_double_buffer);
}
static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) {
@@ -2096,6 +2225,18 @@ static void xxmc_update_bob(void *this_gen, xine_cfg_entry_t *entry) {
this->bob = entry->num_value;
}
+static void xxmc_update_disable_bob_for_progressive_frames(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->disable_bob_for_progressive_frames = entry->num_value;
+}
+
+static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entry_t *entry) {
+ xxmc_driver_t *this = (xxmc_driver_t *) this_gen;
+
+ this->disable_bob_for_scaled_osd = entry->num_value;
+}
+
static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
{
@@ -2129,7 +2270,7 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
return;
}
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: XvMC extension present.\n");
+ LOG_MODULE ": XvMC extension present.\n");
surfaceInfo = XvMCListSurfaceTypes(this->display, xv_port, &numSurf);
if (0 == surfaceInfo) {
@@ -2145,7 +2286,7 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
curCap = this->xvmc_cap;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Found %d XvMC surface types\n",numSurf);
+ LOG_MODULE ": Found %d XvMC surface types\n", numSurf);
for (i=0; i< numSurf; ++i) {
curCap->mpeg_flags = 0;
@@ -2169,10 +2310,10 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
curCap->sub_max_height = curInfo->subpicture_max_height;
curCap->flags = curInfo->flags;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Surface type %d: Max size: %d %d.\n",
+ LOG_MODULE ": Surface type %d: Max size: %d %d.\n",
i,curCap->max_width,curCap->max_height);
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Surface type %d: Max subpic size: %d %d.\n",
+ LOG_MODULE ": Surface type %d: Max subpic size: %d %d.\n",
i,curCap->sub_max_width,curCap->sub_max_height);
curCap->type_id = curInfo->surface_type_id;
@@ -2181,21 +2322,18 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
curCap->subPicType.id = 0;
if (formatValues) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Surface type %d: Found %d XvMC subpicture "
- "types\n",i,numSub);
+ LOG_MODULE ": Surface type %d: Found %d XvMC subpicture types\n",i,numSub);
for (j = 0; j<numSub; ++j) {
if (formatValues[j].id == FOURCC_IA44) {
curCap->subPicType = formatValues[j];
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Surface type %d: Detected and using "
- "IA44 subpicture type.\n",i);
+ LOG_MODULE ": Surface type %d: Detected and using IA44 subpicture type.\n",i);
/* Prefer IA44 */
break;
} else if (formatValues[j].id == FOURCC_AI44) {
curCap->subPicType = formatValues[j];
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Surface type %d: Detected AI44 "
- "subpicture type.\n",i);
+ LOG_MODULE ": Surface type %d: Detected AI44 subpicture type.\n",i);
}
}
}
@@ -2226,9 +2364,8 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port)
free(this->xvmc_cap);
this->xvmc_cap = 0;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out_xxmc: Apparent attempt to use a direct XvMC "
- "context\nvideo_out_xxmc: on a remote display. "
- "Falling back to XV.\n");
+ LOG_MODULE ": Apparent attempt to use a direct XvMC context on a remote display.\n"
+ LOG_MODULE ": Falling back to Xv.\n");
XVMCUNLOCKDISPLAY( this->display );
xvmc_context_writer_unlock( &this->xvmc_lock );
return;
@@ -2284,7 +2421,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
XLockDisplay(this->display);
if (Success != XvQueryExtension(this->display, &ver,&rel, &req, &ev,&err)) {
- xprintf (class->xine, XINE_VERBOSITY_LOG, _("video_out_xxmc: Xv extension not present.\n"));
+ xprintf (class->xine, XINE_VERBOSITY_LOG, _("%s: Xv extension not present.\n"), LOG_MODULE);
XUnlockDisplay(this->display);
return NULL;
}
@@ -2294,7 +2431,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
*/
if (Success != XvQueryAdaptors(this->display,DefaultRootWindow(this->display), &adaptors, &adaptor_info)) {
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: XvQueryAdaptors failed.\n");
+ xprintf(class->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": XvQueryAdaptors failed.\n");
XUnlockDisplay(this->display);
return NULL;
}
@@ -2321,8 +2458,9 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
if (!xv_port) {
xprintf(class->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: Xv extension is present but I couldn't find a usable yuv12 port.\n"
- " Looks like your graphics hardware driver doesn't support Xv?!\n"));
+ _("%s: Xv extension is present but I couldn't find a usable yuv12 port.\n"
+ "\tLooks like your graphics hardware driver doesn't support Xv?!\n"),
+ LOG_MODULE);
/* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/
XUnlockDisplay(this->display);
@@ -2330,8 +2468,8 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
}
else
xprintf(class->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: using Xv port %ld from adaptor %s for hardware "
- "colorspace conversion and scaling.\n"), xv_port,
+ _("%s: using Xv port %ld from adaptor %s for hardware "
+ "colour space conversion and scaling.\n"), LOG_MODULE, xv_port,
adaptor_info[adaptor_num].name);
XUnlockDisplay(this->display);
@@ -2407,7 +2545,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) {
if(!strcmp(attr[k].name, "XV_HUE")) {
if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) {
- xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xxmc: ignoring broken XV_HUE settings on NVidia cards\n");
+ xprintf (this->xine, XINE_VERBOSITY_NONE, LOG_MODULE ": ignoring broken XV_HUE settings on NVidia cards\n");
} else {
xxmc_check_capability (this, VO_PROP_HUE, attr[k],
adaptor_info[adaptor_num].base_id, "XV_HUE",
@@ -2442,7 +2580,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
adaptor_info[adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY",
"video.device.xv_autopaint_colorkey",
_("autopaint colour key"),
- _("Make Xv autopaint its colorkey."));
+ _("Make Xv autopaint its colour key."));
} else if(!strcmp(attr[k].name, "XV_FILTER")) {
int xv_filter;
@@ -2477,7 +2615,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
XFree(attr);
}
else
- xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: no port attributes defined.\n");
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": no port attributes defined.\n");
XvFreeAdaptorInfo(adaptor_info);
/*
@@ -2506,12 +2644,12 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
this->xv_format_yv12 = fo[i].id;
this->capabilities |= VO_CAP_YV12;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: this adaptor supports the yv12 format.\n"));
+ _("%s: this adaptor supports the yv12 format.\n"), LOG_MODULE);
} else if (fo[i].id == XINE_IMGFMT_YUY2) {
this->xv_format_yuy2 = fo[i].id;
this->capabilities |= VO_CAP_YUY2;
xprintf(this->xine, XINE_VERBOSITY_LOG,
- _("video_out_xxmc: this adaptor supports the yuy2 format.\n"));
+ _("%s: this adaptor supports the yuy2 format.\n"), LOG_MODULE);
}
}
@@ -2554,25 +2692,39 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
10, xxmc_update_cpu_save, this);
this->reverse_nvidia_palette =
config->register_bool (config, "video.device.xvmc_nvidia_color_fix", 0,
- _("Fix buggy NVIDIA XvMC subpicture colors"),
- _("There's a bug in NVIDIA's XvMC lib that makes red OSD colors\n"
+ _("Fix buggy NVIDIA XvMC subpicture colours"),
+ _("There's a bug in NVIDIA's XvMC lib that makes red OSD colours\n"
"look blue and vice versa. This option provides a workaround.\n"),
10, xxmc_update_nvidia_fix, this);
this->bob =
config->register_bool (config, "video.device.xvmc_bob_deinterlacing", 0,
_("Use bob as accelerated deinterlace method."),
_("When interlacing is enabled for hardware accelerated frames,\n"
- "Alternate between top and bottom field at double the frame rate.\n"),
+ "alternate between top and bottom field at double the frame rate.\n"),
10, xxmc_update_bob, this);
+ this->disable_bob_for_progressive_frames =
+ config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_progressive_frames", 0,
+ _("Don't use bob deinterlacing for progressive frames."),
+ _("Progressive frames don't need deinterlacing, so disabling it on\n"
+ "demand should result in a better picture.\n"),
+ 10, xxmc_update_disable_bob_for_progressive_frames, this);
+
+ this->disable_bob_for_scaled_osd =
+ config->register_bool (config, "video.device.xvmc_disable_bob_deinterlacing_for_scaled_osd", 0,
+ _("Don't use bob deinterlacing while a scaled OSD is active."),
+ _("Bob deinterlacing adds some noise to horizontal lines, so disabling it\n"
+ "on demand should result in a better OSD picture.\n"),
+ 10, xxmc_update_disable_bob_for_scaled_osd, this);
+
this->deinterlace_enabled = 0;
this->cur_field = XVMC_FRAME_PICTURE;
#ifdef HAVE_VLDXVMC
- printf("video_out_xxmc: Unichrome CPU saving is %s.\n",
+ printf("%s: Unichrome CPU saving is %s.\n", LOG_MODULE,
(this->cpu_save_enabled) ? "on":"off");
#else
- printf("video_out_xxmc: warning - compiled with no vld extensions.\n");
+ printf("%s: warning - compiled with no vld extensions.\n", LOG_MODULE);
#endif
this->props[VO_PROP_MAX_NUM_FRAMES].value = (use_more_frames) ? 15:8;
this->cpu_saver = 0.;
@@ -2609,28 +2761,13 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi
/*
* class functions
*/
-
-static char* get_identifier (video_driver_class_t *this_gen) {
- return "XxMC";
-}
-
-static char* get_description (video_driver_class_t *this_gen) {
- return _("xine video output plugin using the MIT X video extension");
-}
-
-static void dispose_class (video_driver_class_t *this_gen) {
- xxmc_class_t *this = (xxmc_class_t *) this_gen;
-
- free (this);
-}
-
static void *init_class (xine_t *xine, void *visual_gen) {
xxmc_class_t *this = (xxmc_class_t *) xine_xmalloc (sizeof (xxmc_class_t));
this->driver_class.open_plugin = open_plugin;
- this->driver_class.get_identifier = get_identifier;
- this->driver_class.get_description = get_description;
- this->driver_class.dispose = dispose_class;
+ this->driver_class.identifier = "XxMC";
+ this->driver_class.description = N_("xine video output plugin using the MIT X video extension");
+ this->driver_class.dispose = default_video_driver_class_dispose;
this->config = xine->config;
this->xine = xine;
@@ -2652,7 +2789,7 @@ static const vo_info_t vo_info_xxmc = {
const plugin_info_t xine_plugin_info[] EXPORTED = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_VIDEO_OUT, 21, "xxmc", XINE_VERSION_CODE, &vo_info_xxmc, init_class },
+ { PLUGIN_VIDEO_OUT, 22, "xxmc", XINE_VERSION_CODE, &vo_info_xxmc, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};