From acf91785ef6939e549fb8c1348f5f7a7b44f09ff Mon Sep 17 00:00:00 2001 From: Guenter Bartsch Date: Sun, 24 Jun 2001 22:20:25 +0000 Subject: lots of bugfixes for race condtitions, X11 in general and support for remote Xv output CVS patchset: 228 CVS date: 2001/06/24 22:20:25 --- src/libw32dll/wine/Makefile.am | 2 +- src/video_out/video_out_xshm.c | 22 ++- src/video_out/video_out_xv.c | 319 ++++++++++++++++++++++++++++------------ src/xine-engine/metronom.c | 4 +- src/xine-engine/video_decoder.c | 4 +- src/xine-engine/video_out.c | 34 ++++- 6 files changed, 277 insertions(+), 108 deletions(-) diff --git a/src/libw32dll/wine/Makefile.am b/src/libw32dll/wine/Makefile.am index 711758b16..9c32a5bdc 100644 --- a/src/libw32dll/wine/Makefile.am +++ b/src/libw32dll/wine/Makefile.am @@ -28,7 +28,7 @@ noinst_HEADERS = avifmt.h elfdll.h msacm.h pshpack1.h winbase.h \ pshpack4.h windows.h winuser.h debugtools.h mmreg.h \ pe_image.h pshpack8.h winerror.h driver.h module.h \ poppack.h vfw.h loader.h registry.h win32.h \ - wineacm.h winestring.h + wineacm.h winestring.h config.h stubs.lo: stubs.s $(CC) -c $(top_srcdir)/src/libw32dll/wine/stubs.s -o stubs.lo diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 3fac1dad7..7c52d9745 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.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: video_out_xshm.c,v 1.10 2001/06/21 17:34:24 guenter Exp $ + * $Id: video_out_xshm.c,v 1.11 2001/06/24 22:20:26 guenter Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -188,7 +188,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, if (myimage == NULL ) { printf ("video_out_xshm: shared memory error when allocating image\n"); - printf ("=> not using MIT Shared Memory extension.\n"); + printf ("video_out_xshm: => not using MIT Shared Memory extension.\n"); this->use_shm = 0; goto finishShmTesting; } @@ -573,8 +573,6 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; - /* printf ("video_out_xshm: display frame %d\n", frame); */ - if (this->expecting_event) { this->expecting_event--; @@ -608,16 +606,20 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { this->expecting_event = 10; + XFlush(this->display); + } else { + XPutImage(this->display, this->drawable, this->gc, frame->image, 0, 0, 0, 0, frame->rgb_width, frame->rgb_height); + + XFlush(this->display); + frame->vo_frame.displayed (&frame->vo_frame); } - XFlush(this->display); - XUnlockDisplay (this->display); } @@ -703,6 +705,8 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, if (xev->count == 0) { + XLockDisplay (this->display); + if (this->use_shm) { XShmPutImage(this->display, @@ -712,11 +716,15 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, False); } else { + XPutImage(this->display, this->drawable, this->gc, this->cur_frame->image, 0, 0, this->output_xoffset, this->output_yoffset, this->cur_frame->rgb_width, this->cur_frame->rgb_height); } + XFlush (this->display); + + XUnlockDisplay (this->display); } } @@ -835,7 +843,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { } /* - * try to create shared image + * try to create a shared image * to find out if MIT shm really works * and what bpp it uses */ diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index eb9d0bb5c..7c77a53cc 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.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: video_out_xv.c,v 1.44 2001/06/18 15:43:00 richwareham Exp $ + * $Id: video_out_xv.c,v 1.45 2001/06/24 22:20:26 guenter Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -50,6 +50,7 @@ #include #include "monitor.h" +#include "utils.h" #include "video_out.h" #include "video_out_x11.h" #include "xine_internal.h" @@ -95,6 +96,7 @@ typedef struct { XvPortID xv_port; XColor black; int expecting_event; /* completion event handling */ + int use_shm; xv_property_t props[VO_NUM_PROPERTIES]; uint32_t capabilities; @@ -127,9 +129,8 @@ typedef struct { } xv_driver_t; -/* - * - */ +int gX11Fail; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -186,9 +187,174 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { return (vo_frame_t *) frame; } -/* - * - */ +int HandleXError (Display *display, XErrorEvent *xevent) { + + char str [1024]; + + XGetErrorText (display, xevent->error_code, str, 1024); + + printf ("received X error event: %s\n", str); + + gX11Fail = 1; + return 0; + +} + +static void x11_InstallXErrorHandler (xv_driver_t *this) +{ + XSetErrorHandler (HandleXError); + XFlush (this->display); +} + +static void x11_DeInstallXErrorHandler (xv_driver_t *this) +{ + XSetErrorHandler (NULL); + XFlush (this->display); +} + +static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo, + int width, int height, int format) { + + unsigned int xv_format; + XvImage *image; + + switch (format) { + case IMGFMT_YV12: + xv_format = this->xv_format_yv12; + break; + case IMGFMT_RGB: + xv_format = this->xv_format_rgb; + break; + case IMGFMT_YUY2: + xv_format = this->xv_format_yuy2; + break; + default: + fprintf (stderr, "create_ximage: unknown format %08x\n",format); + exit (1); + } + + if (this->use_shm) { + + /* + * try shm + */ + + gX11Fail = 0; + x11_InstallXErrorHandler (this); + + image = XvShmCreateImage(this->display, this->xv_port, xv_format, 0, + width, height, shminfo); + + if (image == NULL ) { + printf("video_out_xv: XvShmCreateImage failed\n"); + printf("video_out_xv: => not using MIT Shared Memory extension.\n"); + this->use_shm = 0; + goto finishShmTesting; + } + + shminfo->shmid=shmget(IPC_PRIVATE, + image->data_size, + IPC_CREAT | 0777); + + if (image->data_size==0) { + printf("video_out_xv: XvShmCreateImage returned a zero size\n"); + printf("video_out_xv: => not using MIT Shared Memory extension.\n"); + this->use_shm = 0; + goto finishShmTesting; + } + + if (shminfo->shmid < 0 ) { + perror("video_out_xv: shared memory error in shmget: "); + printf("video_out_xv: => not using MIT Shared Memory extension.\n"); + this->use_shm = 0; + goto finishShmTesting; + } + + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); + + if (shminfo->shmaddr == NULL) { + printf("video_out_xv: shared memory error (address error NULL)\n"); + this->use_shm = 0; + goto finishShmTesting; + } + + if (shminfo->shmaddr == ((char *) -1)) { + printf("video_out_xv: shared memory error (address error)\n"); + this->use_shm = 0; + goto finishShmTesting; + } + + shminfo->readOnly = False; + image->data = shminfo->shmaddr; + + XShmAttach(this->display, shminfo); + + XSync(this->display, False); + shmctl(shminfo->shmid, IPC_RMID, 0); + + if (gX11Fail) { + printf ("video_out_xv: x11 error during shared memory XImage creation\n"); + printf ("video_out_xv: => not using MIT Shared Memory extension.\n"); + shmdt (shminfo->shmaddr); + shmctl (shminfo->shmid, IPC_RMID, 0); + shminfo->shmid = -1; + this->use_shm = 0; + goto finishShmTesting; + } + + /* + * Now that the Xserver has learned about and attached to the + * shared memory segment, delete it. It's actually deleted by + * the kernel when all users of that segment have detached from + * it. Gives an automatic shared memory cleanup in case we crash. + */ + shmctl (shminfo->shmid, IPC_RMID, 0); + shminfo->shmid = -1; + + finishShmTesting: + x11_DeInstallXErrorHandler(this); + } + + + /* + * fall back to plain Xv if necessary + */ + + if (!this->use_shm) { + + char *data; + + data = xmalloc (width * height * 3/2); + + image = XvCreateImage (this->display, this->xv_port, + xv_format, data, width, height); + + + } + return image; +} + +static void dispose_ximage (xv_driver_t *this, + XShmSegmentInfo *shminfo, + XvImage *myimage) { + + if (this->use_shm) { + + XShmDetach (this->display, shminfo); + XFree (myimage); + shmdt (shminfo->shmaddr); + if (shminfo->shmid >= 0) { + shmctl (shminfo->shmid, IPC_RMID, 0); + shminfo->shmid = -1; + } + + } else { + + XFree (myimage); + + } +} + static void xv_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, @@ -196,7 +362,6 @@ static void xv_update_frame_format (vo_driver_t *this_gen, xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; - unsigned int xv_format; if ((frame->width != width) || (frame->height != height) @@ -211,77 +376,12 @@ static void xv_update_frame_format (vo_driver_t *this_gen, */ if (frame->image) { - XShmDetach (this->display, &frame->shminfo); - - XFree (frame->image); - shmdt (frame->shminfo.shmaddr); - shmctl (frame->shminfo.shmid, IPC_RMID,NULL); - + dispose_ximage (this, &frame->shminfo, frame->image); frame->image = NULL; } - switch (format) { - case IMGFMT_YV12: - xv_format = this->xv_format_yv12; - break; - case IMGFMT_RGB: - xv_format = this->xv_format_rgb; - break; - case IMGFMT_YUY2: - xv_format = this->xv_format_yuy2; - break; - default: - fprintf (stderr, "xv_update_frame_format: unknown format %08x\n",format); - exit (1); - } - - frame->image = XvShmCreateImage(this->display, this->xv_port, xv_format, 0, - width, height, &frame->shminfo); - - if (frame->image == NULL ) { - fprintf(stderr, "xv_image_format: XvShmCreateImage failed.\n"); - exit (1); - } - - frame->shminfo.shmid=shmget(IPC_PRIVATE, - frame->image->data_size, - IPC_CREAT | 0777); - - if (frame->image->data_size==0) { - fprintf(stderr, "xv_update_frame_format: XvShmCreateImage " - "returned a zero size\n"); - exit (1); - } - - if (frame->shminfo.shmid < 0 ) { - perror("xv_update_frame_format: shared memory error in shmget: "); - exit (1); - } + frame->image = create_ximage (this, &frame->shminfo, width, height, format); - frame->shminfo.shmaddr = (char *) shmat(frame->shminfo.shmid, 0, 0); - - if (frame->shminfo.shmaddr == NULL) { - fprintf(stderr, "xv_update_frame_format: shared memory " - "error (address error NULL)\n"); - exit (1); - } - - if (frame->shminfo.shmaddr == ((char *) -1)) { - fprintf(stderr, "xv_update_frame_format: shared memory " - "error (address error)\n"); - exit (1); - } - - frame->shminfo.readOnly = False; - frame->image->data = frame->shminfo.shmaddr; - - /* memset (frame->image->data,0,frame->image->data_size); */ - - XShmAttach(this->display, &frame->shminfo); - - XSync(this->display, False); - shmctl(frame->shminfo.shmid, IPC_RMID, 0); - frame->vo_frame.base[0] = frame->image->data; frame->vo_frame.base[1] = frame->image->data + width * height * 5 / 4; frame->vo_frame.base[2] = frame->image->data + width * height; @@ -326,6 +426,7 @@ static void xv_adapt_to_output_area (xv_driver_t *this, * clear unused output area */ + XLockDisplay (this->display); XSetForeground (this->display, this->gc, this->black.pixel); XFillRectangle(this->display, this->drawable, this->gc, @@ -343,7 +444,7 @@ static void xv_adapt_to_output_area (xv_driver_t *this, this->output_xoffset+this->output_width, dest_y, dest_width - this->output_xoffset - this->output_width, dest_height); - + XUnlockDisplay (this->display); } /* @@ -470,13 +571,22 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { XLockDisplay (this->display); this->cur_frame = frame; - XvShmPutImage(this->display, this->xv_port, - this->drawable, this->gc, frame->image, - 0, 0, frame->width, frame->height-5, - this->output_xoffset, this->output_yoffset, - this->output_width, this->output_height, True); - - this->expecting_event = 10; + + if (this->use_shm) { + XvShmPutImage(this->display, this->xv_port, + this->drawable, this->gc, frame->image, + 0, 0, frame->width, frame->height-5, + this->output_xoffset, this->output_yoffset, + this->output_width, this->output_height, True); + + this->expecting_event = 10; + } else { + XvPutImage(this->display, this->xv_port, + this->drawable, this->gc, frame->image, + 0, 0, frame->width, frame->height-5, + this->output_xoffset, this->output_yoffset, + this->output_width, this->output_height); + } XFlush(this->display); @@ -587,12 +697,26 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, /* FIXME : take care of completion events */ if (xev->count == 0) { - if (this->cur_frame) - XvShmPutImage(this->display, this->xv_port, - this->drawable, this->gc, this->cur_frame->image, - 0, 0, this->cur_frame->width, this->cur_frame->height-5, - this->output_xoffset, this->output_yoffset, - this->output_width, this->output_height, False); + if (this->cur_frame) { + XLockDisplay (this->display); + + if (this->use_shm) { + XvShmPutImage(this->display, this->xv_port, + this->drawable, this->gc, this->cur_frame->image, + 0, 0, this->cur_frame->width, this->cur_frame->height-5, + this->output_xoffset, this->output_yoffset, + this->output_width, this->output_height, False); + } else { + XvPutImage(this->display, this->xv_port, + this->drawable, this->gc, this->cur_frame->image, + 0, 0, this->cur_frame->width, this->cur_frame->height-5, + this->output_xoffset, this->output_yoffset, + this->output_width, this->output_height); + } + XFlush(this->display); + + XUnlockDisplay (this->display); + } } } break; @@ -613,9 +737,11 @@ static void xv_exit (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; + XLockDisplay (this->display); if(XvUngrabPort (this->display, this->xv_port, CurrentTime) != Success) { fprintf(stderr, "xv_exit: XvUngrabPort() failed.\n"); } + XUnlockDisplay (this->display); } /* @@ -676,6 +802,8 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { int nattr; x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; + XvImage *myimage; + XShmSegmentInfo myshminfo; display = visual->display; xine_debug = config->lookup_int (config, "xine_debug", 0); @@ -685,7 +813,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { */ if (Success != XvQueryExtension(display,&ver,&rel,&req,&ev,&err)) { - fprintf (stderr, "video_out_xv: Xv extension not present.\n"); + printf ("video_out_xv: Xv extension not present.\n"); return NULL; } @@ -695,7 +823,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { if (Success != XvQueryAdaptors(display,DefaultRootWindow(display), &adaptors,&adaptor_info)) { - fprintf(stderr, "video_out_xv: XvQueryAdaptors failed.\n"); + printf("video_out_xv: XvQueryAdaptors failed.\n"); return NULL; } @@ -869,6 +997,15 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { } } + /* + * try to create a shared image + * to find out if MIT shm really works + */ + + myimage = create_ximage (this, &myshminfo, 100, 100, IMGFMT_YV12); + dispose_ximage (this, &myshminfo, myimage); + + return &this->vo_driver; } diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 6dbac7d92..3871ddf68 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.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: metronom.c,v 1.10 2001/06/24 02:19:29 guenter Exp $ + * $Id: metronom.c,v 1.11 2001/06/24 22:20:26 guenter Exp $ */ #ifdef HAVE_CONFIG_H @@ -297,7 +297,7 @@ static uint32_t metronom_got_video_frame (metronom_t *this, uint32_t pts) { * for too long */ - if ( !this->audio_stream_starting + if ( !this->audio_stream_starting && this->have_audio && (this->video_wrap_offset != this->audio_wrap_offset)) { this->wrap_diff_counter++; diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index 2a6ba6cc6..77cc12e54 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.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: video_decoder.c,v 1.27 2001/06/24 04:32:36 guenter Exp $ + * $Id: video_decoder.c,v 1.28 2001/06/24 22:20:26 guenter Exp $ * */ @@ -43,7 +43,7 @@ void *video_decoder_loop (void *this_gen) { if (buf->input_pos) this->cur_input_pos = buf->input_pos; - /* printf ("video_decoder: got buffer %d\n", buf->type); */ + /* printf ("video_decoder: got buffer %d\n", buf->type); */ switch (buf->type) { case BUF_CONTROL_START: diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index b497799ce..80bfd7b83 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.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: video_out.c,v 1.25 2001/06/21 17:34:24 guenter Exp $ + * $Id: video_out.c,v 1.26 2001/06/24 22:20:26 guenter Exp $ * */ @@ -93,6 +93,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue (img_buf_fifo_t *queue) { pthread_mutex_lock (&queue->mutex); while (!queue->first) { + /* printf ("video_out: queue %d empty...\n", queue); */ pthread_cond_wait (&queue->bNotEmpty, &queue->mutex); } @@ -235,10 +236,11 @@ static void *video_out_loop (void *this_gen) { img = vo_remove_from_img_buf_queue (this->display_img_buf_queue); pthread_mutex_lock (&img->mutex); + img->bDisplayLock = 0; + if (!img->bDecoderLock) vo_append_to_img_buf_queue (this->free_img_buf_queue, img); - img->bDisplayLock = 0; pthread_mutex_unlock (&img->mutex); img = this->display_img_buf_queue->first; @@ -276,9 +278,10 @@ static void *video_out_loop (void *this_gen) { pthread_mutex_unlock (&img->mutex); /* Overlay SPU FIXME: Check image format */ + this->spu_decoder->overlay_yuv (this->spu_decoder, pts, img->base[0], img->base[1], img->base[2]); - + xprintf (VERBOSE|VIDEO, "video_out : passing to video driver, image with pts = %d\n", pts); this->driver->display_frame (this->driver, img); } @@ -326,6 +329,11 @@ static vo_frame_t *vo_get_frame (vo_instance_t *this, vo_frame_t *img; + /* + printf ("video_out: get_frame %d x %d from queue %d\n", + width, height, this->free_img_buf_queue); + */ + if (this->pts_per_frame != duration) { this->pts_per_frame = duration; this->pts_per_half_frame = duration / 2; @@ -418,7 +426,10 @@ static int vo_frame_draw (vo_frame_t *img) { this->num_frames_delivered++; xprintf (VERBOSE|VIDEO,"video_out: got image. vpts for picture is %d\n", pic_vpts); - + /* + printf ("video_out: got image %d. vpts for picture is %d\n", + img, pic_vpts); + */ cur_vpts = this->metronom->get_current_time(this->metronom); diff = pic_vpts - cur_vpts; @@ -433,6 +444,12 @@ static int vo_frame_draw (vo_frame_t *img) { this->num_frames_discarded++; xprintf (VERBOSE|VIDEO, "vo_frame_draw: rejected, %d frames to skip\n", frames_to_skip); + pthread_mutex_lock (&img->mutex); + img->bDisplayLock = 0; + pthread_mutex_unlock (&img->mutex); + + vo_frame_displayed (img); + return frames_to_skip; } @@ -451,9 +468,16 @@ static int vo_frame_draw (vo_frame_t *img) { vo_append_to_img_buf_queue (this->display_img_buf_queue, img); - } else + } else { this->num_frames_skipped++; + pthread_mutex_lock (&img->mutex); + img->bDisplayLock = 0; + pthread_mutex_unlock (&img->mutex); + + vo_frame_displayed (img); + } + /* * performance measurement */ -- cgit v1.2.3