From 67e571f02b4d333f39f22067019dc55f544bb887 Mon Sep 17 00:00:00 2001 From: Johns Date: Thu, 23 Feb 2012 17:57:21 +0100 Subject: [PATCH] Survive lost X11 display. --- ChangeLog | 1 + softhddev.c | 4 ++-- video.c | 56 +++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0c1d9d..d618e53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ User johns Date: + Survive lost X11 display. Fix bug: 100% cpu use with plugins like mp3. Wakeup display thread on channel switch, osd can now be shown without video. diff --git a/softhddev.c b/softhddev.c index b9c4dfd..a49b103 100644 --- a/softhddev.c +++ b/softhddev.c @@ -1848,7 +1848,7 @@ int SetPlayMode(int play_mode) NewAudioStream = 1; } } - if (play_mode == 2 || play_mode == 3 ) { + if (play_mode == 2 || play_mode == 3) { Debug(3, "softhddev: FIXME: audio only, silence video errors\n"); } Play(); @@ -1997,7 +1997,7 @@ void StillPicture(const uint8_t * data, int size) int Poll(int timeout) { // buffers are too full - if ( atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX * 2 / 3 + if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX * 2 / 3 || AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE * 2) { if (timeout) { // let display thread work usleep(timeout * 1000); diff --git a/video.c b/video.c index 0a6ee76..dcf2250 100644 --- a/video.c +++ b/video.c @@ -73,6 +73,7 @@ #endif #include #include +#include #ifndef HAVE_PTHREAD_NAME /// only available with newer glibc #define pthread_setname_np(thread, name) @@ -363,6 +364,7 @@ static int64_t VideoDeltaPTS; ///< FIXME: fix pts static void VideoThreadLock(void); ///< lock video thread static void VideoThreadUnlock(void); ///< unlock video thread +static void VideoThreadExit(void); ///< exit/kill video thread #if defined(DEBUG) || defined(AV_INFO) /// @@ -1354,6 +1356,9 @@ static void VaapiBlackSurface(VaapiDecoder *); /// forward destroy deinterlace images static void VaapiDestroyDeinterlaceImages(VaapiDecoder *); + /// forward definition release surface +static void VaapiReleaseSurface(VaapiDecoder *, VASurfaceID); + //---------------------------------------------------------------------------- // VA-API Functions //---------------------------------------------------------------------------- @@ -1467,8 +1472,8 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height) decoder->SurfaceFreeN = decoder->SurfacesNeeded; // VA_RT_FORMAT_YUV420 VA_RT_FORMAT_YUV422 VA_RT_FORMAT_YUV444 if (vaCreateSurfaces(decoder->VaDisplay, VA_RT_FORMAT_YUV420, width, - height, decoder->SurfacesFree, decoder->SurfaceFreeN, - NULL, 0) != VA_STATUS_SUCCESS) { + height, decoder->SurfacesFree, decoder->SurfaceFreeN, NULL, + 0) != VA_STATUS_SUCCESS) { Fatal(_("video/vaapi: can't create %d surfaces\n"), decoder->SurfaceFreeN); // FIXME: write error handler / fallback @@ -1507,9 +1512,6 @@ static void VaapiDestroySurfaces(VaapiDecoder * decoder) // FIXME surfaces used for output } - /// forward definition release surface -static void VaapiReleaseSurface(VaapiDecoder *, VASurfaceID); - /// /// Get a free surface. /// @@ -1932,8 +1934,8 @@ static void Vaapi1080i(void) Error(_("codec: can't create config")); return; } - if (vaCreateSurfaces(VaDisplay, VA_RT_FORMAT_YUV420, 1920, 1080, - surfaces, 32, NULL, 0) != VA_STATUS_SUCCESS) { + if (vaCreateSurfaces(VaDisplay, VA_RT_FORMAT_YUV420, 1920, 1080, surfaces, + 32, NULL, 0) != VA_STATUS_SUCCESS) { Error(_("video/vaapi: can't create surfaces\n")); return; } @@ -2979,10 +2981,10 @@ static void VaapiQueueSurface(VaapiDecoder * decoder, VASurfaceID surface, if ((old = decoder->SurfacesRb[decoder->SurfaceWrite]) != VA_INVALID_ID) { +#if 0 if (vaSyncSurface(decoder->VaDisplay, old) != VA_STATUS_SUCCESS) { Error(_("video/vaapi: vaSyncSurface failed\n")); } -#if 0 VASurfaceStatus status; if (vaQuerySurfaceStatus(decoder->VaDisplay, old, &status) @@ -3063,8 +3065,8 @@ static void VaapiBlackSurface(VaapiDecoder * decoder) if (decoder->BlackSurface == VA_INVALID_ID) { if (vaCreateSurfaces(decoder->VaDisplay, VA_RT_FORMAT_YUV420, - VideoWindowWidth, VideoWindowHeight, - &decoder->BlackSurface, 1, NULL, 0) != VA_STATUS_SUCCESS) { + VideoWindowWidth, VideoWindowHeight, &decoder->BlackSurface, 1, + NULL, 0) != VA_STATUS_SUCCESS) { Error(_("video/vaapi: can't create a surface\n")); return; } @@ -8218,6 +8220,37 @@ static void VideoDisplayFrame(void) /// C callback feed key press extern void FeedKeyPress(const char *, const char *, int, int); +/// +/// Handle XLib I/O Errors. +/// +/// @param display display with i/o error +/// +static int VideoIOErrorHandler( __attribute__ ((unused)) Display * display) +{ + + Error(_("video: fatal i/o error\n")); + // should be called from VideoThread + if (VideoThread && VideoThread == pthread_self()) { + Debug(3, "video: called from video thread\n"); + VideoUsedModule = NULL; // FIXME: NoopModule; + XlibDisplay = NULL; + VideoWindow = XCB_NONE; +#ifdef USE_VIDEO_THREAD + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_cond_destroy(&VideoWakeupCond); + pthread_mutex_destroy(&VideoLockMutex); + pthread_mutex_destroy(&VideoMutex); + VideoThread = 0; + pthread_exit("video thread exit"); +#endif + } + do { + sleep(1000); + } while (1); // let other threads running + + return -1; +} + /// /// Handle X11 events. /// @@ -9233,6 +9266,9 @@ void VideoInit(const char *display_name) return; } // XInitThreads(); + // Register error handler + XSetIOErrorHandler(VideoIOErrorHandler); + // Convert XLIB display to XCB connection if (!(Connection = XGetXCBConnection(XlibDisplay))) { Error(_("video: Can't convert XLIB display to XCB connection\n"));