static int vdp_device_Create (vlc_object_t *obj, void **sysp, VdpDevice *devp, VdpGetProcAddress **gpap) { VdpStatus err; if (!vlc_xlib_init (obj)) { msg_Err (obj, "Xlib is required for VDPAU"); return VLC_EGENERIC; } Display *x11 = XOpenDisplay (NULL); if (x11 == NULL) { msg_Err (obj, "windowing system failure failure"); return VLC_EGENERIC; } err = vdp_device_create_x11 (x11, XDefaultScreen (x11), devp, gpap); if (err) { msg_Err (obj, "device creation failure: error %d", (int)err); XCloseDisplay (x11); return VLC_EGENERIC; } *sysp = x11; return VLC_SUCCESS; }
vlc_va_t *vlc_va_NewVaapi( vlc_object_t *obj, int i_codec_id ) { if( !vlc_xlib_init( obj ) ) return NULL; vlc_va_vaapi_t *p_va = calloc( 1, sizeof(*p_va) ); if( !p_va ) return NULL; p_va->log = obj; if( Open( p_va, i_codec_id ) ) { free( p_va ); return NULL; } /* */ p_va->va.setup = Setup; p_va->va.get = Get; p_va->va.release = Release; p_va->va.extract = Extract; p_va->va.close = Delete; return &p_va->va; }
/* Open Interface */ static int Open( vlc_object_t *p_this, bool isDialogProvider ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; #ifdef Q_WS_X11 if( !vlc_xlib_init( p_this ) ) return VLC_EGENERIC; char *display = var_CreateGetNonEmptyString( p_intf, "x11-display" ); Display *p_display = XOpenDisplay( x11_display ); if( !p_display ) { msg_Err( p_intf, "Could not connect to X server" ); free (display); return VLC_EGENERIC; } XCloseDisplay( p_display ); #else char *display = NULL; #endif QMutexLocker locker (&lock); if (busy) { msg_Err (p_this, "cannot start Qt4 multiple times"); free (display); return VLC_EGENERIC; } /* Allocations of p_sys */ intf_sys_t *p_sys = p_intf->p_sys = new intf_sys_t; p_intf->p_sys->b_isDialogProvider = isDialogProvider; p_sys->p_mi = NULL; p_sys->p_playlist = pl_Get( p_intf ); /* */ #ifdef Q_WS_X11 x11_display = display; #endif vlc_sem_init (&ready, 0); if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { delete p_sys; free (display); return VLC_ENOMEM; } /* */ vlc_sem_wait (&ready); vlc_sem_destroy (&ready); busy = active = true; if( !p_sys->b_isDialogProvider ) { playlist_t *pl = pl_Get(p_this); var_Create (pl, "qt4-iface", VLC_VAR_ADDRESS); var_SetAddress (pl, "qt4-iface", p_this); } return VLC_SUCCESS; }
/** * This function allocates and initializes a aa vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; #ifndef _WIN32 if (!vlc_xlib_init (object)) return VLC_EGENERIC; #endif /* Allocate structure */ vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) return VLC_ENOMEM; /* Don't parse any options, but take $AAOPTS into account */ aa_parseoptions(NULL, NULL, NULL, NULL); /* */ sys->aa_context = aa_autoinit(&aa_defparams); if (!sys->aa_context) { msg_Err(vd, "cannot initialize aalib"); goto error; } vout_display_DeleteWindow(vd, NULL); aa_autoinitkbd(sys->aa_context, 0); aa_autoinitmouse(sys->aa_context, AA_MOUSEALLMASK); /* */ video_format_t fmt = vd->fmt; fmt.i_chroma = VLC_CODEC_RGB8; fmt.i_width = aa_imgwidth(sys->aa_context); fmt.i_height = aa_imgheight(sys->aa_context); fmt.i_visible_width = fmt.i_width; fmt.i_visible_height = fmt.i_height; /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info.has_pictures_invalid = true; vd->info.needs_event_thread = true; vd->pool = Pool; vd->prepare = Prepare; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* Inspect initial configuration and send correction events * FIXME how to handle aspect ratio with aa ? */ vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height); return VLC_SUCCESS; error: if (sys && sys->aa_context) aa_close(sys->aa_context); free(sys); return VLC_EGENERIC; }
bool X11Factory::init() { // make sure xlib is safe-thread if( !vlc_xlib_init( VLC_OBJECT( getIntf() ) ) ) { msg_Err( getIntf(), "initializing xlib for multi-threading failed" ); return false; } // Create the X11 display m_pDisplay = new X11Display( getIntf() ); // Get the display Display *pDisplay = m_pDisplay->getDisplay(); if( pDisplay == NULL ) { // Initialization failed return false; } // Create the timer loop m_pTimerLoop = new X11TimerLoop( getIntf(), ConnectionNumber( pDisplay ) ); // Initialize the resource path char *datadir = config_GetUserDir( VLC_DATA_DIR ); m_resourcePath.push_back( (std::string)datadir + "/skins2" ); free( datadir ); m_resourcePath.push_back( (std::string)"share/skins2" ); datadir = config_GetDataDir(); m_resourcePath.push_back( (std::string)datadir + "/skins2" ); free( datadir ); // Determine the monitor geometry getDefaultGeometry( &m_screenWidth, &m_screenHeight ); // list all available monitors int num_screen; XineramaScreenInfo* info = XineramaQueryScreens( pDisplay, &num_screen ); if( info ) { msg_Dbg( getIntf(), "number of monitors detected : %i", num_screen ); for( int i = 0; i < num_screen; i++ ) msg_Dbg( getIntf(), " monitor #%i : %ix%i at +%i+%i", i, info[i].width, info[i].height, info[i].x_org, info[i].y_org ); XFree( info ); } return true; }
/***************************************************************************** * Module callbacks *****************************************************************************/ static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; intf_sys_t *p_sys; vlc_value_t val; if( !vlc_xlib_init( p_this ) ) return VLC_EGENERIC; /* Allocate instance and initialize some members */ p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) ); if( p_intf->p_sys == NULL ) return VLC_ENOMEM; p_sys->p_playlist = pl_Get( p_intf ); p_sys->p_input = NULL; p_sys->p_main_window = NULL; p_sys->p_video_window = NULL; p_sys->p_control_window = NULL; p_sys->b_fullscreen = false; p_sys->i_event = 0; vlc_spin_init( &p_sys->event_lock ); /* Create separate thread for main interface */ vlc_sem_init (&p_sys->ready, 0); if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { free (p_sys); return VLC_ENOMEM; } /* Wait for interface thread to be fully initialised */ vlc_sem_wait (&p_sys->ready); vlc_sem_destroy (&p_sys->ready); var_Create (p_this->p_libvlc, "hildon-iface", VLC_VAR_ADDRESS); val.p_address = p_this; var_Set (p_this->p_libvlc, "hildon-iface", val); return VLC_SUCCESS; }
/** * This function initializes libcaca vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; if (vout_display_IsWindowed(vd)) return VLC_EGENERIC; #if !defined(__APPLE__) && !defined(_WIN32) # ifndef X_DISPLAY_MISSING if (!vlc_xlib_init(object)) return VLC_EGENERIC; # endif #endif #if defined(_WIN32) CONSOLE_SCREEN_BUFFER_INFO csbiInfo; SMALL_RECT rect; COORD coord; HANDLE hstdout; if (!AllocConsole()) { msg_Err(vd, "cannot create console"); return VLC_EGENERIC; } hstdout = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); if (!hstdout || hstdout == INVALID_HANDLE_VALUE) { msg_Err(vd, "cannot create screen buffer"); FreeConsole(); return VLC_EGENERIC; } if (!SetConsoleActiveScreenBuffer(hstdout)) { msg_Err(vd, "cannot set active screen buffer"); FreeConsole(); return VLC_EGENERIC; } coord = GetLargestConsoleWindowSize(hstdout); msg_Dbg(vd, "SetConsoleWindowInfo: %ix%i", coord.X, coord.Y); /* Force size for now */ coord.X = 100; coord.Y = 40; if (!SetConsoleScreenBufferSize(hstdout, coord)) msg_Warn(vd, "SetConsoleScreenBufferSize %i %i", coord.X, coord.Y); /* Get the current screen buffer size and window position. */ if (GetConsoleScreenBufferInfo(hstdout, &csbiInfo)) { rect.Top = 0; rect.Left = 0; rect.Right = csbiInfo.dwMaximumWindowSize.X - 1; rect.Bottom = csbiInfo.dwMaximumWindowSize.Y - 1; if (!SetConsoleWindowInfo(hstdout, TRUE, &rect)) msg_Dbg(vd, "SetConsoleWindowInfo failed: %ix%i", rect.Right, rect.Bottom); } #endif /* Allocate structure */ vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) goto error; sys->cv = cucul_create_canvas(0, 0); if (!sys->cv) { msg_Err(vd, "cannot initialize libcucul"); goto error; } const char *driver = NULL; #ifdef __APPLE__ // Make sure we don't try to open a window. driver = "ncurses"; #endif sys->dp = caca_create_display_with_driver(sys->cv, driver); if (!sys->dp) { msg_Err(vd, "cannot initialize libcaca"); goto error; } if (vd->cfg->display.title) caca_set_display_title(sys->dp, vd->cfg->display.title); else caca_set_display_title(sys->dp, VOUT_TITLE "(Colour AsCii Art)"); /* Fix format */ video_format_t fmt = vd->fmt; if (fmt.i_chroma != VLC_CODEC_RGB32) { fmt.i_chroma = VLC_CODEC_RGB32; fmt.i_rmask = 0x00ff0000; fmt.i_gmask = 0x0000ff00; fmt.i_bmask = 0x000000ff; } /* TODO */ vout_display_info_t info = vd->info; /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = Prepare; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* Fix initial state */ vout_display_SendEventFullscreen(vd, false); Refresh(vd); return VLC_SUCCESS; error: if (sys) { if (sys->pool) picture_pool_Release(sys->pool); if (sys->dither) cucul_free_dither(sys->dither); if (sys->dp) caca_free_display(sys->dp); if (sys->cv) cucul_free_canvas(sys->cv); free(sys); } #if defined(_WIN32) FreeConsole(); #endif return VLC_EGENERIC; }
static int Open (vlc_object_t *obj) { vlc_gl_t *gl = (vlc_gl_t *)obj; if (gl->surface->type != VOUT_WINDOW_TYPE_XID || !vlc_xlib_init (obj)) return VLC_EGENERIC; /* Initialize GLX display */ Display *dpy = XOpenDisplay (gl->surface->display.x11); if (dpy == NULL) return VLC_EGENERIC; vlc_gl_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) { XCloseDisplay (dpy); return VLC_ENOMEM; } gl->sys = sys; sys->display = dpy; if (!CheckGLX (obj, dpy)) goto error; /* Determine our pixel format */ XWindowAttributes wa; if (!XGetWindowAttributes (dpy, gl->surface->handle.xid, &wa)) goto error; const int snum = XScreenNumberOfScreen (wa.screen); const VisualID visual = XVisualIDFromVisual (wa.visual); static const int attr[] = { GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5, GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, True, GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, None }; int nelem; GLXFBConfig *confs = glXChooseFBConfig (dpy, snum, attr, &nelem); if (confs == NULL) { msg_Err (obj, "cannot choose GLX frame buffer configurations"); goto error; } GLXFBConfig conf; bool found = false; for (int i = 0; i < nelem && !found; i++) { conf = confs[i]; XVisualInfo *vi = glXGetVisualFromFBConfig (dpy, conf); if (vi == NULL) continue; if (vi->visualid == visual) found = true; XFree (vi); } XFree (confs); if (!found) { msg_Err (obj, "cannot match GLX frame buffer configuration"); goto error; } /* Create a drawing surface */ sys->win = glXCreateWindow (dpy, conf, gl->surface->handle.xid, NULL); if (sys->win == None) { msg_Err (obj, "cannot create GLX window"); goto error; } /* Create an OpenGL context */ sys->ctx = glXCreateNewContext (dpy, conf, GLX_RGBA_TYPE, NULL, True); if (sys->ctx == NULL) { glXDestroyWindow (dpy, sys->win); msg_Err (obj, "cannot create GLX context"); goto error; } /* Initialize OpenGL callbacks */ gl->sys = sys; gl->makeCurrent = MakeCurrent; gl->releaseCurrent = ReleaseCurrent; gl->resize = NULL; gl->swap = SwapBuffers; gl->getProcAddress = GetSymbol; #ifdef GLX_ARB_get_proc_address bool is_swap_interval_set = false; MakeCurrent (gl); # ifdef GLX_SGI_swap_control if (!is_swap_interval_set && CheckGLXext (dpy, snum, "GLX_SGI_swap_control")) { PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB ((const GLubyte *)"glXSwapIntervalSGI"); assert (SwapIntervalSGI != NULL); is_swap_interval_set = !SwapIntervalSGI (1); } # endif # ifdef GLX_EXT_swap_control if (!is_swap_interval_set && CheckGLXext (dpy, snum, "GLX_EXT_swap_control")) { PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress ((const GLubyte *)"glXSwapIntervalEXT"); assert (SwapIntervalEXT != NULL); SwapIntervalEXT (dpy, sys->win, 1); is_swap_interval_set = true; } # endif ReleaseCurrent (gl); #endif return VLC_SUCCESS; error: XCloseDisplay (dpy); free (sys); return VLC_EGENERIC; }
/** * Probe EGL display availability */ static int Open (vlc_object_t *obj, const struct gl_api *api) { vlc_gl_t *gl = (vlc_gl_t *)obj; vlc_gl_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; gl->sys = sys; sys->display = EGL_NO_DISPLAY; sys->surface = EGL_NO_SURFACE; vout_window_t *wnd = gl->surface; EGLSurface (*createSurface)(EGLDisplay, EGLConfig, void *, const EGLint *) = CreateWindowSurface; void *window; #ifdef USE_PLATFORM_X11 sys->x11 = NULL; if (wnd->type != VOUT_WINDOW_TYPE_XID || !vlc_xlib_init(obj)) goto error; window = &wnd->handle.xid; sys->x11 = XOpenDisplay(wnd->display.x11); if (sys->x11 == NULL) goto error; int snum; { XWindowAttributes wa; if (!XGetWindowAttributes(sys->x11, wnd->handle.xid, &wa)) goto error; snum = XScreenNumberOfScreen(wa.screen); } # ifdef EGL_EXT_platform_x11 if (CheckClientExt("EGL_EXT_platform_x11")) { const EGLint attrs[] = { EGL_PLATFORM_X11_SCREEN_EXT, snum, EGL_NONE }; sys->display = GetDisplayEXT(EGL_PLATFORM_X11_EXT, sys->x11, attrs); createSurface = CreateWindowSurfaceEXT; } else # endif { # ifdef __unix__ if (snum == XDefaultScreen(sys->x11)) sys->display = eglGetDisplay(sys->x11); } # endif #elif defined (USE_PLATFORM_WAYLAND) sys->window = NULL; if (wnd->type != VOUT_WINDOW_TYPE_WAYLAND) goto error; # ifdef EGL_EXT_platform_wayland if (!CheckClientExt("EGL_EXT_platform_wayland")) goto error; /* Resize() should be called with the proper size before Swap() */ window = wl_egl_window_create(wnd->handle.wl, 1, 1); if (window == NULL) goto error; sys->window = window; sys->display = GetDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, wnd->display.wl, NULL); createSurface = CreateWindowSurfaceEXT; # endif #elif defined (USE_PLATFORM_WIN32) if (wnd->type != VOUT_WINDOW_TYPE_HWND) goto error; window = &wnd->handle.hwnd; # if defined (_WIN32) || defined (__VC32__) \ && !defined (__CYGWIN__) && !defined (__SCITECH_SNAP__) sys->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); # endif #elif defined (USE_PLATFORM_ANDROID) if (wnd->type != VOUT_WINDOW_TYPE_ANDROID_NATIVE) goto error; window = &wnd->handle.anativewindow; # if defined (__ANDROID__) || defined (ANDROID) sys->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); # endif #endif if (sys->display == EGL_NO_DISPLAY) goto error; /* Initialize EGL display */ EGLint major, minor; if (eglInitialize(sys->display, &major, &minor) != EGL_TRUE) goto error; msg_Dbg(obj, "EGL version %s by %s", eglQueryString(sys->display, EGL_VERSION), eglQueryString(sys->display, EGL_VENDOR)); const char *ext = eglQueryString(sys->display, EGL_EXTENSIONS); if (*ext) msg_Dbg(obj, " extensions: %s", ext); if (major != 1 || minor < api->min_minor || !CheckAPI(sys->display, api->name)) { msg_Err(obj, "cannot select %s API", api->name); goto error; } const EGLint conf_attr[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_RENDERABLE_TYPE, api->render_bit, EGL_NONE }; EGLConfig cfgv[1]; EGLint cfgc; if (eglChooseConfig(sys->display, conf_attr, cfgv, 1, &cfgc) != EGL_TRUE || cfgc == 0) { msg_Err (obj, "cannot choose EGL configuration"); goto error; } /* Create a drawing surface */ sys->surface = createSurface(sys->display, cfgv[0], window, NULL); if (sys->surface == EGL_NO_SURFACE) { msg_Err (obj, "cannot create EGL window surface"); goto error; } if (eglBindAPI (api->api) != EGL_TRUE) { msg_Err (obj, "cannot bind EGL API"); goto error; } EGLContext ctx = eglCreateContext(sys->display, cfgv[0], EGL_NO_CONTEXT, api->attr); if (ctx == EGL_NO_CONTEXT) { msg_Err (obj, "cannot create EGL context"); goto error; } sys->context = ctx; /* Initialize OpenGL callbacks */ gl->makeCurrent = MakeCurrent; gl->releaseCurrent = ReleaseCurrent; gl->resize = Resize; gl->swap = SwapBuffers; gl->getProcAddress = GetSymbol; return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
/** * This function initializes SDL vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; #if !defined(WIN32) && !defined(__OS2__) if (!vlc_xlib_init (object)) return VLC_EGENERIC; #endif /* XXX: check for conflicts with the SDL audio output */ vlc_mutex_lock(&sdl_lock); /* Check if SDL video module has been initialized */ if (SDL_WasInit(SDL_INIT_VIDEO) != 0) { vlc_mutex_unlock(&sdl_lock); return VLC_EGENERIC; } vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&sdl_lock); return VLC_ENOMEM; } /* */ int sdl_flags = SDL_INIT_VIDEO; #ifndef WIN32 /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/ sdl_flags |= SDL_INIT_EVENTTHREAD; #endif /* In debug mode you may want vlc to dump a core instead of staying stuck */ sdl_flags |= SDL_INIT_NOPARACHUTE; /* Initialize library */ if (SDL_Init(sdl_flags) < 0) { vlc_mutex_unlock(&sdl_lock); msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError()); free(sys); return VLC_EGENERIC; } vlc_mutex_unlock(&sdl_lock); /* Translate keys into unicode */ SDL_EnableUNICODE(1); /* Get the desktop resolution */ /* FIXME: SDL has a problem with virtual desktop */ sys->desktop_width = SDL_GetVideoInfo()->current_w; sys->desktop_height = SDL_GetVideoInfo()->current_h; /* */ video_format_t fmt = vd->fmt; /* */ vout_display_info_t info = vd->info; /* Set main window's size */ int display_width; int display_height; if (vd->cfg->is_fullscreen) { display_width = sys->desktop_width; display_height = sys->desktop_height; } else { display_width = vd->cfg->display.width; display_height = vd->cfg->display.height; } /* Initialize flags and cursor */ sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF; sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE; sys->display_bpp = SDL_VideoModeOK(display_width, display_height, 16, sys->display_flags); if (sys->display_bpp == 0) { msg_Err(vd, "no video mode available"); goto error; } vout_display_DeleteWindow(vd, NULL); sys->display = SDL_SetVideoMode(display_width, display_height, sys->display_bpp, sys->display_flags); if (!sys->display) { msg_Err(vd, "cannot set video mode"); goto error; } /* We keep the surface locked forever */ SDL_LockSurface(sys->display); /* */ vlc_fourcc_t forced_chroma = 0; char *psz_chroma = var_InheritString(vd, "sdl-chroma"); if (psz_chroma) { forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma); if (forced_chroma) msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)", forced_chroma, (const char*)&forced_chroma); free(psz_chroma); } /* Try to open an overlay if requested */ sys->overlay = NULL; const bool is_overlay = var_InheritBool(vd, "overlay"); if (is_overlay) { static const struct { vlc_fourcc_t vlc; uint32_t sdl; } vlc_to_sdl[] = { { VLC_CODEC_YV12, SDL_YV12_OVERLAY }, { VLC_CODEC_I420, SDL_IYUV_OVERLAY }, { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY }, { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY }, { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY }, { 0, 0 } }; const vlc_fourcc_t forced_chromas[] = { forced_chroma, 0 }; const vlc_fourcc_t *fallback_chromas = vlc_fourcc_GetYUVFallback(fmt.i_chroma); const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas; for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) { for (int i = 0; chromas[i] != 0; i++) { const vlc_fourcc_t vlc = chromas[i]; uint32_t sdl = 0; for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) { if (vlc_to_sdl[j].vlc == vlc) sdl = vlc_to_sdl[j].sdl; } if (!sdl) continue; sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height, sdl, sys->display); if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) { /* Ignore non hardware overlay surface in first pass */ SDL_FreeYUVOverlay(sys->overlay); sys->overlay = NULL; } if (sys->overlay) { /* We keep the surface locked forever */ SDL_LockYUVOverlay(sys->overlay); fmt.i_chroma = vlc; sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma, vd->fmt.i_chroma); if (sys->is_uv_swapped) fmt.i_chroma = vd->fmt.i_chroma; break; } } } } else { msg_Warn(vd, "SDL overlay disabled by the user"); } /* */ vout_display_cfg_t place_cfg = *vd->cfg; place_cfg.display.width = display_width; place_cfg.display.height = display_height; vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay); /* If no overlay, fallback to software output */ if (!sys->overlay) { /* */ switch (sys->display->format->BitsPerPixel) { case 8: fmt.i_chroma = VLC_CODEC_RGB8; break; case 15: fmt.i_chroma = VLC_CODEC_RGB15; break; case 16: fmt.i_chroma = VLC_CODEC_RGB16; break; case 24: fmt.i_chroma = VLC_CODEC_RGB24; break; case 32: fmt.i_chroma = VLC_CODEC_RGB32; break; default: msg_Err(vd, "unknown screen depth %i", sys->display->format->BitsPerPixel); goto error; } /* All we have is an RGB image with square pixels */ fmt.i_width = display_width; fmt.i_height = display_height; fmt.i_rmask = sys->display->format->Rmask; fmt.i_gmask = sys->display->format->Gmask; fmt.i_bmask = sys->display->format->Bmask; info.has_pictures_invalid = true; } if (vd->cfg->display.title) SDL_WM_SetCaption(vd->cfg->display.title, vd->cfg->display.title); else if (!sys->overlay) SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)", VOUT_TITLE " (software RGB SDL output)"); else if (sys->overlay->hw_overlay) SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)", VOUT_TITLE " (hardware YUV SDL output)"); else SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)", VOUT_TITLE " (software YUV SDL output)"); /* Setup events */ SDL_EventState(SDL_KEYUP, SDL_IGNORE); /* ignore keys up */ /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* */ vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen); return VLC_SUCCESS; error: msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError()); if (sys->display) { SDL_UnlockSurface(sys->display); SDL_FreeSurface(sys->display); } vlc_mutex_lock(&sdl_lock); SDL_QuitSubSystem(SDL_INIT_VIDEO); vlc_mutex_unlock(&sdl_lock); free(sys); return VLC_EGENERIC; }
/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/ static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; intf_sys_t *p_sys; xosd *p_osd; char *psz_font, *psz_colour; if (!vlc_xlib_init(p_this)) return VLC_EGENERIC; if( getenv( "DISPLAY" ) == NULL ) { msg_Err( p_intf, "no display, please set the DISPLAY variable" ); return VLC_EGENERIC; } /* Allocate instance and initialize some members */ p_sys = p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); if( p_sys == NULL ) return VLC_ENOMEM; /* Initialize library */ psz_font = var_InheritString( p_intf, "xosd-font" ); psz_colour = var_InheritString( p_intf, "xosd-colour" ); p_osd = xosd_create( 1 ); if( p_osd == NULL ) { msg_Err( p_intf, "couldn't initialize libxosd" ); free( psz_colour ); free( psz_font ); free( p_sys ); return VLC_EGENERIC; } p_sys->p_osd = p_osd; /* Set user preferences */ xosd_set_outline_colour( p_osd, "black" ); xosd_set_font( p_osd, psz_font ); xosd_set_colour( p_osd, psz_colour ); xosd_set_timeout( p_osd, 3 ); xosd_set_pos( p_osd, var_InheritBool( p_intf, "xosd-position" ) ? XOSD_bottom: XOSD_top ); xosd_set_horizontal_offset( p_osd, var_InheritInteger( p_intf, "xosd-text-offset" ) ); xosd_set_vertical_offset( p_osd, var_InheritInteger( p_intf, "xosd-text-offset" ) ); xosd_set_shadow_offset( p_osd, var_InheritInteger( p_intf, "xosd-shadow-offset" )); /* Initialize to NULL */ xosd_display( p_osd, 0, XOSD_string, "XOSD interface initialized" ); free( psz_colour ); free( psz_font ); // Initialize mutex and condition variable before adding the callbacks vlc_mutex_init( &p_sys->lock ); vlc_cond_init( &p_sys->cond ); // Add the callbacks playlist_t *p_playlist = pl_Get( p_intf ); var_AddCallback( p_playlist, "item-current", PlaylistNext, p_this ); var_AddCallback( p_playlist, "item-change", PlaylistNext, p_this ); p_sys->b_need_update = true; p_intf->pf_run = Run; return VLC_SUCCESS; }
/** * Probe EGL display availability */ static int Open (vlc_object_t *obj, const struct gl_api *api) { vlc_gl_t *gl = (vlc_gl_t *)obj; #ifdef __unix__ /* EGL can only use the default X11 display */ if (gl->surface->display.x11 != NULL) return VLC_EGENERIC; if (!vlc_xlib_init (obj)) return VLC_EGENERIC; #endif /* Initialize EGL display */ /* TODO: support various display types */ EGLDisplay dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); if (dpy == EGL_NO_DISPLAY) return VLC_EGENERIC; vlc_gl_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; gl->sys = sys; sys->display = dpy; EGLint major, minor; if (eglInitialize (dpy, &major, &minor) != EGL_TRUE) { /* No need to call eglTerminate() in this case */ free (sys); return VLC_EGENERIC; } if (major != 1 || minor < api->min_minor || !CheckAPI (dpy, api->name)) goto error; msg_Dbg (obj, "EGL version %s by %s", eglQueryString (dpy, EGL_VERSION), eglQueryString (dpy, EGL_VENDOR)); { const char *ext = eglQueryString (dpy, EGL_EXTENSIONS); if (*ext) msg_Dbg (obj, " extensions: %s", ext); } const EGLint conf_attr[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_RENDERABLE_TYPE, api->render_bit, EGL_NONE }; EGLConfig cfgv[1]; EGLint cfgc; if (eglChooseConfig (dpy, conf_attr, cfgv, 1, &cfgc) != EGL_TRUE || cfgc == 0) goto error; /* Create a drawing surface */ #if defined (WIN32) EGLNativeWindowType win = gl->surface->handle.hwnd; #elif defined (__unix__) EGLNativeWindowType win = gl->surface->handle.xid; #endif EGLSurface surface = eglCreateWindowSurface (dpy, cfgv[0], win, NULL); if (surface == EGL_NO_SURFACE) { msg_Err (obj, "cannot create EGL window surface"); goto error; } sys->surface = surface; if (eglBindAPI (api->api) != EGL_TRUE) { msg_Err (obj, "cannot bind EGL API"); goto error; } EGLContext ctx = eglCreateContext (dpy, cfgv[0], EGL_NO_CONTEXT, api->attr); if (ctx == EGL_NO_CONTEXT) { msg_Err (obj, "cannot create EGL context"); goto error; } sys->context = ctx; /* Initialize OpenGL callbacks */ gl->sys = sys; gl->makeCurrent = MakeCurrent; gl->swap = SwapBuffers; gl->lock = NULL; gl->unlock = NULL; return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
static int Create( vlc_va_t *va, AVCodecContext *ctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys ) { if( pix_fmt != AV_PIX_FMT_VAAPI_VLD ) return VLC_EGENERIC; (void) fmt; (void) p_sys; #ifdef VLC_VA_BACKEND_XLIB if( !vlc_xlib_init( VLC_OBJECT(va) ) ) { msg_Warn( va, "Ignoring VA-X11 API" ); return VLC_EGENERIC; } #endif VAProfile i_profile, *p_profiles_list; bool b_supported_profile = false; int i_profiles_nb = 0; unsigned count = 3; /* */ switch( ctx->codec_id ) { case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: i_profile = VAProfileMPEG2Main; count = 4; break; case AV_CODEC_ID_MPEG4: i_profile = VAProfileMPEG4AdvancedSimple; break; case AV_CODEC_ID_WMV3: i_profile = VAProfileVC1Main; break; case AV_CODEC_ID_VC1: i_profile = VAProfileVC1Advanced; break; case AV_CODEC_ID_H264: i_profile = VAProfileH264High; count = 18; break;; default: return VLC_EGENERIC; } count += ctx->thread_count; vlc_va_sys_t *sys; void *mem; assert(popcount(sizeof (sys->surfaces)) == 1); if (unlikely(posix_memalign(&mem, sizeof (sys->surfaces), sizeof (*sys)))) return VLC_ENOMEM; sys = mem; memset(sys, 0, sizeof (*sys)); /* */ sys->hw_ctx.display = NULL; sys->hw_ctx.config_id = VA_INVALID_ID; sys->hw_ctx.context_id = VA_INVALID_ID; sys->width = ctx->coded_width; sys->height = ctx->coded_height; sys->count = count; sys->available = (1 << sys->count) - 1; assert(count < sizeof (sys->available) * CHAR_BIT); assert(count * sizeof (sys->surfaces[0]) <= sizeof (sys->surfaces)); /* Create a VA display */ #ifdef VLC_VA_BACKEND_XLIB sys->p_display_x11 = XOpenDisplay(NULL); if( !sys->p_display_x11 ) { msg_Err( va, "Could not connect to X server" ); goto error; } sys->hw_ctx.display = vaGetDisplay(sys->p_display_x11); #endif #ifdef VLC_VA_BACKEND_DRM sys->drm_fd = vlc_open("/dev/dri/card0", O_RDWR); if( sys->drm_fd == -1 ) { msg_Err( va, "Could not access rendering device: %m" ); goto error; } sys->hw_ctx.display = vaGetDisplayDRM(sys->drm_fd); #endif if (sys->hw_ctx.display == NULL) { msg_Err( va, "Could not get a VAAPI device" ); goto error; } int major, minor; if (vaInitialize(sys->hw_ctx.display, &major, &minor)) { msg_Err( va, "Failed to initialize the VAAPI device" ); goto error; } /* Check if the selected profile is supported */ i_profiles_nb = vaMaxNumProfiles(sys->hw_ctx.display); p_profiles_list = calloc( i_profiles_nb, sizeof( VAProfile ) ); if( !p_profiles_list ) goto error; if (vaQueryConfigProfiles(sys->hw_ctx.display, p_profiles_list, &i_profiles_nb) == VA_STATUS_SUCCESS) { for( int i = 0; i < i_profiles_nb; i++ ) { if ( p_profiles_list[i] == i_profile ) { b_supported_profile = true; break; } } } free( p_profiles_list ); if ( !b_supported_profile ) { msg_Dbg( va, "Codec and profile not supported by the hardware" ); goto error; } /* Create a VA configuration */ VAConfigAttrib attrib; memset( &attrib, 0, sizeof(attrib) ); attrib.type = VAConfigAttribRTFormat; if (vaGetConfigAttributes(sys->hw_ctx.display, i_profile, VAEntrypointVLD, &attrib, 1)) goto error; /* Not sure what to do if not, I don't have a way to test */ if( (attrib.value & VA_RT_FORMAT_YUV420) == 0 ) goto error; if (vaCreateConfig(sys->hw_ctx.display, i_profile, VAEntrypointVLD, &attrib, 1, &sys->hw_ctx.config_id)) { sys->hw_ctx.config_id = VA_INVALID_ID; goto error; } /* Create surfaces */ assert(ctx->coded_width > 0 && ctx->coded_height > 0); if (vaCreateSurfaces(sys->hw_ctx.display, VA_RT_FORMAT_YUV420, ctx->coded_width, ctx->coded_height, sys->surfaces, sys->count, NULL, 0)) { goto error; } /* Create a context */ if (vaCreateContext(sys->hw_ctx.display, sys->hw_ctx.config_id, ctx->coded_width, ctx->coded_height, VA_PROGRESSIVE, sys->surfaces, sys->count, &sys->hw_ctx.context_id)) { sys->hw_ctx.context_id = VA_INVALID_ID; vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count); goto error; } if (FindFormat(sys)) goto error; if (unlikely(CopyInitCache(&sys->image_cache, ctx->coded_width))) goto error; vlc_mutex_init(&sys->lock); msg_Dbg(va, "using %s image format 0x%08x", sys->do_derive ? "derive" : "get", sys->format.fourcc); ctx->hwaccel_context = &sys->hw_ctx; va->sys = sys; va->description = vaQueryVendorString(sys->hw_ctx.display); va->get = Get; va->release = Release; va->extract = Extract; return VLC_SUCCESS; error: if (sys->hw_ctx.context_id != VA_INVALID_ID) { vaDestroyContext(sys->hw_ctx.display, sys->hw_ctx.context_id); vaDestroySurfaces(sys->hw_ctx.display, sys->surfaces, sys->count); } if (sys->hw_ctx.config_id != VA_INVALID_ID) vaDestroyConfig(sys->hw_ctx.display, sys->hw_ctx.config_id); if (sys->hw_ctx.display != NULL) vaTerminate(sys->hw_ctx.display); #ifdef VLC_VA_BACKEND_XLIB if( sys->p_display_x11 != NULL ) XCloseDisplay( sys->p_display_x11 ); #endif #ifdef VLC_VA_BACKEND_DRM if( sys->drm_fd != -1 ) close( sys->drm_fd ); #endif free( sys ); return VLC_EGENERIC; }
/***************************************************************************** * Open: open the audio device *****************************************************************************/ static int Open ( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys; struct pa_sample_spec ss; const struct pa_buffer_attr *buffer_attr; struct pa_buffer_attr a; struct pa_channel_map map; char * p_client_name; if( !vlc_xlib_init( p_this ) ) return VLC_EGENERIC; /* Allocate structures */ p_aout->output.p_sys = p_sys = calloc( 1, sizeof( aout_sys_t ) ); if( p_sys == NULL ) return VLC_ENOMEM; PULSE_DEBUG( "Pulse start initialization"); ss.channels = aout_FormatNbChannels( &p_aout->output.output ); /* Get the input stream channel count */ /* Setup the pulse audio stream based on the input stream count */ switch(ss.channels) { case 8: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case 6: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case 4: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; break; case 2: p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case 1: p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; break; default: msg_Err(p_aout,"Invalid number of channels"); goto fail; } /* Add a quick command line info message */ msg_Dbg(p_aout, "%d audio channels", ss.channels); ss.rate = p_aout->output.output.i_rate; if (HAVE_FPU) { ss.format = PA_SAMPLE_FLOAT32NE; p_aout->output.output.i_format = VLC_CODEC_FL32; } else { ss.format = PA_SAMPLE_S16NE; p_aout->output.output.i_format = VLC_CODEC_S16N; } if (!pa_sample_spec_valid(&ss)) { msg_Err(p_aout,"Invalid sample spec"); goto fail; } /* Reduce overall latency to 200mS to reduce audible clicks * Also pulse minreq and internal buffers are now 20mS which reduces resampling */ a.tlength = pa_bytes_per_second(&ss)/5; a.maxlength = a.tlength * 2; a.prebuf = a.tlength / 2; a.minreq = a.tlength / 10; /* Buffer size is 20mS */ p_sys->buffer_size = a.minreq; /* Initialise the speaker map setup above */ pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA); if (!(p_sys->mainloop = pa_threaded_mainloop_new())) { msg_Err(p_aout, "Failed to allocate main loop"); goto fail; } if ((p_client_name = var_InheritString(p_aout, "user-agent")) == NULL) { msg_Err(p_aout, "No user-agent string available."); goto fail; } p_sys->context = pa_context_new(pa_threaded_mainloop_get_api(p_sys->mainloop), p_client_name); free(p_client_name); if(!p_sys->context) { msg_Err(p_aout, "Failed to allocate context"); goto fail; } pa_context_set_state_callback(p_sys->context, context_state_cb, p_aout); PULSE_DEBUG( "Pulse before context connect"); if (pa_context_connect(p_sys->context, NULL, 0, NULL) < 0) { msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto fail; } PULSE_DEBUG( "Pulse after context connect"); pa_threaded_mainloop_lock(p_sys->mainloop); if (pa_threaded_mainloop_start(p_sys->mainloop) < 0) { msg_Err(p_aout, "Failed to start main loop"); goto unlock_and_fail; } msg_Dbg(p_aout, "Pulse mainloop started"); /* Wait until the context is ready */ pa_threaded_mainloop_wait(p_sys->mainloop); if (pa_context_get_state(p_sys->context) != PA_CONTEXT_READY) { msg_Dbg(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } if (!(p_sys->stream = pa_stream_new(p_sys->context, "audio stream", &ss, &map))) { msg_Err(p_aout, "Failed to create stream: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG( "Pulse after new stream"); pa_stream_set_state_callback(p_sys->stream, stream_state_cb, p_aout); pa_stream_set_write_callback(p_sys->stream, stream_request_cb, p_aout); pa_stream_set_latency_update_callback(p_sys->stream, stream_latency_update_cb, p_aout); if (pa_stream_connect_playback(p_sys->stream, NULL, &a, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE|PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0) { msg_Err(p_aout, "Failed to connect stream: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG("Pulse stream connect"); /* Wait until the stream is ready */ pa_threaded_mainloop_wait(p_sys->mainloop); msg_Dbg(p_aout,"Pulse stream connected"); if (pa_stream_get_state(p_sys->stream) != PA_STREAM_READY) { msg_Err(p_aout, "Failed to connect to server: %s", pa_strerror(pa_context_errno(p_sys->context))); goto unlock_and_fail; } PULSE_DEBUG("Pulse after stream get status"); pa_threaded_mainloop_unlock(p_sys->mainloop); buffer_attr = pa_stream_get_buffer_attr(p_sys->stream); p_aout->output.i_nb_samples = buffer_attr->minreq / pa_frame_size(&ss); p_aout->output.pf_play = Play; aout_VolumeSoftInit(p_aout); msg_Dbg(p_aout, "Pulse initialized successfully"); { char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; msg_Dbg(p_aout, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u", buffer_attr->maxlength, buffer_attr->tlength, buffer_attr->prebuf, buffer_attr->minreq); msg_Dbg(p_aout, "Using sample spec '%s', channel map '%s'.", pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(p_sys->stream)), pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(p_sys->stream))); msg_Dbg(p_aout, "Connected to device %s (%u, %ssuspended).", pa_stream_get_device_name(p_sys->stream), pa_stream_get_device_index(p_sys->stream), pa_stream_is_suspended(p_sys->stream) ? "" : "not "); } return VLC_SUCCESS; unlock_and_fail: msg_Dbg(p_aout, "Pulse initialization unlock and fail"); if (p_sys->mainloop) pa_threaded_mainloop_unlock(p_sys->mainloop); fail: msg_Dbg(p_aout, "Pulse initialization failed"); uninit(p_aout); return VLC_EGENERIC; }
static int Open(vlc_va_t *va, AVCodecContext *ctx, const es_format_t *fmt) { VdpStatus err; VdpDecoderProfile profile; int level = fmt->i_level; if (av_vdpau_get_profile(ctx, &profile)) { msg_Err(va, "unsupported codec %d or profile %d", ctx->codec_id, fmt->i_profile); return VLC_EGENERIC; } switch (ctx->codec_id) { case AV_CODEC_ID_MPEG1VIDEO: level = VDP_DECODER_LEVEL_MPEG1_NA; break; case AV_CODEC_ID_MPEG2VIDEO: level = VDP_DECODER_LEVEL_MPEG2_HL; break; case AV_CODEC_ID_H263: level = VDP_DECODER_LEVEL_MPEG4_PART2_ASP_L5; break; case AV_CODEC_ID_H264: if ((fmt->i_profile & FF_PROFILE_H264_INTRA) && (fmt->i_level == 11)) level = VDP_DECODER_LEVEL_H264_1b; default: break; } if (!vlc_xlib_init(VLC_OBJECT(va))) { msg_Err(va, "Xlib is required for VDPAU"); return VLC_EGENERIC; } vlc_va_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->context = av_vdpau_alloc_context(); if (unlikely(sys->context == NULL)) { free(sys); return VLC_ENOMEM; } err = vdp_get_x11(NULL, -1, &sys->vdp, &sys->device); if (err != VDP_STATUS_OK) { free(sys->context); free(sys); return VLC_EGENERIC; } void *func; err = vdp_get_proc_address(sys->vdp, sys->device, VDP_FUNC_ID_DECODER_RENDER, &func); if (err != VDP_STATUS_OK) goto error; sys->context->decoder = VDP_INVALID_HANDLE; sys->context->render = func; sys->profile = profile; /* Check capabilities */ VdpBool support; uint32_t l, mb, w, h; if (vdp_video_surface_query_capabilities(sys->vdp, sys->device, VDP_CHROMA_TYPE_420, &support, &w, &h) != VDP_STATUS_OK) support = VDP_FALSE; if (!support) { msg_Err(va, "video surface format not supported: %s", "YUV 4:2:0"); goto error; } msg_Dbg(va, "video surface limits: %"PRIu32"x%"PRIu32, w, h); if (w < fmt->video.i_width || h < fmt->video.i_height) { msg_Err(va, "video surface above limits: %ux%u", fmt->video.i_width, fmt->video.i_height); goto error; } if (vdp_decoder_query_capabilities(sys->vdp, sys->device, profile, &support, &l, &mb, &w, &h) != VDP_STATUS_OK) support = VDP_FALSE; if (!support) { msg_Err(va, "decoder profile not supported: %u", profile); goto error; } msg_Dbg(va, "decoder profile limits: level %"PRIu32" mb %"PRIu32" " "%"PRIu32"x%"PRIu32, l, mb, w, h); if ((int)l < level || w < fmt->video.i_width || h < fmt->video.i_height) { msg_Err(va, "decoder profile above limits: level %d %ux%u", level, fmt->video.i_width, fmt->video.i_height); goto error; } const char *infos; if (vdp_get_information_string(sys->vdp, &infos) != VDP_STATUS_OK) infos = "VDPAU"; va->sys = sys; va->description = (char *)infos; va->pix_fmt = AV_PIX_FMT_VDPAU; va->setup = Setup; va->get = Lock; va->release = Unlock; va->extract = Copy; return VLC_SUCCESS; error: vdp_release_x11(sys->vdp); av_free(sys->context); free(sys); return VLC_EGENERIC; }
/** * Probe EGL display availability */ static int Open (vlc_object_t *obj, const struct gl_api *api) { vlc_gl_t *gl = (vlc_gl_t *)obj; /* <EGL/eglplatform.h> defines the list and order of platforms */ #if defined(_WIN32) || defined(__VC32__) \ && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) # define vlc_eglGetWindow(w) ((w)->handle.hwnd) #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ # error Symbian EGL not supported. #elif defined(WL_EGL_PLATFORM) # error Wayland EGL not supported. #elif defined(__GBM__) # error Glamor EGL not supported. #elif defined(ANDROID) # error Android EGL not supported #elif defined(__unix__) /* X11 */ # define vlc_eglGetWindow(w) ((w)->handle.xid) /* EGL can only use the default X11 display */ if (gl->surface->display.x11 != NULL) return VLC_EGENERIC; if (!vlc_xlib_init (obj)) return VLC_EGENERIC; #else # error EGL platform not recognized. #endif /* Initialize EGL display */ /* TODO: support various display types */ EGLDisplay dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); if (dpy == EGL_NO_DISPLAY) return VLC_EGENERIC; vlc_gl_sys_t *sys = malloc (sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; gl->sys = sys; sys->display = dpy; EGLint major, minor; if (eglInitialize (dpy, &major, &minor) != EGL_TRUE) { /* No need to call eglTerminate() in this case */ free (sys); return VLC_EGENERIC; } if (major != 1 || minor < api->min_minor || !CheckAPI (dpy, api->name)) goto error; msg_Dbg (obj, "EGL version %s by %s", eglQueryString (dpy, EGL_VERSION), eglQueryString (dpy, EGL_VENDOR)); { const char *ext = eglQueryString (dpy, EGL_EXTENSIONS); if (*ext) msg_Dbg (obj, " extensions: %s", ext); } const EGLint conf_attr[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_RENDERABLE_TYPE, api->render_bit, EGL_NONE }; EGLConfig cfgv[1]; EGLint cfgc; if (eglChooseConfig (dpy, conf_attr, cfgv, 1, &cfgc) != EGL_TRUE || cfgc == 0) goto error; /* Create a drawing surface */ EGLNativeWindowType win = vlc_eglGetWindow(gl->surface); EGLSurface surface = eglCreateWindowSurface (dpy, cfgv[0], win, NULL); if (surface == EGL_NO_SURFACE) { msg_Err (obj, "cannot create EGL window surface"); goto error; } sys->surface = surface; if (eglBindAPI (api->api) != EGL_TRUE) { msg_Err (obj, "cannot bind EGL API"); goto error; } EGLContext ctx = eglCreateContext (dpy, cfgv[0], EGL_NO_CONTEXT, api->attr); if (ctx == EGL_NO_CONTEXT) { msg_Err (obj, "cannot create EGL context"); goto error; } sys->context = ctx; /* Initialize OpenGL callbacks */ gl->sys = sys; gl->makeCurrent = MakeCurrent; gl->swap = SwapBuffers; gl->getProcAddress = GetSymbol; gl->lock = NULL; gl->unlock = NULL; return VLC_SUCCESS; error: Close (obj); return VLC_EGENERIC; }
/* Open Interface */ static int Open( vlc_object_t *p_this, bool isDialogProvider ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; #if defined (QT5_HAS_X11) || defined (Q_WS_X11) if( !vlc_xlib_init( p_this ) ) return VLC_EGENERIC; Display *p_display = XOpenDisplay( NULL ); if( !p_display ) { msg_Err( p_intf, "Could not connect to X server" ); return VLC_EGENERIC; } XCloseDisplay( p_display ); #endif QMutexLocker locker (&lock); if (busy) { msg_Err (p_this, "cannot start Qt multiple times"); return VLC_EGENERIC; } /* Allocations of p_sys */ intf_sys_t *p_sys = p_intf->p_sys = new intf_sys_t; p_intf->p_sys->b_isDialogProvider = isDialogProvider; p_sys->p_mi = NULL; p_sys->pl_model = NULL; /* set up the playlist to work on */ if( isDialogProvider ) p_intf->p_sys->p_playlist = pl_Get( (intf_thread_t *)p_intf->p_parent ); else p_intf->p_sys->p_playlist = pl_Get( p_intf ); /* */ vlc_sem_init (&ready, 0); #ifdef Q_OS_MAC /* Run mainloop on the main thread as Cocoa requires */ libvlc_SetExitHandler( p_intf->p_libvlc, Abort, p_intf ); Thread( (void *)p_intf ); #else if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { delete p_sys; return VLC_ENOMEM; } #endif /* Wait for the interface to be ready. This prevents the main * LibVLC thread from starting video playback before we can create * an embedded video window. */ vlc_sem_wait (&ready); vlc_sem_destroy (&ready); busy = active = true; #ifndef Q_OS_MAC if( !isDialogProvider ) RegisterIntf( p_intf ); #endif return VLC_SUCCESS; }
static int Open(vlc_va_t *va, AVCodecContext *avctx, enum PixelFormat pix_fmt, const es_format_t *fmt, picture_sys_t *p_sys) { if (pix_fmt != AV_PIX_FMT_VDPAU) return VLC_EGENERIC; (void) fmt; (void) p_sys; void *func; VdpStatus err; VdpChromaType type; uint32_t width, height; if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) return VLC_EGENERIC; switch (type) { case VDP_CHROMA_TYPE_420: case VDP_CHROMA_TYPE_422: case VDP_CHROMA_TYPE_444: break; default: msg_Err(va, "unsupported chroma type %"PRIu32, type); return VLC_EGENERIC; } if (!vlc_xlib_init(VLC_OBJECT(va))) { msg_Err(va, "Xlib is required for VDPAU"); return VLC_EGENERIC; } unsigned refs = avctx->refs + 2 * avctx->thread_count + 5; vlc_va_sys_t *sys = malloc(sizeof (*sys) + (refs + 1) * sizeof (sys->pool[0])); if (unlikely(sys == NULL)) return VLC_ENOMEM; sys->type = type; sys->width = width; sys->height = height; err = vdp_get_x11(NULL, -1, &sys->vdp, &sys->device); if (err != VDP_STATUS_OK) { free(sys); return VLC_EGENERIC; } unsigned flags = AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH; err = vdp_get_proc_address(sys->vdp, sys->device, VDP_FUNC_ID_GET_PROC_ADDRESS, &func); if (err != VDP_STATUS_OK) goto error; if (av_vdpau_bind_context(avctx, sys->device, func, flags)) goto error; va->sys = sys; unsigned i = 0; while (i < refs) { sys->pool[i] = CreateSurface(va); if (sys->pool[i] == NULL) break; i++; } sys->pool[i] = NULL; if (i < avctx->refs + 3u) { msg_Err(va, "not enough video RAM"); while (i > 0) DestroySurface(sys->pool[--i]); goto error; } if (i < refs) msg_Warn(va, "video RAM low (allocated %u of %u buffers)", i, refs); const char *infos; if (vdp_get_information_string(sys->vdp, &infos) != VDP_STATUS_OK) infos = "VDPAU"; va->description = infos; va->get = Lock; va->release = NULL; va->extract = Copy; return VLC_SUCCESS; error: vdp_release_x11(sys->vdp); free(sys); return VLC_EGENERIC; }