mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1912 lines
58 KiB
1912 lines
58 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: VMRDvava.cpp
|
|
*
|
|
* VMR video accelerator functionality
|
|
*
|
|
*
|
|
* Created: Wed 05/10/2000
|
|
* Author: Stephen Estrop [StEstrop]
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
\**************************************************************************/
|
|
#include <streams.h>
|
|
#include <dvdmedia.h>
|
|
#include <windowsx.h>
|
|
|
|
#include "VMRenderer.h"
|
|
#include <malloc.h> // for __alloca
|
|
|
|
#define VA_ERROR_LEVEL 1
|
|
#define VA_TRACE_LEVEL 2
|
|
|
|
#if defined( EHOME_WMI_INSTRUMENTATION )
|
|
#include "dxmperf.h"
|
|
#endif
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* IsSuitableVideoAcceleratorGuid
|
|
*
|
|
* Check if a media subtype GUID is a video accelerator type GUID
|
|
*
|
|
* This function calls the DirectDraw video accelerator container
|
|
* to list the video accelerator GUIDs and checks to see if the
|
|
* Guid passed in is a supported video accelerator GUID.
|
|
*
|
|
* We should only do this if the upstream pin support IVideoAccleratorNotify
|
|
* since otherwise they may be trying to use the GUID without the
|
|
* video accelerator interface
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
CVMRInputPin::IsSuitableVideoAcceleratorGuid(
|
|
const GUID * pGuid
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::IsSuitableVideoAcceleratorGuid")));
|
|
ASSERT(pGuid);
|
|
|
|
HRESULT hr = NOERROR;
|
|
DWORD dwNumGuidsSupported = 0, i = 0;
|
|
LPGUID pGuidsSupported = NULL;
|
|
BOOL bMatchFound = FALSE;
|
|
LPDIRECTDRAW7 pDirectDraw = m_pRenderer->m_lpDirectDraw;
|
|
|
|
if (!pDirectDraw) {
|
|
return bMatchFound;
|
|
}
|
|
|
|
if (!m_pIDDVAContainer) {
|
|
|
|
hr = pDirectDraw->QueryInterface(IID_IDDVideoAcceleratorContainer,
|
|
(void**)&m_pIDDVAContainer);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pDirectDraw->QueryInterface(")
|
|
TEXT("IID_IVideoAcceleratorContainer) failed, hr = 0x%x"),
|
|
hr));
|
|
return bMatchFound;
|
|
}
|
|
else {
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("pDirectDraw->QueryInterface(")
|
|
TEXT("IID_IVideoAcceleratorContainer) succeeded")));
|
|
}
|
|
}
|
|
|
|
ASSERT(m_pIDDVAContainer);
|
|
|
|
// get the guids supported by the vga
|
|
|
|
// find the number of guids supported
|
|
hr = m_pIDDVAContainer->GetVideoAcceleratorGUIDs(&dwNumGuidsSupported, NULL);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVAContainer->GetVideoAcceleratorGUIDs ")
|
|
TEXT("failed, hr = 0x%x"), hr));
|
|
return bMatchFound;
|
|
}
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL, TEXT("%d Motion comp GUIDs supported")));
|
|
ASSERT(dwNumGuidsSupported);
|
|
if (0 == dwNumGuidsSupported) {
|
|
return bMatchFound;
|
|
}
|
|
|
|
// allocate the necessary memory
|
|
pGuidsSupported = (LPGUID)_alloca(dwNumGuidsSupported*sizeof(GUID));
|
|
|
|
// get the guids proposed
|
|
hr = m_pIDDVAContainer->GetVideoAcceleratorGUIDs(&dwNumGuidsSupported,
|
|
pGuidsSupported);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVAContainer->GetVideoAcceleratorGUIDs")
|
|
TEXT(" failed, hr = 0x%x"), hr));
|
|
return bMatchFound;
|
|
}
|
|
|
|
for (i = 0; i < dwNumGuidsSupported; i++) {
|
|
if (*pGuid == pGuidsSupported[i]) {
|
|
bMatchFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("%s %s suitable video accelerator GUID"),
|
|
(LPCTSTR)CDisp(*pGuid), bMatchFound ? TEXT("is") : TEXT("is not")));
|
|
|
|
return bMatchFound;
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* InitializeUncompDataInfo
|
|
*
|
|
* initialize the m_ddUncompDataInfo struct
|
|
* get the uncompressed pixel format by choosing the first of all formats
|
|
* supported by the vga
|
|
*
|
|
* BUGBUG why the first?
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::InitializeUncompDataInfo(
|
|
BITMAPINFOHEADER *pbmiHeader
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::InitializeUncompDataInfo")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
AMVAUncompBufferInfo amvaUncompBufferInfo;
|
|
|
|
// find the number of entries to be proposed
|
|
hr = m_pIVANotify->GetUncompSurfacesInfo(&m_mcGuid, &amvaUncompBufferInfo);
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIVANotify->GetUncompSurfacesInfo failed, hr = 0x%x"),
|
|
hr));
|
|
return hr;
|
|
}
|
|
|
|
// initialize the m_ddUncompDataInfo structure
|
|
// We choose the first pixel format since we don't care
|
|
// provided we can make a surface (which we assume we can)
|
|
INITDDSTRUCT(m_ddUncompDataInfo);
|
|
m_ddUncompDataInfo.dwUncompWidth = pbmiHeader->biWidth;
|
|
m_ddUncompDataInfo.dwUncompHeight = pbmiHeader->biHeight;
|
|
m_ddUncompDataInfo.ddUncompPixelFormat = amvaUncompBufferInfo.ddUncompPixelFormat;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Uncompressed buffer pixel format %s"),
|
|
(LPCTSTR)CDispPixelFormat(&amvaUncompBufferInfo.ddUncompPixelFormat)));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* AllocateVACompSurfaces
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::AllocateVACompSurfaces(
|
|
LPDIRECTDRAW7 pDirectDraw,
|
|
BITMAPINFOHEADER *pbmiHeader
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
DWORD i = 0, j = 0;
|
|
LPDDVACompBufferInfo pddCompSurfInfo = NULL;
|
|
DDSURFACEDESC2 SurfaceDesc2;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::AllocateVACompSurfaces")));
|
|
|
|
ASSERT(pDirectDraw);
|
|
ASSERT(pbmiHeader);
|
|
|
|
// get the compressed buffer info
|
|
|
|
// find the number of entries to be proposed
|
|
hr = m_pIDDVAContainer->GetCompBufferInfo(&m_mcGuid, &m_ddUncompDataInfo,
|
|
&m_dwCompSurfTypes, NULL);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pIVANotify->GetCompBufferInfo failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
if (!m_dwCompSurfTypes) {
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
// allocate the necessary memory
|
|
pddCompSurfInfo = (DDVACompBufferInfo *)_alloca(
|
|
sizeof(DDVACompBufferInfo) * m_dwCompSurfTypes);
|
|
|
|
// memset the allocated memory to zero
|
|
memset(pddCompSurfInfo, 0, m_dwCompSurfTypes*sizeof(DDVACompBufferInfo));
|
|
|
|
// set the right size of all the structs
|
|
for (i = 0; i < m_dwCompSurfTypes; i++) {
|
|
pddCompSurfInfo[i].dwSize = sizeof(DDVACompBufferInfo);
|
|
}
|
|
|
|
// get the entries proposed
|
|
hr = m_pIDDVAContainer->GetCompBufferInfo(&m_mcGuid,
|
|
&m_ddUncompDataInfo,
|
|
&m_dwCompSurfTypes,
|
|
pddCompSurfInfo);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("GetCompBufferInfo failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
// Set the surface description common to all kinds of surfaces
|
|
INITDDSTRUCT(SurfaceDesc2);
|
|
SurfaceDesc2.dwFlags = DDSD_CAPS | DDSD_WIDTH |
|
|
DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
|
|
|
// allocate memory for storing comp_surface_info
|
|
m_pCompSurfInfo = new COMP_SURFACE_INFO[m_dwCompSurfTypes + 1];
|
|
if (!m_pCompSurfInfo) {
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
|
|
// memset the allocated memory to zero
|
|
ZeroMemory(m_pCompSurfInfo, (m_dwCompSurfTypes+1)*sizeof(COMP_SURFACE_INFO));
|
|
|
|
// allocate the compressed surfaces
|
|
for (i = 1; i <= m_dwCompSurfTypes; i++) {
|
|
|
|
DWORD dwAlloc = pddCompSurfInfo[i-1].dwNumCompBuffers;
|
|
if (dwAlloc == 0) {
|
|
continue;
|
|
}
|
|
|
|
ASSERT(pddCompSurfInfo[i-1].dwNumCompBuffers);
|
|
|
|
// allocate memory for storing surface_info for surfaces of this type
|
|
m_pCompSurfInfo[i].pSurfInfo = new SURFACE_INFO[dwAlloc];
|
|
if (!m_pCompSurfInfo[i].pSurfInfo) {
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
|
|
// memset the allocated memory to zero
|
|
ZeroMemory(m_pCompSurfInfo[i].pSurfInfo, dwAlloc*sizeof(SURFACE_INFO));
|
|
|
|
// intialize the pddCompSurfInfo[i-1] struct
|
|
dwAlloc = m_pCompSurfInfo[i].dwAllocated =
|
|
pddCompSurfInfo[i-1].dwNumCompBuffers;
|
|
|
|
SurfaceDesc2.ddsCaps = pddCompSurfInfo[i-1].ddCompCaps;
|
|
SurfaceDesc2.dwWidth = pddCompSurfInfo[i-1].dwWidthToCreate;
|
|
SurfaceDesc2.dwHeight = pddCompSurfInfo[i-1].dwHeightToCreate;
|
|
memcpy(&SurfaceDesc2.ddpfPixelFormat,
|
|
&pddCompSurfInfo[i-1].ddPixelFormat, sizeof(DDPIXELFORMAT));
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("SurfType=%d Buffs=%u %dx%d pixels at %d bpp"),
|
|
i, dwAlloc, SurfaceDesc2.dwWidth, SurfaceDesc2.dwHeight,
|
|
SurfaceDesc2.ddpfPixelFormat.dwRGBBitCount));
|
|
|
|
// create the surfaces, storing surfaces handles for each
|
|
for (j = 0; j < dwAlloc; j++) {
|
|
|
|
hr = pDirectDraw->CreateSurface(
|
|
&SurfaceDesc2,
|
|
&m_pCompSurfInfo[i].pSurfInfo[j].pSurface,
|
|
NULL);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("Function CreateSurface failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* AllocateMCUncompSurfaces
|
|
*
|
|
* This function needs re-writting and possible moving into the AP object.
|
|
*
|
|
* allocate the uncompressed buffer
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::AllocateMCUncompSurfaces(
|
|
const CMediaType *pMediaType,
|
|
LPDIRECTDRAW7 pDirectDraw,
|
|
BITMAPINFOHEADER *lpHdr
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::AllocateMCUncompSurfaces")));
|
|
HRESULT hr = NOERROR;
|
|
|
|
AMVAUncompBufferInfo amUncompBuffInfo;
|
|
LPDIRECTDRAWSURFACE7 pSurface7 = NULL;
|
|
DDSCAPS2 ddSurfaceCaps;
|
|
DWORD i = 0, dwTotalBufferCount = 0;
|
|
SURFACE_INFO *pSurfaceInfo;
|
|
AM_MEDIA_TYPE *pNewMediaType = NULL;
|
|
|
|
|
|
ASSERT(pDirectDraw);
|
|
ASSERT(lpHdr);
|
|
|
|
__try {
|
|
|
|
// get the uncompressed surface info from the decoder
|
|
ZeroMemory(&amUncompBuffInfo, sizeof(AMVAUncompBufferInfo));
|
|
hr = m_pIVANotify->GetUncompSurfacesInfo(&m_mcGuid, &amUncompBuffInfo);
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("AllocateMCUncompSurfaces: m_pIVANotify->")
|
|
TEXT("GetUncompSurfacesInfo failed, hr = 0x%x"), hr));
|
|
__leave;
|
|
}
|
|
|
|
|
|
if (amUncompBuffInfo.dwMinNumSurfaces > amUncompBuffInfo.dwMaxNumSurfaces) {
|
|
hr = E_INVALIDARG;
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("AllocateMCUncompSurfaces: dwMinNumSurfaces >")
|
|
TEXT("dwMaxNumSurfaces")));
|
|
__leave;
|
|
}
|
|
|
|
if (amUncompBuffInfo.dwMinNumSurfaces == 0) {
|
|
hr = E_INVALIDARG;
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("AllocateMCUncompSurfaces: dwMinNumSurfaces == 0") ));
|
|
__leave;
|
|
}
|
|
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
INITDDSTRUCT(ddsd);
|
|
DWORD dwSurfFlags = VMR_SF_NONE;
|
|
GUID guidDeint;
|
|
GUID* lpDeinterlaceGUID = NULL;
|
|
|
|
if (m_pRenderer->m_VMRModePassThru) {
|
|
|
|
VMRALLOCATIONINFO p;
|
|
CHECK_HR(hr = GetImageAspectRatio(pMediaType,
|
|
&p.szAspectRatio.cx,
|
|
&p.szAspectRatio.cy));
|
|
|
|
p.dwFlags = (AMAP_PIXELFORMAT_VALID | AMAP_DIRECTED_FLIP | AMAP_DXVA_TARGET);
|
|
|
|
p.lpHdr = lpHdr;
|
|
p.lpPixFmt = &m_ddUncompDataInfo.ddUncompPixelFormat;
|
|
p.dwMinBuffers = amUncompBuffInfo.dwMinNumSurfaces;
|
|
p.dwMaxBuffers = max(amUncompBuffInfo.dwMaxNumSurfaces,3);
|
|
p.szNativeSize.cx = abs(lpHdr->biWidth);
|
|
p.szNativeSize.cy = abs(lpHdr->biHeight);
|
|
|
|
CHECK_HR(hr = GetInterlaceFlagsFromMediaType(pMediaType,
|
|
&p.dwInterlaceFlags));
|
|
|
|
CHECK_HR(hr = m_pRenderer->m_lpRLNotify->AllocateSurface(
|
|
m_pRenderer->m_dwUserID, &p,
|
|
&dwTotalBufferCount, &pSurface7));
|
|
}
|
|
else {
|
|
|
|
// Set the surface description common to all kinds of surfaces
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH |
|
|
DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
|
|
|
// store the caps and dimensions
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
|
|
ddsd.dwWidth = abs(lpHdr->biWidth);
|
|
ddsd.dwHeight = abs(lpHdr->biHeight);
|
|
|
|
// define the pixel format
|
|
ddsd.ddpfPixelFormat = m_ddUncompDataInfo.ddUncompPixelFormat;
|
|
|
|
BITMAPINFOHEADER* pTmp = GetbmiHeader(pMediaType);
|
|
DWORD dwFourccTmp = pTmp->biCompression;
|
|
pTmp->biCompression = ddsd.ddpfPixelFormat.dwFourCC;
|
|
hr = GetStreamInterlaceProperties(pMediaType,
|
|
&m_InterlacedStream,
|
|
&guidDeint,
|
|
&m_DeinterlaceCaps);
|
|
pTmp->biCompression = dwFourccTmp;
|
|
|
|
//
|
|
// don't use the SUCCEEDED macro here as
|
|
// GetStreamInterlaceProperties can return S_FALSE
|
|
//
|
|
if (hr == S_OK && m_InterlacedStream) {
|
|
|
|
//
|
|
// we need to allocate enough samples for the
|
|
// de-interlacer and enough for the DX-VA decode operation.
|
|
//
|
|
|
|
dwTotalBufferCount = amUncompBuffInfo.dwMinNumSurfaces;
|
|
dwTotalBufferCount += (m_DeinterlaceCaps.NumForwardRefSamples +
|
|
m_DeinterlaceCaps.NumBackwardRefSamples);
|
|
DbgLog((LOG_TRACE, 0, TEXT("UnComp Buffers = %d"), dwTotalBufferCount));
|
|
|
|
m_DeinterlaceGUID = guidDeint;
|
|
lpDeinterlaceGUID = &m_DeinterlaceGUID;
|
|
|
|
}
|
|
else {
|
|
m_InterlacedStream = FALSE;
|
|
dwTotalBufferCount = amUncompBuffInfo.dwMinNumSurfaces;
|
|
|
|
ZeroMemory(&m_DeinterlaceCaps, sizeof(m_DeinterlaceCaps));
|
|
ZeroMemory(&m_DeinterlaceGUID, sizeof(m_DeinterlaceGUID));
|
|
lpDeinterlaceGUID = NULL;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
// CleanUp stuff from the last loop
|
|
RELEASE(pSurface7);
|
|
|
|
switch (i) {
|
|
case 0:
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
|
|
dwSurfFlags = VMR_SF_TEXTURE;
|
|
break;
|
|
|
|
case 1:
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_TEXTURE;
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
|
dwSurfFlags = VMR_SF_NONE;
|
|
break;
|
|
}
|
|
|
|
if (dwTotalBufferCount > 1) {
|
|
|
|
ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
|
|
ddsd.ddsCaps.dwCaps |=
|
|
DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_LOCALVIDMEM;
|
|
|
|
ddsd.dwBackBufferCount = dwTotalBufferCount - 1;
|
|
}
|
|
else {
|
|
ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP | DDSCAPS_COMPLEX);
|
|
ddsd.dwBackBufferCount = 0;
|
|
}
|
|
|
|
hr = pDirectDraw->CreateSurface(&ddsd, &pSurface7, NULL);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("Function CreateSurface failed in Video memory, ")
|
|
TEXT("BackBufferCount = %d, hr = 0x%x"),
|
|
dwTotalBufferCount-1, hr));
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
PaintDDrawSurfaceBlack(pSurface7);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Tell the VMR's mixer about the new DX-VA connection we have just made.
|
|
// Also, create the DX-VA/Mixer sync event.
|
|
//
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("AllocateMCUncompSurfaces: Could not ")
|
|
TEXT("create UnComp surfaces") ));
|
|
__leave;
|
|
}
|
|
|
|
ASSERT(m_hDXVAEvent == NULL);
|
|
m_hDXVAEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
if (m_hDXVAEvent == NULL) {
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("Could not create DX-VA sync event") ));
|
|
hr = E_FAIL;
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
//
|
|
// create a media type for this surface.
|
|
//
|
|
ASSERT(pSurface7);
|
|
CHECK_HR(hr = pSurface7->GetSurfaceDesc(&ddsd));
|
|
CHECK_HR(hr = ConvertSurfaceDescToMediaType(&ddsd,
|
|
pMediaType,
|
|
&pNewMediaType));
|
|
m_mtNew = *(CMediaType *)pNewMediaType;
|
|
m_mtNew.subtype = pMediaType->subtype;
|
|
|
|
//
|
|
// free the temporary mediatype
|
|
//
|
|
DeleteMediaType(pNewMediaType);
|
|
pNewMediaType = NULL;
|
|
|
|
if (!m_pRenderer->m_VMRModePassThru) {
|
|
|
|
IVMRMixerStream* lpMixStream = m_pRenderer->m_lpMixStream;
|
|
if (lpMixStream) {
|
|
|
|
DbgLog((LOG_TRACE, 1,
|
|
TEXT("Pin %d calling SetStreamMediaType on the Mixer"),
|
|
m_dwPinID ));
|
|
|
|
AM_MEDIA_TYPE mtTmp;
|
|
CHECK_HR(hr = CopyMediaType(&mtTmp, (AM_MEDIA_TYPE*)pMediaType));
|
|
|
|
BITMAPINFOHEADER *pTmp = GetbmiHeader(&mtTmp);
|
|
BITMAPINFOHEADER *pCnt = GetbmiHeader(&m_mtNew);
|
|
|
|
pTmp->biCompression = pCnt->biCompression;
|
|
|
|
hr = lpMixStream->SetStreamMediaType(m_dwPinID, &mtTmp,
|
|
dwSurfFlags,
|
|
lpDeinterlaceGUID,
|
|
&m_DeinterlaceCaps);
|
|
FreeMediaType(mtTmp);
|
|
|
|
if (FAILED(hr)) {
|
|
__leave;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// store the complex surface in m_pDDS
|
|
m_pDDS = pSurface7;
|
|
m_pDDS->AddRef();
|
|
m_dwBackBufferCount = dwTotalBufferCount - 1;
|
|
|
|
ASSERT(m_pCompSurfInfo && NULL == m_pCompSurfInfo[0].pSurfInfo);
|
|
m_pCompSurfInfo[0].pSurfInfo = new SURFACE_INFO[m_dwBackBufferCount + 1];
|
|
|
|
if (NULL == m_pCompSurfInfo[0].pSurfInfo) {
|
|
hr = E_OUTOFMEMORY;
|
|
DbgLog((LOG_ERROR, 1,
|
|
TEXT("AllocateMCUncompSurfaces: memory allocation failed") ));
|
|
__leave;
|
|
}
|
|
|
|
// memset the allcated memory to zero
|
|
ZeroMemory(m_pCompSurfInfo[0].pSurfInfo,
|
|
(m_dwBackBufferCount + 1) * sizeof(SURFACE_INFO));
|
|
|
|
pSurfaceInfo = m_pCompSurfInfo[0].pSurfInfo;
|
|
m_pCompSurfInfo[0].dwAllocated = m_dwBackBufferCount + 1;
|
|
|
|
// initalize the m_ppUncompSurfaceList
|
|
pSurfaceInfo->pSurface = pSurface7;
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FRONTBUFFER | DDSCAPS_VISIBLE);
|
|
|
|
|
|
for (i = 0; i < m_dwBackBufferCount; i++) {
|
|
|
|
// Get the back buffer surface
|
|
// New version of DirectX now requires DDSCAPS2 (header file bug)
|
|
// Note that this AddRef's the surface so we should be sure to
|
|
// release them
|
|
|
|
CHECK_HR(hr = pSurfaceInfo[i].pSurface->GetAttachedSurface(
|
|
&ddsd.ddsCaps,
|
|
&pSurfaceInfo[i+1].pSurface));
|
|
}
|
|
|
|
//
|
|
// fix up the de-interlace surface structures
|
|
//
|
|
if (!m_pRenderer->m_VMRModePassThru && m_InterlacedStream) {
|
|
|
|
DWORD dwBuffCount = 1 +
|
|
m_DeinterlaceCaps.NumForwardRefSamples +
|
|
m_DeinterlaceCaps.NumBackwardRefSamples;
|
|
m_pVidHistorySamps = new DXVA_VideoSample[dwBuffCount];
|
|
if (m_pVidHistorySamps == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
__leave;
|
|
}
|
|
ZeroMemory(m_pVidHistorySamps, (dwBuffCount * sizeof(DXVA_VideoSample)));
|
|
m_dwNumHistorySamples = dwBuffCount;
|
|
}
|
|
|
|
// Pass back number of surfaces actually allocated
|
|
CHECK_HR(hr = m_pIVANotify->SetUncompSurfacesInfo(dwTotalBufferCount));
|
|
}
|
|
__finally {
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
if (m_hDXVAEvent) {
|
|
CloseHandle(m_hDXVAEvent);
|
|
m_hDXVAEvent = NULL;
|
|
}
|
|
|
|
ReleaseAllocatedSurfaces();
|
|
RELEASE(pSurface7);
|
|
}
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CreateVideoAcceleratorObject
|
|
*
|
|
* create the motion comp object, using the misc data from the decoder
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::CreateVideoAcceleratorObject()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
DWORD dwSizeMiscData = 0;
|
|
LPVOID pMiscData = NULL;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::CreateVideoAcceleratorObject")));
|
|
|
|
// get the data to be passed from the decoder
|
|
hr = m_pIVANotify->GetCreateVideoAcceleratorData(&m_mcGuid,
|
|
&dwSizeMiscData,
|
|
&pMiscData);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIVANotify->GetCreateVideoAcceleratorData failed,")
|
|
TEXT(" hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
// ask the vga for the motion comp object
|
|
hr = m_pIDDVAContainer->CreateVideoAccelerator(&m_mcGuid,
|
|
&m_ddUncompDataInfo,
|
|
pMiscData,
|
|
dwSizeMiscData,
|
|
&m_pIDDVideoAccelerator,
|
|
NULL);
|
|
// Free motion comp data
|
|
CoTaskMemFree(pMiscData);
|
|
|
|
if (FAILED(hr) || !m_pIDDVideoAccelerator) {
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVAContainer->CreateVideoAcceleratorideo ")
|
|
TEXT("failed, hr = 0x%x"), hr));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* VACompleteConnect
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::VACompleteConnect(
|
|
IPin *pReceivePin,
|
|
const CMediaType *pMediaType
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
BITMAPINFOHEADER *pbmiHeader = NULL;
|
|
DWORD dwNumUncompFormats = 0;
|
|
LPDIRECTDRAW7 pDirectDraw = NULL;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::VACompleteConnect")));
|
|
|
|
ASSERT(m_pIDDVAContainer);
|
|
ASSERT(pReceivePin);
|
|
ASSERT(pMediaType);
|
|
|
|
pbmiHeader = GetbmiHeader(pMediaType);
|
|
if (!pbmiHeader) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("Could not get bitmap header from MT")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (!m_pIVANotify) {
|
|
DbgLog((LOG_ERROR, 1, TEXT("IAMVANotify not valid")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
pDirectDraw = m_pRenderer->m_lpDirectDraw;
|
|
ASSERT(pDirectDraw);
|
|
|
|
// save the decoder's guid
|
|
m_mcGuid = pMediaType->subtype;
|
|
|
|
// initialize the get the uncompressed formats supported by the vga
|
|
hr = InitializeUncompDataInfo(pbmiHeader);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("InitializeUncompDataInfo failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
// allocate compressed buffers
|
|
hr = AllocateVACompSurfaces(pDirectDraw, pbmiHeader);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("AllocateVACompSurfaces failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
// allocate uncompressed buffers
|
|
hr = AllocateMCUncompSurfaces(pMediaType, pDirectDraw, pbmiHeader);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("AllocateMCUncompSurfaces failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
// create the motion comp object
|
|
hr = CreateVideoAcceleratorObject();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CreateVideoAcceleratorObject failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* VABreakConnect()
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::VABreakConnect()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
DWORD i = 0, j = 0;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::VABreakConnect")));
|
|
|
|
if (m_pCompSurfInfo) {
|
|
|
|
for (i = 0; i < m_dwCompSurfTypes + 1; i++) {
|
|
|
|
DWORD dwAlloc = m_pCompSurfInfo[i].dwAllocated;
|
|
|
|
if (!m_pCompSurfInfo[i].pSurfInfo)
|
|
continue;
|
|
|
|
// release the compressed surfaces
|
|
for (j = 0; j < dwAlloc; j++) {
|
|
|
|
if (m_pCompSurfInfo[i].pSurfInfo[j].pSurface) {
|
|
|
|
// Unlock if necessary
|
|
if (m_pCompSurfInfo[i].pSurfInfo[j].pBuffer) {
|
|
|
|
m_pCompSurfInfo[i].pSurfInfo[j].pSurface->Unlock(NULL);
|
|
}
|
|
m_pCompSurfInfo[i].pSurfInfo[j].pSurface->Release();
|
|
}
|
|
}
|
|
delete [] m_pCompSurfInfo[i].pSurfInfo;
|
|
}
|
|
delete [] m_pCompSurfInfo;
|
|
m_pCompSurfInfo = NULL;
|
|
}
|
|
m_dwCompSurfTypes = 0;
|
|
|
|
if (m_hDXVAEvent) {
|
|
CloseHandle(m_hDXVAEvent);
|
|
m_hDXVAEvent = NULL;
|
|
}
|
|
|
|
RELEASE(m_pIDDVideoAccelerator);
|
|
RELEASE(m_pIDDVAContainer);
|
|
RELEASE(m_pIVANotify);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
// IAMVideoAccelerator
|
|
// -------------------------------------------------------------------------
|
|
//
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetVideoAcceleratorGUIDs
|
|
*
|
|
* pdwNumGuidsSupported is an IN OUT paramter
|
|
* pGuidsSupported is an IN OUT paramter
|
|
*
|
|
* if pGuidsSupported is NULL, pdwNumGuidsSupported should return back with the
|
|
* number of uncompressed pixel formats supported
|
|
* Otherwise pGuidsSupported is an array of *pdwNumGuidsSupported structures
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetVideoAcceleratorGUIDs(
|
|
LPDWORD pdwNumGuidsSupported,
|
|
LPGUID pGuidsSupported)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::GetVideoAcceleratorGUIDs")));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
LPDIRECTDRAW7 pDirectDraw;
|
|
pDirectDraw = m_pRenderer->m_lpDirectDraw;
|
|
if (!pDirectDraw) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("GetVideoAcceleratorGUIDs: VMR not inialized yet!")));
|
|
return VFW_E_WRONG_STATE;
|
|
}
|
|
|
|
if (!m_pIDDVAContainer) {
|
|
|
|
hr = pDirectDraw->QueryInterface(IID_IDDVideoAcceleratorContainer,
|
|
(void**)&m_pIDDVAContainer);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pDirectDraw->QueryInterface(")
|
|
TEXT("IID_IVideoAcceleratorContainer) failed, hr = 0x%x"),
|
|
hr));
|
|
return hr;
|
|
}
|
|
else {
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("pDirectDraw->QueryInterface(")
|
|
TEXT("IID_IVideoAcceleratorContainer) succeeded")));
|
|
}
|
|
}
|
|
|
|
ASSERT(m_pIDDVAContainer);
|
|
|
|
hr = m_pIDDVAContainer->GetVideoAcceleratorGUIDs(pdwNumGuidsSupported,
|
|
pGuidsSupported);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetUncompFormatsSupported
|
|
*
|
|
* pGuid is an IN parameter
|
|
* pdwNumFormatsSupported is an IN OUT paramter
|
|
* pFormatsSupported is an IN OUT paramter (caller should make sure to set
|
|
* the size of EACH struct)
|
|
*
|
|
* if pFormatsSupported is NULL, pdwNumFormatsSupported should return back with
|
|
* the number of uncompressed pixel formats supported
|
|
* Otherwise pFormatsSupported is an array of *pdwNumFormatsSupported structures
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetUncompFormatsSupported(
|
|
const GUID * pGuid, LPDWORD pdwNumFormatsSupported,
|
|
LPDDPIXELFORMAT pFormatsSupported)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::GetUncompFormatsSupported")));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
if (!m_pIDDVAContainer) {
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pIDDVAContainer->GetUncompFormatsSupported((GUID *)pGuid,
|
|
pdwNumFormatsSupported,
|
|
pFormatsSupported);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetInternalMemInfo
|
|
*
|
|
* pGuid is an IN parameter
|
|
* pddvaUncompDataInfo is an IN parameter
|
|
* pddvaInternalMemInfo is an IN OUT parameter
|
|
*
|
|
* (caller should make sure to set the size of struct)
|
|
* currently only gets info about how much scratch memory will the
|
|
* hal allocate for its private use
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetInternalMemInfo(
|
|
const GUID * pGuid,
|
|
const AMVAUncompDataInfo *pamvaUncompDataInfo,
|
|
LPAMVAInternalMemInfo pamvaInternalMemInfo)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::GetInternalMemInfo")));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
if (!m_pIDDVAContainer) {
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
DDVAUncompDataInfo ddvaDataInfo;
|
|
INITDDSTRUCT(ddvaDataInfo);
|
|
|
|
ddvaDataInfo.dwUncompWidth = pamvaUncompDataInfo->dwUncompWidth;
|
|
ddvaDataInfo.dwUncompHeight = pamvaUncompDataInfo->dwUncompHeight;
|
|
ddvaDataInfo.ddUncompPixelFormat = pamvaUncompDataInfo->ddUncompPixelFormat;
|
|
|
|
DDVAInternalMemInfo ddvaInternalMemInfo;
|
|
INITDDSTRUCT(ddvaInternalMemInfo);
|
|
|
|
// Unfortunately the ddraw header files don't use const
|
|
hr = m_pIDDVAContainer->GetInternalMemInfo((GUID *)pGuid,
|
|
&ddvaDataInfo,
|
|
&ddvaInternalMemInfo);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pamvaInternalMemInfo->dwScratchMemAlloc =
|
|
ddvaInternalMemInfo.dwScratchMemAlloc;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetCompBufferInfo
|
|
*
|
|
* pGuid is an IN parameter
|
|
* pddvaUncompDataInfo is an IN parameter
|
|
* pdwNumTypesCompBuffers is an IN OUT paramter
|
|
* pddvaCompBufferInfo is an IN OUT paramter
|
|
*
|
|
* (caller should make sure to set the size of EACH struct)
|
|
* if pddvaCompBufferInfo is NULL, pdwNumTypesCompBuffers should return
|
|
* back with the number of types of compressed buffers
|
|
* Otherwise pddvaCompBufferInfo is an array of *pdwNumTypesCompBuffers structures
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetCompBufferInfo(
|
|
const GUID * pGuid,
|
|
const AMVAUncompDataInfo *pamvaUncompDataInfo,
|
|
LPDWORD pdwNumTypesCompBuffers,
|
|
LPAMVACompBufferInfo pamvaCompBufferInfo)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
// Stays NULL if pamvaComBufferInfo is NULL
|
|
DDVACompBufferInfo *pddvaCompBufferInfo = NULL;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::GetCompBufferInfo")));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
if (!m_pIDDVAContainer) {
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
DDVAUncompDataInfo ddvaDataInfo;
|
|
INITDDSTRUCT(ddvaDataInfo);
|
|
ddvaDataInfo.dwUncompWidth = pamvaUncompDataInfo->dwUncompWidth;
|
|
ddvaDataInfo.dwUncompHeight = pamvaUncompDataInfo->dwUncompHeight;
|
|
ddvaDataInfo.ddUncompPixelFormat = pamvaUncompDataInfo->ddUncompPixelFormat;
|
|
|
|
|
|
if (pamvaCompBufferInfo) {
|
|
|
|
pddvaCompBufferInfo = (DDVACompBufferInfo *)
|
|
_alloca(sizeof(DDVACompBufferInfo) *
|
|
(*pdwNumTypesCompBuffers));
|
|
|
|
for (DWORD j = 0; j < *pdwNumTypesCompBuffers; j++) {
|
|
INITDDSTRUCT(pddvaCompBufferInfo[j]);
|
|
}
|
|
}
|
|
|
|
hr = m_pIDDVAContainer->GetCompBufferInfo((GUID *)pGuid,
|
|
&ddvaDataInfo,
|
|
pdwNumTypesCompBuffers,
|
|
pddvaCompBufferInfo);
|
|
|
|
if ((SUCCEEDED(hr) || hr == DDERR_MOREDATA) && pamvaCompBufferInfo) {
|
|
|
|
for (DWORD i = 0; i < *pdwNumTypesCompBuffers; i++) {
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Compressed buffer type(%d) %d buffers")
|
|
TEXT(" width(%d) height(%d) bytes(%d)"),
|
|
i,
|
|
pddvaCompBufferInfo[i].dwNumCompBuffers,
|
|
pddvaCompBufferInfo[i].dwWidthToCreate,
|
|
pddvaCompBufferInfo[i].dwHeightToCreate,
|
|
pddvaCompBufferInfo[i].dwBytesToAllocate));
|
|
|
|
|
|
pamvaCompBufferInfo[i].dwNumCompBuffers =
|
|
pddvaCompBufferInfo[i].dwNumCompBuffers;
|
|
|
|
pamvaCompBufferInfo[i].dwWidthToCreate =
|
|
pddvaCompBufferInfo[i].dwWidthToCreate;
|
|
|
|
pamvaCompBufferInfo[i].dwHeightToCreate =
|
|
pddvaCompBufferInfo[i].dwHeightToCreate;
|
|
|
|
pamvaCompBufferInfo[i].dwBytesToAllocate =
|
|
pddvaCompBufferInfo[i].dwBytesToAllocate;
|
|
|
|
pamvaCompBufferInfo[i].ddCompCaps =
|
|
pddvaCompBufferInfo[i].ddCompCaps;
|
|
|
|
pamvaCompBufferInfo[i].ddPixelFormat =
|
|
pddvaCompBufferInfo[i].ddPixelFormat;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CheckValidMCConnection
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
HRESULT
|
|
CVMRInputPin::CheckValidMCConnection()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
AMTRACE((TEXT("CVMRInputPin::CheckValidMCConnection")));
|
|
|
|
// if not connected, this function does not make much sense
|
|
// if (!IsCompletelyConnected()) {
|
|
// DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
// TEXT("pin not connected, exiting")));
|
|
// hr = VFW_E_NOT_CONNECTED;
|
|
// return hr;
|
|
// }
|
|
//
|
|
// if (m_RenderTransport != AM_VIDEOACCELERATOR) {
|
|
// hr = VFW_E_INVALIDSUBTYPE;
|
|
// return hr;
|
|
// }
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetInternalCompBufferInfo
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetInternalCompBufferInfo(
|
|
LPDWORD pdwNumTypesCompBuffers,
|
|
LPAMVACompBufferInfo pamvaCompBufferInfo)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::GetInternalCompBufferInfo")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
ASSERT(m_pIDDVAContainer);
|
|
|
|
DDVACompBufferInfo ddvaCompBufferInfo;
|
|
INITDDSTRUCT(ddvaCompBufferInfo);
|
|
|
|
AMVAUncompDataInfo amvaUncompDataInfo;
|
|
amvaUncompDataInfo.dwUncompWidth = m_ddUncompDataInfo.dwUncompWidth;
|
|
amvaUncompDataInfo.dwUncompHeight = m_ddUncompDataInfo.dwUncompHeight;
|
|
amvaUncompDataInfo.ddUncompPixelFormat = m_ddUncompDataInfo.ddUncompPixelFormat;
|
|
|
|
hr = GetCompBufferInfo(&m_mcGuid, &amvaUncompDataInfo,
|
|
pdwNumTypesCompBuffers, pamvaCompBufferInfo);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BeginFrame
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::BeginFrame(
|
|
const AMVABeginFrameInfo *pamvaBeginFrameInfo
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::BeginFrame")));
|
|
|
|
// BUGBUG - check surface isn't being flipped
|
|
HRESULT hr = NOERROR;
|
|
DDVABeginFrameInfo ddvaBeginFrameInfo;
|
|
SURFACE_INFO *pSurfInfo;
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
if (!pamvaBeginFrameInfo) {
|
|
hr = E_POINTER;
|
|
return hr;
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("BeginFrame index %d"),
|
|
pamvaBeginFrameInfo->dwDestSurfaceIndex));
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
INITDDSTRUCT(ddvaBeginFrameInfo);
|
|
|
|
pSurfInfo = SurfaceInfoFromTypeAndIndex(
|
|
0xFFFFFFFF,
|
|
pamvaBeginFrameInfo->dwDestSurfaceIndex);
|
|
if (pSurfInfo == NULL) {
|
|
hr = E_INVALIDARG;
|
|
return hr;
|
|
}
|
|
ddvaBeginFrameInfo.pddDestSurface = pSurfInfo->pSurface;
|
|
|
|
DbgLog((LOG_TRACE, 2, TEXT("BeginFrame to surface %p"), pSurfInfo->pSurface));
|
|
|
|
|
|
ddvaBeginFrameInfo.dwSizeInputData = pamvaBeginFrameInfo->dwSizeInputData;
|
|
ddvaBeginFrameInfo.pInputData = pamvaBeginFrameInfo->pInputData;
|
|
ddvaBeginFrameInfo.dwSizeOutputData = pamvaBeginFrameInfo->dwSizeOutputData;
|
|
ddvaBeginFrameInfo.pOutputData = pamvaBeginFrameInfo->pOutputData;
|
|
|
|
ASSERT(m_pIDDVideoAccelerator);
|
|
hr = m_pIDDVideoAccelerator->BeginFrame(&ddvaBeginFrameInfo);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVideoAccelerator->BeginFrame failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EndFrame
|
|
*
|
|
* end a frame, the pMiscData is passed directly to the hal
|
|
* only valid to call this after the pins are connected
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::EndFrame(
|
|
const AMVAEndFrameInfo *pEndFrameInfo
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::EndFrame")));
|
|
HRESULT hr = NOERROR;
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
if (NULL == pEndFrameInfo) {
|
|
hr = E_POINTER;
|
|
return hr;
|
|
}
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
ASSERT(m_pIDDVideoAccelerator);
|
|
|
|
DDVAEndFrameInfo ddvaEndFrameInfo;
|
|
INITDDSTRUCT(ddvaEndFrameInfo);
|
|
ddvaEndFrameInfo.dwSizeMiscData = pEndFrameInfo->dwSizeMiscData;
|
|
ddvaEndFrameInfo.pMiscData = pEndFrameInfo->pMiscData;
|
|
|
|
hr = m_pIDDVideoAccelerator->EndFrame(&ddvaEndFrameInfo);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVideoAccelerator->EndFrame failed, hr = 0x%x"),
|
|
hr));
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* SurfaceInfoFromTypeAndIndex
|
|
*
|
|
* Get surface into structure given buffer type and buffer index
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
SURFACE_INFO *
|
|
CVMRInputPin::SurfaceInfoFromTypeAndIndex(
|
|
DWORD dwTypeIndex,
|
|
DWORD dwBufferIndex
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::SurfaceInfoFromTypeAndIndex")));
|
|
|
|
LPCOMP_SURFACE_INFO pCompSurfInfo;
|
|
|
|
// make sure that type-index is less than the number of types
|
|
if ((DWORD)(dwTypeIndex + 1) > m_dwCompSurfTypes) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("dwTypeIndex is invalid, dwTypeIndex = %d,")
|
|
TEXT(" m_dwCompSurfTypes = %d"),
|
|
dwTypeIndex, m_dwCompSurfTypes));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// cache the pointer to the list they are interested in
|
|
// Add 1 to allow for uncompressed surfaces
|
|
pCompSurfInfo = m_pCompSurfInfo + (DWORD)(dwTypeIndex + 1);
|
|
ASSERT(pCompSurfInfo);
|
|
if (dwBufferIndex >= pCompSurfInfo->dwAllocated) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("dwBufferIndex is invalid, dwBufferIndex = %d,")
|
|
TEXT(" dwAllocated = %d"),
|
|
dwBufferIndex, pCompSurfInfo->dwAllocated));
|
|
return NULL;
|
|
}
|
|
ASSERT(pCompSurfInfo->dwAllocated != 0);
|
|
|
|
// get the pointer to the next available unlocked buffer info struct
|
|
return pCompSurfInfo->pSurfInfo + dwBufferIndex;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetBuffer
|
|
*
|
|
* Cycle through the compressed buffers
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::GetBuffer(
|
|
DWORD dwTypeIndex,
|
|
DWORD dwBufferIndex,
|
|
BOOL bReadOnly,
|
|
LPVOID *ppBuffer,
|
|
LPLONG lpStride
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::GetBuffer")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
LPSURFACE_INFO pSurfInfo = NULL;
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Entering CVMRInputPin::GetBuffer type %d, index %d"),
|
|
dwTypeIndex, dwBufferIndex));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
if (ppBuffer == NULL || lpStride == NULL) {
|
|
hr = E_POINTER;
|
|
return hr;
|
|
}
|
|
|
|
pSurfInfo = SurfaceInfoFromTypeAndIndex(dwTypeIndex, dwBufferIndex);
|
|
|
|
if (pSurfInfo == NULL) {
|
|
hr = E_INVALIDARG;
|
|
return hr;
|
|
}
|
|
|
|
// Check buffer not already locked
|
|
if (pSurfInfo->pBuffer != NULL) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUSY);
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("No more free buffers left or the decoder is releasing")
|
|
TEXT(" buffers out of order, returning E_UNEXPECTED")));
|
|
return hr;
|
|
}
|
|
|
|
// Wait until previous motion comp operation is complete
|
|
while (DDERR_WASSTILLDRAWING ==
|
|
m_pIDDVideoAccelerator->QueryRenderStatus(
|
|
pSurfInfo->pSurface,
|
|
bReadOnly ? DDVA_QUERYRENDERSTATUSF_READ : 0)) {
|
|
Sleep(1);
|
|
}
|
|
|
|
// Now lock the surface
|
|
INITDDSTRUCT(ddsd);
|
|
|
|
for (; ;) {
|
|
// BUGBUG - check for uncompressed surfaces??
|
|
hr = pSurfInfo->pSurface->Lock(NULL, &ddsd, DDLOCK_NOSYSLOCK, NULL);
|
|
if (hr == DDERR_WASSTILLDRAWING) {
|
|
DbgLog((LOG_TRACE, 1, TEXT("Compressed surface is busy")));
|
|
Sleep(1);
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwBufferIndex == 0xFFFFFFFF && !bReadOnly) {
|
|
// Check if surface is being displayed
|
|
// BUGBUG implement
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pSurfInfo->pSurface->Lock failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
pSurfInfo->pBuffer = ddsd.lpSurface;
|
|
*ppBuffer = ddsd.lpSurface;
|
|
*lpStride = ddsd.lPitch;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("leaving CVMRInputPin::GetBuffer returned 0x%8.8X"), hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ReleaseBuffer
|
|
*
|
|
* unlock a compressed buffer
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::ReleaseBuffer(
|
|
DWORD dwTypeIndex,
|
|
DWORD dwBufferIndex
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::ReleaseBuffer")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
LPSURFACE_INFO pSurfInfo;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Entering CVMRInputPin::ReleaseBuffer type %d, index %d"),
|
|
dwTypeIndex, dwBufferIndex));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
pSurfInfo = SurfaceInfoFromTypeAndIndex(dwTypeIndex, dwBufferIndex);
|
|
if (NULL == pSurfInfo) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("GetInfoFromCookie failed, hr = 0x%x"), hr));
|
|
hr = E_INVALIDARG;
|
|
return hr;
|
|
}
|
|
// make sure there is a valid buffer pointer and it is the same as
|
|
// what we have cached
|
|
if (NULL == pSurfInfo->pBuffer) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pBuffer is not valid, pBuffer = 0x%x, pSurfInfo->pBuffer")
|
|
TEXT(" = 0x%x"), pSurfInfo->pBuffer, pSurfInfo->pSurface));
|
|
hr = HRESULT_FROM_WIN32(ERROR_NOT_LOCKED);
|
|
return hr;
|
|
}
|
|
|
|
// For some reason IDirectDrawSurface7 wants an LPRECT here
|
|
// I hope NULL is OK
|
|
hr = pSurfInfo->pSurface->Unlock(NULL);
|
|
if (SUCCEEDED(hr)) {
|
|
pSurfInfo->pBuffer = NULL;
|
|
}
|
|
else {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("pSurfInfo->pSurface->Unlock failed, hr = 0x%x"), hr));
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("leaving CVMRInputPin::ReleaseBuffer returned 0x%8.8X"), hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Execute
|
|
*
|
|
* Perform a decode operation
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::Execute(
|
|
DWORD dwFunction,
|
|
LPVOID lpPrivateInputData,
|
|
DWORD cbPrivateInputData,
|
|
LPVOID lpPrivateOutputData,
|
|
DWORD cbPrivateOutputData,
|
|
DWORD dwNumBuffers,
|
|
const AMVABUFFERINFO *pamvaBufferInfo
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::Execute")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
DWORD i = 0;
|
|
DDVABUFFERINFO *pddvaBufferInfo = NULL;
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
pddvaBufferInfo = (DDVABUFFERINFO *)_alloca(sizeof(DDVABUFFERINFO) * dwNumBuffers);
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL, TEXT("Execute Function %d, %d buffers :"),
|
|
dwFunction, dwNumBuffers));
|
|
|
|
for (i = 0; i < dwNumBuffers; i++) {
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT(" Type(%d) Index(%d) offset(%d) size(%d)"),
|
|
pamvaBufferInfo[i].dwTypeIndex,
|
|
pamvaBufferInfo[i].dwBufferIndex,
|
|
pamvaBufferInfo[i].dwDataOffset,
|
|
pamvaBufferInfo[i].dwDataSize));
|
|
|
|
LPSURFACE_INFO pSurfInfo =
|
|
SurfaceInfoFromTypeAndIndex(
|
|
pamvaBufferInfo[i].dwTypeIndex,
|
|
pamvaBufferInfo[i].dwBufferIndex);
|
|
|
|
if (pSurfInfo == NULL) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("GetInfoFromCookie failed, hr = 0x%x, i = %d"),
|
|
hr, i));
|
|
|
|
hr = E_INVALIDARG;
|
|
return hr;
|
|
}
|
|
|
|
INITDDSTRUCT(pddvaBufferInfo[i]);
|
|
pddvaBufferInfo[i].dwDataOffset = pamvaBufferInfo[i].dwDataOffset;
|
|
pddvaBufferInfo[i].dwDataSize = pamvaBufferInfo[i].dwDataSize;
|
|
pddvaBufferInfo[i].pddCompSurface = pSurfInfo->pSurface;
|
|
}
|
|
|
|
ASSERT(m_pIDDVideoAccelerator);
|
|
|
|
|
|
hr = m_pIDDVideoAccelerator->Execute(dwFunction,
|
|
lpPrivateInputData,
|
|
cbPrivateInputData,
|
|
lpPrivateOutputData,
|
|
cbPrivateOutputData,
|
|
dwNumBuffers,
|
|
pddvaBufferInfo);
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVideoAccelerator->Execute failed, hr = 0x%x"),
|
|
hr));
|
|
return hr;
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("leaving CVMRInputPin::Execute returned 0x%8.8X"), hr));
|
|
return hr;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* QueryRenderStatus
|
|
*
|
|
* QueryRenderStatus of a particular (possibly a set of) macro block
|
|
* dwNumBlocks is an IN parameter
|
|
*
|
|
* pdwCookies is an IN parameter which is array (of length dwNumBlocks)
|
|
* of cookies which server as identifiers for the corresponding members of
|
|
* pddvaMacroBlockInfo
|
|
*
|
|
* pddvaMacroBlockInfo is an IN parameter which is array (of length
|
|
* dwNumBlocks) of structures only valid to call this after the pins
|
|
* are connected
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::QueryRenderStatus(
|
|
DWORD dwTypeIndex,
|
|
DWORD dwBufferIndex,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::QueryRenderStatus")));
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Entering CVMRInputPin::QueryRenderStatus - type(%d), ")
|
|
TEXT("buffer(%d), flags(0x%8.8X)"),
|
|
dwTypeIndex, dwBufferIndex, dwFlags));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
LPSURFACE_INFO pSurfInfo =
|
|
SurfaceInfoFromTypeAndIndex(dwTypeIndex, dwBufferIndex);
|
|
|
|
if (pSurfInfo == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pIDDVideoAccelerator->QueryRenderStatus(pSurfInfo->pSurface, dwFlags);
|
|
if (FAILED(hr) && hr != DDERR_WASSTILLDRAWING) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("m_pIDDVideoAccelerator->QueryRenderStatus")
|
|
TEXT(" failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("leaving CVMRInputPin::QueryRenderStatus returned 0x%8.8X"),
|
|
hr));
|
|
|
|
if (hr == DDERR_WASSTILLDRAWING) {
|
|
hr = E_PENDING;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* FlipDVASurface
|
|
*
|
|
* Flips our internal surface pointers to match those used by DDraw.
|
|
*
|
|
* History:
|
|
* Mon 12/04/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CVMRInputPin::FlipDVASurface(
|
|
DWORD dwFlipToIndex,
|
|
DWORD dwFlipFromIndex
|
|
)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::FlipDVASurface")));
|
|
|
|
LPDIRECTDRAWSURFACE7 pTempSurface;
|
|
|
|
// we should have successfully called flip by this point, swap the two
|
|
pTempSurface = m_pCompSurfInfo[0].pSurfInfo[dwFlipToIndex].pSurface;
|
|
|
|
m_pCompSurfInfo[0].pSurfInfo[dwFlipToIndex].pSurface =
|
|
m_pCompSurfInfo[0].pSurfInfo[dwFlipFromIndex].pSurface;
|
|
|
|
m_pCompSurfInfo[0].pSurfInfo[dwFlipFromIndex].pSurface = pTempSurface;
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DisplayFrame
|
|
*
|
|
* This function needs re-writting and possible moving into the AP object.
|
|
*
|
|
* History:
|
|
* Wed 05/10/2000 - StEstrop - Created
|
|
*
|
|
\**************************************************************************/
|
|
STDMETHODIMP
|
|
CVMRInputPin::DisplayFrame(
|
|
DWORD dwFlipToIndex,
|
|
IMediaSample *pMediaSample)
|
|
{
|
|
AMTRACE((TEXT("CVMRInputPin::DisplayFrame")));
|
|
|
|
#if defined( EHOME_WMI_INSTRUMENTATION )
|
|
PERFLOG_STREAMTRACE(
|
|
1,
|
|
PERFINFO_STREAMTRACE_VMR_END_DECODE,
|
|
0, 0, 0, 0, 0 );
|
|
#endif
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
DWORD dwNumUncompFrames = m_dwBackBufferCount + 1;
|
|
DWORD dwFlipFromIndex = 0, i = 0;
|
|
SURFACE_INFO *pSurfInfo;
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("Entering CVMRInputPin::DisplayFrame - index %d"),
|
|
dwFlipToIndex));
|
|
|
|
CAutoLock cLock(m_pInterfaceLock);
|
|
|
|
// make sure that we have a valid motion-comp connection
|
|
hr = CheckValidMCConnection();
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("CheckValidMCConnection failed, hr = 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
pSurfInfo = SurfaceInfoFromTypeAndIndex(0xFFFFFFFF, dwFlipToIndex);
|
|
if (pSurfInfo == NULL) {
|
|
hr = E_INVALIDARG;
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL, TEXT("dwFlipToIndex not valid")));
|
|
return hr;
|
|
}
|
|
|
|
for (i = 0; i < dwNumUncompFrames; i++) {
|
|
if (IsEqualObject(m_pCompSurfInfo[0].pSurfInfo[i].pSurface, m_pDDS)) {
|
|
dwFlipFromIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we are in pass thru mode it is very important that we
|
|
// know whether a Flip completed or not. If are in mixer mode
|
|
// we have to be notified when the mixer has finished with the sample
|
|
//
|
|
|
|
if (m_pRenderer->m_VMRModePassThru) {
|
|
m_pRenderer->m_hrSurfaceFlipped = E_FAIL;
|
|
}
|
|
else {
|
|
ResetEvent(m_hDXVAEvent);
|
|
}
|
|
|
|
|
|
//
|
|
// Create our temp VMR sample and intialize it from the sample
|
|
// specified by the upstream decoder, copy across all the relevant
|
|
// properties.
|
|
//
|
|
|
|
IMediaSample2 *pSample2;
|
|
CVMRMediaSample vmrSamp(TEXT(""), (CBaseAllocator *)-1, &hr, NULL, 0, m_hDXVAEvent);
|
|
|
|
if (SUCCEEDED(pMediaSample->QueryInterface(IID_IMediaSample2, (void **)&pSample2))) {
|
|
|
|
AM_SAMPLE2_PROPERTIES SampleProps;
|
|
hr = pSample2->GetProperties(sizeof(m_SampleProps), (PBYTE)&SampleProps);
|
|
pSample2->Release();
|
|
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("GetProperties on the supplied ")
|
|
TEXT("media sample failed hr = %#X"), hr));
|
|
return hr;
|
|
}
|
|
|
|
hr = vmrSamp.SetProps(SampleProps, pSurfInfo->pSurface);
|
|
if (FAILED(hr)) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("SetProperties on the VMR mixer ")
|
|
TEXT("media sample failed hr = %#X"), hr));
|
|
return hr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
REFERENCE_TIME rtSTime = 0, rtETime = 0;
|
|
if (VFW_E_SAMPLE_TIME_NOT_SET ==
|
|
pMediaSample->GetTime(&rtSTime, &rtETime)) {
|
|
|
|
vmrSamp.SetTime(NULL, NULL);
|
|
}
|
|
else {
|
|
vmrSamp.SetTime(&rtSTime, &rtETime);
|
|
}
|
|
|
|
AM_MEDIA_TYPE *pMediaType;
|
|
hr = pMediaSample->GetMediaType(&pMediaType);
|
|
|
|
if (hr == E_OUTOFMEMORY) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("Out off memory calling GetMediaType ")
|
|
TEXT("on the media sample")));
|
|
return hr;
|
|
}
|
|
|
|
if (hr == S_OK) {
|
|
|
|
hr = vmrSamp.SetMediaType(pMediaType);
|
|
DeleteMediaType(pMediaType);
|
|
|
|
if (hr != S_OK) {
|
|
DbgLog((LOG_ERROR, VA_ERROR_LEVEL,
|
|
TEXT("SetMediaType on the VMR mixer ")
|
|
TEXT("media sample failed hr = %#X"), hr));
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
vmrSamp.SetSurface(pSurfInfo->pSurface);
|
|
}
|
|
|
|
|
|
//
|
|
// We do not want to hold any locks during Receive
|
|
//
|
|
m_pInterfaceLock->Unlock();
|
|
hr = Receive(&vmrSamp);
|
|
m_pInterfaceLock->Lock();
|
|
|
|
|
|
//
|
|
// If we are in pass thru mode a DDraw flip may have
|
|
// occurred. DDraw switches the memory under the pointers
|
|
// during a flip so mimic that in our list - but only if the
|
|
// flip actually happened.
|
|
//
|
|
|
|
if (m_pRenderer->m_VMRModePassThru) {
|
|
|
|
if (m_pRenderer->m_hrSurfaceFlipped == DD_OK) {
|
|
FlipDVASurface(dwFlipToIndex, dwFlipFromIndex);
|
|
}
|
|
}
|
|
else {
|
|
|
|
//
|
|
// wait for the sample to be released by the mixer, but only if the
|
|
// sample was actuall placed onto one of the mixers queues.
|
|
//
|
|
|
|
if (hr == S_OK) {
|
|
|
|
m_pInterfaceLock->Unlock();
|
|
WaitForSingleObject(m_hDXVAEvent, INFINITE);
|
|
m_pInterfaceLock->Lock();
|
|
}
|
|
}
|
|
|
|
|
|
DbgLog((LOG_TRACE, VA_TRACE_LEVEL,
|
|
TEXT("leaving CVMRInputPin::DisplayFrame return 0x%8.8X"), hr));
|
|
|
|
#if defined( EHOME_WMI_INSTRUMENTATION )
|
|
//
|
|
// From BryanW:
|
|
//
|
|
// Seems countintertuitive, however according to StEstrop, this
|
|
// is the way we measure the time spent in the decoder. This happens
|
|
// to work.
|
|
//
|
|
PERFLOG_STREAMTRACE(
|
|
1,
|
|
PERFINFO_STREAMTRACE_VMR_BEGIN_DECODE,
|
|
0, 0, 0, 0, 0 );
|
|
#endif
|
|
|
|
return hr;
|
|
}
|