Suspend can close and open video and audio device.

This commit is contained in:
Johns 2012-01-22 20:49:43 +01:00
parent 98d2e0f728
commit 9546233175
6 changed files with 174 additions and 50 deletions

View File

@ -1,6 +1,8 @@
User johns User johns
Date: Date:
Suspend can close/open X11 window, connection and audio device.
User Morone User Morone
Date: Sun Jan 22 16:43:23 CET 2012 Date: Sun Jan 22 16:43:23 CET 2012

View File

@ -140,6 +140,13 @@ Setup: /etc/vdr/setup.conf
if auto-crop is over after 'n' intervals the same, the cropping is if auto-crop is over after 'n' intervals the same, the cropping is
used. used.
softhddevice.Suspend.Close = 0
1 suspend closes x11 window, connection and audio device.
(use svdrpsend plug softhddevice RESU to resume, if you have no lirc)
softhddevice.Suspend.X11 = 0
1 suspend stops X11 server (not working yet)
Setup: /etc/vdr/remote.conf Setup: /etc/vdr/remote.conf
------ ------
@ -159,7 +166,7 @@ Setup: /etc/vdr/remote.conf
Commandline: Commandline:
------------ ------------
Use vdr -h to see the command line arguments support by the plugin. Use vdr -h to see the command line arguments supported by the plugin.
-a audio_device -a audio_device
@ -170,6 +177,12 @@ Commandline:
other to use alsa audio module (if compiled with alsa other to use alsa audio module (if compiled with alsa
support) support)
SVDRP:
------
Use 'svdrpsend.pl plug softhddevice HELP' to see the SVDRP commands
help and which are supported by the plugin.
Running: Running:
-------- --------

View File

@ -1932,6 +1932,7 @@ static void AudioExitThread(void)
} }
pthread_cond_destroy(&AudioStartCond); pthread_cond_destroy(&AudioStartCond);
pthread_mutex_destroy(&AudioMutex); pthread_mutex_destroy(&AudioMutex);
AudioThread = 0;
} }
} }
@ -2187,6 +2188,7 @@ void AudioExit(void)
#ifdef USE_AUDIORING #ifdef USE_AUDIORING
AudioRingExit(); AudioRingExit();
#endif #endif
AudioRunning = 0;
} }
#ifdef AUDIO_TEST #ifdef AUDIO_TEST

View File

@ -58,8 +58,8 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
#endif #endif
static char ConfigFullscreen; ///< fullscreen modus static char ConfigFullscreen; ///< fullscreen modus
static char ConfigSuspendClose = 1; ///< suspend should close devices char ConfigSuspendClose; ///< suspend should close devices
static char ConfigSuspendX11 = 1; ///< suspend should stop x11 char ConfigSuspendX11; ///< suspend should stop x11
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
@ -347,7 +347,8 @@ void SetVolumeDevice(int volume)
#include <alsa/iatomic.h> // portable atomic_t #include <alsa/iatomic.h> // portable atomic_t
uint32_t VideoSwitch; ///< debug video switch ticks uint32_t VideoSwitch; ///< debug video switch ticks
static volatile char NewVideoStream; ///< new video stream static volatile char NewVideoStream; ///< flag new video stream
static VideoHwDecoder *MyHwDecoder; ///< video hw decoder
static VideoDecoder *MyVideoDecoder; ///< video decoder static VideoDecoder *MyVideoDecoder; ///< video decoder
static enum CodecID VideoCodecID; ///< current codec id static enum CodecID VideoCodecID; ///< current codec id
@ -592,16 +593,35 @@ static void StartVideo(void)
} }
VideoOsdInit(); VideoOsdInit();
if (!MyVideoDecoder) { if (!MyVideoDecoder) {
VideoHwDecoder *hw_decoder; if ((MyHwDecoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(MyHwDecoder);
if ((hw_decoder = VideoNewHwDecoder())) {
MyVideoDecoder = CodecVideoNewDecoder(hw_decoder);
} }
VideoCodecID = CODEC_ID_NONE; VideoCodecID = CODEC_ID_NONE;
} }
VideoPacketInit(); VideoPacketInit();
} }
/**
** Stop video.
*/
static void StopVideo(void)
{
VideoOsdExit();
VideoExit();
if (MyVideoDecoder) {
CodecVideoClose(MyVideoDecoder);
CodecVideoDelDecoder(MyVideoDecoder);
MyVideoDecoder = NULL;
}
if (MyHwDecoder) {
// done by exit: VideoDelHwDecoder(MyHwDecoder);
MyHwDecoder = NULL;
}
VideoPacketExit();
NewVideoStream = 0;
}
#ifdef DEBUG #ifdef DEBUG
/** /**
@ -1152,20 +1172,15 @@ void SoftHdDeviceExit(void)
{ {
// lets hope that vdr does a good thread cleanup // lets hope that vdr does a good thread cleanup
VideoOsdExit();
VideoExit();
AudioExit(); AudioExit();
if (MyVideoDecoder) {
CodecVideoClose(MyVideoDecoder);
CodecVideoDelDecoder(MyVideoDecoder);
MyVideoDecoder = NULL;
}
if (MyAudioDecoder) { if (MyAudioDecoder) {
CodecAudioClose(MyAudioDecoder); CodecAudioClose(MyAudioDecoder);
CodecAudioDelDecoder(MyAudioDecoder); CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL; MyAudioDecoder = NULL;
} }
NewAudioStream = 0;
StopVideo();
CodecExit(); CodecExit();
VideoPacketExit(); VideoPacketExit();
@ -1242,9 +1257,17 @@ void Suspend(void)
if (ConfigSuspendClose) { if (ConfigSuspendClose) {
pthread_mutex_lock(&SuspendLockMutex); pthread_mutex_lock(&SuspendLockMutex);
// FIXME: close audio
// FIXME: close video AudioExit();
if (MyAudioDecoder) {
CodecAudioClose(MyAudioDecoder);
CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL;
}
NewAudioStream = 0;
StopVideo();
pthread_mutex_unlock(&SuspendLockMutex); pthread_mutex_unlock(&SuspendLockMutex);
} }
if (ConfigSuspendX11) { if (ConfigSuspendX11) {
@ -1267,6 +1290,10 @@ void Resume(void)
} }
if (ConfigSuspendClose) { if (ConfigSuspendClose) {
pthread_mutex_lock(&SuspendLockMutex); pthread_mutex_lock(&SuspendLockMutex);
StartVideo();
AudioInit();
pthread_mutex_unlock(&SuspendLockMutex); pthread_mutex_unlock(&SuspendLockMutex);
} }

View File

@ -38,6 +38,8 @@ extern "C"
#include "video.h" #include "video.h"
extern void AudioPoller(void); extern void AudioPoller(void);
extern void CodecSetAudioPassthrough(int); extern void CodecSetAudioPassthrough(int);
extern char ConfigSuspendClose; ///< suspend should close devices
extern char ConfigSuspendX11; ///< suspend should stop x11
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -368,6 +370,8 @@ class cMenuSetupSoft:public cMenuSetupPage
int AudioPassthrough; int AudioPassthrough;
int AutoCropInterval; int AutoCropInterval;
int AutoCropDelay; int AutoCropDelay;
int SuspendClose;
int SuspendX11;
protected: protected:
virtual void Store(void); virtual void Store(void);
public: public:
@ -457,6 +461,16 @@ cMenuSetupSoft::cMenuSetupSoft(void)
AutoCropDelay = ConfigAutoCropDelay; AutoCropDelay = ConfigAutoCropDelay;
Add(new cMenuEditIntItem(tr("autocrop delay (n * interval)"), Add(new cMenuEditIntItem(tr("autocrop delay (n * interval)"),
&AutoCropDelay, 0, 200)); &AutoCropDelay, 0, 200));
//
// suspend
//
Add(SeparatorItem(tr("Suspend")));
SuspendClose = ConfigSuspendClose;
Add(new cMenuEditBoolItem(tr("suspend closes video+audio"), &SuspendClose,
trVDR("no"), trVDR("yes")));
SuspendX11 = ConfigSuspendX11;
Add(new cMenuEditBoolItem(tr("suspend stops x11"), &SuspendX11,
trVDR("no"), trVDR("yes")));
} }
/** /**
@ -499,8 +513,10 @@ void cMenuSetupSoft::Store(void)
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval); SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay); SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay); VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay);
SetupStore("Suspend.Close", ConfigSuspendClose = SuspendClose);
SetupStore("Suspend.X11", ConfigSuspendX11 = SuspendX11);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -705,6 +721,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
case pmNone: case pmNone:
return true; return true;
case pmExtern_THIS_SHOULD_BE_AVOIDED: case pmExtern_THIS_SHOULD_BE_AVOIDED:
dsyslog("[softhddev] play mode external\n");
break; break;
default: default:
dsyslog("[softhddev]playmode not implemented... %d\n", play_mode); dsyslog("[softhddev]playmode not implemented... %d\n", play_mode);
@ -1198,6 +1215,14 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
if (!strcmp(name, "Suspend.Close")) {
ConfigSuspendClose = atoi(value);
return true;
}
if (!strcmp(name, "Suspend.X11")) {
ConfigSuspendX11 = atoi(value);
return true;
}
return false; return false;
} }
@ -1226,10 +1251,10 @@ const char **cPluginSoftHdDevice::SVDRPHelpPages(void)
{ {
// FIXME: translation? // FIXME: translation?
static const char *text[] = { static const char *text[] = {
"SUSP\n", "SUSP\n"
" Suspend plugin", " Suspend plugin.\n",
"RESU\n", "RESU\n"
" Resume plugin", " Resume plugin.\n",
NULL NULL
}; };
@ -1250,8 +1275,11 @@ cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
return "SoftHdDevice is suspended"; return "SoftHdDevice is suspended";
} }
if (!strcasecmp(command, "RESU")) { if (!strcasecmp(command, "RESU")) {
if (ShutdownHandler.GetUserInactiveTime()) {
ShutdownHandler.SetUserInactiveTimeout();
}
Resume(); Resume();
cControl::Shutdown(); cControl::Shutdown(); // not need, if not suspended
return "SoftHdDevice is resumed"; return "SoftHdDevice is resumed";
} }
return NULL; return NULL;

104
video.c
View File

@ -203,6 +203,10 @@ typedef struct _video_module_
void (*const Thread) (void); ///< module thread handler void (*const Thread) (void); ///< module thread handler
/// allocate new video hw decoder
VideoHwDecoder *(*const NewHwDecoder)(void);
void (*const DelHwDecoder) (VideoHwDecoder *);
void (*const Init) (const char *); ///< initialize video output module void (*const Init) (const char *); ///< initialize video output module
void (*const Exit) (void); ///< cleanup video output module void (*const Exit) (void); ///< cleanup video output module
} VideoModule; } VideoModule;
@ -1551,6 +1555,9 @@ static void VaapiCleanup(VaapiDecoder * decoder)
/// ///
static void VaapiDelDecoder(VaapiDecoder * decoder) static void VaapiDelDecoder(VaapiDecoder * decoder)
{ {
VaapiDecoderN = 0;
VaapiDecoders[0] = NULL;
VaapiCleanup(decoder); VaapiCleanup(decoder);
if (decoder->BlackSurface != VA_INVALID_ID) { if (decoder->BlackSurface != VA_INVALID_ID) {
@ -3717,6 +3724,8 @@ static void VaapiOsdExit(void)
/// ///
static const VideoModule VaapiModule = { static const VideoModule VaapiModule = {
.Name = "va-api", .Name = "va-api",
.NewHwDecoder = (VideoHwDecoder * (*const)(void))VaapiNewDecoder,
.DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelDecoder,
.Init = VideoVaapiInit, .Init = VideoVaapiInit,
.Exit = VideoVaapiExit, .Exit = VideoVaapiExit,
}; };
@ -4389,6 +4398,10 @@ static void VdpauCleanup(VdpauDecoder * decoder)
/// ///
static void VdpauDelDecoder(VdpauDecoder * decoder) static void VdpauDelDecoder(VdpauDecoder * decoder)
{ {
// FIXME: hack
VdpauDecoderN = 0;
VdpauDecoders[0] = NULL;
VdpauCleanup(decoder); VdpauCleanup(decoder);
VdpauPrintFrames(decoder); VdpauPrintFrames(decoder);
@ -4477,14 +4490,6 @@ static void VdpauExitOutputQueue(void)
{ {
int i; int i;
if (VdpauQueue) {
VdpauPresentationQueueDestroy(VdpauQueue);
VdpauQueue = 0;
}
if (VdpauQueueTarget) {
VdpauPresentationQueueTargetDestroy(VdpauQueueTarget);
VdpauQueueTarget = 0;
}
// //
// destroy display output surfaces // destroy display output surfaces
// //
@ -4502,6 +4507,14 @@ static void VdpauExitOutputQueue(void)
VdpauSurfacesRb[i] = VDP_INVALID_HANDLE; VdpauSurfacesRb[i] = VDP_INVALID_HANDLE;
} }
} }
if (VdpauQueue) {
VdpauPresentationQueueDestroy(VdpauQueue);
VdpauQueue = 0;
}
if (VdpauQueueTarget) {
VdpauPresentationQueueTargetDestroy(VdpauQueueTarget);
VdpauQueueTarget = 0;
}
} }
/// ///
@ -4915,6 +4928,7 @@ static void VideoVdpauExit(void)
} }
if (VdpauDevice) { if (VdpauDevice) {
xcb_flush(Connection);
VdpauExitOutputQueue(); VdpauExitOutputQueue();
// FIXME: more VDPAU cleanups... // FIXME: more VDPAU cleanups...
@ -6612,6 +6626,8 @@ static void VdpauOsdExit(void)
/// ///
static const VideoModule VdpauModule = { static const VideoModule VdpauModule = {
.Name = "vdpau", .Name = "vdpau",
.NewHwDecoder = (VideoHwDecoder * (*const)(void))VdpauNewDecoder,
.DelHwDecoder = (void (*const) (VideoHwDecoder *))VdpauDelDecoder,
.Init = VideoVdpauInit, .Init = VideoVdpauInit,
.Exit = VideoVdpauExit, .Exit = VideoVdpauExit,
}; };
@ -7157,9 +7173,12 @@ static void VideoThreadExit(void)
void *retval; void *retval;
Debug(3, "video: video thread canceled\n"); Debug(3, "video: video thread canceled\n");
VideoThreadLock();
// FIXME: can't cancel locked
if (pthread_cancel(VideoThread)) { if (pthread_cancel(VideoThread)) {
Error(_("video: can't queue cancel video display thread\n")); Error(_("video: can't queue cancel video display thread\n"));
} }
VideoThreadUnlock();
if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) { if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("video: can't cancel video display thread\n")); Error(_("video: can't cancel video display thread\n"));
} }
@ -7213,20 +7232,22 @@ struct _video_hw_decoder_
/// ///
VideoHwDecoder *VideoNewHwDecoder(void) VideoHwDecoder *VideoNewHwDecoder(void)
{ {
if (!XlibDisplay) { // waiting for x11 start if (!XlibDisplay && !VideoUsedModule) { // waiting for x11 start
return NULL; return NULL;
} }
#ifdef USE_VAAPI return VideoUsedModule->NewHwDecoder();
if (VideoVaapiEnabled) { }
return (VideoHwDecoder *) VaapiNewDecoder();
///
/// Destroy a video hw decoder.
///
/// @param decoder video hw decoder
///
void VideoDelHwDecoder(VideoHwDecoder * decoder)
{
if (decoder && VideoUsedModule) {
VideoUsedModule->DelHwDecoder(decoder);
} }
#endif
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
return (VideoHwDecoder *) VdpauNewDecoder();
}
#endif
return NULL;
} }
/// ///
@ -7484,12 +7505,12 @@ void VideoDisplayHandler(void)
int64_t VideoGetClock(void) int64_t VideoGetClock(void)
{ {
#ifdef USE_VAAPI #ifdef USE_VAAPI
if (VideoVaapiEnabled) { if (VideoVaapiEnabled && VaapiDecoders[0]) {
return VaapiGetClock(VaapiDecoders[0]); return VaapiGetClock(VaapiDecoders[0]);
} }
#endif #endif
#ifdef USE_VDPAU #ifdef USE_VDPAU
if (VideoVdpauEnabled) { if (VideoVdpauEnabled && VdpauDecoders[0]) {
return VdpauGetClock(VdpauDecoders[0]); return VdpauGetClock(VdpauDecoders[0]);
} }
#endif #endif
@ -7535,6 +7556,9 @@ uint8_t *VideoGrab(int *size, int *width, int *height)
} }
#endif #endif
#endif #endif
(void)size;
(void)width;
(void)height;
return NULL; return NULL;
} }
@ -7733,6 +7757,7 @@ void VideoSetVideoMode( __attribute__ ((unused))
if (VideoVaapiEnabled && VaapiDecoders[0]) { if (VideoVaapiEnabled && VaapiDecoders[0]) {
VaapiDeassociate(VaapiDecoders[0]); VaapiDeassociate(VaapiDecoders[0]);
VideoOsdExit(); VideoOsdExit();
VideoOsdInit(); VideoOsdInit();
if (VaapiDecoders[0]->InputWidth && VaapiDecoders[0]->InputHeight) { if (VaapiDecoders[0]->InputWidth && VaapiDecoders[0]->InputHeight) {
VaapiAssociate(VaapiDecoders[0], VaapiDecoders[0]->InputWidth, VaapiAssociate(VaapiDecoders[0], VaapiDecoders[0]->InputWidth,
@ -7747,6 +7772,7 @@ void VideoSetVideoMode( __attribute__ ((unused))
if (VideoVdpauEnabled && VdpauDecoders[0]) { if (VideoVdpauEnabled && VdpauDecoders[0]) {
VdpauExitOutputQueue(); VdpauExitOutputQueue();
VideoOsdExit(); VideoOsdExit();
VideoOsdInit(); VideoOsdInit();
VdpauInitOutputQueue(); VdpauInitOutputQueue();
VdpauUpdateOutput(VdpauDecoders[0]); VdpauUpdateOutput(VdpauDecoders[0]);
@ -7866,14 +7892,26 @@ void VideoSetAudioDelay(int ms)
void VideoSetAutoCrop(int interval, int delay) void VideoSetAutoCrop(int interval, int delay)
{ {
#ifdef USE_AUTOCROP #ifdef USE_AUTOCROP
int i;
AutoCropInterval = interval; AutoCropInterval = interval;
AutoCropDelay = delay; AutoCropDelay = delay;
#ifdef USE_VDPAU #ifdef USE_VDPAU
for (i = 0; i < VdpauDecoderN; ++i) { if (VideoVdpauEnabled) {
VdpauDecoders[i]->AutoCrop->State = 0; int i;
VdpauDecoders[i]->AutoCrop->Count = 0;
for (i = 0; i < VdpauDecoderN; ++i) {
VdpauDecoders[i]->AutoCrop->State = 0;
VdpauDecoders[i]->AutoCrop->Count = 0;
}
}
#endif
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
int i;
for (i = 0; i < VaapiDecoderN; ++i) {
// FIXME: VaapiDecoders[i]->AutoCrop->State = 0;
// FIXME: VaapiDecoders[i]->AutoCrop->Count = 0;
}
} }
#endif #endif
#endif #endif
@ -8035,6 +8073,20 @@ void VideoExit(void)
// FIXME: cleanup. // FIXME: cleanup.
// //
//RandrExit(); //RandrExit();
//
// X11/xcb cleanup
//
if (VideoWindow != XCB_NONE) {
xcb_destroy_window(Connection, VideoWindow);
VideoWindow = XCB_NONE;
}
if (XlibDisplay) {
if (XCloseDisplay(XlibDisplay)) {
Error(_("video: error closing display\n"));
}
XlibDisplay = NULL;
}
} }
#endif #endif