📄 directx.c
字号:
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_visible_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 ); } DirectDrawUpdateOverlay( 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; bool b_result = 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 = 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 = 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, &ddpfPixelFormat ); if( ddpfPixelFormat.dwFlags & DDPF_RGB ) { switch( ddpfPixelFormat.dwRGBBitCount ) { case 8: p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); p_vout->output.pf_setpalette = SetPalette; break; case 15: p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); break; case 16: p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); break; case 24: p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); break; case 32: p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); break; default: msg_Err( p_vout, "unknown screen depth" ); return VLC_EGENERIC; } p_vout->output.i_rmask = ddpfPixelFormat.dwRBitMask; p_vout->output.i_gmask = ddpfPixelFormat.dwGBitMask; p_vout->output.i_bmask = ddpfPixelFormat.dwBBitMask; } p_vout->p_sys->b_hw_yuv = 0; i_ret = DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, 0 /* no overlay */, 0 /* no back buffers */ ); if( i_ret && !p_vout->p_sys->b_use_sysmem ) { /* Give it a last try with b_use_sysmem enabled */ p_vout->p_sys->b_use_sysmem = 1; i_ret = DirectXCreateSurface( p_vout, &p_surface, p_vout->output.i_chroma, 0 /* no overlay */, 0 /* no back buffers */ ); } } if( i_ret == VLC_SUCCESS ) { /* 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; } p_pic[0].p_sys->p_surface = p_pic[0].p_sys->p_front_surface = p_surface; I_OUTPUTPICTURES = 1; msg_Dbg( p_vout, "created plain surface of chroma:%.4s", (char *)&p_vout->output.i_chroma ); } } /* Now that we've got all our direct-buffers, we can finish filling in the * picture_t structures */ for( i = 0; i < I_OUTPUTPICTURES; i++ ) { p_pic[i].i_status = DESTROYED_PICTURE; p_pic[i].i_type = DIRECT_PICTURE; p_pic[i].b_slow = true; p_pic[i].pf_lock = DirectXLockSurface; p_pic[i].pf_unlock = DirectXUnlockSurface; PP_OUTPUTPICTURE[i] = &p_pic[i]; if( DirectXLockSurface( p_vout, &p_pic[i] ) != VLC_SUCCESS ) { /* AAARRGG */ FreePictureVec( p_vout, p_pic, I_OUTPUTPICTURES ); I_OUTPUTPICTURES = 0; msg_Err( p_vout, "cannot lock surface" ); return VLC_EGENERIC; } DirectXUnlockSurface( p_vout, &p_pic[i] ); } msg_Dbg( p_vout, "End NewPictureVec (%s)", I_OUTPUTPICTURES ? "succeeded" : "failed" ); return VLC_SUCCESS;}/***************************************************************************** * FreePicture: destroy a picture vector allocated with NewPictureVec ***************************************************************************** * *****************************************************************************/static void FreePictureVec( vout_thread_t *p_vout, picture_t *p_pic, int i_num_pics ){ int i; vlc_mutex_lock( &p_vout->p_sys->lock ); p_vout->p_sys->p_current_surface = 0; vlc_mutex_unlock( &p_vout->p_sys->lock ); for( i = 0; i < i_num_pics; i++ ) { DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface ); for( i = 0; i < i_num_pics; i++ ) { free( p_pic[i].p_sys ); } }}/***************************************************************************** * UpdatePictureStruct: updates the internal data in the picture_t structure ***************************************************************************** * This will setup stuff for use by the video_output thread *****************************************************************************/static int UpdatePictureStruct( vout_thread_t *p_vout, picture_t *p_pic, int i_chroma ){ switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','G','B','2'): case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','6'): case VLC_FOURCC('R','V','2','4'): case VLC_FOURCC('R','V','3','2'): p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface; p_pic->p->i_lines = p_vout->output.i_height; p_pic->p->i_visible_lines = p_vout->output.i_height; p_pic->p->i_pitch = p_pic->p_sys->ddsd.lPitch; switch( p_vout->output.i_chroma ) { case VLC_FOURCC('R','G','B','2'): p_pic->p->i_pixel_pitch = 1; break; case VLC_FOURCC('R','V','1','5'): case VLC_FOURCC('R','V','1','6'): p_pic->p->i_pixel_pitch = 2; break; case VLC_FOURCC('R','V','2','4'): p_pic->p->i_pixel_pitch = 3; break; case VLC_FOURCC('R','V','3','2'): p_pic->p->i_pixel_pitch = 4; break; default: return VLC_EGENERIC; } p_pic->p->i_visible_pitch = p_vout->output.i_width * p_pic->p->i_pixel_pitch; p_pic->i_planes = 1; break; case VLC_FOURCC('Y','V','1','2'): case VLC_FOURCC('I','4','2','0'): /* U and V inverted compared to I420 * Fixme: this should be handled by the vout core */ p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0'); p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface; p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height; p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height; p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch; p_pic->p[Y_PLANE].i_pixel_pitch = 1; p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width * p_pic->p[Y_PLANE].i_pixel_pitch; p_pic->V_PIXELS = p_pic->Y_PIXELS + p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch; p_pic->p[V_PLANE].i_lines = p_vout->output
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -