📄 vo_directx.c.orig
字号:
#include <windows.h>#include <windowsx.h>#include <ddraw.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#ifndef WM_XBUTTONDOWN# define WM_XBUTTONDOWN 0x020B# define WM_XBUTTONUP 0x020C# define WM_XBUTTONDBLCLK 0x020D#endif#define WNDCLASSNAME_WINDOWED "MPlayer - The Movie Player"#define WNDCLASSNAME_FULLSCREEN "MPlayer - Fullscreen"#define WNDSTYLE WS_OVERLAPPEDWINDOW|WS_SIZEBOXstatic LPDIRECTDRAWCOLORCONTROL g_cc = NULL; //color control interfacestatic LPDIRECTDRAW7 g_lpdd = NULL; //DirectDraw Objectstatic LPDIRECTDRAWSURFACE7 g_lpddsPrimary = NULL; //Primary Surface: viewport through the Desktopstatic LPDIRECTDRAWSURFACE7 g_lpddsOverlay = NULL; //Overlay Surfacestatic LPDIRECTDRAWSURFACE7 g_lpddsBack = NULL; //Back surfacestatic LPDIRECTDRAWCLIPPER g_lpddclipper; //clipper object, can only be used without overlaystatic DDSURFACEDESC2 ddsdsf; //surface descripiton needed for lockingstatic HINSTANCE hddraw_dll; //handle to ddraw.dllstatic RECT rd; //rect of our stretched imagestatic RECT rs; //rect of our source imagestatic HWND hWnd=NULL; //handle to the windowstatic HWND hWndFS=NULL; //fullscreen windowstatic HBRUSH colorbrush = NULL; // Handle to colorkey brushstatic HBRUSH blackbrush = NULL; // Handle to black brushstatic HICON mplayericon = NULL; // Handle to mplayer iconstatic HCURSOR mplayercursor = NULL; // Handle to mplayer cursorstatic uint32_t image_width, image_height; //image width and heightstatic uint32_t d_image_width, d_image_height; //image width and height zoomedstatic uint8_t *image=NULL; //image datastatic void* tmp_image = NULL;static uint32_t image_format=0; //image formatstatic uint32_t primary_image_format;static uint32_t vm_height=0;static uint32_t vm_width=0;static uint32_t vm_bpp=0;static uint32_t dstride; //surface stridestatic uint32_t nooverlay = 0; //NonOverlay modestatic DWORD destcolorkey; //colorkey for our surfacestatic COLORREF windowcolor = RGB(0,0,16); //windowcolor == colorkeystatic int adapter_count=0;static GUID selected_guid;static GUID *selected_guid_ptr = NULL;static RECT monitor_rect; //monitor coordinatesstatic float window_aspect;static BOOL (WINAPI* myGetMonitorInfo)(HMONITOR, LPMONITORINFO) = NULL;static RECT last_rect = {0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE};/***************************************************************************** * DirectDraw GUIDs. * Defining them here allows us to get rid of the dxguid library during * the linking stage. *****************************************************************************/const GUID IID_IDirectDraw7 ={ 0x15e65ec0,0x3b9c,0x11d2,{0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b}};const GUID IID_IDirectDrawColorControl ={ 0x4b9f0ee0,0x0d7e,0x11d0,{0x9b,0x06,0x00,0xa0,0xc9,0x03,0xa3,0xb8}};typedef struct directx_fourcc_caps{ char* img_format_name; //human readable name uint32_t img_format; //as MPlayer image format uint32_t drv_caps; //what hw supports with this format DDPIXELFORMAT g_ddpfOverlay; //as Directx Sourface description} directx_fourcc_caps;static directx_fourcc_caps g_ddpf[] ={ {"YV12 ",IMGFMT_YV12 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','1','2'),0,0,0,0,0}}, {"I420 ",IMGFMT_I420 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','4','2','0'),0,0,0,0,0}}, //yv12 with swapped uv {"IYUV ",IMGFMT_IYUV ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('I','Y','U','V'),0,0,0,0,0}}, //same as i420 {"YVU9 ",IMGFMT_YVU9 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','V','U','9'),0,0,0,0,0}}, {"YUY2 ",IMGFMT_YUY2 ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}}, {"UYVY ",IMGFMT_UYVY ,0,{sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}}, {"BGR8 ",IMGFMT_BGR8 ,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 8, 0x00000000, 0x00000000, 0x00000000, 0}}, {"RGB15",IMGFMT_RGB15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000003E0, 0x00007C00, 0}}, {"BGR15",IMGFMT_BGR15,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00007C00, 0x000003E0, 0x0000001F, 0}}, {"RGB16",IMGFMT_RGB16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000001F, 0x000007E0, 0x0000F800, 0}}, {"BGR16",IMGFMT_BGR16,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x0000F800, 0x000007E0, 0x0000001F, 0}}, {"RGB24",IMGFMT_RGB24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}}, {"BGR24",IMGFMT_BGR24,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}}, {"RGB32",IMGFMT_RGB32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0}}, {"BGR32",IMGFMT_BGR32,0,{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0}}};#define NUM_FORMATS (sizeof(g_ddpf) / sizeof(g_ddpf[0]))static uint32_t Directx_CreatePrimarySurface(){ DDSURFACEDESC2 ddsd; if (g_lpddsPrimary) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); g_lpddsPrimary=NULL; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsd, &g_lpddsPrimary, NULL ) == DD_OK) av_log(NULL, AV_LOG_INFO, "vo_directx: primary surface created\n"); else { av_log(NULL, AV_LOG_ERROR, "vo_directx: could not create primary surface\n"); return -1; } return 0;}static uint32_t Directx_CreateOverlay(uint32_t imgfmt){ HRESULT ddrval; DDSURFACEDESC2 ddsdOverlay; uint32_t i=0; while ( i < NUM_FORMATS +1 && imgfmt != g_ddpf[i].img_format ) { i++; } if (!g_lpdd || !g_lpddsPrimary) return 1; if( g_lpddsOverlay ) g_lpddsOverlay->lpVtbl->Release( g_lpddsOverlay ); if( g_lpddsBack ) g_lpddsBack->lpVtbl->Release( g_lpddsBack ); g_lpddsOverlay = NULL; g_lpddsBack = NULL; //create our overlay ZeroMemory(&ddsdOverlay, sizeof(ddsdOverlay)); ddsdOverlay.dwSize = sizeof(ddsdOverlay); ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY; ddsdOverlay.dwFlags = DDSD_CAPS|DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT; ddsdOverlay.dwWidth = image_width; ddsdOverlay.dwHeight = image_height; ddsdOverlay.dwBackBufferCount = 2; ddsdOverlay.ddpfPixelFormat = g_ddpf[i].g_ddpfOverlay; if( vo_doublebuffering ) { if (g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL)== DD_OK) { av_log(NULL, AV_LOG_INFO, "vo_directx: overlay with format %s created\n",g_ddpf[i].img_format_name); //get the surface directly attached to the primary (the back buffer) ddsdOverlay.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if (g_lpddsOverlay->lpVtbl->GetAttachedSurface(g_lpddsOverlay,&ddsdOverlay.ddsCaps, &g_lpddsBack) != DD_OK) { av_log(NULL, AV_LOG_ERROR, "vo_directx: can't get attached surface\n"); return -1; } return 0; } vo_doublebuffering=0; /* disable tribblebuffering */ av_log(NULL, AV_LOG_INFO, "vo_directx: cannot create tribblebuffer overlay with format %s\n",g_ddpf[i].img_format_name); } /* single buffer */ mp_msg(MSGT_VO, MSGL_V,"<vo_directx><INFO>using singlebuffer overlay\n"); ddsdOverlay.dwBackBufferCount=0; ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY; ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT; ddsdOverlay.ddpfPixelFormat=g_ddpf[i].g_ddpfOverlay; // try to create the overlay surface ddrval = g_lpdd->lpVtbl->CreateSurface(g_lpdd,&ddsdOverlay, &g_lpddsOverlay, NULL); if (ddrval != DD_OK) { if (ddrval == DDERR_INVALIDPIXELFORMAT)mp_msg(MSGT_VO,MSGL_V,"<vo_directx><ERROR> invalid pixelformat: %s\n",g_ddpf[i].img_format_name); else mp_msg(MSGT_VO, MSGL_ERR,"<vo_directx><ERROR>"); switch (ddrval) { case DDERR_INCOMPATIBLEPRIMARY: { mp_msg(MSGT_VO, MSGL_ERR,"incompatible primary surface\n"); break; } case DDERR_INVALIDCAPS: { mp_msg(MSGT_VO, MSGL_ERR,"invalid caps\n"); break; } case DDERR_INVALIDOBJECT: { mp_msg(MSGT_VO, MSGL_ERR,"invalid object\n"); break; } case DDERR_INVALIDPARAMS: { mp_msg(MSGT_VO, MSGL_ERR,"invalid parameters\n"); break; } case DDERR_NODIRECTDRAWHW: { mp_msg(MSGT_VO, MSGL_ERR,"no directdraw hardware\n"); break; } case DDERR_NOEMULATION: { mp_msg(MSGT_VO, MSGL_ERR,"can't emulate\n"); break; } case DDERR_NOFLIPHW: { mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do flip\n"); break; } case DDERR_NOOVERLAYHW: { mp_msg(MSGT_VO, MSGL_ERR,"hardware can't do overlay\n"); break; } case DDERR_OUTOFMEMORY: { mp_msg(MSGT_VO, MSGL_ERR,"not enough system memory\n"); break; } case DDERR_UNSUPPORTEDMODE: { mp_msg(MSGT_VO, MSGL_ERR,"unsupported mode\n"); break; } case DDERR_OUTOFVIDEOMEMORY: { mp_msg(MSGT_VO, MSGL_ERR,"not enough video memory\n"); break; } default: mp_msg(MSGT_VO, MSGL_ERR,"create surface failed with 0x%x\n",ddrval); } return 1; } g_lpddsBack = g_lpddsOverlay; return 0;}static uint32_t Directx_CreateBackpuffer(){ DDSURFACEDESC2 ddsd; //cleanup if (g_lpddsBack)g_lpddsBack->lpVtbl->Release(g_lpddsBack); g_lpddsBack=NULL; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwFlags= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.dwWidth=image_width; ddsd.dwHeight=image_height; if (g_lpdd->lpVtbl->CreateSurface( g_lpdd, &ddsd, &g_lpddsBack, 0 ) != DD_OK ) { mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't create backpuffer\n"); return 1; } mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>backbuffer created\n"); return 0;}static void uninit(void){ if (g_cc != NULL) { g_cc->lpVtbl->Release(g_cc); } g_cc=NULL; if (g_lpddclipper != NULL) g_lpddclipper->lpVtbl->Release(g_lpddclipper); g_lpddclipper = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>clipper released\n"); if (g_lpddsBack != NULL) g_lpddsBack->lpVtbl->Release(g_lpddsBack); g_lpddsBack = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>back surface released\n"); if (vo_doublebuffering && !nooverlay) { if (g_lpddsOverlay != NULL)g_lpddsOverlay->lpVtbl->Release(g_lpddsOverlay); g_lpddsOverlay = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>overlay surface released\n"); } if (g_lpddsPrimary != NULL) g_lpddsPrimary->lpVtbl->Release(g_lpddsPrimary); g_lpddsPrimary = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>primary released\n"); if (hWndFS)DestroyWindow(hWndFS); hWndFS = NULL; if ((WinID == -1) && hWnd) DestroyWindow(hWnd); hWnd = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>window destroyed\n"); UnregisterClass(WNDCLASSNAME_WINDOWED, GetModuleHandle(NULL)); UnregisterClass(WNDCLASSNAME_FULLSCREEN, GetModuleHandle(NULL)); if (mplayericon) DestroyIcon(mplayericon); mplayericon = NULL; if (mplayercursor) DestroyCursor(mplayercursor); mplayercursor = NULL; if (blackbrush) DeleteObject(blackbrush); blackbrush = NULL; if (colorbrush) DeleteObject(colorbrush); colorbrush = NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>GDI resources deleted\n"); if (g_lpdd != NULL) { if (vidmode)g_lpdd->lpVtbl->RestoreDisplayMode(g_lpdd); g_lpdd->lpVtbl->Release(g_lpdd); } mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>directdrawobject released\n"); FreeLibrary( hddraw_dll); hddraw_dll= NULL; mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>ddraw.dll freed\n"); mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>uninited\n");}static BOOL WINAPI EnumCallbackEx(GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm){ mp_msg(MSGT_VO, MSGL_INFO ,"<vo_directx> adapter %d: ", adapter_count); if (!lpGUID) { mp_msg(MSGT_VO, MSGL_INFO ,"%s", "Primary Display Adapter"); } else { mp_msg(MSGT_VO, MSGL_INFO ,"%s", lpDriverDescription); } if (adapter_count == vo_adapter_num) { MONITORINFO mi; if (!lpGUID) selected_guid_ptr = NULL; else { selected_guid = *lpGUID; selected_guid_ptr = &selected_guid; } mi.cbSize = sizeof(mi); if (myGetMonitorInfo(hm, &mi)) { monitor_rect = mi.rcMonitor; } mp_msg(MSGT_VO, MSGL_INFO ,"\t\t<--"); } mp_msg(MSGT_VO, MSGL_INFO ,"\n"); adapter_count++; return 1; // list all adapters}static uint32_t Directx_InitDirectDraw(){ HRESULT (WINAPI *OurDirectDrawCreateEx)(GUID *,LPVOID *, REFIID,IUnknown FAR *); DDSURFACEDESC2 ddsd; LPDIRECTDRAWENUMERATEEX OurDirectDrawEnumerateEx; HINSTANCE user32dll=LoadLibrary("user32.dll"); adapter_count = 0; if (user32dll) { myGetMonitorInfo=GetProcAddress(user32dll,"GetMonitorInfoA"); if (!myGetMonitorInfo && vo_adapter_num) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_directx> -adapter is not supported on Win95\n"); vo_adapter_num = 0; } } mp_msg(MSGT_VO, MSGL_DBG3,"<vo_directx><INFO>Initing DirectDraw\n" ); //load direct draw DLL: based on videolans code hddraw_dll = LoadLibrary("DDRAW.DLL"); if ( hddraw_dll == NULL ) { mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed loading ddraw.dll\n" ); return 1; } last_rect.left = 0xDEADC0DE; // reset window position cache if (vo_adapter_num) //display other than default { OurDirectDrawEnumerateEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress(hddraw_dll,"DirectDrawEnumerateExA"); if (!OurDirectDrawEnumerateEx) { FreeLibrary( hddraw_dll ); hddraw_dll = NULL; mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawEnumerateEx\n"); mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>no directx 7 or higher installed\n"); return 1; } // enumerate all display devices attached to the desktop OurDirectDrawEnumerateEx(EnumCallbackEx, NULL, DDENUM_ATTACHEDSECONDARYDEVICES ); if (vo_adapter_num >= adapter_count) mp_msg(MSGT_VO, MSGL_ERR,"Selected adapter (%d) doesn't exist: Default Display Adapter selected\n",vo_adapter_num); } FreeLibrary(user32dll); OurDirectDrawCreateEx = (void *)GetProcAddress(hddraw_dll, "DirectDrawCreateEx"); if ( OurDirectDrawCreateEx == NULL ) { FreeLibrary( hddraw_dll ); hddraw_dll = NULL; mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>failed geting proc address: DirectDrawCreateEx\n"); return 1; } // initialize DirectDraw and create directx v7 object if (OurDirectDrawCreateEx(selected_guid_ptr, (VOID**)&g_lpdd, &IID_IDirectDraw7, NULL ) != DD_OK ) { FreeLibrary( hddraw_dll ); hddraw_dll = NULL; mp_msg(MSGT_VO, MSGL_FATAL,"<vo_directx><FATAL ERROR>can't initialize ddraw\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -