📄 dx_video_render_wce.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-2006 Intel Corporation. All Rights Reserved.
//
*/
#include "umc_defs.h"
#if defined(UMC_ENABLE_DXWCE_VIDEO_RENDER)
#include "ippi.h"
#include "umc_video_data.h"
#include "dx_video_render_wce.h"
namespace UMC
{
DXWCEVideoRenderParams::DXWCEVideoRenderParams() :
m_hWnd(NULL)
{
} // DXWCEVideoRenderParams::DXWCEVideoRenderParams() :
static DDPIXELFORMAT ddpfOverlayFormats[] =
{
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','V','1','2'), 0, 0, 0, 0, 0}, // YV12
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','V'), 0, 0, 0, 0, 0}, // YUYV
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U','Y','V','Y'), 0, 0, 0, 0, 0}, // UYVY
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00, 0x03e0, 0x001F, 0}, // 16-bit RGB 5:5:5
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0} // 16-bit RGB 5:6:5
};
DXWCEVideoRender::DXWCEVideoRender() :
m_hWnd(NULL),
m_pDD(NULL),
m_pDDSPrimary(NULL),
m_pDDSOverlay(NULL),
m_bShow(true)
{
memset(&m_SrcRect, 0, sizeof(m_SrcRect));
memset(&m_SrcRect, 0, sizeof(m_DstRect));
} // DXWCEVideoRender::DXWCEVideoRender() :
DXWCEVideoRender::~DXWCEVideoRender()
{
Close();
} // DXWCEVideoRender::~DXWCEVideoRender()
HRESULT DXWCEVideoRender::InitDDraw(HWND hWnd, UMC::RECT Rect)
{
HRESULT hRet = DD_OK;
LPDIRECTDRAW pDD = NULL;
DDSURFACEDESC2 ddsd;
DDCAPS ddcaps;
if (DD_OK == hRet)
{
hRet = DirectDrawCreate(NULL, &pDD, NULL);
if (DD_OK != hRet)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("DirectDrawCreate FAILED"));
}
// Fetch DirectDraw4 interface.
if (DD_OK == hRet)
{
hRet = pDD->QueryInterface(IID_IDirectDraw4, (LPVOID*)&m_pDD);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("QueryInterface FAILED"));
else
{
pDD->Release();
pDD = NULL;
}
}
// Get normal mode.
if (DD_OK == hRet)
{
hRet = m_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("SetCooperativeLevel FAILED"));
}
// Get a primary surface interface pointer (only needed for init.)
if (DD_OK == hRet)
{
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hRet = m_pDD->CreateSurface(&ddsd, &m_pDDSPrimary, NULL);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("CreateSurface FAILED"));
}
// See if we can support overlays.
if (DD_OK == hRet)
{
memset(&ddcaps, 0, sizeof(ddcaps));
ddcaps.dwSize = sizeof(ddcaps);
hRet = m_pDD->GetCaps(&ddcaps,NULL);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("GetCaps FAILED"));
}
if (DD_OK == hRet && !(ddcaps.dwCaps & DDCAPS_OVERLAY))
{
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("Overlays are not supported in hardware!"));
hRet = DDERR_INVALIDSURFACETYPE;
}
// Get alignment info to compute our overlay surface size.
if (DD_OK == hRet)
{
m_SrcRect.left = Rect.left;
m_SrcRect.top = Rect.top;
m_SrcRect.right = Rect.right;
m_SrcRect.bottom = Rect.bottom;
if (ddcaps.dwCaps & DDCAPS_ALIGNSIZESRC && ddcaps.dwAlignSizeSrc)
m_SrcRect.right += m_SrcRect.right % ddcaps.dwAlignSizeSrc;
// Create the overlay flipping surface. We will attempt the pixel
// formats in our table one at a time until we find one that jives.
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX |
DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH |
DDSD_BACKBUFFERCOUNT | DDSD_PIXELFORMAT;
ddsd.dwWidth = m_SrcRect.right;
ddsd.dwHeight = m_SrcRect.bottom;
ddsd.dwBackBufferCount = 1;
#if defined(_WIN32_WCE) && (defined(x86) || defined(_X86_))
ddsd.ddpfPixelFormat = ddpfOverlayFormats[0];
#else // ! defined(_WIN32_WCE) && (defined(x86) || defined(_X86_))
ddsd.ddpfPixelFormat = ddpfOverlayFormats[4];
#endif // defined(_WIN32_WCE) && (defined(x86) || defined(_X86_))
hRet = m_pDD->CreateSurface(&ddsd, &m_pDDSOverlay, NULL);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("Unable to create overlay surface!"));
}
// Finish setting up the overlay.
if (DD_OK == hRet)
{
Ipp32s StretchFactor1000 = ddcaps.dwMinOverlayStretch > 1000 ?
(ddcaps.dwMinOverlayStretch) : (1000);
m_DstRect.left = 0;
m_DstRect.top = 0;
// Adding 999 takes care of integer truncation problems.
m_DstRect.right = (m_SrcRect.right * StretchFactor1000 + 999) / 1000;
m_DstRect.bottom = m_SrcRect.bottom * StretchFactor1000 / 1000;
if (ddcaps.dwCaps & DDCAPS_ALIGNSIZEDEST && ddcaps.dwAlignSizeDest)
{
m_DstRect.right = (Ipp32s)((m_DstRect.right +
ddcaps.dwAlignSizeDest - 1) /
ddcaps.dwAlignSizeDest) * ddcaps.dwAlignSizeDest;
}
// Set the flags we'll send to UpdateOverlay
Ipp32u dwUpdateFlags = DDOVER_SHOW;
// Does the overlay hardware support source color keying?
// If so, we can hide the black background around the image.
// This probably won't work with YUV formats
DDOVERLAYFX ovfx;
memset(&ovfx, 0, sizeof(ovfx));
ovfx.dwSize = sizeof(ovfx);
if (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCOVERLAY)
{
dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE | DDOVER_DDFX;
// Create an overlay FX structure so we can specify a source color
// key. This information is ignored if the DDOVER_SRCKEYOVERRIDE
// flag isn't set.
// black as the color key
ovfx.dckSrcColorkey.dwColorSpaceLowValue = 0;
ovfx.dckSrcColorkey.dwColorSpaceHighValue = 0;
}
// Update the overlay parameters.
hRet = m_pDDSOverlay->UpdateOverlay(&m_SrcRect,
m_pDDSPrimary,
&m_DstRect,
dwUpdateFlags,
&ovfx);
if (hRet != DD_OK)
vm_debug_trace(VM_DEBUG_INFO,VM_STRING("Unable to show overlay surface!"));
}
return hRet;
} // HRESULT DXWCEVideoRender::InitDDraw(HWND hWnd, UMC::RECT Rect)
Status DXWCEVideoRender::Init(MediaReceiverParams* pInit)
{
Status umcRes = UMC_OK;
DXWCEVideoRenderParams* pParams = DynamicCast<DXWCEVideoRenderParams>(pInit);
if (NULL == pParams)
umcRes = UMC_ERR_NULL_PTR;
if (UMC_OK == umcRes)
umcRes = MobileVideoRender::Init(pInit);
if (UMC_OK == umcRes)
{
m_hWnd = pParams->m_hWnd;
UMCRect2Rect(pParams->disp, m_DstRect);
VM_ASSERT(NULL != m_hWnd);
if (NULL == m_hWnd)
umcRes = UMC_ERR_NULL_PTR;
}
if (UMC_OK == umcRes && !GetWindowRect( m_hWnd, &m_DstRect ))
umcRes = UMC_ERR_FAILED;
HBRUSH hBrush = NULL;
if (UMC_OK == umcRes)
{
hBrush = CreateSolidBrush(0);
if (NULL == hBrush)
umcRes = UMC_ERR_FAILED;
}
if (UMC_OK == umcRes && 0 == FillRect(GetDC(m_hWnd),&m_DstRect, hBrush))
umcRes = UMC_ERR_FAILED;
if (UMC_OK == umcRes)
{
HRESULT hRet = InitDDraw(pParams->m_hWnd, pParams->disp);
if (FAILED(hRet))
umcRes = UMC_ERR_FAILED;
}
return umcRes;
} // Status DXWCEVideoRender::Init(MediaReceiverParams* pInit)
Status DXWCEVideoRender::Close()
{
Status umcRes = MobileVideoRender::Close();
if (NULL != m_pDDSOverlay)
{
// Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay
// from the display.
m_pDDSOverlay->UpdateOverlay(NULL,
m_pDDSPrimary,
NULL,
DDOVER_HIDE,
NULL);
m_pDDSOverlay->Release();
m_pDDSOverlay = NULL;
}
if (NULL != m_pDDSPrimary)
{
m_pDDSPrimary->Release();
m_pDDSPrimary = NULL;
}
if (NULL != m_pDD)
{
m_pDD->Release();
m_pDD = NULL;
}
m_hWnd = 0;
memset(&m_SrcRect, 0, sizeof(m_SrcRect));
memset(&m_SrcRect, 0, sizeof(m_DstRect));
return umcRes;
} // Status DXWCEVideoRender::Close()
// Lock input buffer
Status DXWCEVideoRender::LockInputBuffer(MediaData* pInData)
{
Status umcRes = UMC_OK;
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
VideoData* pVideoData = DynamicCast<VideoData>(pInData);
if (NULL == pVideoData)
umcRes = UMC_ERR_NULL_PTR;
if (UMC_OK == umcRes && NULL == m_pDDSOverlay)
umcRes = UMC_ERR_NOT_INITIALIZED;
// Wait for the end od prev frame or Stop()
while (UMC_OK == umcRes &&
!m_bStopFlag &&
m_dfFrameTime != -1.0 &&
UMC_ERR_TIMEOUT == m_ReadySema.Wait(1000));
if (UMC_OK == umcRes && (m_bStopFlag || m_dfFrameTime == -1.0))
umcRes = UMC_ERR_END_OF_STREAM;
if (UMC_OK == umcRes)
{
HRESULT hRes = m_pDDSOverlay->Lock(NULL,
&ddsd,
DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,
NULL);
if (FAILED(hRes))
umcRes = UMC_ERR_FAILED;
}
if (UMC_OK == umcRes)
{
Ipp32u uiSize = ddsd.dwWidth * ddsd.dwHeight;
pVideoData->SetDest((LPBYTE)ddsd.lpSurface,
((LPBYTE)ddsd.lpSurface) + uiSize,
((LPBYTE)ddsd.lpSurface) + uiSize + uiSize / 4);
if (NULL != ddsd.lpSurface)
pVideoData->SetPitch(ddsd.lPitch, ddsd.lPitch / 2, ddsd.lPitch / 2);
else
pVideoData->SetPitch(0);
}
else
{
pVideoData->SetDest(NULL);
pVideoData->SetPitch(0);
}
return umcRes;
} // Status DXWCEVideoRender::LockInputBuffer(MediaData* pInData)
// Unlock input buffer
Status DXWCEVideoRender::UnLockInputBuffer(MediaData *pInData,
Status StreamStatus)
{
Status umcRes = UMC_OK;
VideoData* pVideoData = DynamicCast<VideoData, MediaData>(pInData);
if (NULL == pVideoData)
umcRes = UMC_ERR_NULL_PTR;
if (UMC_OK == umcRes && NULL == m_pDDSOverlay)
umcRes = UMC_ERR_NOT_INITIALIZED;
if (UMC_OK == umcRes)
{
HRESULT hRes = m_pDDSOverlay->Unlock(NULL);
if (FAILED(hRes))
umcRes = UMC_ERR_FAILED;
}
if (UMC_OK == umcRes)
{
Ipp64f dfEndTime;
pVideoData->GetTime(m_dfFrameTime, dfEndTime);
umcRes = m_DoneSema.Signal();
}
if (UMC_ERR_END_OF_STREAM == StreamStatus)
Stop();
return umcRes;
} // Status DXWCEVideoRender::UnLockInputBuffer(MediaData *pInData,
Status DXWCEVideoRender::RenderFrame()
{
Status umcRes = UMC_OK;
if (NULL == m_pDDSPrimary && NULL == m_pDDSOverlay)
umcRes = UMC_ERR_NOT_INITIALIZED;
if (UMC_OK == umcRes)
{
Ipp32u dwShowCmd = m_bShow ? DDOVER_SHOW : DDOVER_HIDE;
HRESULT hRes = m_pDDSOverlay->UpdateOverlay(&m_SrcRect, m_pDDSPrimary,
&m_DstRect, dwShowCmd, 0);
if (FAILED(hRes))
umcRes = UMC_ERR_FAILED;
}
if (UMC_OK == umcRes)
umcRes = MobileVideoRender::RenderFrame();
return umcRes;
} // Status DXWCEVideoRender::RenderFrame()
} // namespace UMC
#endif // defined(UMC_ENABLE_DXWCE_VIDEO_RENDER)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -