/** * It returns the format (closest to chroma) that can be converted to target */ static const d3d_format_t *Direct3DFindFormat(vout_display_t *vd, vlc_fourcc_t chroma, D3DFORMAT target) { vout_display_sys_t *sys = vd->sys; for (unsigned pass = 0; pass < 2; pass++) { const vlc_fourcc_t *list; if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma)) list = vlc_fourcc_GetYUVFallback(chroma); else if (pass == 1) list = vlc_fourcc_GetRGBFallback(chroma); else continue; for (unsigned i = 0; list[i] != 0; i++) { for (unsigned j = 0; d3d_formats[j].name; j++) { const d3d_format_t *format = &d3d_formats[j]; if (format->fourcc != list[i]) continue; msg_Warn(vd, "trying surface pixel format: %s", format->name); if (!Direct3DCheckConversion(vd, format->format, target)) { msg_Dbg(vd, "selected surface pixel format is %s", format->name); return format; } } } } return NULL; }
static int DirectXCreatePictureResource(vout_display_t *vd, bool *use_overlay, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; /* */ picture_sys_t *picsys = calloc(1, sizeof(*picsys)); if (unlikely(picsys == NULL)) return VLC_ENOMEM; sys->picsys = picsys; /* */ bool allow_hw_yuv = sys->can_blit_fourcc && vlc_fourcc_IsYUV(fmt->i_chroma) && var_InheritBool(vd, "directx-hw-yuv"); bool allow_overlay = var_InheritBool(vd, "directx-overlay"); /* Try to use an yuv surface */ if (allow_hw_yuv) { const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma); /* Try with overlay first */ for (unsigned pass = allow_overlay ? 0 : 1; pass < 2; pass++) { for (unsigned i = 0; list[i] != 0; i++) { const DWORD fourcc = DirectXGetFourcc(list[i]); if (!fourcc) continue; if (pass == 0) { if (DirectXCreatePictureResourceYuvOverlay(vd, fmt, fourcc)) { #ifndef NDEBUG msg_Dbg(vd, "Failed to create YUV overlay surface %4.4s", (const char*)&fourcc); #endif continue; } } else { if (DirectXCreatePictureResourceYuv(vd, fmt, fourcc)) { #ifndef NDEBUG msg_Dbg(vd, "Failed to create YUV surface %4.4s", (const char*)&fourcc); #endif continue; } } /* */ *use_overlay = pass == 0; fmt->i_chroma = list[i]; return VLC_SUCCESS; } } } /* Try plain RGB */ return DirectXCreatePictureResourceRgb(vd, fmt); }
static int DirectXCreatePictureResource(vout_display_t *vd, bool *use_overlay, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; /* */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = calloc(1, sizeof(*rsc->p_sys)); if (!rsc->p_sys) return VLC_ENOMEM; /* */ bool allow_hw_yuv = sys->can_blit_fourcc && vlc_fourcc_IsYUV(fmt->i_chroma) && var_InheritBool(vd, "directx-hw-yuv"); bool allow_overlay = var_InheritBool(vd, "overlay"); /* Try to use an yuv surface */ if (allow_hw_yuv) { const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma); /* Try with overlay first */ for (unsigned pass = allow_overlay ? 0 : 1; pass < 2; pass++) { for (unsigned i = 0; list[i] != 0; i++) { const DWORD fourcc = DirectXGetFourcc(list[i]); if (!fourcc) continue; if (pass == 0) { if (DirectXCreatePictureResourceYuvOverlay(vd, fmt, fourcc)) continue; } else { if (DirectXCreatePictureResourceYuv(vd, fmt, fourcc)) continue; } /* */ *use_overlay = pass == 0; fmt->i_chroma = list[i]; return VLC_SUCCESS; } } } /* Try plain RGB */ return DirectXCreatePictureResourceRgb(vd, fmt); }
/** * 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; /* 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; } #ifdef HAVE_SETENV char *psz_driver = var_CreateGetNonEmptyString(vd, "sdl-video-driver"); if (psz_driver) { setenv("SDL_VIDEODRIVER", psz_driver, 1); free(psz_driver); } #endif /* */ int sdl_flags = SDL_INIT_VIDEO; #ifndef WIN32 /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/ sdl_flags |= SDL_INIT_EVENTTHREAD; #endif #ifndef NDEBUG /* In debug mode you may want vlc to dump a core instead of staying stuck */ sdl_flags |= SDL_INIT_NOPARACHUTE; #endif /* 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; } 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_CreateGetNonEmptyString(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_CreateGetBool(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->get = Get; vd->prepare = NULL; vd->display = Display; 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; }
/***************************************************************************** * OpenDisplay: open and initialize KVA device ***************************************************************************** * Open and initialize display according to preferences specified in the vout * thread fields. *****************************************************************************/ static int OpenDisplay( vout_display_t *vd, video_format_t *fmt ) { vout_display_sys_t * sys = vd->sys; const vlc_fourcc_t *fallback; bool b_hw_accel = 0; FOURCC i_kva_fourcc; int i_chroma_shift; char sz_title[ 256 ]; RECTL rcl; int w, h; msg_Dbg( vd, "render chroma = %4.4s", ( const char * )&fmt->i_chroma ); for( int pass = 0; pass < 2 && !b_hw_accel; pass++ ) { fallback = ( pass == 0 ) ? vlc_fourcc_GetYUVFallback( fmt->i_chroma ) : vlc_fourcc_GetRGBFallback( fmt->i_chroma ); for( int i = 0; fallback[ i ]; i++ ) { switch( fallback[ i ]) { case VLC_CODEC_YV12: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YV12; i_kva_fourcc = FOURCC_YV12; i_chroma_shift = 1; break; case VLC_CODEC_YUYV: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YUY2; i_kva_fourcc = FOURCC_Y422; i_chroma_shift = 0; break; case VLC_CODEC_YV9: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YVU9; i_kva_fourcc = FOURCC_YVU9; i_chroma_shift = 2; break; case VLC_CODEC_RGB32: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR32; i_kva_fourcc = FOURCC_BGR4; i_chroma_shift = 0; break; case VLC_CODEC_RGB24: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR24; i_kva_fourcc = FOURCC_BGR3; i_chroma_shift = 0; break; case VLC_CODEC_RGB16: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR16; i_kva_fourcc = FOURCC_R565; i_chroma_shift = 0; break; case VLC_CODEC_RGB15: b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR15; i_kva_fourcc = FOURCC_R555; i_chroma_shift = 0; break; } if( b_hw_accel ) { fmt->i_chroma = fallback[ i ]; break; } } } if( !b_hw_accel ) { msg_Err( vd, "Ooops. There is no fourcc supported by KVA at all."); return VLC_EGENERIC; } /* Set the RGB masks */ fmt->i_rmask = sys->kvac.ulRMask; fmt->i_gmask = sys->kvac.ulGMask; fmt->i_bmask = sys->kvac.ulBMask; msg_Dbg( vd, "output chroma = %4.4s", ( const char * )&fmt->i_chroma ); msg_Dbg( vd, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc ); w = vd->source.i_width; h = vd->source.i_height; sys->kvas.ulLength = sizeof( KVASETUP ); sys->kvas.szlSrcSize.cx = w; sys->kvas.szlSrcSize.cy = h; sys->kvas.rclSrcRect.xLeft = 0; sys->kvas.rclSrcRect.yTop = 0; sys->kvas.rclSrcRect.xRight = w; sys->kvas.rclSrcRect.yBottom = h; sys->kvas.ulRatio = KVAR_FORCEANY; sys->kvas.ulAspectWidth = w; sys->kvas.ulAspectHeight = h; sys->kvas.fccSrcColor = i_kva_fourcc; sys->kvas.fDither = TRUE; if( kvaSetup( &sys->kvas )) { msg_Err( vd, "cannot set up KVA"); return VLC_EGENERIC; } /* Create the associated picture */ picture_resource_t *rsc = &sys->resource; rsc->p_sys = malloc( sizeof( *rsc->p_sys )); if( !rsc->p_sys ) return VLC_EGENERIC; rsc->p_sys->i_chroma_shift = i_chroma_shift; for( int i = 0; i < PICTURE_PLANE_MAX; i++ ) { rsc->p[ i ].p_pixels = NULL; rsc->p[ i ].i_pitch = 0; rsc->p[ i ].i_lines = 0; } picture_t *picture = picture_NewFromResource( fmt, rsc ); if( !picture ) goto exit_picture; /* Wrap it into a picture pool */ picture_pool_configuration_t pool_cfg; memset( &pool_cfg, 0, sizeof( pool_cfg )); pool_cfg.picture_count = 1; pool_cfg.picture = &picture; pool_cfg.lock = KVALock; pool_cfg.unlock = KVAUnlock; sys->pool = picture_pool_NewExtended( &pool_cfg ); if( !sys->pool ) { picture_Release( picture ); goto exit_picture; } if (vd->cfg->display.title) snprintf( sz_title, sizeof( sz_title ), "%s", vd->cfg->display.title ); else snprintf( sz_title, sizeof( sz_title ), "%s (%4.4s to %4.4s - %s mode KVA output)", VOUT_TITLE, ( char * )&vd->fmt.i_chroma, ( char * )&sys->kvas.fccSrcColor, psz_video_mode[ sys->kvac.ulMode - 1 ]); WinSetWindowText( sys->frame, sz_title ); sys->i_screen_width = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); sys->i_screen_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); if( sys->parent_window ) WinQueryWindowRect( sys->parent, &sys->client_rect ); else { sys->client_rect.xLeft = ( sys->i_screen_width - w ) / 2; sys->client_rect.yBottom = ( sys->i_screen_height - h ) / 2 ; sys->client_rect.xRight = sys->client_rect.xLeft + w; sys->client_rect.yTop = sys->client_rect.yBottom + h; } rcl = sys->client_rect; WinCalcFrameRect( sys->frame, &rcl, FALSE); WinSetWindowPos( sys->frame, HWND_TOP, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE ); return VLC_SUCCESS; exit_picture: free( rsc->p_sys ); return VLC_EGENERIC; }