📄 directx.c
字号:
{ *pp_surface_final = NULL; return VLC_EGENERIC; } } if( !b_overlay ) { vlc_bool_t b_rgb_surface = ( i_chroma == VLC_FOURCC('R','G','B','2') ) || ( i_chroma == VLC_FOURCC('R','V','1','5') ) || ( i_chroma == VLC_FOURCC('R','V','1','6') ) || ( i_chroma == VLC_FOURCC('R','V','2','4') ) || ( i_chroma == VLC_FOURCC('R','V','3','2') ); memset( &ddsd, 0, sizeof( DDSURFACEDESC ) ); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwHeight = p_vout->render.i_height; ddsd.dwWidth = p_vout->render.i_width; if( p_vout->p_sys->b_use_sysmem ) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; else ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; if( !b_rgb_surface ) { ddsd.dwFlags |= DDSD_PIXELFORMAT; ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwFourCC = i_chroma; } dxresult = IDirectDraw2_CreateSurface( p_vout->p_sys->p_ddobject, &ddsd, &p_surface, NULL ); if( dxresult != DD_OK ) { *pp_surface_final = NULL; return VLC_EGENERIC; } } /* Now that the surface is created, try to get a newer DirectX interface */ dxresult = IDirectDrawSurface_QueryInterface( p_surface, &IID_IDirectDrawSurface2, (LPVOID *)pp_surface_final ); IDirectDrawSurface_Release( p_surface ); /* Release the old interface */ if ( dxresult != DD_OK ) { msg_Err( p_vout, "cannot query IDirectDrawSurface2 interface " "(error %li)", dxresult ); *pp_surface_final = NULL; return VLC_EGENERIC; } if( b_overlay ) { /* Check the overlay is useable as some graphics cards allow creating * several overlays but only one can be used at one time. */ p_vout->p_sys->p_current_surface = *pp_surface_final; if( DirectXUpdateOverlay( p_vout ) != VLC_SUCCESS ) { IDirectDrawSurface2_Release( *pp_surface_final ); *pp_surface_final = NULL; msg_Err( p_vout, "overlay unuseable (might already be in use)" ); return VLC_EGENERIC; } } return VLC_SUCCESS;}/***************************************************************************** * DirectXUpdateOverlay: Move or resize overlay surface on video display. ***************************************************************************** * This function is used to move or resize an overlay surface on the screen. * Ususally the overlay is moved by the user and thus, by a move or resize * event (in Manage). *****************************************************************************/int DirectXUpdateOverlay( vout_thread_t *p_vout ){ DDOVERLAYFX ddofx; DWORD dwFlags; HRESULT dxresult; if( p_vout->p_sys->p_current_surface == NULL || !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC; /* The new window dimensions should already have been computed by the * caller of this function */ /* Position and show the overlay */ memset(&ddofx, 0, sizeof(DDOVERLAYFX)); ddofx.dwSize = sizeof(DDOVERLAYFX); ddofx.dckDestColorkey.dwColorSpaceLowValue = p_vout->p_sys->i_colorkey; ddofx.dckDestColorkey.dwColorSpaceHighValue = p_vout->p_sys->i_colorkey; dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE; dxresult = IDirectDrawSurface2_UpdateOverlay( p_vout->p_sys->p_current_surface, &p_vout->p_sys->rect_src_clipped, p_vout->p_sys->p_display, &p_vout->p_sys->rect_dest_clipped, dwFlags, &ddofx ); if(dxresult != DD_OK) { msg_Warn( p_vout, "DirectXUpdateOverlay cannot move or resize overlay" ); return VLC_EGENERIC; } return VLC_SUCCESS;}/***************************************************************************** * DirectXCloseDDraw: Release the DDraw object allocated by DirectXInitDDraw ***************************************************************************** * This function returns all resources allocated by DirectXInitDDraw. *****************************************************************************/static void DirectXCloseDDraw( vout_thread_t *p_vout ){ msg_Dbg( p_vout, "DirectXCloseDDraw" ); if( p_vout->p_sys->p_ddobject != NULL ) { IDirectDraw2_Release(p_vout->p_sys->p_ddobject); p_vout->p_sys->p_ddobject = NULL; } if( p_vout->p_sys->hddraw_dll != NULL ) { FreeLibrary( p_vout->p_sys->hddraw_dll ); p_vout->p_sys->hddraw_dll = NULL; } if( p_vout->p_sys->p_display_driver != NULL ) { free( p_vout->p_sys->p_display_driver ); p_vout->p_sys->p_display_driver = NULL; } p_vout->p_sys->hmonitor = NULL;}/***************************************************************************** * DirectXCloseDisplay: close and reset the DirectX display device ***************************************************************************** * This function returns all resources allocated by DirectXCreateDisplay. *****************************************************************************/static void DirectXCloseDisplay( vout_thread_t *p_vout ){ msg_Dbg( p_vout, "DirectXCloseDisplay" ); if( p_vout->p_sys->p_clipper != NULL ) { msg_Dbg( p_vout, "DirectXCloseDisplay clipper" ); IDirectDrawClipper_Release( p_vout->p_sys->p_clipper ); p_vout->p_sys->p_clipper = NULL; } if( p_vout->p_sys->p_display != NULL ) { msg_Dbg( p_vout, "DirectXCloseDisplay display" ); IDirectDrawSurface2_Release( p_vout->p_sys->p_display ); p_vout->p_sys->p_display = NULL; }}/***************************************************************************** * DirectXCloseSurface: close the YUV overlay or RGB surface. ***************************************************************************** * This function returns all resources allocated for the surface. *****************************************************************************/static void DirectXCloseSurface( vout_thread_t *p_vout, LPDIRECTDRAWSURFACE2 p_surface ){ msg_Dbg( p_vout, "DirectXCloseSurface" ); if( p_surface != NULL ) { IDirectDrawSurface2_Release( p_surface ); }}/***************************************************************************** * NewPictureVec: allocate a vector of identical pictures ***************************************************************************** * Returns 0 on success, -1 otherwise *****************************************************************************/static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, int i_num_pics ){ int i; int i_ret = VLC_SUCCESS; LPDIRECTDRAWSURFACE2 p_surface; msg_Dbg( p_vout, "NewPictureVec overlay:%s chroma:%.4s", p_vout->p_sys->b_using_overlay ? "yes" : "no", (char *)&p_vout->output.i_chroma ); I_OUTPUTPICTURES = 0; /* First we try to use an YUV overlay surface. * The overlay surface that we create won't be used to decode directly * into it because accessing video memory directly is way to slow (remember * that pictures are decoded macroblock per macroblock). Instead the video * will be decoded in picture buffers in system memory which will then be * memcpy() to the overlay surface. */ if( p_vout->p_sys->b_using_overlay ) { /* Triple buffering rocks! it doesn't have any processing overhead * (you don't have to wait for the vsync) and provides for a very nice * video quality (no tearing). */ if( p_vout->p_sys->b_3buf_overlay ) i_ret = DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, p_vout->p_sys->b_using_overlay, 2 /* number of backbuffers */ ); if( !p_vout->p_sys->b_3buf_overlay || i_ret != VLC_SUCCESS ) { /* Try to reduce the number of backbuffers */ i_ret = DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, p_vout->p_sys->b_using_overlay, 0 /* number of backbuffers */ ); } if( i_ret == VLC_SUCCESS ) { DDSCAPS dds_caps; picture_t front_pic; picture_sys_t front_pic_sys; front_pic.p_sys = &front_pic_sys; /* Allocate internal structure */ p_pic[0].p_sys = malloc( sizeof( picture_sys_t ) ); if( p_pic[0].p_sys == NULL ) { DirectXCloseSurface( p_vout, p_surface ); return VLC_ENOMEM; } /* set front buffer */ p_pic[0].p_sys->p_front_surface = p_surface; /* Get the back buffer */ memset( &dds_caps, 0, sizeof( DDSCAPS ) ); dds_caps.dwCaps = DDSCAPS_BACKBUFFER; if( DD_OK != IDirectDrawSurface2_GetAttachedSurface( p_surface, &dds_caps, &p_pic[0].p_sys->p_surface ) ) { msg_Warn( p_vout, "NewPictureVec could not get back buffer" ); /* front buffer is the same as back buffer */ p_pic[0].p_sys->p_surface = p_surface; } p_vout->p_sys->p_current_surface = front_pic.p_sys->p_surface = p_pic[0].p_sys->p_front_surface; /* Reset the front buffer memory */ if( DirectXLockSurface( p_vout, &front_pic ) == VLC_SUCCESS ) { int i,j; for( i = 0; i < front_pic.i_planes; i++ ) for( j = 0; j < front_pic.p[i].i_lines; j++) memset( front_pic.p[i].p_pixels + j * front_pic.p[i].i_pitch, 127, front_pic.p[i].i_visible_pitch ); DirectXUnlockSurface( p_vout, &front_pic ); } DirectXUpdateOverlay( p_vout ); I_OUTPUTPICTURES = 1; msg_Dbg( p_vout, "YUV overlay created successfully" ); } } /* As we can't have an overlay, we'll try to create a plain offscreen * surface. This surface will reside in video memory because there's a * better chance then that we'll be able to use some kind of hardware * acceleration like rescaling, blitting or YUV->RGB conversions. * We then only need to blit this surface onto the main display when we * want to display it */ if( !p_vout->p_sys->b_using_overlay ) { if( p_vout->p_sys->b_hw_yuv ) { DWORD i_codes; DWORD *pi_codes; vlc_bool_t b_result = VLC_FALSE; /* Check if the chroma is supported first. This is required * because a few buggy drivers don't mind creating the surface * even if they don't know about the chroma. */ if( IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject, &i_codes, NULL ) == DD_OK ) { pi_codes = malloc( i_codes * sizeof(DWORD) ); if( pi_codes && IDirectDraw2_GetFourCCCodes( p_vout->p_sys->p_ddobject, &i_codes, pi_codes ) == DD_OK ) { for( i = 0; i < (int)i_codes; i++ ) { if( p_vout->output.i_chroma == pi_codes[i] ) { b_result = VLC_TRUE; break; } } } } if( b_result ) i_ret = DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, 0 /* no overlay */, 0 /* no back buffers */ ); else p_vout->p_sys->b_hw_yuv = VLC_FALSE; } if( i_ret || !p_vout->p_sys->b_hw_yuv ) { /* Our last choice is to use a plain RGB surface */ DDPIXELFORMAT ddpfPixelFormat; ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); IDirectDrawSurface2_GetPixelFormat( p_vout->p_sys->p_display,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -