📄 dx_video_render.cpp
字号:
/*//// INTEL CORPORATION PROPRIETARY INFORMATION// This software is supplied under the terms of a license agreement or// nondisclosure agreement with Intel Corporation and may not be copied// or disclosed except in accordance with the terms of that agreement.// Copyright(c) 2003-2005 Intel Corporation. All Rights Reserved.//*/#include "vm_debug.h"#include "dx_video_render.h"#if defined(UMC_ENABLE_DX_VIDEO_RENDER)#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))namespace UMC{DXVideoRenderParams::DXVideoRenderParams() : m_hWnd(NULL), m_ColorKey(0){} // DXVideoRenderParams::DXVideoRenderParams() :const DDPIXELFORMAT DXVideoRender::g_overlay_formats[] ={ {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('Y','V','1','2'), 12, 0, 0, 0, 0}, // YV12 {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('Y','U','Y','2'), 16, 0, 0, 0, 0}, // YUY2 {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('U','Y','V','Y'), 16, 0, 0, 0, 0}, // UYVY {sizeof(DDPIXELFORMAT), DDPF_FOURCC | DDPF_YUV, MAKEFOURCC('N','V','1','2'), 12, 0, 0, 0, 0}, // UYVY {sizeof(DDPIXELFORMAT), DDPF_RGB,0,16,0xf800,0x07e0,0x001f,0} // RGB565};DXVideoRender::DXVideoRender() : m_primary(NULL), m_front(NULL){} // DXVideoRender::DXVideoRender() :DXVideoRender::~DXVideoRender(){ // Close method is called by VideoRender::~VideoRender // Close is virtual so no need to call it again vm_debug_trace(4,__VM_STRING("~DXVideoRender\n")); Close(); if (m_DDrawObj) m_DDrawObj->Release();} // DXVideoRender::~DXVideoRender()Status DXVideoRender::SetFullScreen(ModuleContext& rContext, bool full){ Status umcRes = (NULL != m_DDrawObj) ? UMC_OK : UMC_NOT_INITIALIZED; HWNDModuleContext *pHWNDCont = DynamicCast<HWNDModuleContext> (&rContext); if (NULL == pHWNDCont) umcRes = UMC_NULL_PTR; if (UMC_OK == umcRes) { m_SuncMut.Lock(); DWORD dwFlags = full ? DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_SETFOCUSWINDOW : DDSCL_NORMAL; HRESULT hRes = m_DDrawObj->SetCooperativeLevel(pHWNDCont->m_hWnd, dwFlags); if (DD_OK != hRes) umcRes = UMC_OPERATION_FAILED; m_SuncMut.Unlock(); } return umcRes;} // Status DXVideoRender::SetFullScreen(ModuleContext& rContext, bool full)Status DXVideoRender::GetOverlayFormat(ColorFormat Format, DDPIXELFORMAT& rOverlayFormat){ Status umcRes = UMC_OK; switch (Format) { case YV12: rOverlayFormat = DXVideoRender::g_overlay_formats[0]; break; case YUY2: rOverlayFormat = DXVideoRender::g_overlay_formats[1]; break; case UYVY: rOverlayFormat = DXVideoRender::g_overlay_formats[2]; break; case NV12: rOverlayFormat = DXVideoRender::g_overlay_formats[3]; break; case RGB565: rOverlayFormat = DXVideoRender::g_overlay_formats[4]; break; default: umcRes = UMC_BAD_FORMAT; } return umcRes;} // Status DXVideoRender::GetOverlayFormat(ColorFormat Format,Status DXVideoRender::InitDDObjs(){ HRESULT hRes; Status umcRes = UMC_OK; // Create DDraw object if (UMC_OK == umcRes) { hRes = ::DirectDrawCreate(0, &m_DDrawObj, 0); if (hRes != DD_OK) { vm_debug_msg(-1, VM_STRING("Failed to create the DirectDraw object @DXVideoRender\n")); m_DDrawObj = NULL; umcRes = UMC_FAILED_TO_INITIALIZE; } } m_hd_caps.min_stretch = m_hd_caps.max_stretch = 1; m_hd_caps.overlay_support = false; DDCAPS caps; INIT_DIRECTDRAW_STRUCT(caps); if (UMC_OK == umcRes) { hRes = m_DDrawObj->GetCaps(&caps, NULL); if (FAILED(hRes)) { vm_debug_msg(-1,VM_STRING("Failed to retrieve graphic card caps @DXVideoRender\n")); umcRes = UMC_FAILED_TO_INITIALIZE; } } m_hd_caps.overlay_support = (0 != (caps.dwCaps & DDCAPS_OVERLAY)); m_hd_caps.colorkey_support = (0 != (caps.dwCaps & DDCKEYCAPS_DESTOVERLAYYUV)); if (caps.dwCaps & DDCAPS_OVERLAYSTRETCH) { m_hd_caps.min_stretch = (double)caps.dwMinOverlayStretch / 1000.0; m_hd_caps.max_stretch = (double)caps.dwMaxOverlayStretch / 1000.0; } return umcRes;} // Status DXVideoRender::InitDDObjs()Status DXVideoRender::Init(MediaReceiverParams* pInit){ HRESULT hRes = DD_OK; Status umcRes = UMC_OK; DXVideoRenderParams *pParams = DynamicCast<DXVideoRenderParams> (pInit); if (UMC_OK == umcRes) umcRes = m_SuncMut.Init(); assert(NULL != pParams); if (UMC_OK == umcRes) umcRes = InitDDObjs(); if (UMC_OK == umcRes) { umcRes = (NULL != m_DDrawObj && m_hd_caps.overlay_support) ? UMC_OK : UMC_NOT_INITIALIZED; } m_hWnd = pParams->m_hWnd; if (UMC_OK == umcRes) { if (DD_OK != m_DDrawObj->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL)) umcRes = UMC_OPERATION_FAILED; } // Create the primary surface if (UMC_OK == umcRes) { INIT_DIRECTDRAW_STRUCT(m_ddsd); m_ddsd.dwFlags = DDSD_CAPS; m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; hRes = m_DDrawObj->CreateSurface(&m_ddsd, &m_primary, 0); if (DD_OK != hRes) { vm_debug_msg(-1,VM_STRING("Failed to create the DirectDraw primary surface\n")); umcRes = UMC_FAILED_TO_ALLOCATE_BUFFER; } } // Set color key if (UMC_OK == umcRes) { if (!(FLAG_VREN_USECOLORKEY & pParams->lFlags)) m_hd_caps.colorkey_support = false; if (m_hd_caps.colorkey_support) { DDCOLORKEY key; key.dwColorSpaceLowValue = pParams->m_ColorKey; key.dwColorSpaceHighValue = pParams->m_ColorKey; hRes = m_primary->SetColorKey(DDCKEY_DESTOVERLAY,&key); umcRes = (DD_OK == hRes) ? UMC_OK : UMC_BAD_FORMAT; } } // Create overlay buffers DDSURFACEDESC ddsdOverlay; if (UMC_OK == umcRes) { INIT_DIRECTDRAW_STRUCT(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 = pParams->info.width; ddsdOverlay.dwHeight= pParams->info.height; umcRes = GetOverlayFormat(pParams->color_format, ddsdOverlay.ddpfPixelFormat); } if (UMC_OK == umcRes) { for (m_iBuffersNum = MAX_FRAME_BUFFERS; m_iBuffersNum >= MIN_FRAME_BUFFERS; m_iBuffersNum--) { ddsdOverlay.dwBackBufferCount = m_iBuffersNum; hRes = m_DDrawObj->CreateSurface(&ddsdOverlay, &m_front, NULL); if (!FAILED(hRes)) break; } if (m_iBuffersNum < MIN_FRAME_BUFFERS || FAILED(hRes)) { vm_debug_msg(-1,VM_STRING("Unsupported YUV format or fail to allocate enough overlay buffers for this format\n")); umcRes = UMC_FAILED_TO_ALLOCATE_BUFFER; } } // Obtain chained overlay surfaces if (UMC_OK == umcRes) { memset(m_Buffers,0,sizeof(m_Buffers)); m_Buffers[0].surface = m_front; for (int i = 1; i < m_iBuffersNum; i++) { IDirectDrawSurface *surface = (IDirectDrawSurface*)(m_Buffers[i-1].surface); hRes = surface->GetAttachedSurface(&ddsdOverlay.ddsCaps, (IDirectDrawSurface**)&m_Buffers[i].surface); if (FAILED(hRes)) { vm_debug_msg(-1,VM_STRING("Failed to retrieve allocated overlay surfaces @Init\n")); umcRes = UMC_FAILED_TO_ALLOCATE_BUFFER; break; } } } if (UMC_OK == umcRes) umcRes = BaseVideoRender::Init(pInit); return umcRes;} // Status DXVideoRender::Init(MediaReceiverParams* pInit)Status DXVideoRender::Close(){ vm_debug_trace(4,VM_STRING("DXVideoRender Close\n")); BaseVideoRender::Close(); m_SuncMut.LockIfInitialized(); if (m_front) { if (m_front->IsLost()) m_front->Restore(); m_front->Release(); m_front = NULL; } if (m_primary) { if (m_primary->IsLost()) m_primary->Restore(); m_primary->Release(); m_primary = NULL; } m_SuncMut.UnlockIfInitialized(); return UMC_OK;} // Status DXVideoRender::Close()int DXVideoRender::LockSurface(unsigned char** vidmem){ if (m_iWriteIndex < 0) return 0; for (;;Sleep(0)) { IDirectDrawSurface *surface = (IDirectDrawSurface*)m_Buffers[m_iWriteIndex].surface; vm_debug_trace(0, VM_STRING("Lock surface %d\n"), m_iWriteIndex); HRESULT hr = surface->Lock(0, &m_ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, 0); *vidmem = (unsigned char*)m_ddsd.lpSurface; if (*vidmem) break; if (hr == DDERR_SURFACELOST) { m_primary->Restore(); for(int i = 0; i < m_iBuffersNum; i++) { if (m_Buffers[i].surface) ((IDirectDrawSurface*)m_Buffers[i].surface)->Restore(); } } else if (hr != DDERR_WASSTILLDRAWING) return 0; } return m_ddsd.lPitch;} // int DXVideoRender::LockSurface(unsigned char** vidmem)int DXVideoRender::UnlockSurface(unsigned char** /*vidmem*/){ int iRes = 1; if (m_iWriteIndex < 0) iRes = 0; if (1 == iRes) { IDirectDrawSurface *surface = (IDirectDrawSurface*)m_Buffers[m_iWriteIndex].surface; if (DD_OK != surface->Unlock(m_ddsd.lpSurface)) iRes = 0; vm_debug_trace(0, VM_STRING("Unlock surface %d\n"), m_iWriteIndex); } return iRes;} // int DXVideoRender::UnlockSurface(unsigned char **)Status DXVideoRender::RenderFrame(){ ::RECT dst, src; Status umcRes = (m_iReadIndex >= 0 && NULL != m_DDrawObj) ? UMC_OK : UMC_NOT_INITIALIZED; if (UMC_OK == umcRes) { m_SuncMut.Lock(); DWORD show_cmd = DDOVER_HIDE; if (m_bShow) { show_cmd = m_hd_caps.overlay_support ? DDOVER_SHOW : DDOVER_HIDE; if (DDOVER_SHOW == show_cmd && m_hd_caps.colorkey_support) show_cmd |= DDOVER_KEYDEST; } IDirectDrawSurface *surface = (IDirectDrawSurface*)m_Buffers[m_iReadIndex].surface; m_SuncMut.Unlock(); UMCRect2Rect(m_dst_rect, dst); UMCRect2Rect(m_src_rect, src); vm_debug_trace(0, VM_STRING("Update surface %d +\n"), m_iReadIndex); HRESULT hRes = surface->UpdateOverlay(&src, m_primary, &dst, show_cmd, 0); vm_debug_trace(0, VM_STRING("Update surface %d -\n"), m_iReadIndex); m_SuncMut.Lock(); if (DDERR_SURFACELOST == hRes) { hRes = surface->IsLost(); if (DDERR_SURFACELOST == hRes) hRes = surface->Restore(); if (DD_OK == hRes) { hRes = m_primary->IsLost(); if (DDERR_SURFACELOST == hRes) m_primary->Restore(); } if (DD_OK == hRes) { m_SuncMut.Unlock(); hRes = surface->UpdateOverlay(&src, m_primary, &dst, show_cmd, 0); m_SuncMut.Lock(); } } umcRes = (DD_OK == hRes) ? UMC_OK : UMC_OPERATION_FAILED; m_SuncMut.Unlock(); } if (UMC_OK == umcRes) m_hFreeBufSema.Signal(); vm_debug_trace(0, VM_STRING("%lf\n") ,m_Buffers[m_iReadIndex].frame_time); return umcRes;} // Status DXVideoRender::RenderFrame()Status DXVideoRender::ShowLastFrame(){ ::RECT dst, src; Status umcRes = (m_iReadIndex >= 0 && NULL != m_DDrawObj) ? UMC_OK : UMC_NOT_INITIALIZED; if (UMC_OK == umcRes) { m_SuncMut.Lock(); DWORD show_cmd = DDOVER_HIDE; if (m_bShow) { show_cmd = m_hd_caps.overlay_support ? DDOVER_SHOW : DDOVER_HIDE; if (DDOVER_SHOW == show_cmd && m_hd_caps.colorkey_support) show_cmd |= DDOVER_KEYDEST; } IDirectDrawSurface *surface = (IDirectDrawSurface*)m_Buffers[m_iReadIndex].surface; m_SuncMut.Unlock(); UMCRect2Rect(m_dst_rect, dst); UMCRect2Rect(m_src_rect, src); vm_debug_trace(0, VM_STRING("Update surface %d +\n"), m_iReadIndex); HRESULT hRes = surface->UpdateOverlay(&src, m_primary, &dst, show_cmd, 0); vm_debug_trace(0, VM_STRING("Update surface %d -\n"), m_iReadIndex); m_SuncMut.Lock(); if (DDERR_SURFACELOST == hRes) { hRes = surface->IsLost(); if (DDERR_SURFACELOST == hRes) hRes = surface->Restore(); if (DD_OK == hRes) { hRes = m_primary->IsLost(); if (DDERR_SURFACELOST == hRes) m_primary->Restore(); } if (DD_OK == hRes) { m_SuncMut.Unlock(); hRes = surface->UpdateOverlay(&src, m_primary, &dst, show_cmd, 0); m_SuncMut.Lock(); } } umcRes = (DD_OK == hRes) ? UMC_OK : UMC_OPERATION_FAILED; m_SuncMut.Unlock(); } vm_debug_trace(0, VM_STRING("%lf\n") ,m_Buffers[m_iReadIndex].frame_time); return umcRes;} // Status DXVideoRender::ShowLastFrame()void DXVideoRender::HideSurface(){ vm_debug_trace(0, VM_STRING("HideSurface\n")); BaseVideoRender::HideSurface(); RenderFrame();} // void DXVideoRender::HideSurface()} // namespace UMC#endif // defined(UMC_ENABLE_DX_VIDEO_RENDER)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -