Fix xcb deadlock while closing PIP decoder.

Close video decoder from inside the decoder thread,
otherwise xcb hangs in a lock.
This commit is contained in:
Johns 2013-02-07 16:54:16 +01:00
parent ebd2f85f90
commit d4535a34c9
4 changed files with 75 additions and 11 deletions

6
Todo
View File

@ -54,7 +54,7 @@ libva:
[drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung
[drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ... [drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ...
missing OSD support for 3d SBS / Top-Bottom streams, like VPDAU. missing OSD support for 3d SBS / Top-Bottom streams, like VPDAU.
PIP support PIP support / multistream handling
libva: branch vaapi-ext / staging libva: branch vaapi-ext / staging
add support for vaapi-ext / staging add support for vaapi-ext / staging
@ -117,16 +117,14 @@ setup:
unsorted: unsorted:
stoping vdr while plugin is suspended opens and closes a window. stoping vdr while plugin is suspended opens and closes a window.
svdrp prim: support plugin names for device numbers. svdrp prim: support plugin names for device numbers.
hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll Workaround exists: hangup PipVideoStream -> Vdpau_get_format -> xcb -> poll
+ lock DecoderLockMutex + lock DecoderLockMutex
future features (not planed for 1.0 - 1.5) future features (not planed for 1.0 - 1.5)
video out with xv video out with xv
video out with opengl video out with opengl
video out with xvba
software decoder for xv / opengl software decoder for xv / opengl
multistream handling
save and use auto-crop with channel zapping save and use auto-crop with channel zapping
upmix stereo to AC-3 (supported by alsa plugin) upmix stereo to AC-3 (supported by alsa plugin)

View File

@ -181,6 +181,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64;
#endif
// render // render
frame->data[0] = (void *)vrs; frame->data[0] = (void *)vrs;
frame->data[1] = NULL; frame->data[1] = NULL;
@ -205,6 +208,9 @@ static int Codec_get_buffer(AVCodecContext * video_ctx, AVFrame * frame)
//Debug(3, "codec: use surface %#010x\n", surface); //Debug(3, "codec: use surface %#010x\n", surface);
frame->type = FF_BUFFER_TYPE_USER; frame->type = FF_BUFFER_TYPE_USER;
#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(53,46,0)
frame->age = 256 * 256 * 256 * 64;
#endif
// vaapi needs both fields set // vaapi needs both fields set
frame->data[0] = (void *)(size_t) surface; frame->data[0] = (void *)(size_t) surface;
frame->data[3] = (void *)(size_t) surface; frame->data[3] = (void *)(size_t) surface;

View File

@ -1269,7 +1269,8 @@ struct __video_stream__
volatile char Freezed; ///< stream freezed volatile char Freezed; ///< stream freezed
volatile char TrickSpeed; ///< current trick speed volatile char TrickSpeed; ///< current trick speed
volatile char ClearBuffers; ///< clear video buffers volatile char Close; ///< command close video stream
volatile char ClearBuffers; ///< command clear video buffers
volatile char ClearClose; ///< clear video buffers for close volatile char ClearClose; ///< clear video buffers for close
AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer
@ -1681,6 +1682,39 @@ static void FixPacketForFFMpeg(VideoDecoder * vdecoder, AVPacket * avpkt)
#endif #endif
/**
** Close video stream.
**
** @param stream video stream
**
** @note must be called from the video thread, othewise xcb has a
** deadlock.
*/
static void VideoStreamClose(VideoStream * stream)
{
// FIXME: use this function to close the main video stream!
stream->SkipStream = 1;
if (stream->Decoder) {
VideoDecoder *decoder;
decoder = stream->Decoder;
// FIXME: this lock shouldn't be necessary now
pthread_mutex_lock(&stream->DecoderLockMutex);
stream->Decoder = NULL; // lock read thread
pthread_mutex_unlock(&stream->DecoderLockMutex);
CodecVideoClose(decoder);
CodecVideoDelDecoder(decoder);
}
if (stream->HwDecoder) {
VideoDelHwDecoder(stream->HwDecoder);
stream->HwDecoder = NULL;
// FIXME: CodecVideoClose calls/uses hw decoder
}
VideoPacketExit(stream);
stream->NewStream = 1;
}
/** /**
** Poll PES packet ringbuffer. ** Poll PES packet ringbuffer.
** **
@ -1700,6 +1734,11 @@ int VideoPollInput(VideoStream * stream)
return -1; return -1;
} }
if (stream->Close) { // close stream request
VideoStreamClose(stream);
stream->Close = 0;
return 1;
}
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
@ -1738,6 +1777,11 @@ int VideoDecodeInput(VideoStream * stream)
return -1; return -1;
} }
if (stream->Close) { // close stream request
VideoStreamClose(stream);
stream->Close = 0;
return 1;
}
if (stream->ClearBuffers) { // clear buffer request if (stream->ClearBuffers) { // clear buffer request
atomic_set(&stream->PacketsFilled, 0); atomic_set(&stream->PacketsFilled, 0);
stream->PacketRead = stream->PacketWrite; stream->PacketRead = stream->PacketWrite;
@ -3254,10 +3298,15 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
*/ */
void PipStop(void) void PipStop(void)
{ {
int i;
if (!MyVideoStream->HwDecoder) { // video not running if (!MyVideoStream->HwDecoder) { // video not running
return; return;
} }
ScaleVideo(0, 0, 0, 0);
#if 0
PipVideoStream->SkipStream = 1; // lock write thread PipVideoStream->SkipStream = 1; // lock write thread
if (PipVideoStream->Decoder) { if (PipVideoStream->Decoder) {
VideoDecoder *decoder; VideoDecoder *decoder;
@ -3277,8 +3326,13 @@ void PipStop(void)
VideoPacketExit(PipVideoStream); VideoPacketExit(PipVideoStream);
PipVideoStream->NewStream = 1; PipVideoStream->NewStream = 1;
#else
ScaleVideo(0, 0, 0, 0); PipVideoStream->Close = 1;
for (i = 0; PipVideoStream->Close && i < 50; ++i) {
usleep(1 * 1000);
}
Info("[softhddev]%s: pip close %dms\n", __FUNCTION__, i);
#endif
} }
/** /**

14
video.c
View File

@ -2237,7 +2237,6 @@ static void VaapiExit(void)
int i; int i;
// FIXME: more VA-API cleanups... // FIXME: more VA-API cleanups...
// FIXME: can hang with vdpau in pthread_rwlock_wrlock
for (i = 0; i < VaapiDecoderN; ++i) { for (i = 0; i < VaapiDecoderN; ++i) {
if (VaapiDecoders[i]) { if (VaapiDecoders[i]) {
@ -8484,6 +8483,7 @@ static void VdpauDisplayHandlerThread(void)
} else { } else {
err = VideoPollInput(decoder->Stream); err = VideoPollInput(decoder->Stream);
} }
// decoder can be invalid here
if (err) { if (err) {
// nothing buffered? // nothing buffered?
if (err == -1 && decoder->Closing) { if (err == -1 && decoder->Closing) {
@ -9589,9 +9589,15 @@ VideoHwDecoder *VideoNewHwDecoder(VideoStream * stream)
void VideoDelHwDecoder(VideoHwDecoder * hw_decoder) void VideoDelHwDecoder(VideoHwDecoder * hw_decoder)
{ {
if (hw_decoder) { if (hw_decoder) {
VideoThreadLock(); #ifdef DEBUG
if (!pthread_equal(pthread_self(), VideoThread)) {
Debug(3, "video: should only be called from inside the thread\n");
}
#endif
// only called from inside the thread
//VideoThreadLock();
VideoUsedModule->DelHwDecoder(hw_decoder); VideoUsedModule->DelHwDecoder(hw_decoder);
VideoThreadUnlock(); //VideoThreadUnlock();
} }
} }
@ -10806,7 +10812,7 @@ void VideoInit(const char *display_name)
// FIXME: we need to retry connection // FIXME: we need to retry connection
return; return;
} }
XInitThreads(); //XInitThreads();
// Register error handler // Register error handler
XSetIOErrorHandler(VideoIOErrorHandler); XSetIOErrorHandler(VideoIOErrorHandler);