From acc35fe30c6b48d771cc75c6168c51490d24953f Mon Sep 17 00:00:00 2001 From: Johns Date: Wed, 7 Mar 2012 15:31:43 +0100 Subject: [PATCH] Video cleanup. Add noop video output module. Move VideoThread check into lock/unlock functions. Add support for choosing video output module. --- ChangeLog | 1 + Todo | 4 +- softhddev.c | 42 +++-- video.c | 495 ++++++++++++++++++++++++++++------------------------ video.h | 3 + 5 files changed, 298 insertions(+), 247 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c699cb..026b736 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ User johns Date: + Video source code cleanup. Fix fast backward with some h264 streams. Make soft start sync setup menu configurable. Fix bug: StillPicture NAL end of sequence is 10 and not 0x10. diff --git a/Todo b/Todo index 9955574..c6aa762 100644 --- a/Todo +++ b/Todo @@ -27,6 +27,8 @@ missing: ColorSpace aren't configurable with the gui. Replay of old vdr 1.6 recordings. svdrp support for hot-keys. + Remote learning support. + restart vdr not working, when started x11 was killed. crash: AudioPlayHandlerThread -> pthread_cond_wait @@ -88,7 +90,7 @@ audio: samplerate problem resume/suspend. only wait for video start, if video is running. Not primary device, don't use and block audio/video. - Remote learning support. + multiple open of audio device, reduce them. audio/alsa: better downmix of >2 channels on 2 channel hardware diff --git a/softhddev.c b/softhddev.c index 6de211c..ff44b8c 100644 --- a/softhddev.c +++ b/softhddev.c @@ -2079,6 +2079,7 @@ const char *CommandLineHelp(void) " -d display\tdisplay of x11 server (fe. :0.0)\n" " -f\t\tstart with fullscreen window (only with window manager)\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" " -w workaround\tenable/disable workarounds\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. // 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 AudioSetDevice(optarg); continue; @@ -2123,6 +2124,13 @@ int ProcessArgs(int argc, char *const argv[]) return 0; } 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 ConfigStartX11Server = 1; continue; @@ -2392,30 +2400,26 @@ void Suspend(int video, int audio, int dox11) SkipVideo = 1; SkipAudio = 1; - pthread_mutex_unlock(&SuspendLockMutex); - if (audio || video) { - pthread_mutex_lock(&SuspendLockMutex); - - if (audio) { - AudioExit(); - if (MyAudioDecoder) { - CodecAudioClose(MyAudioDecoder); - CodecAudioDelDecoder(MyAudioDecoder); - MyAudioDecoder = NULL; - } - NewAudioStream = 0; - av_free_packet(AudioAvPkt); + if (audio) { + AudioExit(); + if (MyAudioDecoder) { + CodecAudioClose(MyAudioDecoder); + CodecAudioDelDecoder(MyAudioDecoder); + MyAudioDecoder = NULL; } - if (video) { - StopVideo(); - } - - pthread_mutex_unlock(&SuspendLockMutex); + NewAudioStream = 0; + av_free_packet(AudioAvPkt); } + if (video) { + StopVideo(); + } + if (dox11) { // FIXME: stop x11, if started } + + pthread_mutex_unlock(&SuspendLockMutex); } /** diff --git a/video.c b/video.c index 5b0c236..ad6ef4b 100644 --- a/video.c +++ b/video.c @@ -221,7 +221,6 @@ typedef enum _video_color_space_ typedef struct _video_module_ { const char *Name; ///< video output module name - char Enabled; ///< flag output module enabled /// allocate new video hw decoder @@ -238,11 +237,12 @@ typedef struct _video_module_ void (*const SetVideoMode) (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 + /// draw OSD ARGB area void (*const OsdDrawARGB) (int, int, int, int, const uint8_t *); - ///< draw OSD ARGB area void (*const OsdInit) (int, int); ///< initialize OSD void (*const OsdExit) (void); ///< cleanup OSD @@ -274,6 +274,7 @@ typedef struct _video_module_ char VideoIgnoreRepeatPict; ///< disable repeat pict warning +static const char *VideoDevice; ///< video output device static Display *XlibDisplay; ///< Xlib X11 display static xcb_connection_t *Connection; ///< xcb connection 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 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 @@ -1658,9 +1662,9 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * 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; int i; @@ -1815,7 +1819,7 @@ static void VaapiCleanup(VaapiDecoder * decoder) /// /// @param decoder VA-API decoder /// -static void VaapiDelDecoder(VaapiDecoder * decoder) +static void VaapiDelHwDecoder(VaapiDecoder * decoder) { int i; @@ -2084,7 +2088,7 @@ static void VaapiExit(void) for (i = 0; i < VaapiDecoderN; ++i) { if (VaapiDecoders[i]) { - VaapiDelDecoder(VaapiDecoders[i]); + VaapiDelHwDecoder(VaapiDecoders[i]); VaapiDecoders[i] = NULL; } } @@ -4414,11 +4418,14 @@ static void VaapiSyncRenderFrame(VaapiDecoder * decoder, { VideoSetPts(&decoder->PTS, decoder->Interlaced, frame); +#ifdef DEBUG if (!atomic_read(&decoder->SurfacesFilled)) { Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch); } +#endif if (decoder->DropNextFrame) { // drop frame requested + // FIXME: interlace this drops two frames ++decoder->FramesDropped; Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped, decoder->FrameCounter); @@ -4555,6 +4562,10 @@ static void VaapiDisplayHandlerThread(void) pthread_mutex_unlock(&VideoLockMutex); } +#else + +#define VaapiDisplayHandlerThread NULL + #endif //---------------------------------------------------------------------------- @@ -4783,8 +4794,8 @@ static void VaapiOsdExit(void) static const VideoModule VaapiModule = { .Name = "va-api", .Enabled = 1, - .NewHwDecoder = (VideoHwDecoder * (*const)(void))VaapiNewDecoder, - .DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelDecoder, + .NewHwDecoder = (VideoHwDecoder * (*const)(void))VaapiNewHwDecoder, + .DelHwDecoder = (void (*const) (VideoHwDecoder *))VaapiDelHwDecoder, .GetSurface = (unsigned (*const) (VideoHwDecoder *))VaapiGetSurface, .ReleaseSurface = (void (*const) (VideoHwDecoder *, unsigned))VaapiReleaseSurface, @@ -4796,7 +4807,7 @@ static const VideoModule VaapiModule = { .SetBackground = VaapiSetBackground, .SetVideoMode = VaapiSetVideoMode, .ResetAutoCrop = VaapiResetAutoCrop, - .Thread = VaapiDisplayHandlerThread, + .DisplayHandlerThread = VaapiDisplayHandlerThread, .OsdClear = VaapiOsdClear, .OsdDrawARGB = VaapiOsdDrawARGB, .OsdInit = VaapiOsdInit, @@ -5444,7 +5455,7 @@ static void VdpauMixerCreate(VdpauDecoder * decoder) /// /// @returns a new prepared vdpau hardware decoder. /// -static VdpauDecoder *VdpauNewDecoder(void) +static VdpauDecoder *VdpauNewHwDecoder(void) { VdpauDecoder *decoder; int i; @@ -5563,7 +5574,7 @@ static void VdpauCleanup(VdpauDecoder * decoder) /// /// @param decoder VDPAU hw decoder /// -static void VdpauDelDecoder(VdpauDecoder * decoder) +static void VdpauDelHwDecoder(VdpauDecoder * decoder) { int i; @@ -6143,7 +6154,7 @@ static void VdpauExit(void) for (i = 0; i < VdpauDecoderN; ++i) { if (VdpauDecoders[i]) { - VdpauDelDecoder(VdpauDecoders[i]); + VdpauDelHwDecoder(VdpauDecoders[i]); VdpauDecoders[i] = NULL; } } @@ -7478,11 +7489,14 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder, VideoSetPts(&decoder->PTS, decoder->Interlaced, frame); +#ifdef DEBUG if (!atomic_read(&decoder->SurfacesFilled)) { Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch); } +#endif if (decoder->DropNextFrame) { // drop frame requested + // FIXME: interlace this drops two frames ++decoder->FramesDropped; Warning(_("video: dropping frame (%d/%d)\n"), decoder->FramesDropped, decoder->FrameCounter); @@ -7681,6 +7695,10 @@ static void VdpauDisplayHandlerThread(void) pthread_mutex_unlock(&VideoLockMutex); } +#else + +#define VdpauDisplayHandlerThread NULL + #endif /// @@ -7942,8 +7960,8 @@ static void VdpauOsdExit(void) static const VideoModule VdpauModule = { .Name = "vdpau", .Enabled = 1, - .NewHwDecoder = (VideoHwDecoder * (*const)(void))VdpauNewDecoder, - .DelHwDecoder = (void (*const) (VideoHwDecoder *))VdpauDelDecoder, + .NewHwDecoder = (VideoHwDecoder * (*const)(void))VdpauNewHwDecoder, + .DelHwDecoder = (void (*const) (VideoHwDecoder *))VdpauDelHwDecoder, .GetSurface = (unsigned (*const) (VideoHwDecoder *))VdpauGetSurface, .ReleaseSurface = (void (*const) (VideoHwDecoder *, unsigned))VdpauReleaseSurface, @@ -7955,7 +7973,7 @@ static const VideoModule VdpauModule = { .SetBackground = VdpauSetBackground, .SetVideoMode = VdpauSetVideoMode, .ResetAutoCrop = VdpauResetAutoCrop, - .Thread = VdpauDisplayHandlerThread, + .DisplayHandlerThread = VdpauDisplayHandlerThread, .OsdClear = VdpauOsdClear, .OsdDrawARGB = VdpauOsdDrawARGB, .OsdInit = VdpauOsdInit, @@ -7966,6 +7984,152 @@ static const VideoModule VdpauModule = { #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 //---------------------------------------------------------------------------- @@ -7978,9 +8142,7 @@ static const VideoModule VdpauModule = { /// void VideoOsdClear(void) { - if (VideoThread) { - VideoThreadLock(); - } + VideoThreadLock(); #ifdef USE_GLX if (GlxEnabled) { void *texbuf; @@ -7998,18 +8160,15 @@ void VideoOsdClear(void) } #endif - if (VideoUsedModule) { - VideoUsedModule->OsdClear(); - } + VideoUsedModule->OsdClear(); + OsdDirtyX = OsdWidth; OsdDirtyY = OsdHeight; OsdDirtyWidth = 0; OsdDirtyHeight = 0; OsdShown = 0; - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadUnlock(); } /// @@ -8024,9 +8183,7 @@ void VideoOsdClear(void) void VideoOsdDrawARGB(int x, int y, int width, int height, const uint8_t * argb) { - if (VideoThread) { - VideoThreadLock(); - } + VideoThreadLock(); // update dirty area if (x < OsdDirtyX) { if (OsdDirtyWidth) { @@ -8057,14 +8214,10 @@ void VideoOsdDrawARGB(int x, int y, int width, int height, return; } #endif - if (VideoUsedModule) { - VideoUsedModule->OsdDrawARGB(x, y, width, height, argb); - } + VideoUsedModule->OsdDrawARGB(x, y, width, height, argb); OsdShown = 1; - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadUnlock(); } /// @@ -8123,15 +8276,9 @@ void VideoOsdInit(void) } #endif - if (VideoThread) { - VideoThreadLock(); - } - if (VideoUsedModule) { - VideoUsedModule->OsdInit(OsdWidth, OsdHeight); - } - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadLock(); + VideoUsedModule->OsdInit(OsdWidth, OsdHeight); + VideoThreadUnlock(); VideoOsdClear(); } @@ -8140,15 +8287,9 @@ void VideoOsdInit(void) /// void VideoOsdExit(void) { - if (VideoThread) { - VideoThreadLock(); - } - if (VideoUsedModule) { - VideoUsedModule->OsdExit(); - } - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadLock(); + VideoUsedModule->OsdExit(); + VideoThreadUnlock(); OsdDirtyWidth = 0; OsdDirtyHeight = 0; } @@ -8231,39 +8372,6 @@ void VideoDisplayOverlay(void) #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 //---------------------------------------------------------------------------- @@ -8283,7 +8391,7 @@ static int VideoIOErrorHandler( __attribute__ ((unused)) Display * display) // should be called from VideoThread if (VideoThread && VideoThread == pthread_self()) { Debug(3, "video: called from video thread\n"); - VideoUsedModule = NULL; // FIXME: NoopModule; + VideoUsedModule = &NoopModule; XlibDisplay = NULL; VideoWindow = XCB_NONE; #ifdef USE_VIDEO_THREAD @@ -8370,7 +8478,7 @@ static void VideoEvent(void) /// void VideoPollEvent(void) { - while (XPending(XlibDisplay)) { + while (XlibDisplay && XPending(XlibDisplay)) { VideoEvent(); } } @@ -8390,8 +8498,10 @@ static GLXContext GlxThreadContext; ///< our gl context for the thread /// static void VideoThreadLock(void) { - if (pthread_mutex_lock(&VideoLockMutex)) { - Error(_("video: can't lock thread\n")); + if (VideoThread) { + if (pthread_mutex_lock(&VideoLockMutex)) { + Error(_("video: can't lock thread\n")); + } } } @@ -8400,8 +8510,10 @@ static void VideoThreadLock(void) /// static void VideoThreadUnlock(void) { - if (pthread_mutex_unlock(&VideoLockMutex)) { - Error(_("video: can't unlock thread\n")); + if (VideoThread) { + if (pthread_mutex_unlock(&VideoLockMutex)) { + Error(_("video: can't unlock thread\n")); + } } } @@ -8439,16 +8551,7 @@ static void *VideoDisplayHandlerThread(void *dummy) VideoPollEvent(); - if (VideoUsedModule) { - VideoUsedModule->Thread(); - } else { - XEvent event; - - // FIXME: move into noop module - // avoid 100% cpu use - - XPeekEvent(XlibDisplay, &event); - } + VideoUsedModule->DisplayHandlerThread(); } return dummy; @@ -8484,10 +8587,10 @@ static void VideoThreadExit(void) if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) { Error(_("video: can't cancel video display thread\n")); } + VideoThread = 0; pthread_cond_destroy(&VideoWakeupCond); pthread_mutex_destroy(&VideoLockMutex); pthread_mutex_destroy(&VideoMutex); - VideoThread = 0; } } @@ -8525,7 +8628,7 @@ static const VideoModule *VideoModules[] = { #ifdef USE_VAAPI &VaapiModule, #endif - //&NoopModule + &NoopModule }; /// @@ -8551,9 +8654,6 @@ struct _video_hw_decoder_ /// VideoHwDecoder *VideoNewHwDecoder(void) { - if (!XlibDisplay || !VideoUsedModule) { // waiting for x11 start - return NULL; - } return VideoUsedModule->NewHwDecoder(); } @@ -8564,7 +8664,7 @@ VideoHwDecoder *VideoNewHwDecoder(void) /// void VideoDelHwDecoder(VideoHwDecoder * decoder) { - if (decoder && VideoUsedModule) { + if (decoder) { VideoUsedModule->DelHwDecoder(decoder); } } @@ -8578,10 +8678,7 @@ void VideoDelHwDecoder(VideoHwDecoder * decoder) /// unsigned VideoGetSurface(VideoHwDecoder * decoder) { - if (VideoUsedModule) { - return VideoUsedModule->GetSurface(decoder); - } - return -1; + return VideoUsedModule->GetSurface(decoder); } /// @@ -8593,12 +8690,7 @@ unsigned VideoGetSurface(VideoHwDecoder * decoder) void VideoReleaseSurface(VideoHwDecoder * decoder, unsigned surface) { // FIXME: must be guarded against calls, after VideoExit - if (!XlibDisplay) { // no init or failed - return; - } - if (VideoUsedModule) { - VideoUsedModule->ReleaseSurface(decoder, surface); - } + VideoUsedModule->ReleaseSurface(decoder, surface); } /// @@ -8612,10 +8704,8 @@ enum PixelFormat Video_get_format(VideoHwDecoder * decoder, AVCodecContext * video_ctx, const enum PixelFormat *fmt) { AudioVideoReady(); - if (VideoUsedModule) { - return VideoUsedModule->get_format(decoder, video_ctx, fmt); - } - return fmt[0]; + return VideoUsedModule->get_format(decoder, video_ctx, fmt); + //return fmt[0]; } /// @@ -8632,9 +8722,7 @@ void VideoRenderFrame(VideoHwDecoder * decoder, Warning(_("video: repeated pict %d found, but not handled\n"), 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 + /// /// Draw ffmpeg vdpau render state. /// @@ -8707,36 +8796,6 @@ void VideoDrawRenderState(VideoHwDecoder * hw_decoder, } 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 @@ -8759,7 +8818,7 @@ int64_t VideoGetClock(void) return VaapiGetClock(VaapiDecoders[0]); } #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"); #ifdef USE_GRAB - if (VideoUsedModule && VideoUsedModule->GrabOutput) { + if (VideoUsedModule->GrabOutput) { uint8_t *data; uint8_t *rgb; char buf[64]; @@ -8995,6 +9054,16 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual, // FIXME: free cursor/pixmap needed? } +/// +/// Set video device. +/// +/// Currently this only choose the driver. +/// +void VideoSetDevice(const char *device) +{ + VideoDevice = device; +} + /// /// Set video geometry. /// @@ -9053,12 +9122,8 @@ void VideoSetOutputPosition(int x, int y, int width, int height) y = (y * VideoWindowHeight) / OsdHeight; width = (width * VideoWindowWidth) / OsdWidth; height = (height * VideoWindowHeight) / OsdHeight; - if (VideoThread) { - VideoThreadLock(); - } - if (VideoUsedModule) { - // FIXME: what stream? - } + VideoThreadLock(); + // FIXME: what stream? #ifdef USE_VDPAU if (VideoUsedModule == &VdpauModule) { 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: if used to position video inside osd #endif - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadUnlock(); } /// @@ -9097,17 +9160,11 @@ void VideoSetVideoMode( __attribute__ ((unused)) VideoOsdExit(); // FIXME: must tell VDR that the OsdSize has been changed! - if (VideoThread) { - VideoThreadLock(); - } + VideoThreadLock(); VideoWindowWidth = width; VideoWindowHeight = height; - if (VideoUsedModule) { - VideoUsedModule->SetVideoMode(); - } - if (VideoThread) { - VideoThreadUnlock(); - } + VideoUsedModule->SetVideoMode(); + VideoThreadUnlock(); VideoOsdInit(); } @@ -9119,9 +9176,7 @@ void VideoSetDisplayFormat(int format) VideoOsdExit(); // FIXME: must tell VDR that the OsdSize has been changed! - if (VideoThread) { - VideoThreadLock(); - } + VideoThreadLock(); switch (format) { case 0: // pan&scan (we have no pan&scan) @@ -9135,12 +9190,8 @@ void VideoSetDisplayFormat(int format) break; } - if (VideoUsedModule) { - VideoUsedModule->SetVideoMode(); - } - if (VideoThread) { - VideoThreadUnlock(); - } + VideoUsedModule->SetVideoMode(); + VideoThreadUnlock(); VideoOsdInit(); } @@ -9151,32 +9202,30 @@ void VideoSetDisplayFormat(int format) /// 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 - return; + 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]); } - - 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) { - VideoBackground = rgba; // save for later start - if (VideoUsedModule) { - VideoUsedModule->SetBackground(rgba); - } + VideoBackground = rgba; // saved for later start + VideoUsedModule->SetBackground(rgba); } /// @@ -9306,15 +9353,9 @@ void VideoSetAutoCrop(int interval, int delay, int tolerance) AutoCropDelay = delay; AutoCropTolerance = tolerance; - if (VideoThread) { - VideoThreadLock(); - } - if (VideoUsedModule) { - VideoUsedModule->ResetAutoCrop(); - } - if (VideoThread) { - VideoThreadUnlock(); - } + VideoThreadLock(); + VideoUsedModule->ResetAutoCrop(); + VideoThreadUnlock(); #else (void)interval; (void)delay; @@ -9423,10 +9464,12 @@ void VideoInit(const char *display_name) // // prepare hardware decoder VA-API/VDPAU - // FIXME: make the used output modules configurable // 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)) { VideoUsedModule = VideoModules[i]; break; @@ -9470,10 +9513,8 @@ void VideoExit(void) // XUnlockDisplay(XlibDisplay); // xcb_flush(Connection); #endif - if (VideoUsedModule) { - VideoUsedModule->Exit(); - } - VideoUsedModule = NULL; // FIXME: NoopModule; + VideoUsedModule->Exit(); + VideoUsedModule = &NoopModule; #ifdef USE_GLX if (GlxEnabled) { GlxExit(); diff --git a/video.h b/video.h index 77a4068..4db8a07 100644 --- a/video.h +++ b/video.h @@ -77,6 +77,9 @@ extern void VideoPollEvent(void); /// Wakeup display handler. extern void VideoDisplayWakeup(void); + /// Set video device. +extern void VideoSetDevice(const char *); + /// Set video geometry. extern int VideoSetGeometry(const char *);