Video cleanup.

Add noop video output module.
Move VideoThread check into lock/unlock functions.
Add support for choosing video output module.
This commit is contained in:
Johns 2012-03-07 15:31:43 +01:00
parent ee5804fed7
commit acc35fe30c
5 changed files with 298 additions and 247 deletions

View File

@ -1,6 +1,7 @@
User johns User johns
Date: Date:
Video source code cleanup.
Fix fast backward with some h264 streams. Fix fast backward with some h264 streams.
Make soft start sync setup menu configurable. Make soft start sync setup menu configurable.
Fix bug: StillPicture NAL end of sequence is 10 and not 0x10. Fix bug: StillPicture NAL end of sequence is 10 and not 0x10.

4
Todo
View File

@ -27,6 +27,8 @@ missing:
ColorSpace aren't configurable with the gui. ColorSpace aren't configurable with the gui.
Replay of old vdr 1.6 recordings. Replay of old vdr 1.6 recordings.
svdrp support for hot-keys. svdrp support for hot-keys.
Remote learning support.
restart vdr not working, when started x11 was killed.
crash: crash:
AudioPlayHandlerThread -> pthread_cond_wait AudioPlayHandlerThread -> pthread_cond_wait
@ -88,7 +90,7 @@ audio:
samplerate problem resume/suspend. samplerate problem resume/suspend.
only wait for video start, if video is running. only wait for video start, if video is running.
Not primary device, don't use and block audio/video. Not primary device, don't use and block audio/video.
Remote learning support. multiple open of audio device, reduce them.
audio/alsa: audio/alsa:
better downmix of >2 channels on 2 channel hardware better downmix of >2 channels on 2 channel hardware

View File

@ -2079,6 +2079,7 @@ const char *CommandLineHelp(void)
" -d display\tdisplay of x11 server (fe. :0.0)\n" " -d display\tdisplay of x11 server (fe. :0.0)\n"
" -f\t\tstart with fullscreen window (only with window manager)\n" " -f\t\tstart with fullscreen window (only with window manager)\n"
" -g geometry\tx11 window geometry wxh+x+y\n" " -g geometry\tx11 window geometry wxh+x+y\n"
" -v device\tvideo device (va-api, vdpau, noop)\n"
" -s\t\tstart in suspended mode\n" " -x\t\tstart x11 server\n" " -s\t\tstart in suspended mode\n" " -x\t\tstart x11 server\n"
" -w workaround\tenable/disable workarounds\n" " -w workaround\tenable/disable workarounds\n"
"\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n" "\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n"
@ -2099,7 +2100,7 @@ int ProcessArgs(int argc, char *const argv[])
// Parse arguments. // Parse arguments.
// //
for (;;) { for (;;) {
switch (getopt(argc, argv, "-a:c:d:fg:p:sw:x")) { switch (getopt(argc, argv, "-a:c:d:fg:p:sv:w:x")) {
case 'a': // audio device for pcm case 'a': // audio device for pcm
AudioSetDevice(optarg); AudioSetDevice(optarg);
continue; continue;
@ -2123,6 +2124,13 @@ int ProcessArgs(int argc, char *const argv[])
return 0; return 0;
} }
continue; continue;
case 'v': // video driver
VideoSetDevice(optarg);
#ifdef USE_VDPAU
// FIXME: this is a big hack
ConfigVdpauDecoder = !strcasecmp(optarg, "vdpau");
#endif
continue;
case 'x': // x11 server case 'x': // x11 server
ConfigStartX11Server = 1; ConfigStartX11Server = 1;
continue; continue;
@ -2392,30 +2400,26 @@ void Suspend(int video, int audio, int dox11)
SkipVideo = 1; SkipVideo = 1;
SkipAudio = 1; SkipAudio = 1;
pthread_mutex_unlock(&SuspendLockMutex);
if (audio || video) { if (audio) {
pthread_mutex_lock(&SuspendLockMutex); AudioExit();
if (MyAudioDecoder) {
if (audio) { CodecAudioClose(MyAudioDecoder);
AudioExit(); CodecAudioDelDecoder(MyAudioDecoder);
if (MyAudioDecoder) { MyAudioDecoder = NULL;
CodecAudioClose(MyAudioDecoder);
CodecAudioDelDecoder(MyAudioDecoder);
MyAudioDecoder = NULL;
}
NewAudioStream = 0;
av_free_packet(AudioAvPkt);
} }
if (video) { NewAudioStream = 0;
StopVideo(); av_free_packet(AudioAvPkt);
}
pthread_mutex_unlock(&SuspendLockMutex);
} }
if (video) {
StopVideo();
}
if (dox11) { if (dox11) {
// FIXME: stop x11, if started // FIXME: stop x11, if started
} }
pthread_mutex_unlock(&SuspendLockMutex);
} }
/** /**

495
video.c
View File

@ -221,7 +221,6 @@ typedef enum _video_color_space_
typedef struct _video_module_ typedef struct _video_module_
{ {
const char *Name; ///< video output module name const char *Name; ///< video output module name
char Enabled; ///< flag output module enabled char Enabled; ///< flag output module enabled
/// allocate new video hw decoder /// allocate new video hw decoder
@ -238,11 +237,12 @@ typedef struct _video_module_
void (*const SetVideoMode) (void); void (*const SetVideoMode) (void);
void (*const ResetAutoCrop) (void); void (*const ResetAutoCrop) (void);
void (*const Thread) (void); ///< module display handler thread /// module display handler thread
void (*const DisplayHandlerThread) (void);
void (*const OsdClear) (void); ///< clear OSD void (*const OsdClear) (void); ///< clear OSD
/// draw OSD ARGB area
void (*const OsdDrawARGB) (int, int, int, int, const uint8_t *); void (*const OsdDrawARGB) (int, int, int, int, const uint8_t *);
///< draw OSD ARGB area
void (*const OsdInit) (int, int); ///< initialize OSD void (*const OsdInit) (int, int); ///< initialize OSD
void (*const OsdExit) (void); ///< cleanup OSD void (*const OsdExit) (void); ///< cleanup OSD
@ -274,6 +274,7 @@ typedef struct _video_module_
char VideoIgnoreRepeatPict; ///< disable repeat pict warning char VideoIgnoreRepeatPict; ///< disable repeat pict warning
static const char *VideoDevice; ///< video output device
static Display *XlibDisplay; ///< Xlib X11 display static Display *XlibDisplay; ///< Xlib X11 display
static xcb_connection_t *Connection; ///< xcb connection static xcb_connection_t *Connection; ///< xcb connection
static xcb_colormap_t VideoColormap; ///< video colormap static xcb_colormap_t VideoColormap; ///< video colormap
@ -285,7 +286,10 @@ static int VideoWindowY; ///< video outout window y coordinate
static unsigned VideoWindowWidth; ///< video output window width static unsigned VideoWindowWidth; ///< video output window width
static unsigned VideoWindowHeight; ///< video output window height static unsigned VideoWindowHeight; ///< video output window height
static const VideoModule *VideoUsedModule; ///< selected video module static const VideoModule NoopModule; ///< forward definition of noop module
/// selected video module
static const VideoModule *VideoUsedModule = &NoopModule;
static char VideoHardwareDecoder; ///< flag use hardware decoder static char VideoHardwareDecoder; ///< flag use hardware decoder
@ -1658,9 +1662,9 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
/// ///
/// Allocate new VA-API decoder. /// Allocate new VA-API decoder.
/// ///
/// @returns a new prepared va-api hardware decoder. /// @returns a new prepared VA-API hardware decoder.
/// ///
static VaapiDecoder *VaapiNewDecoder(void) static VaapiDecoder *VaapiNewHwDecoder(void)
{ {
VaapiDecoder *decoder; VaapiDecoder *decoder;
int i; int i;
@ -1815,7 +1819,7 @@ static void VaapiCleanup(VaapiDecoder * decoder)
/// ///
/// @param decoder VA-API decoder /// @param decoder VA-API decoder
/// ///
static void VaapiDelDecoder(VaapiDecoder * decoder) static void VaapiDelHwDecoder(VaapiDecoder * decoder)
{ {
int i; int i;
@ -2084,7 +2088,7 @@ static void VaapiExit(void)
for (i = 0; i < VaapiDecoderN; ++i) { for (i = 0; i < VaapiDecoderN; ++i) {
if (VaapiDecoders[i]) { if (VaapiDecoders[i]) {
VaapiDelDecoder(VaapiDecoders[i]); VaapiDelHwDecoder(VaapiDecoders[i]);
VaapiDecoders[i] = NULL; VaapiDecoders[i] = NULL;
} }
} }
@ -4414,11 +4418,14 @@ static void VaapiSyncRenderFrame(VaapiDecoder * decoder,
{ {
VideoSetPts(&decoder->PTS, decoder->Interlaced, frame); VideoSetPts(&decoder->PTS, decoder->Interlaced, frame);
#ifdef DEBUG
if (!atomic_read(&decoder->SurfacesFilled)) { if (!atomic_read(&decoder->SurfacesFilled)) {
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch); Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
} }
#endif
if (decoder->DropNextFrame) { // drop frame requested if (decoder->DropNextFrame) { // drop frame requested
// FIXME: interlace this drops two frames
++decoder->FramesDropped; ++decoder->FramesDropped;
Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped, Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped,
decoder->FrameCounter); decoder->FrameCounter);
@ -4555,6 +4562,10 @@ static void VaapiDisplayHandlerThread(void)
pthread_mutex_unlock(&VideoLockMutex); pthread_mutex_unlock(&VideoLockMutex);
} }
#else
#define VaapiDisplayHandlerThread NULL
#endif #endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -4783,8 +4794,8 @@ static void VaapiOsdExit(void)
static const VideoModule VaapiModule = { static const VideoModule VaapiModule = {
.Name = "va-api", .Name = "va-api",
.Enabled = 1, .Enabled = 1,
.NewHwDecoder = (VideoHwDecoder * (*const)(void))VaapiNewDecoder, .NewHwDecoder = (VideoHwDecoder * (*const)(void))VaapiNewHwDecoder,
.DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelDecoder, .DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelHwDecoder,
.GetSurface = (unsigned (*const) (VideoHwDecoder *))VaapiGetSurface, .GetSurface = (unsigned (*const) (VideoHwDecoder *))VaapiGetSurface,
.ReleaseSurface = .ReleaseSurface =
(void (*const) (VideoHwDecoder *, unsigned))VaapiReleaseSurface, (void (*const) (VideoHwDecoder *, unsigned))VaapiReleaseSurface,
@ -4796,7 +4807,7 @@ static const VideoModule VaapiModule = {
.SetBackground = VaapiSetBackground, .SetBackground = VaapiSetBackground,
.SetVideoMode = VaapiSetVideoMode, .SetVideoMode = VaapiSetVideoMode,
.ResetAutoCrop = VaapiResetAutoCrop, .ResetAutoCrop = VaapiResetAutoCrop,
.Thread = VaapiDisplayHandlerThread, .DisplayHandlerThread = VaapiDisplayHandlerThread,
.OsdClear = VaapiOsdClear, .OsdClear = VaapiOsdClear,
.OsdDrawARGB = VaapiOsdDrawARGB, .OsdDrawARGB = VaapiOsdDrawARGB,
.OsdInit = VaapiOsdInit, .OsdInit = VaapiOsdInit,
@ -5444,7 +5455,7 @@ static void VdpauMixerCreate(VdpauDecoder * decoder)
/// ///
/// @returns a new prepared vdpau hardware decoder. /// @returns a new prepared vdpau hardware decoder.
/// ///
static VdpauDecoder *VdpauNewDecoder(void) static VdpauDecoder *VdpauNewHwDecoder(void)
{ {
VdpauDecoder *decoder; VdpauDecoder *decoder;
int i; int i;
@ -5563,7 +5574,7 @@ static void VdpauCleanup(VdpauDecoder * decoder)
/// ///
/// @param decoder VDPAU hw decoder /// @param decoder VDPAU hw decoder
/// ///
static void VdpauDelDecoder(VdpauDecoder * decoder) static void VdpauDelHwDecoder(VdpauDecoder * decoder)
{ {
int i; int i;
@ -6143,7 +6154,7 @@ static void VdpauExit(void)
for (i = 0; i < VdpauDecoderN; ++i) { for (i = 0; i < VdpauDecoderN; ++i) {
if (VdpauDecoders[i]) { if (VdpauDecoders[i]) {
VdpauDelDecoder(VdpauDecoders[i]); VdpauDelHwDecoder(VdpauDecoders[i]);
VdpauDecoders[i] = NULL; VdpauDecoders[i] = NULL;
} }
} }
@ -7478,11 +7489,14 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
VideoSetPts(&decoder->PTS, decoder->Interlaced, frame); VideoSetPts(&decoder->PTS, decoder->Interlaced, frame);
#ifdef DEBUG
if (!atomic_read(&decoder->SurfacesFilled)) { if (!atomic_read(&decoder->SurfacesFilled)) {
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch); Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
} }
#endif
if (decoder->DropNextFrame) { // drop frame requested if (decoder->DropNextFrame) { // drop frame requested
// FIXME: interlace this drops two frames
++decoder->FramesDropped; ++decoder->FramesDropped;
Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped, Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped,
decoder->FrameCounter); decoder->FrameCounter);
@ -7681,6 +7695,10 @@ static void VdpauDisplayHandlerThread(void)
pthread_mutex_unlock(&VideoLockMutex); pthread_mutex_unlock(&VideoLockMutex);
} }
#else
#define VdpauDisplayHandlerThread NULL
#endif #endif
/// ///
@ -7942,8 +7960,8 @@ static void VdpauOsdExit(void)
static const VideoModule VdpauModule = { static const VideoModule VdpauModule = {
.Name = "vdpau", .Name = "vdpau",
.Enabled = 1, .Enabled = 1,
.NewHwDecoder = (VideoHwDecoder * (*const)(void))VdpauNewDecoder, .NewHwDecoder = (VideoHwDecoder * (*const)(void))VdpauNewHwDecoder,
.DelHwDecoder = (void (*const) (VideoHwDecoder *))VdpauDelDecoder, .DelHwDecoder = (void (*const) (VideoHwDecoder *))VdpauDelHwDecoder,
.GetSurface = (unsigned (*const) (VideoHwDecoder *))VdpauGetSurface, .GetSurface = (unsigned (*const) (VideoHwDecoder *))VdpauGetSurface,
.ReleaseSurface = .ReleaseSurface =
(void (*const) (VideoHwDecoder *, unsigned))VdpauReleaseSurface, (void (*const) (VideoHwDecoder *, unsigned))VdpauReleaseSurface,
@ -7955,7 +7973,7 @@ static const VideoModule VdpauModule = {
.SetBackground = VdpauSetBackground, .SetBackground = VdpauSetBackground,
.SetVideoMode = VdpauSetVideoMode, .SetVideoMode = VdpauSetVideoMode,
.ResetAutoCrop = VdpauResetAutoCrop, .ResetAutoCrop = VdpauResetAutoCrop,
.Thread = VdpauDisplayHandlerThread, .DisplayHandlerThread = VdpauDisplayHandlerThread,
.OsdClear = VdpauOsdClear, .OsdClear = VdpauOsdClear,
.OsdDrawARGB = VdpauOsdDrawARGB, .OsdDrawARGB = VdpauOsdDrawARGB,
.OsdInit = VdpauOsdInit, .OsdInit = VdpauOsdInit,
@ -7966,6 +7984,152 @@ static const VideoModule VdpauModule = {
#endif #endif
//----------------------------------------------------------------------------
// NOOP
//----------------------------------------------------------------------------
///
/// Allocate new noop decoder.
///
/// @returns always NULL.
///
static VideoHwDecoder *NoopNewHwDecoder(void)
{
return NULL;
}
///
/// Release a surface.
///
/// Can be called while exit.
///
/// @param decoder noop hw decoder
/// @param surface surface no longer used
///
static void NoopReleaseSurface(
__attribute__ ((unused)) VideoHwDecoder * decoder, __attribute__ ((unused))
unsigned surface)
{
}
///
/// Set noop background color.
///
/// @param rgba 32 bit RGBA color.
///
static void NoopSetBackground( __attribute__ ((unused)) uint32_t rgba)
{
}
///
/// Noop initialize OSD.
///
/// @param width osd width
/// @param height osd height
///
static void NoopOsdInit( __attribute__ ((unused))
int width, __attribute__ ((unused))
int height)
{
}
///
/// Draw OSD ARGB image.
///
/// @param x x position of image in osd
/// @param y y position of image in osd
/// @param width width of image
/// @param height height of image
/// @param argb argb image
///
/// @note looked by caller
///
static void NoopOsdDrawARGB( __attribute__ ((unused))
int x, __attribute__ ((unused))
int y, __attribute__ ((unused))
int width, __attribute__ ((unused))
int height, __attribute__ ((unused))
const uint8_t * argb)
{
}
///
/// Noop setup.
///
/// @param display_name x11/xcb display name
///
/// @returns always true.
///
static int NoopInit(const char *display_name)
{
Info("video/noop: noop driver running on display '%s'\n", display_name);
return 1;
}
#ifdef USE_VIDEO_THREAD
///
/// Handle a noop display.
///
static void NoopDisplayHandlerThread(void)
{
// avoid 100% cpu use
usleep(20 * 1000);
#if 0
// this can't be canceled
if (XlibDisplay) {
XEvent event;
XPeekEvent(XlibDisplay, &event);
}
#endif
}
#else
#define NoopDisplayHandlerThread NULL
#endif
///
/// Noop void function.
///
static void NoopVoid(void)
{
}
///
/// Noop video module.
///
static const VideoModule NoopModule = {
.Name = "noop",
.Enabled = 1,
.NewHwDecoder = NoopNewHwDecoder,
#if 0
// can't be called:
.DelHwDecoder = NoopDelHwDecoder,
.GetSurface = (unsigned (*const) (VideoHwDecoder *))NoopGetSurface,
#endif
.ReleaseSurface = NoopReleaseSurface,
#if 0
.get_format = (enum PixelFormat(*const) (VideoHwDecoder *,
AVCodecContext *, const enum PixelFormat *))Noop_get_format,
.RenderFrame = (void (*const) (VideoHwDecoder *,
const AVCodecContext *, const AVFrame *))NoopSyncRenderFrame,
.GrabOutput = NoopGrabOutputSurface,
#endif
.SetBackground = NoopSetBackground,
.SetVideoMode = NoopVoid,
.ResetAutoCrop = NoopVoid,
.DisplayHandlerThread = NoopDisplayHandlerThread,
.OsdClear = NoopVoid,
.OsdDrawARGB = NoopOsdDrawARGB,
.OsdInit = NoopOsdInit,
.OsdExit = NoopVoid,
.Init = NoopInit,
.Exit = NoopVoid,
};
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// OSD // OSD
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -7978,9 +8142,7 @@ static const VideoModule VdpauModule = {
/// ///
void VideoOsdClear(void) void VideoOsdClear(void)
{ {
if (VideoThread) { VideoThreadLock();
VideoThreadLock();
}
#ifdef USE_GLX #ifdef USE_GLX
if (GlxEnabled) { if (GlxEnabled) {
void *texbuf; void *texbuf;
@ -7998,18 +8160,15 @@ void VideoOsdClear(void)
} }
#endif #endif
if (VideoUsedModule) { VideoUsedModule->OsdClear();
VideoUsedModule->OsdClear();
}
OsdDirtyX = OsdWidth; OsdDirtyX = OsdWidth;
OsdDirtyY = OsdHeight; OsdDirtyY = OsdHeight;
OsdDirtyWidth = 0; OsdDirtyWidth = 0;
OsdDirtyHeight = 0; OsdDirtyHeight = 0;
OsdShown = 0; OsdShown = 0;
if (VideoThread) { VideoThreadUnlock();
VideoThreadUnlock();
}
} }
/// ///
@ -8024,9 +8183,7 @@ void VideoOsdClear(void)
void VideoOsdDrawARGB(int x, int y, int width, int height, void VideoOsdDrawARGB(int x, int y, int width, int height,
const uint8_t * argb) const uint8_t * argb)
{ {
if (VideoThread) { VideoThreadLock();
VideoThreadLock();
}
// update dirty area // update dirty area
if (x < OsdDirtyX) { if (x < OsdDirtyX) {
if (OsdDirtyWidth) { if (OsdDirtyWidth) {
@ -8057,14 +8214,10 @@ void VideoOsdDrawARGB(int x, int y, int width, int height,
return; return;
} }
#endif #endif
if (VideoUsedModule) { VideoUsedModule->OsdDrawARGB(x, y, width, height, argb);
VideoUsedModule->OsdDrawARGB(x, y, width, height, argb);
}
OsdShown = 1; OsdShown = 1;
if (VideoThread) { VideoThreadUnlock();
VideoThreadUnlock();
}
} }
/// ///
@ -8123,15 +8276,9 @@ void VideoOsdInit(void)
} }
#endif #endif
if (VideoThread) { VideoThreadLock();
VideoThreadLock(); VideoUsedModule->OsdInit(OsdWidth, OsdHeight);
} VideoThreadUnlock();
if (VideoUsedModule) {
VideoUsedModule->OsdInit(OsdWidth, OsdHeight);
}
if (VideoThread) {
VideoThreadUnlock();
}
VideoOsdClear(); VideoOsdClear();
} }
@ -8140,15 +8287,9 @@ void VideoOsdInit(void)
/// ///
void VideoOsdExit(void) void VideoOsdExit(void)
{ {
if (VideoThread) { VideoThreadLock();
VideoThreadLock(); VideoUsedModule->OsdExit();
} VideoThreadUnlock();
if (VideoUsedModule) {
VideoUsedModule->OsdExit();
}
if (VideoThread) {
VideoThreadUnlock();
}
OsdDirtyWidth = 0; OsdDirtyWidth = 0;
OsdDirtyHeight = 0; OsdDirtyHeight = 0;
} }
@ -8231,39 +8372,6 @@ void VideoDisplayOverlay(void)
#endif #endif
//----------------------------------------------------------------------------
// Frame
//----------------------------------------------------------------------------
#if 0
///
/// Display a single frame.
///
static void VideoDisplayFrame(void)
{
#ifdef USE_GLX
if (GlxEnabled) {
VideoDisplayOverlay();
#ifdef USE_DOUBLEBUFFER
glXSwapBuffers(XlibDisplay, VideoWindow);
#else
glFinish(); // wait for all execution finished
#endif
GlxCheck();
glClear(GL_COLOR_BUFFER_BIT);
}
#endif
if (VideoUsedModule) {
VideoUsedModule->DisplayFrame();
}
}
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Events // Events
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -8283,7 +8391,7 @@ static int VideoIOErrorHandler( __attribute__ ((unused)) Display * display)
// should be called from VideoThread // should be called from VideoThread
if (VideoThread && VideoThread == pthread_self()) { if (VideoThread && VideoThread == pthread_self()) {
Debug(3, "video: called from video thread\n"); Debug(3, "video: called from video thread\n");
VideoUsedModule = NULL; // FIXME: NoopModule; VideoUsedModule = &NoopModule;
XlibDisplay = NULL; XlibDisplay = NULL;
VideoWindow = XCB_NONE; VideoWindow = XCB_NONE;
#ifdef USE_VIDEO_THREAD #ifdef USE_VIDEO_THREAD
@ -8370,7 +8478,7 @@ static void VideoEvent(void)
/// ///
void VideoPollEvent(void) void VideoPollEvent(void)
{ {
while (XPending(XlibDisplay)) { while (XlibDisplay && XPending(XlibDisplay)) {
VideoEvent(); VideoEvent();
} }
} }
@ -8390,8 +8498,10 @@ static GLXContext GlxThreadContext; ///< our gl context for the thread
/// ///
static void VideoThreadLock(void) static void VideoThreadLock(void)
{ {
if (pthread_mutex_lock(&VideoLockMutex)) { if (VideoThread) {
Error(_("video: can't lock thread\n")); if (pthread_mutex_lock(&VideoLockMutex)) {
Error(_("video: can't lock thread\n"));
}
} }
} }
@ -8400,8 +8510,10 @@ static void VideoThreadLock(void)
/// ///
static void VideoThreadUnlock(void) static void VideoThreadUnlock(void)
{ {
if (pthread_mutex_unlock(&VideoLockMutex)) { if (VideoThread) {
Error(_("video: can't unlock thread\n")); if (pthread_mutex_unlock(&VideoLockMutex)) {
Error(_("video: can't unlock thread\n"));
}
} }
} }
@ -8439,16 +8551,7 @@ static void *VideoDisplayHandlerThread(void *dummy)
VideoPollEvent(); VideoPollEvent();
if (VideoUsedModule) { VideoUsedModule->DisplayHandlerThread();
VideoUsedModule->Thread();
} else {
XEvent event;
// FIXME: move into noop module
// avoid 100% cpu use
XPeekEvent(XlibDisplay, &event);
}
} }
return dummy; return dummy;
@ -8484,10 +8587,10 @@ static void VideoThreadExit(void)
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"));
} }
VideoThread = 0;
pthread_cond_destroy(&VideoWakeupCond); pthread_cond_destroy(&VideoWakeupCond);
pthread_mutex_destroy(&VideoLockMutex); pthread_mutex_destroy(&VideoLockMutex);
pthread_mutex_destroy(&VideoMutex); pthread_mutex_destroy(&VideoMutex);
VideoThread = 0;
} }
} }
@ -8525,7 +8628,7 @@ static const VideoModule *VideoModules[] = {
#ifdef USE_VAAPI #ifdef USE_VAAPI
&VaapiModule, &VaapiModule,
#endif #endif
//&NoopModule &NoopModule
}; };
/// ///
@ -8551,9 +8654,6 @@ struct _video_hw_decoder_
/// ///
VideoHwDecoder *VideoNewHwDecoder(void) VideoHwDecoder *VideoNewHwDecoder(void)
{ {
if (!XlibDisplay || !VideoUsedModule) { // waiting for x11 start
return NULL;
}
return VideoUsedModule->NewHwDecoder(); return VideoUsedModule->NewHwDecoder();
} }
@ -8564,7 +8664,7 @@ VideoHwDecoder *VideoNewHwDecoder(void)
/// ///
void VideoDelHwDecoder(VideoHwDecoder * decoder) void VideoDelHwDecoder(VideoHwDecoder * decoder)
{ {
if (decoder && VideoUsedModule) { if (decoder) {
VideoUsedModule->DelHwDecoder(decoder); VideoUsedModule->DelHwDecoder(decoder);
} }
} }
@ -8578,10 +8678,7 @@ void VideoDelHwDecoder(VideoHwDecoder * decoder)
/// ///
unsigned VideoGetSurface(VideoHwDecoder * decoder) unsigned VideoGetSurface(VideoHwDecoder * decoder)
{ {
if (VideoUsedModule) { return VideoUsedModule->GetSurface(decoder);
return VideoUsedModule->GetSurface(decoder);
}
return -1;
} }
/// ///
@ -8593,12 +8690,7 @@ unsigned VideoGetSurface(VideoHwDecoder * decoder)
void VideoReleaseSurface(VideoHwDecoder * decoder, unsigned surface) void VideoReleaseSurface(VideoHwDecoder * decoder, unsigned surface)
{ {
// FIXME: must be guarded against calls, after VideoExit // FIXME: must be guarded against calls, after VideoExit
if (!XlibDisplay) { // no init or failed VideoUsedModule->ReleaseSurface(decoder, surface);
return;
}
if (VideoUsedModule) {
VideoUsedModule->ReleaseSurface(decoder, surface);
}
} }
/// ///
@ -8612,10 +8704,8 @@ enum PixelFormat Video_get_format(VideoHwDecoder * decoder,
AVCodecContext * video_ctx, const enum PixelFormat *fmt) AVCodecContext * video_ctx, const enum PixelFormat *fmt)
{ {
AudioVideoReady(); AudioVideoReady();
if (VideoUsedModule) { return VideoUsedModule->get_format(decoder, video_ctx, fmt);
return VideoUsedModule->get_format(decoder, video_ctx, fmt); //return fmt[0];
}
return fmt[0];
} }
/// ///
@ -8632,9 +8722,7 @@ void VideoRenderFrame(VideoHwDecoder * decoder,
Warning(_("video: repeated pict %d found, but not handled\n"), Warning(_("video: repeated pict %d found, but not handled\n"),
frame->repeat_pict); frame->repeat_pict);
} }
if (VideoUsedModule) { VideoUsedModule->RenderFrame(decoder, video_ctx, frame);
VideoUsedModule->RenderFrame(decoder, video_ctx, frame);
}
} }
/// ///
@ -8655,6 +8743,7 @@ struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder * decoder)
} }
#ifdef USE_VDPAU #ifdef USE_VDPAU
/// ///
/// Draw ffmpeg vdpau render state. /// Draw ffmpeg vdpau render state.
/// ///
@ -8707,36 +8796,6 @@ void VideoDrawRenderState(VideoHwDecoder * hw_decoder,
} }
Error(_("video/vdpau: draw render state, without vdpau enabled\n")); Error(_("video/vdpau: draw render state, without vdpau enabled\n"));
} }
#endif
#ifndef USE_VIDEO_THREAD
///
/// Video render.
///
/// @FIXME: old, not used and not uptodate code path
///
void VideoDisplayHandler(void)
{
uint32_t now;
if (!XlibDisplay) { // not yet started
return;
}
now = GetMsTicks();
if (now < VaapiDecoders[0]->LastFrameTick) {
return;
}
if (now - VaapiDecoders[0]->LastFrameTick < 500) {
return;
}
VideoPollEvent();
VaapiBlackSurface(VaapiDecoders[0]);
return;
VideoDisplayFrame();
}
#endif #endif
@ -8759,7 +8818,7 @@ int64_t VideoGetClock(void)
return VaapiGetClock(VaapiDecoders[0]); return VaapiGetClock(VaapiDecoders[0]);
} }
#endif #endif
return 0L; return AV_NOPTS_VALUE;
} }
/// ///
@ -8774,7 +8833,7 @@ uint8_t *VideoGrab(int *size, int *width, int *height, int write_header)
Debug(3, "video: grab\n"); Debug(3, "video: grab\n");
#ifdef USE_GRAB #ifdef USE_GRAB
if (VideoUsedModule && VideoUsedModule->GrabOutput) { if (VideoUsedModule->GrabOutput) {
uint8_t *data; uint8_t *data;
uint8_t *rgb; uint8_t *rgb;
char buf[64]; char buf[64];
@ -8995,6 +9054,16 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual,
// FIXME: free cursor/pixmap needed? // FIXME: free cursor/pixmap needed?
} }
///
/// Set video device.
///
/// Currently this only choose the driver.
///
void VideoSetDevice(const char *device)
{
VideoDevice = device;
}
/// ///
/// Set video geometry. /// Set video geometry.
/// ///
@ -9053,12 +9122,8 @@ void VideoSetOutputPosition(int x, int y, int width, int height)
y = (y * VideoWindowHeight) / OsdHeight; y = (y * VideoWindowHeight) / OsdHeight;
width = (width * VideoWindowWidth) / OsdWidth; width = (width * VideoWindowWidth) / OsdWidth;
height = (height * VideoWindowHeight) / OsdHeight; height = (height * VideoWindowHeight) / OsdHeight;
if (VideoThread) { VideoThreadLock();
VideoThreadLock(); // FIXME: what stream?
}
if (VideoUsedModule) {
// FIXME: what stream?
}
#ifdef USE_VDPAU #ifdef USE_VDPAU
if (VideoUsedModule == &VdpauModule) { if (VideoUsedModule == &VdpauModule) {
VdpauSetOutputPosition(VdpauDecoders[0], x, y, width, height); VdpauSetOutputPosition(VdpauDecoders[0], x, y, width, height);
@ -9068,9 +9133,7 @@ void VideoSetOutputPosition(int x, int y, int width, int height)
// FIXME: not supported by vaapi without unscaled OSD, // FIXME: not supported by vaapi without unscaled OSD,
// FIXME: if used to position video inside osd // FIXME: if used to position video inside osd
#endif #endif
if (VideoThread) { VideoThreadUnlock();
VideoThreadUnlock();
}
} }
/// ///
@ -9097,17 +9160,11 @@ void VideoSetVideoMode( __attribute__ ((unused))
VideoOsdExit(); VideoOsdExit();
// FIXME: must tell VDR that the OsdSize has been changed! // FIXME: must tell VDR that the OsdSize has been changed!
if (VideoThread) { VideoThreadLock();
VideoThreadLock();
}
VideoWindowWidth = width; VideoWindowWidth = width;
VideoWindowHeight = height; VideoWindowHeight = height;
if (VideoUsedModule) { VideoUsedModule->SetVideoMode();
VideoUsedModule->SetVideoMode(); VideoThreadUnlock();
}
if (VideoThread) {
VideoThreadUnlock();
}
VideoOsdInit(); VideoOsdInit();
} }
@ -9119,9 +9176,7 @@ void VideoSetDisplayFormat(int format)
VideoOsdExit(); VideoOsdExit();
// FIXME: must tell VDR that the OsdSize has been changed! // FIXME: must tell VDR that the OsdSize has been changed!
if (VideoThread) { VideoThreadLock();
VideoThreadLock();
}
switch (format) { switch (format) {
case 0: // pan&scan (we have no pan&scan) case 0: // pan&scan (we have no pan&scan)
@ -9135,12 +9190,8 @@ void VideoSetDisplayFormat(int format)
break; break;
} }
if (VideoUsedModule) { VideoUsedModule->SetVideoMode();
VideoUsedModule->SetVideoMode(); VideoThreadUnlock();
}
if (VideoThread) {
VideoThreadUnlock();
}
VideoOsdInit(); VideoOsdInit();
} }
@ -9151,32 +9202,30 @@ void VideoSetDisplayFormat(int format)
/// ///
void VideoSetFullscreen(int onoff) void VideoSetFullscreen(int onoff)
{ {
xcb_client_message_event_t event; if (XlibDisplay) { // needs running connection
xcb_client_message_event_t event;
if (!XlibDisplay) { // needs running connection memset(&event, 0, sizeof(event));
return; event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.window = VideoWindow;
event.type = NetWmState;
if (onoff < 0) {
event.data.data32[0] = XCB_EWMH_WM_STATE_TOGGLE;
} else if (onoff) {
event.data.data32[0] = XCB_EWMH_WM_STATE_ADD;
} else {
event.data.data32[0] = XCB_EWMH_WM_STATE_REMOVE;
}
event.data.data32[1] = NetWmStateFullscreen;
xcb_send_event(Connection, XCB_SEND_EVENT_DEST_POINTER_WINDOW,
DefaultRootWindow(XlibDisplay),
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (void *)&event);
Debug(3, "video/x11: send fullscreen message %x %x\n",
event.data.data32[0], event.data.data32[1]);
} }
memset(&event, 0, sizeof(event));
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.window = VideoWindow;
event.type = NetWmState;
if (onoff < 0) {
event.data.data32[0] = XCB_EWMH_WM_STATE_TOGGLE;
} else if (onoff) {
event.data.data32[0] = XCB_EWMH_WM_STATE_ADD;
} else {
event.data.data32[0] = XCB_EWMH_WM_STATE_REMOVE;
}
event.data.data32[1] = NetWmStateFullscreen;
xcb_send_event(Connection, XCB_SEND_EVENT_DEST_POINTER_WINDOW,
DefaultRootWindow(XlibDisplay),
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (void *)&event);
Debug(3, "video/x11: send fullscreen message %x %x\n",
event.data.data32[0], event.data.data32[1]);
} }
/// ///
@ -9280,10 +9329,8 @@ void VideoSetStudioLevels(int onoff)
/// ///
void VideoSetBackground(uint32_t rgba) void VideoSetBackground(uint32_t rgba)
{ {
VideoBackground = rgba; // save for later start VideoBackground = rgba; // saved for later start
if (VideoUsedModule) { VideoUsedModule->SetBackground(rgba);
VideoUsedModule->SetBackground(rgba);
}
} }
/// ///
@ -9306,15 +9353,9 @@ void VideoSetAutoCrop(int interval, int delay, int tolerance)
AutoCropDelay = delay; AutoCropDelay = delay;
AutoCropTolerance = tolerance; AutoCropTolerance = tolerance;
if (VideoThread) { VideoThreadLock();
VideoThreadLock(); VideoUsedModule->ResetAutoCrop();
} VideoThreadUnlock();
if (VideoUsedModule) {
VideoUsedModule->ResetAutoCrop();
}
if (VideoThread) {
VideoThreadUnlock();
}
#else #else
(void)interval; (void)interval;
(void)delay; (void)delay;
@ -9423,10 +9464,12 @@ void VideoInit(const char *display_name)
// //
// prepare hardware decoder VA-API/VDPAU // prepare hardware decoder VA-API/VDPAU
// FIXME: make the used output modules configurable
// //
for (i = 0; i < (int)(sizeof(VideoModules) / sizeof(*VideoModules)); ++i) { for (i = 0; i < (int)(sizeof(VideoModules) / sizeof(*VideoModules)); ++i) {
if (VideoModules[i]->Enabled) { // FIXME: support list of drivers and include display name
// use user device or first working enabled device driver
if ((VideoDevice && !strcasecmp(VideoDevice, VideoModules[i]->Name))
|| (!VideoDevice && VideoModules[i]->Enabled)) {
if (VideoModules[i]->Init(display_name)) { if (VideoModules[i]->Init(display_name)) {
VideoUsedModule = VideoModules[i]; VideoUsedModule = VideoModules[i];
break; break;
@ -9470,10 +9513,8 @@ void VideoExit(void)
// XUnlockDisplay(XlibDisplay); // XUnlockDisplay(XlibDisplay);
// xcb_flush(Connection); // xcb_flush(Connection);
#endif #endif
if (VideoUsedModule) { VideoUsedModule->Exit();
VideoUsedModule->Exit(); VideoUsedModule = &NoopModule;
}
VideoUsedModule = NULL; // FIXME: NoopModule;
#ifdef USE_GLX #ifdef USE_GLX
if (GlxEnabled) { if (GlxEnabled) {
GlxExit(); GlxExit();

View File

@ -77,6 +77,9 @@ extern void VideoPollEvent(void);
/// Wakeup display handler. /// Wakeup display handler.
extern void VideoDisplayWakeup(void); extern void VideoDisplayWakeup(void);
/// Set video device.
extern void VideoSetDevice(const char *);
/// Set video geometry. /// Set video geometry.
extern int VideoSetGeometry(const char *); extern int VideoSetGeometry(const char *);