Cleaning up and getting decoder profiles

This commit is contained in:
Linnea May 2021-11-10 17:33:29 -08:00
Родитель 18220b24b8
Коммит 8b3ab872ec
30 изменённых файлов: 46 добавлений и 9511 удалений

Просмотреть файл

@ -121,13 +121,13 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Users\linneamay\.nuget\packages\microsoft.ai.machinelearning\1.9.1\build\native\include\abi;C:\Windows-Machine-Learning\Samples\BackgroundBlur\BackgroundBlur\common;C:\Windows-Machine-Learning\Samples\BackgroundBlur\DX11VideoRenderer;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Users\linneamay\.nuget\packages\microsoft.ai.machinelearning\1.9.1\build\native\include\abi;$(SolutionDir)DX11VideoRenderer;common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>C:\Program Files %28x86%29\Windows Kits\10\Lib\10.0.19041.0\um\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>C:\Program Files %28x86%29\Windows Kits\10\Lib\10.0.19041.0\um\$(PlatformShortName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\Mfplat.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\Mf.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\Mfcore.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\evr.lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64\mfuuid.lib;C:\Windows-Machine-Learning\Samples\BackgroundBlur\x64\Debug\DX11VideoRenderer.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

Просмотреть файл

@ -1,56 +0,0 @@
DirectX video rendering sample
==============================
This sample shows how to create a media sink that renders video output to a window using DirectX 11.
Specifically, this sample shows how to:
- Decode the video using the Media Foundation APIs
- Render the decoded video using the DirectX 11 APIs
- Output the video stream to multi-monitor displays
For more info about the concepts and APIs demonstrated in this sample, see the following topics:
- [Direct3D 11 graphics APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/ff476080)
- [Media Foundation media APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197)
- [DirectX Graphics Interface (DXGI) APIs](http://msdn.microsoft.com/en-us/library/windows/desktop/bb205169)
**Note** This sample requires Microsoft Visual Studio 2013 or a later version (any SKU) and will not build in Microsoft Visual Studio Express 2013 for Windows .
**Note** The Windows-classic-samples repo contains a variety of code samples that exercise the various programming models, platforms, features, and components available in Windows and/or Windows Server. This repo provides a Visual Studio solution (SLN) file for each sample, along with the source files, assets, resources, and metadata needed to compile and run the sample. For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, check out the documentation on the [Windows Dev Center](https://dev.windows.com). This sample is provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows and/or Windows Server. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. This sample was created for Windows 8.1 and/or Windows Server 2012 R2 using Visual Studio 2013, but in many cases it will run unaltered using later versions. Please provide feedback on this sample!
To get a copy of Windows, go to [Downloads and tools](http://go.microsoft.com/fwlink/p/?linkid=301696).
To get a copy of Visual Studio, go to [Visual Studio Downloads](http://go.microsoft.com/fwlink/p/?linkid=301697).
Related technologies
--------------------
[Media Foundation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197)
Operating system requirements
-----------------------------
Client
Windows 8.1
Server
Windows Server 2012 R2
Build the sample
----------------
To build this sample:
1. Open the solutions (.sln) file titled DX11VideoRenderer.sln from Visual Studio. You'll find the solutions file in \<*install\_root*\>\\DX11VideoRenderer\\C++.
2. After the sample has loaded, press the F7 (or F6 for Visual Studio 2013) key or select **Build Solution** from the **Build** menu.
Run the sample
--------------
1. Register the DLL by running the command `regsvr32 DX11VideoRenderer.dll` from an elevated command prompt.
2. Run [the `topoedit.exe` program from the Windows SDK](https://docs.microsoft.com/en-us/windows/desktop/medfound/topoedit).
3. From the Topology menu, select "Add DX11 Video Renderer."
4. When you are finished using the sample, unregister the DLL by running the command `regsvr32 /u DX11VideoRenderer.dll` from an elevated command prompt.

Просмотреть файл

@ -1,213 +0,0 @@
#include "Activate.h"
HRESULT DX11VideoRenderer::CActivate::CreateInstance(HWND hwnd, IMFActivate** ppActivate)
{
if (ppActivate == NULL)
{
return E_POINTER;
}
CActivate* pActivate = new CActivate();
if (pActivate == NULL)
{
return E_OUTOFMEMORY;
}
pActivate->AddRef();
HRESULT hr = S_OK;
do
{
hr = pActivate->Initialize();
if (FAILED(hr))
{
break;
}
hr = pActivate->QueryInterface(IID_PPV_ARGS(ppActivate));
if (FAILED(hr))
{
break;
}
pActivate->m_hwnd = hwnd;
}
while (FALSE);
SafeRelease(pActivate);
return hr;
}
// IUnknown
ULONG DX11VideoRenderer::CActivate::AddRef(void)
{
return InterlockedIncrement(&m_lRefCount);
}
// IUnknown
HRESULT DX11VideoRenderer::CActivate::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(static_cast<IMFActivate*>(this));
}
else if (iid == __uuidof(IMFActivate))
{
*ppv = static_cast<IMFActivate*>(this);
}
else if (iid == __uuidof(IPersistStream))
{
*ppv = static_cast<IPersistStream*>(this);
}
else if (iid == __uuidof(IPersist))
{
*ppv = static_cast<IPersist*>(this);
}
else if (iid == __uuidof(IMFAttributes))
{
*ppv = static_cast<IMFAttributes*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// IUnknown
ULONG DX11VideoRenderer::CActivate::Release(void)
{
ULONG lRefCount = InterlockedDecrement(&m_lRefCount);
if (lRefCount == 0)
{
delete this;
}
return lRefCount;
}
// IMFActivate
HRESULT DX11VideoRenderer::CActivate::ActivateObject(__RPC__in REFIID riid, __RPC__deref_out_opt void** ppvObject)
{
HRESULT hr = S_OK;
IMFGetService* pSinkGetService = NULL;
IMFVideoDisplayControl* pSinkVideoDisplayControl = NULL;
do
{
if (m_pMediaSink == NULL)
{
hr = CMediaSink::CreateInstance(IID_PPV_ARGS(&m_pMediaSink));
if (FAILED(hr))
{
break;
}
hr = m_pMediaSink->QueryInterface(IID_PPV_ARGS(&pSinkGetService));
if (FAILED(hr))
{
break;
}
hr = pSinkGetService->GetService(MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pSinkVideoDisplayControl));
if (FAILED(hr))
{
break;
}
hr = pSinkVideoDisplayControl->SetVideoWindow(m_hwnd);
if (FAILED(hr))
{
break;
}
}
hr = m_pMediaSink->QueryInterface(riid, ppvObject);
if (FAILED(hr))
{
break;
}
}
while (FALSE);
SafeRelease(pSinkGetService);
SafeRelease(pSinkVideoDisplayControl);
return hr;
}
// IMFActivate
HRESULT DX11VideoRenderer::CActivate::DetachObject(void)
{
SafeRelease(m_pMediaSink);
return S_OK;
}
// IMFActivate
HRESULT DX11VideoRenderer::CActivate::ShutdownObject(void)
{
if (m_pMediaSink != NULL)
{
m_pMediaSink->Shutdown();
SafeRelease(m_pMediaSink);
}
return S_OK;
}
// IPersistStream
HRESULT DX11VideoRenderer::CActivate::GetSizeMax(__RPC__out ULARGE_INTEGER* pcbSize)
{
return E_NOTIMPL;
}
// IPersistStream
HRESULT DX11VideoRenderer::CActivate::IsDirty(void)
{
return E_NOTIMPL;
}
// IPersistStream
HRESULT DX11VideoRenderer::CActivate::Load(__RPC__in_opt IStream* pStream)
{
return E_NOTIMPL;
}
// IPersistStream
HRESULT DX11VideoRenderer::CActivate::Save(__RPC__in_opt IStream* pStream, BOOL bClearDirty)
{
return E_NOTIMPL;
}
// IPersist
HRESULT DX11VideoRenderer::CActivate::GetClassID(__RPC__out CLSID* pClassID)
{
if (pClassID == NULL)
{
return E_POINTER;
}
*pClassID = CLSID_DX11VideoRendererActivate;
return S_OK;
}
// ctor
DX11VideoRenderer::CActivate::CActivate(void) :
m_lRefCount(0),
m_pMediaSink(NULL),
m_hwnd(NULL)
{
}
// dtor
DX11VideoRenderer::CActivate::~CActivate(void)
{
SafeRelease(m_pMediaSink);
}

Просмотреть файл

@ -1,43 +0,0 @@
#pragma once
#include "Common.h"
#include "MFAttributesImpl.h"
#include "MediaSink.h"
namespace DX11VideoRenderer
{
class CActivate : public CMFAttributesImpl<IMFActivate>, public IPersistStream, private CBase
{
public:
static HRESULT CreateInstance(HWND hwnd, IMFActivate** ppActivate);
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID riid, __RPC__deref_out _Result_nullonfailure_ void** ppvObject);
STDMETHODIMP_(ULONG) Release(void);
// IMFActivate
STDMETHODIMP ActivateObject(__RPC__in REFIID riid, __RPC__deref_out_opt void** ppvObject);
STDMETHODIMP DetachObject(void);
STDMETHODIMP ShutdownObject(void);
// IPersistStream
STDMETHODIMP GetSizeMax(__RPC__out ULARGE_INTEGER* pcbSize);
STDMETHODIMP IsDirty(void);
STDMETHODIMP Load(__RPC__in_opt IStream* pStream);
STDMETHODIMP Save(__RPC__in_opt IStream* pStream, BOOL bClearDirty);
// IPersist (from IPersistStream)
STDMETHODIMP GetClassID(__RPC__out CLSID* pClassID);
private:
CActivate(void);
~CActivate(void);
long m_lRefCount;
IMFMediaSink* m_pMediaSink;
HWND m_hwnd;
};
}

Просмотреть файл

@ -1,88 +0,0 @@
#include "ClassFactory.h"
BOOL DX11VideoRenderer::CClassFactory::IsLocked(void)
{
return (s_lLockCount == 0) ? FALSE : TRUE;
}
DX11VideoRenderer::CClassFactory::CClassFactory(void) :
m_lRefCount(0)
{
}
DX11VideoRenderer::CClassFactory::~CClassFactory(void)
{
}
// IUnknown
ULONG DX11VideoRenderer::CClassFactory::AddRef(void)
{
return InterlockedIncrement(&m_lRefCount);
}
// IUnknown
HRESULT DX11VideoRenderer::CClassFactory::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(static_cast<IClassFactory*>(this));
}
else if (iid == __uuidof(IClassFactory))
{
*ppv = static_cast<IClassFactory*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// IUnknown
ULONG DX11VideoRenderer::CClassFactory::Release(void)
{
ULONG lRefCount = InterlockedDecrement(&m_lRefCount);
if (lRefCount == 0)
{
delete this;
}
return lRefCount;
}
// IClassFactory
HRESULT DX11VideoRenderer::CClassFactory::CreateInstance(_In_opt_ IUnknown* pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
if (ppvObject == NULL)
{
return E_POINTER;
}
*ppvObject = NULL;
if (pUnkOuter != NULL)
{
return CLASS_E_NOAGGREGATION;
}
return CMediaSink::CreateInstance(riid, ppvObject);
}
// IClassFactory
HRESULT DX11VideoRenderer::CClassFactory::LockServer(BOOL bLock)
{
if (bLock == FALSE)
{
InterlockedDecrement(&s_lLockCount);
}
else
{
InterlockedIncrement(&s_lLockCount);
}
return S_OK;
}

Просмотреть файл

@ -1,32 +0,0 @@
#pragma once
#include "Common.h"
#include "MediaSink.h"
namespace DX11VideoRenderer
{
class CClassFactory : public IClassFactory, private CBase
{
public:
static BOOL IsLocked(void);
CClassFactory(void);
~CClassFactory(void);
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID riid, __RPC__deref_out _Result_nullonfailure_ void** ppvObject);
STDMETHODIMP_(ULONG) Release(void);
// IClassFactory
STDMETHODIMP CreateInstance(_In_opt_ IUnknown* pUnkOuter, _In_ REFIID riid, _COM_Outptr_ void** ppvObject);
STDMETHODIMP LockServer(BOOL bLock);
private:
static volatile long s_lLockCount;
long m_lRefCount;
};
}

Просмотреть файл

@ -1,386 +0,0 @@
#pragma once
#include <windows.h>
#include <float.h> // for FLT_MAX
#include <tchar.h>
#include <math.h>
#include <strsafe.h>
#include <mmsystem.h>
#include <mfapi.h>
#include <mfidl.h>
#include <evr.h>
#include <mferror.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <dcomp.h>
#include <wmcodecdsp.h> // for MEDIASUBTYPE_V216
#include "DX11VideoRenderer.h"
#include "linklist.h"
#include "staticasynccallback.h"
#ifndef CLSID_VideoProcessorMFT
//DEFINE_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);
#endif
// MF_XVP_PLAYBACK_MODE
// Data type: UINT32 (treat as BOOL)
// If this attribute is TRUE, the XVP will run in playback mode where it will:
// 1) Allow caller to allocate D3D output samples
// 2) Not perform FRC
// 3) Allow last frame regeneration (repaint)
// This attribute should be set on the transform's attrbiute store prior to setting the input type.
DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12, 0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9);
namespace DX11VideoRenderer
{
inline void SafeCloseHandle(HANDLE& h)
{
if (h != NULL)
{
CloseHandle(h);
h = NULL;
}
}
template <class T> inline void SafeDelete(T*& pT)
{
delete pT;
pT = NULL;
}
template <class T> inline void SafeDeleteArray(T*& pT)
{
delete[] pT;
pT = NULL;
}
template <class T> inline void SafeRelease(T*& pT)
{
if (pT != NULL)
{
pT->Release();
pT = NULL;
}
}
template <class T> inline double TicksToMilliseconds(const T& t)
{
return t / 10000.0;
}
template <class T> inline T MillisecondsToTicks(const T& t)
{
return t * 10000;
}
// returns the greatest common divisor of A and B
inline int gcd(int A, int B)
{
int Temp;
if (A < B)
{
Temp = A;
A = B;
B = Temp;
}
while (B != 0)
{
Temp = A % B;
A = B;
B = Temp;
}
return A;
}
// Convert a fixed-point to a float.
inline float MFOffsetToFloat(const MFOffset& offset)
{
return (float)offset.value + ((float)offset.value / 65536.0f);
}
inline RECT MFVideoAreaToRect(const MFVideoArea area)
{
float left = MFOffsetToFloat(area.OffsetX);
float top = MFOffsetToFloat(area.OffsetY);
RECT rc =
{
int( left + 0.5f ),
int( top + 0.5f ),
int( left + area.Area.cx + 0.5f ),
int( top + area.Area.cy + 0.5f )
};
return rc;
}
inline MFOffset MakeOffset(float v)
{
MFOffset offset;
offset.value = short(v);
offset.fract = WORD(65536 * (v-offset.value));
return offset;
}
inline MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height)
{
MFVideoArea area;
area.OffsetX = MakeOffset(x);
area.OffsetY = MakeOffset(y);
area.Area.cx = width;
area.Area.cy = height;
return area;
}
class CBase
{
public:
static long GetObjectCount(void)
{
return s_lObjectCount;
}
protected:
CBase(void)
{
InterlockedIncrement(&s_lObjectCount);
}
~CBase(void)
{
InterlockedDecrement(&s_lObjectCount);
}
private:
static volatile long s_lObjectCount;
};
//////////////////////////////////////////////////////////////////////////
// CAsyncCallback [template]
//
// Description:
// Helper class that routes IMFAsyncCallback::Invoke calls to a class
// method on the parent class.
//
// Usage:
// Add this class as a member variable. In the parent class constructor,
// initialize the CAsyncCallback class like this:
// m_cb(this, &CYourClass::OnInvoke)
// where
// m_cb = CAsyncCallback object
// CYourClass = parent class
// OnInvoke = Method in the parent class to receive Invoke calls.
//
// The parent's OnInvoke method (you can name it anything you like) must
// have a signature that matches the InvokeFn typedef below.
//////////////////////////////////////////////////////////////////////////
// T: Type of the parent object
template<class T>
class CAsyncCallback : public IMFAsyncCallback
{
public:
typedef HRESULT (T::*InvokeFn)(IMFAsyncResult* pAsyncResult);
CAsyncCallback(T* pParent, InvokeFn fn) :
m_pParent(pParent),
m_pInvokeFn(fn)
{
}
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void)
{
// Delegate to parent class.
return m_pParent->AddRef();
}
STDMETHODIMP_(ULONG) Release(void)
{
// Delegate to parent class.
return m_pParent->Release();
}
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == __uuidof(IUnknown))
{
*ppv = static_cast<IUnknown*>(static_cast<IMFAsyncCallback*>(this));
}
else if (iid == __uuidof(IMFAsyncCallback))
{
*ppv = static_cast<IMFAsyncCallback*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// IMFAsyncCallback methods
STDMETHODIMP GetParameters(__RPC__out DWORD* pdwFlags, __RPC__out DWORD* pdwQueue)
{
// Implementation of this method is optional.
return E_NOTIMPL;
}
STDMETHODIMP Invoke(__RPC__in_opt IMFAsyncResult* pAsyncResult)
{
return (m_pParent->*m_pInvokeFn)(pAsyncResult);
}
private:
T* m_pParent;
InvokeFn m_pInvokeFn;
};
//-----------------------------------------------------------------------------
// ThreadSafeQueue template
// Thread-safe queue of COM interface pointers.
//
// T: COM interface type.
//
// This class is used by the scheduler.
//
// Note: This class uses a critical section to protect the state of the queue.
// With a little work, the scheduler could probably use a lock-free queue.
//-----------------------------------------------------------------------------
template <class T>
class ThreadSafeQueue
{
public:
ThreadSafeQueue(void)
{
InitializeCriticalSection(&m_lock);
}
virtual ~ThreadSafeQueue(void)
{
DeleteCriticalSection(&m_lock);
}
HRESULT Queue(T* p)
{
EnterCriticalSection(&m_lock);
HRESULT hr = m_list.InsertBack(p);
LeaveCriticalSection(&m_lock);
return hr;
}
HRESULT Dequeue(T** pp)
{
EnterCriticalSection(&m_lock);
HRESULT hr = S_OK;
if (m_list.IsEmpty())
{
*pp = NULL;
hr = S_FALSE;
}
else
{
hr = m_list.RemoveFront(pp);
}
LeaveCriticalSection(&m_lock);
return hr;
}
HRESULT PutBack(T* p)
{
EnterCriticalSection(&m_lock);
HRESULT hr = m_list.InsertFront(p);
LeaveCriticalSection(&m_lock);
return hr;
}
DWORD GetCount(void)
{
EnterCriticalSection(&m_lock);
DWORD nCount = m_list.GetCount();
LeaveCriticalSection(&m_lock);
return nCount;
}
void Clear(void)
{
EnterCriticalSection(&m_lock);
m_list.Clear();
LeaveCriticalSection(&m_lock);
}
private:
CRITICAL_SECTION m_lock;
ComPtrListEx<T> m_list;
};
class CCritSec
{
public:
CCritSec(void) :
m_cs()
{
InitializeCriticalSection(&m_cs);
}
~CCritSec(void)
{
DeleteCriticalSection(&m_cs);
}
_Acquires_lock_(this->m_cs)
void Lock(void)
{
EnterCriticalSection(&m_cs);
}
_Releases_lock_(this->m_cs)
void Unlock(void)
{
LeaveCriticalSection(&m_cs);
}
private:
CRITICAL_SECTION m_cs;
};
class CAutoLock
{
public:
_Acquires_lock_(this->m_pLock->m_cs)
CAutoLock(CCritSec* pLock) :
m_pLock(pLock)
{
m_pLock->Lock();
}
_Releases_lock_(this->m_pLock->m_cs)
~CAutoLock(void)
{
m_pLock->Unlock();
}
private:
CCritSec* m_pLock;
};
}

Просмотреть файл

@ -1,261 +0,0 @@
#include <initguid.h>
#include "Common.h"
#include "Activate.h"
#include "ClassFactory.h"
#include "MediaSink.h"
HMODULE g_hModule = NULL;
volatile long DX11VideoRenderer::CBase::s_lObjectCount = 0;
volatile long DX11VideoRenderer::CClassFactory::s_lLockCount = 0;
// helper functions
///////////////////////////////////////////////////////////////////////
// Name: CreateObjectKeyName
// Desc: Converts a CLSID into a string with the form "CLSID\{clsid}"
///////////////////////////////////////////////////////////////////////
HRESULT CreateObjectKeyName(const GUID& guid, _Out_writes_(cchMax) TCHAR* pszName, DWORD cchMax)
{
pszName[0] = _T('\0');
// convert CLSID to string
OLECHAR pszCLSID[CHARS_IN_GUID];
HRESULT hr = StringFromGUID2(guid, pszCLSID, CHARS_IN_GUID);
if (SUCCEEDED(hr))
{
// create a string of the form "CLSID\{clsid}"
hr = StringCchPrintf(pszName, cchMax - 1, TEXT("CLSID\\%ls"), pszCLSID);
}
return hr;
}
///////////////////////////////////////////////////////////////////////
// Name: SetKeyValue
// Desc: Sets a string value (REG_SZ) for a registry key
//
// hKey: Handle to the registry key.
// sName: Name of the value. Use NULL for the default value.
// sValue: The string value.
///////////////////////////////////////////////////////////////////////
HRESULT SetKeyValue(HKEY hKey, const TCHAR* pszName, const TCHAR* pszValue)
{
size_t cch = 0;
DWORD cbData = 0;
HRESULT hr = StringCchLength(pszValue, MAXLONG, &cch);
if (SUCCEEDED(hr))
{
cbData = (DWORD) (sizeof(TCHAR) * (cch + 1)); // add 1 for the NULL character
hr = __HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszName, 0, REG_SZ, reinterpret_cast<const BYTE*>(pszValue), cbData));
}
return hr;
}
///////////////////////////////////////////////////////////////////////
// Name: RegisterObject
// Desc: Creates the registry entries for a COM object.
//
// guid: The object's CLSID
// sDescription: Description of the object
// sThreadingMode: Threading model. e.g., "Both"
///////////////////////////////////////////////////////////////////////
HRESULT RegisterObject(GUID guid, const TCHAR* pszDescription, const TCHAR* pszThreadingModel)
{
HRESULT hr = S_OK;
TCHAR pszTemp[MAX_PATH];
HKEY hKey = NULL;
HKEY hSubkey = NULL;
DWORD dwRet = 0;
do
{
hr = CreateObjectKeyName(guid, pszTemp, MAX_PATH);
if (FAILED(hr))
{
break;
}
hr = __HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszTemp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL));
if (FAILED(hr))
{
break;
}
hr = SetKeyValue(hKey, NULL, pszDescription);
if (FAILED(hr))
{
break;
}
hr = __HRESULT_FROM_WIN32(RegCreateKeyEx(hKey, L"InprocServer32", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hSubkey, NULL));
if (FAILED(hr))
{
break;
}
dwRet = GetModuleFileName(g_hModule, pszTemp, MAX_PATH);
if (dwRet == 0)
{
hr = __HRESULT_FROM_WIN32(GetLastError());
break;
}
if (dwRet == MAX_PATH)
{
hr = E_FAIL; // buffer too small
break;
}
hr = SetKeyValue(hSubkey, NULL, pszTemp);
if (FAILED(hr))
{
break;
}
hr = SetKeyValue(hSubkey, L"ThreadingModel", pszThreadingModel);
}
while (FALSE);
if (hSubkey != NULL)
{
RegCloseKey(hSubkey);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
}
return hr;
}
///////////////////////////////////////////////////////////////////////
// Name: UnregisterObject
// Desc: Deletes the registry entries for a COM object.
//
// guid: The object's CLSID
///////////////////////////////////////////////////////////////////////
HRESULT UnregisterObject(GUID guid)
{
HRESULT hr = S_OK;
TCHAR pszTemp[MAX_PATH];
do
{
hr = CreateObjectKeyName(guid, pszTemp, MAX_PATH);
if (FAILED(hr))
{
break;
}
hr = __HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, pszTemp));
}
while (FALSE);
return hr;
}
// DLL Exports
STDAPI CreateDX11VideoRenderer(REFIID riid, void** ppvObject)
{
return DX11VideoRenderer::CMediaSink::CreateInstance(riid, ppvObject);
}
STDAPI CreateDX11VideoRendererActivate(HWND hwnd, IMFActivate** ppActivate)
{
return DX11VideoRenderer::CActivate::CreateInstance(hwnd, ppActivate);
}
STDAPI DllCanUnloadNow(void)
{
return (DX11VideoRenderer::CBase::GetObjectCount() == 0 && DX11VideoRenderer::CClassFactory::IsLocked() == FALSE) ? S_OK : S_FALSE;
}
STDAPI DllGetClassObject(_In_ REFCLSID clsid, _In_ REFIID riid, _Outptr_ void** ppvObject)
{
if (clsid != CLSID_DX11VideoRenderer)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
DX11VideoRenderer::CClassFactory* pFactory = new DX11VideoRenderer::CClassFactory();
if (pFactory == NULL)
{
return E_OUTOFMEMORY;
}
pFactory->AddRef();
HRESULT hr = pFactory->QueryInterface(riid, ppvObject);
SafeRelease(pFactory);
return hr;
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
g_hModule = static_cast<HMODULE>(hModule);
break;
}
default:
{
break;
}
}
return TRUE;
}
STDAPI DllRegisterServer(void)
{
HRESULT hr = S_OK;
do
{
hr = RegisterObject(CLSID_DX11VideoRenderer, L"DX11 Video Renderer", L"Both");
if (FAILED(hr))
{
break;
}
hr = RegisterObject(CLSID_DX11VideoRendererActivate, L"DX11 Video Renderer Activate", L"Both");
if (FAILED(hr))
{
break;
}
hr = MFTRegister(
CLSID_DX11VideoRenderer, // CLSID
MFT_CATEGORY_OTHER, // Category
L"DX11 Video Renderer", // Friendly name
0, // Reserved, must be zero.
0,
NULL,
0,
NULL,
NULL
);
}
while (FALSE);
return hr;
}
STDAPI DllUnregisterServer(void)
{
HRESULT hr = UnregisterObject(CLSID_DX11VideoRenderer);
HRESULT hrTemp = MFTUnregister(CLSID_DX11VideoRenderer);
if (SUCCEEDED(hr))
{
hr = hrTemp;
}
return hr;
}

Просмотреть файл

@ -1,9 +0,0 @@
LIBRARY "DX11VideoRenderer"
EXPORTS
CreateDX11VideoRenderer
CreateDX11VideoRendererActivate
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllMain PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

Просмотреть файл

@ -1,11 +0,0 @@
#pragma once
// {83A1FDBC-AB3A-4376-A529-80E18C206534}
DEFINE_GUID(CLSID_DX11VideoRenderer, 0x83a1fdbc, 0xab3a, 0x4376, 0xa5, 0x29, 0x80, 0xe1, 0x8c, 0x20, 0x65, 0x34);
// {0743FA5C-DA9E-4760-8187-CCAC3DC15D77}
DEFINE_GUID(CLSID_DX11VideoRendererActivate, 0x743fa5c, 0xda9e, 0x4760, 0x81, 0x87, 0xcc, 0xac, 0x3d, 0xc1, 0x5d, 0x77);
// creation methods exposed by the lib
STDAPI CreateDX11VideoRenderer(REFIID riid, void** ppvObject);
STDAPI CreateDX11VideoRendererActivate(HWND hwnd, IMFActivate** ppActivate);

Просмотреть файл

@ -1,31 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31729.503
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DX11VideoRenderer", "DX11VideoRenderer.vcxproj", "{ED9D0263-0454-4C86-967B-BEEB81B8330B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|Win32.ActiveCfg = Release|Win32
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|Win32.Build.0 = Release|Win32
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|x64.ActiveCfg = Debug|x64
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Debug|x64.Build.0 = Debug|x64
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|Win32.ActiveCfg = Release|Win32
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|Win32.Build.0 = Release|Win32
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|x64.ActiveCfg = Debug|x64
{ED9D0263-0454-4C86-967B-BEEB81B8330B}.Release|x64.Build.0 = Debug|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6F11A558-643A-4061-815F-1535A55192A9}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,193 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ED9D0263-0454-4C86-967B-BEEB81B8330B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DX11VideoRenderer</RootNamespace>
<TargetRuntime>native</TargetRuntime>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>DX11VideoRenderer.def</ModuleDefinitionFile>
<AdditionalDependencies>winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>DX11VideoRenderer.def</ModuleDefinitionFile>
<AdditionalDependencies>winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>DX11VideoRenderer.def</ModuleDefinitionFile>
<AdditionalDependencies>winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>DX11VideoRenderer.def</ModuleDefinitionFile>
<AdditionalDependencies>winmm.lib;dcomp.lib;d3d11.lib;mfuuid.lib;mfplat.lib;evr.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Activate.cpp" />
<ClCompile Include="ClassFactory.cpp" />
<ClCompile Include="display.cpp" />
<ClCompile Include="DLLMain.cpp" />
<ClCompile Include="Marker.cpp" />
<ClCompile Include="MediaSink.cpp" />
<ClCompile Include="Presenter.cpp" />
<ClCompile Include="Scheduler.cpp" />
<ClCompile Include="StreamSink.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Activate.h" />
<ClInclude Include="ClassFactory.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="display.h" />
<ClInclude Include="DX11VideoRenderer.h" />
<ClInclude Include="linklist.h" />
<ClInclude Include="Marker.h" />
<ClInclude Include="MediaSink.h" />
<ClInclude Include="MFAttributesImpl.h" />
<ClInclude Include="Presenter.h" />
<ClInclude Include="Scheduler.h" />
<ClInclude Include="StreamSink.h" />
<ClInclude Include="StaticAsyncCallback.h" />
</ItemGroup>
<ItemGroup>
<None Include="DX11VideoRenderer.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

Просмотреть файл

@ -1,352 +0,0 @@
#pragma once
template <class TBase=IMFAttributes>
class CMFAttributesImpl : public TBase
{
protected:
// This version of the constructor does not initialize the
// attribute store. The derived class must call Initialize() in
// its own constructor.
CMFAttributesImpl(void) :
_pAttributes(NULL)
{
}
// This version of the constructor initializes the attribute
// store, but the derived class must pass an HRESULT parameter
// to the constructor.
CMFAttributesImpl(HRESULT& hr, UINT32 cInitialSize = 0) :
_pAttributes(NULL)
{
hr = Initialize(cInitialSize);
}
// The next version of the constructor uses a caller-provided
// implementation of IMFAttributes.
// (Sometimes you want to delegate IMFAttributes calls to some
// other object that implements IMFAttributes, rather than using
// MFCreateAttributes.)
CMFAttributesImpl(HRESULT& hr, IUnknown* pUnk) :
_pAttributes(NULL)
{
hr = Initialize(pUnk);
}
virtual ~CMFAttributesImpl(void)
{
if (_pAttributes)
{
_pAttributes->Release();
}
}
// Initializes the object by creating the standard Media Foundation attribute store.
HRESULT Initialize(UINT32 cInitialSize = 0)
{
if (_pAttributes == NULL)
{
return MFCreateAttributes(&_pAttributes, cInitialSize);
}
else
{
return S_OK;
}
}
// Initializes this object from a caller-provided attribute store.
// pUnk: Pointer to an object that exposes IMFAttributes.
HRESULT Initialize(IUnknown* pUnk)
{
if (_pAttributes)
{
_pAttributes->Release();
_pAttributes = NULL;
}
return pUnk->QueryInterface(IID_PPV_ARGS(&_pAttributes));
}
public:
// IMFAttributes methods
STDMETHODIMP GetItem(__RPC__in REFGUID guidKey, __RPC__inout_opt PROPVARIANT* pValue)
{
assert(_pAttributes);
return _pAttributes->GetItem(guidKey, pValue);
}
STDMETHODIMP GetItemType(__RPC__in REFGUID guidKey, __RPC__out MF_ATTRIBUTE_TYPE* pType)
{
assert(_pAttributes);
return _pAttributes->GetItemType(guidKey, pType);
}
STDMETHODIMP CompareItem(__RPC__in REFGUID guidKey, __RPC__in REFPROPVARIANT Value, __RPC__out BOOL* pbResult)
{
assert(_pAttributes);
return _pAttributes->CompareItem(guidKey, Value, pbResult);
}
STDMETHODIMP Compare(__RPC__in_opt IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, __RPC__out BOOL* pbResult)
{
assert(_pAttributes);
return _pAttributes->Compare(pTheirs, MatchType, pbResult);
}
STDMETHODIMP GetUINT32(__RPC__in REFGUID guidKey, __RPC__out UINT32* punValue)
{
assert(_pAttributes);
return _pAttributes->GetUINT32(guidKey, punValue);
}
STDMETHODIMP GetUINT64(__RPC__in REFGUID guidKey, __RPC__out UINT64* punValue)
{
assert(_pAttributes);
return _pAttributes->GetUINT64(guidKey, punValue);
}
STDMETHODIMP GetDouble(__RPC__in REFGUID guidKey, __RPC__out double* pfValue)
{
assert(_pAttributes);
return _pAttributes->GetDouble(guidKey, pfValue);
}
STDMETHODIMP GetGUID(__RPC__in REFGUID guidKey, __RPC__out GUID* pguidValue)
{
assert(_pAttributes);
return _pAttributes->GetGUID(guidKey, pguidValue);
}
STDMETHODIMP GetStringLength(__RPC__in REFGUID guidKey, __RPC__out UINT32* pcchLength)
{
assert(_pAttributes);
return _pAttributes->GetStringLength(guidKey, pcchLength);
}
STDMETHODIMP GetString(__RPC__in REFGUID guidKey, __RPC__out_ecount_full(cchBufSize) LPWSTR pwszValue, UINT32 cchBufSize, __RPC__inout_opt UINT32* pcchLength)
{
assert(_pAttributes);
return _pAttributes->GetString(guidKey, pwszValue, cchBufSize, pcchLength);
}
STDMETHODIMP GetAllocatedString(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(( *pcchLength + 1 ) ) LPWSTR* ppwszValue, __RPC__out UINT32* pcchLength)
{
assert(_pAttributes);
return _pAttributes->GetAllocatedString(guidKey, ppwszValue, pcchLength);
}
STDMETHODIMP GetBlobSize(__RPC__in REFGUID guidKey, __RPC__out UINT32* pcbBlobSize)
{
assert(_pAttributes);
return _pAttributes->GetBlobSize(guidKey, pcbBlobSize);
}
STDMETHODIMP GetBlob(__RPC__in REFGUID guidKey, __RPC__out_ecount_full(cbBufSize) UINT8* pBuf, UINT32 cbBufSize, __RPC__inout_opt UINT32* pcbBlobSize)
{
assert(_pAttributes);
return _pAttributes->GetBlob(guidKey, pBuf, cbBufSize, pcbBlobSize);
}
STDMETHODIMP GetAllocatedBlob(__RPC__in REFGUID guidKey, __RPC__deref_out_ecount_full_opt(*pcbSize) UINT8** ppBuf, __RPC__out UINT32* pcbSize)
{
assert(_pAttributes);
return _pAttributes->GetAllocatedBlob(guidKey, ppBuf, pcbSize);
}
STDMETHODIMP GetUnknown(__RPC__in REFGUID guidKey, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppv)
{
assert(_pAttributes);
return _pAttributes->GetUnknown(guidKey, riid, ppv);
}
STDMETHODIMP SetItem(__RPC__in REFGUID guidKey, __RPC__in REFPROPVARIANT Value)
{
assert(_pAttributes);
return _pAttributes->SetItem(guidKey, Value);
}
STDMETHODIMP DeleteItem(__RPC__in REFGUID guidKey)
{
assert(_pAttributes);
return _pAttributes->DeleteItem(guidKey);
}
STDMETHODIMP DeleteAllItems(void)
{
assert(_pAttributes);
return _pAttributes->DeleteAllItems();
}
STDMETHODIMP SetUINT32(__RPC__in REFGUID guidKey, UINT32 unValue)
{
assert(_pAttributes);
return _pAttributes->SetUINT32(guidKey, unValue);
}
STDMETHODIMP SetUINT64(__RPC__in REFGUID guidKey, UINT64 unValue)
{
assert(_pAttributes);
return _pAttributes->SetUINT64(guidKey, unValue);
}
STDMETHODIMP SetDouble(__RPC__in REFGUID guidKey, double fValue)
{
assert(_pAttributes);
return _pAttributes->SetDouble(guidKey, fValue);
}
STDMETHODIMP SetGUID(__RPC__in REFGUID guidKey, __RPC__in REFGUID guidValue)
{
assert(_pAttributes);
return _pAttributes->SetGUID(guidKey, guidValue);
}
STDMETHODIMP SetString(__RPC__in REFGUID guidKey, __RPC__in_string LPCWSTR wszValue)
{
assert(_pAttributes);
return _pAttributes->SetString(guidKey, wszValue);
}
STDMETHODIMP SetBlob(__RPC__in REFGUID guidKey, __RPC__in_ecount_full(cbBufSize) const UINT8* pBuf, UINT32 cbBufSize)
{
assert(_pAttributes);
return _pAttributes->SetBlob(guidKey, pBuf, cbBufSize);
}
STDMETHODIMP SetUnknown(__RPC__in REFGUID guidKey, __RPC__in_opt IUnknown* pUnknown)
{
assert(_pAttributes);
return _pAttributes->SetUnknown(guidKey, pUnknown);
}
STDMETHODIMP LockStore(void)
{
assert(_pAttributes);
return _pAttributes->LockStore();
}
STDMETHODIMP UnlockStore(void)
{
assert(_pAttributes);
return _pAttributes->UnlockStore();
}
STDMETHODIMP GetCount(__RPC__out UINT32* pcItems)
{
assert(_pAttributes);
return _pAttributes->GetCount(pcItems);
}
STDMETHODIMP GetItemByIndex(UINT32 unIndex, __RPC__out GUID* pguidKey, __RPC__inout_opt PROPVARIANT* pValue)
{
assert(_pAttributes);
return _pAttributes->GetItemByIndex(unIndex, pguidKey, pValue);
}
STDMETHODIMP CopyAllItems(__RPC__in_opt IMFAttributes* pDest)
{
assert(_pAttributes);
return _pAttributes->CopyAllItems(pDest);
}
// Helper functions
HRESULT SerializeToStream(DWORD dwOptions, IStream* pStm)
// dwOptions: Flags from MF_ATTRIBUTE_SERIALIZE_OPTIONS
{
assert(_pAttributes);
return MFSerializeAttributesToStream(_pAttributes, dwOptions, pStm);
}
HRESULT DeserializeFromStream(DWORD dwOptions, IStream* pStm)
{
assert(_pAttributes);
return MFDeserializeAttributesFromStream(_pAttributes, dwOptions, pStm);
}
// SerializeToBlob: Stores the attributes in a byte array.
//
// ppBuf: Receives a pointer to the byte array.
// pcbSize: Receives the size of the byte array.
//
// The caller must free the array using CoTaskMemFree.
HRESULT SerializeToBlob(UINT8** ppBuffer, UINT* pcbSize)
{
assert(_pAttributes);
if (ppBuffer == NULL)
{
return E_POINTER;
}
if (pcbSize == NULL)
{
return E_POINTER;
}
HRESULT hr = S_OK;
UINT32 cbSize = 0;
BYTE* pBuffer = NULL;
CHECK_HR(hr = MFGetAttributesAsBlobSize(_pAttributes, &cbSize));
pBuffer = (BYTE*)CoTaskMemAlloc(cbSize);
if (pBuffer == NULL)
{
CHECK_HR(hr = E_OUTOFMEMORY);
}
CHECK_HR(hr = MFGetAttributesAsBlob(_pAttributes, pBuffer, cbSize));
*ppBuffer = pBuffer;
*pcbSize = cbSize;
if (FAILED(hr))
{
*ppBuffer = NULL;
*pcbSize = 0;
CoTaskMemFree(pBuffer);
}
return hr;
}
HRESULT DeserializeFromBlob(const UINT8* pBuffer, UINT cbSize)
{
assert(_pAttributes);
return MFInitAttributesFromBlob(_pAttributes, pBuffer, cbSize);
}
HRESULT GetRatio(REFGUID guidKey, UINT32* pnNumerator, UINT32* punDenominator)
{
assert(_pAttributes);
return MFGetAttributeRatio(_pAttributes, guidKey, pnNumerator, punDenominator);
}
HRESULT SetRatio(REFGUID guidKey, UINT32 unNumerator, UINT32 unDenominator)
{
assert(_pAttributes);
return MFSetAttributeRatio(_pAttributes, guidKey, unNumerator, unDenominator);
}
// Gets an attribute whose value represents the size of something (eg a video frame).
HRESULT GetSize(REFGUID guidKey, UINT32* punWidth, UINT32* punHeight)
{
assert(_pAttributes);
return MFGetAttributeSize(_pAttributes, guidKey, punWidth, punHeight);
}
// Sets an attribute whose value represents the size of something (eg a video frame).
HRESULT SetSize(REFGUID guidKey, UINT32 unWidth, UINT32 unHeight)
{
assert(_pAttributes);
return MFSetAttributeSize (_pAttributes, guidKey, unWidth, unHeight);
}
protected:
IMFAttributes* _pAttributes;
};

Просмотреть файл

@ -1,142 +0,0 @@
#include "Marker.h"
//////////////////////
// CMarker class
// Holds information from IMFStreamSink::PlaceMarker
//
DX11VideoRenderer::CMarker::CMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType) :
m_nRefCount(1),
m_eMarkerType(eMarkerType)
{
PropVariantInit(&m_varMarkerValue);
PropVariantInit(&m_varContextValue);
}
DX11VideoRenderer::CMarker::~CMarker(void)
{
assert(m_nRefCount == 0);
PropVariantClear(&m_varMarkerValue);
PropVariantClear(&m_varContextValue);
}
/* static */
HRESULT DX11VideoRenderer::CMarker::Create(
MFSTREAMSINK_MARKER_TYPE eMarkerType,
const PROPVARIANT* pvarMarkerValue, // Can be NULL.
const PROPVARIANT* pvarContextValue, // Can be NULL.
IMarker** ppMarker
)
{
if (ppMarker == NULL)
{
return E_POINTER;
}
HRESULT hr = S_OK;
CMarker* pMarker = new CMarker(eMarkerType);
if (pMarker == NULL)
{
hr = E_OUTOFMEMORY;
}
// Copy the marker data.
if (SUCCEEDED(hr))
{
if (pvarMarkerValue)
{
hr = PropVariantCopy(&pMarker->m_varMarkerValue, pvarMarkerValue);
}
}
if (SUCCEEDED(hr))
{
if (pvarContextValue)
{
hr = PropVariantCopy(&pMarker->m_varContextValue, pvarContextValue);
}
}
if (SUCCEEDED(hr))
{
*ppMarker = pMarker;
(*ppMarker)->AddRef();
}
SafeRelease(pMarker);
return hr;
}
// IUnknown methods.
ULONG DX11VideoRenderer::CMarker::AddRef(void)
{
return InterlockedIncrement(&m_nRefCount);
}
ULONG DX11VideoRenderer::CMarker::Release(void)
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
// For thread safety, return a temporary variable.
return uCount;
}
HRESULT DX11VideoRenderer::CMarker::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
}
else if (iid == __uuidof(IMarker))
{
*ppv = static_cast<IMarker*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// IMarker methods
HRESULT DX11VideoRenderer::CMarker::GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType)
{
if (pType == NULL)
{
return E_POINTER;
}
*pType = m_eMarkerType;
return S_OK;
}
HRESULT DX11VideoRenderer::CMarker::GetMarkerValue(PROPVARIANT* pvar)
{
if (pvar == NULL)
{
return E_POINTER;
}
return PropVariantCopy(pvar, &m_varMarkerValue);
}
HRESULT DX11VideoRenderer::CMarker::GetContext(PROPVARIANT* pvar)
{
if (pvar == NULL)
{
return E_POINTER;
}
return PropVariantCopy(pvar, &m_varContextValue);
}

Просмотреть файл

@ -1,62 +0,0 @@
#pragma once
#include "Common.h"
#include "Scheduler.h"
#include "display.h"
namespace DX11VideoRenderer
{
// IMarker:
// Custom interface for handling IMFStreamSink::PlaceMarker calls asynchronously.
// A marker consists of a marker type, marker data, and context data.
// By defining this interface, we can store the marker data inside an IUnknown object
// and keep that object on the same queue that holds the media samples. This is
// useful because samples and markers must be serialized. That is, we cannot respond
// to a marker until we have processed all of the samples that came before it.
// Note that IMarker is not a standard Media Foundation interface.
MIDL_INTERFACE("3AC82233-933C-43a9-AF3D-ADC94EABF406")
IMarker : public IUnknown
{
virtual STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType) = 0;
virtual STDMETHODIMP GetMarkerValue(PROPVARIANT* pvar) = 0;
virtual STDMETHODIMP GetContext(PROPVARIANT* pvar) = 0;
};
// Holds marker information for IMFStreamSink::PlaceMarker
class CMarker : public IMarker, private CBase
{
public:
static HRESULT Create(
MFSTREAMSINK_MARKER_TYPE eMarkerType,
const PROPVARIANT* pvarMarkerValue,
const PROPVARIANT* pvarContextValue,
IMarker** ppMarker
);
// IUnknown methods.
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
STDMETHODIMP GetMarkerType(MFSTREAMSINK_MARKER_TYPE* pType);
STDMETHODIMP GetMarkerValue(PROPVARIANT* pvar);
STDMETHODIMP GetContext(PROPVARIANT* pvar);
protected:
MFSTREAMSINK_MARKER_TYPE m_eMarkerType;
PROPVARIANT m_varMarkerValue;
PROPVARIANT m_varContextValue;
private:
CMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType);
virtual ~CMarker(void);
long m_nRefCount;
};
}

Просмотреть файл

@ -1,791 +0,0 @@
#include "MediaSink.h"
/////////////////////////////////////////////////////////////////////////////////////////////
//
// CMediaSink class. - Implements the media sink.
//
// Notes:
// - Most public methods calls CheckShutdown. This method fails if the sink was shut down.
//
/////////////////////////////////////////////////////////////////////////////////////////////
DX11VideoRenderer::CCritSec DX11VideoRenderer::CMediaSink::s_csStreamSinkAndScheduler;
//-------------------------------------------------------------------
// Name: CreateInstance
// Description: Creates an instance of the DX11 Video Renderer sink object.
//-------------------------------------------------------------------
/* static */ HRESULT DX11VideoRenderer::CMediaSink::CreateInstance(_In_ REFIID iid, _COM_Outptr_ void** ppSink)
{
if (ppSink == NULL)
{
return E_POINTER;
}
*ppSink = NULL;
HRESULT hr = S_OK;
CMediaSink* pSink = new CMediaSink(); // Created with ref count = 1.
if (pSink == NULL)
{
hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
hr = pSink->Initialize();
}
if (SUCCEEDED(hr))
{
hr = pSink->QueryInterface(iid, ppSink);
}
SafeRelease(pSink);
return hr;
}
// IUnknown methods
ULONG DX11VideoRenderer::CMediaSink::AddRef(void)
{
return InterlockedIncrement(&m_nRefCount);
}
HRESULT DX11VideoRenderer::CMediaSink::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(static_cast<IMFMediaSink*>(this));
}
else if (iid == __uuidof(IMFMediaSink))
{
*ppv = static_cast<IMFMediaSink*>(this);
}
else if (iid == __uuidof(IMFClockStateSink))
{
*ppv = static_cast<IMFClockStateSink*>(this);
}
else if (iid == __uuidof(IMFGetService))
{
*ppv = static_cast<IMFGetService*>(this);
}
else if (iid == IID_IMFRateSupport)
{
*ppv = static_cast<IMFRateSupport*>(this);
}
else if (iid == IID_IMFMediaSinkPreroll)
{
*ppv = static_cast<IMFMediaSinkPreroll*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG DX11VideoRenderer::CMediaSink::Release(void)
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
// For thread safety, return a temporary variable.
return uCount;
}
/// IMFMediaSink methods.
//-------------------------------------------------------------------
// Name: AddStreamSink
// Description: Adds a new stream to the sink.
//
// Note: This sink has a fixed number of streams, so this method
// always returns MF_E_STREAMSINKS_FIXED.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::AddStreamSink(DWORD dwStreamSinkIdentifier, __RPC__in_opt IMFMediaType* pMediaType, __RPC__deref_out_opt IMFStreamSink** ppStreamSink)
{
return MF_E_STREAMSINKS_FIXED;
}
//-------------------------------------------------------------------
// Name: GetCharacteristics
// Description: Returns the characteristics flags.
//
// Note: This sink has a fixed number of streams.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetCharacteristics(__RPC__out DWORD* pdwCharacteristics)
{
CAutoLock lock(&m_csMediaSink);
if (pdwCharacteristics == NULL)
{
return E_POINTER;
}
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
*pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL;
}
return hr;
}
//-------------------------------------------------------------------
// Name: GetPresentationClock
// Description: Returns a pointer to the presentation clock.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetPresentationClock(__RPC__deref_out_opt IMFPresentationClock** ppPresentationClock)
{
CAutoLock lock(&m_csMediaSink);
if (ppPresentationClock == NULL)
{
return E_POINTER;
}
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
if (m_pClock == NULL)
{
hr = MF_E_NO_CLOCK; // There is no presentation clock.
}
else
{
// Return the pointer to the caller.
*ppPresentationClock = m_pClock;
(*ppPresentationClock)->AddRef();
}
}
return hr;
}
//-------------------------------------------------------------------
// Name: GetStreamSinkById
// Description: Retrieves a stream by ID.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkById(DWORD dwStreamSinkIdentifier, __RPC__deref_out_opt IMFStreamSink** ppStreamSink)
{
CAutoLock lock(&m_csMediaSink);
if (ppStreamSink == NULL)
{
return E_POINTER;
}
// Fixed stream ID.
if (dwStreamSinkIdentifier != STREAM_ID)
{
return MF_E_INVALIDSTREAMNUMBER;
}
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
*ppStreamSink = m_pStream;
(*ppStreamSink)->AddRef();
}
return hr;
}
//-------------------------------------------------------------------
// Name: GetStreamSinkByIndex
// Description: Retrieves a stream by index.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkByIndex(DWORD dwIndex, __RPC__deref_out_opt IMFStreamSink** ppStreamSink)
{
CAutoLock lock(&m_csMediaSink);
if (ppStreamSink == NULL)
{
return E_POINTER;
}
// Fixed stream: Index 0.
if (dwIndex > 0)
{
return MF_E_INVALIDINDEX;
}
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
*ppStreamSink = m_pStream;
(*ppStreamSink)->AddRef();
}
return hr;
}
//-------------------------------------------------------------------
// Name: GetStreamSinkCount
// Description: Returns the number of streams.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetStreamSinkCount(__RPC__out DWORD* pcStreamSinkCount)
{
CAutoLock lock(&m_csMediaSink);
if (pcStreamSinkCount == NULL)
{
return E_POINTER;
}
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
*pcStreamSinkCount = 1; // Fixed number of streams.
}
return hr;
}
//-------------------------------------------------------------------
// Name: RemoveStreamSink
// Description: Removes a stream from the sink.
//
// Note: This sink has a fixed number of streams, so this method
// always returns MF_E_STREAMSINKS_FIXED.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::RemoveStreamSink(DWORD dwStreamSinkIdentifier)
{
return MF_E_STREAMSINKS_FIXED;
}
//-------------------------------------------------------------------
// Name: SetPresentationClock
// Description: Sets the presentation clock.
//
// pPresentationClock: Pointer to the clock. Can be NULL.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::SetPresentationClock(__RPC__in_opt IMFPresentationClock* pPresentationClock)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = CheckShutdown();
// If we already have a clock, remove ourselves from that clock's
// state notifications.
if (SUCCEEDED(hr))
{
if (m_pClock)
{
hr = m_pClock->RemoveClockStateSink(this);
}
}
// Register ourselves to get state notifications from the new clock.
if (SUCCEEDED(hr))
{
if (pPresentationClock)
{
hr = pPresentationClock->AddClockStateSink(this);
}
}
if (SUCCEEDED(hr))
{
// Release the pointer to the old clock.
// Store the pointer to the new clock.
SafeRelease(m_pClock);
m_pClock = pPresentationClock;
if (m_pClock)
{
m_pClock->AddRef();
}
}
return hr;
}
//-------------------------------------------------------------------
// Name: Shutdown
// Description: Releases resources held by the media sink.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::Shutdown(void)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = MF_E_SHUTDOWN;
m_IsShutdown = TRUE;
if (m_pStream != NULL)
{
m_pStream->Shutdown();
}
if (m_pPresenter != NULL)
{
m_pPresenter->Shutdown();
}
SafeRelease(m_pClock);
SafeRelease(m_pStream);
SafeRelease(m_pPresenter);
if (m_pScheduler != NULL)
{
hr = m_pScheduler->StopScheduler();
}
SafeRelease(m_pScheduler);
return hr;
}
//-------------------------------------------------------------------
// Name: OnClockPause
// Description: Called when the presentation clock paused.
//
// Note: For an archive sink, the paused state is equivalent to the
// running (started) state. We still accept data and archive it.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::OnClockPause(
/* [in] */ MFTIME hnsSystemTime)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
hr = m_pStream->Pause();
}
return hr;
}
//-------------------------------------------------------------------
// Name: OnClockRestart
// Description: Called when the presentation clock restarts.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::OnClockRestart(
/* [in] */ MFTIME hnsSystemTime)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
hr = m_pStream->Restart();
}
return hr;
}
//-------------------------------------------------------------------
// Name: OnClockSetRate
// Description: Called when the presentation clock's rate changes.
//
// Note: For a rateless sink, the clock rate is not important.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::OnClockSetRate(
/* [in] */ MFTIME hnsSystemTime,
/* [in] */ float flRate)
{
if (m_pScheduler != NULL)
{
// Tell the scheduler about the new rate.
m_pScheduler->SetClockRate(flRate);
}
return S_OK;
}
//-------------------------------------------------------------------
// Name: OnClockStart
// Description: Called when the presentation clock starts.
//
// hnsSystemTime: System time when the clock started.
// llClockStartOffset: Starting presentatation time.
//
// Note: For an archive sink, we don't care about the system time.
// But we need to cache the value of llClockStartOffset. This
// gives us the earliest time stamp that we archive. If any
// input samples have an earlier time stamp, we discard them.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::OnClockStart(
/* [in] */ MFTIME hnsSystemTime,
/* [in] */ LONGLONG llClockStartOffset)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = CheckShutdown();
if (FAILED(hr))
{
return hr;
}
// Check if the clock is already active (not stopped).
// And if the clock position changes while the clock is active, it
// is a seek request. We need to flush all pending samples.
if (m_pStream->IsActive() && llClockStartOffset != PRESENTATION_CURRENT_POSITION)
{
// This call blocks until the scheduler threads discards all scheduled samples.
hr = m_pStream->Flush();
}
else
{
if (m_pScheduler != NULL)
{
// Start the scheduler thread.
hr = m_pScheduler->StartScheduler(m_pClock);
}
}
if (SUCCEEDED(hr))
{
hr = m_pStream->Start(llClockStartOffset);
}
return hr;
}
//-------------------------------------------------------------------
// Name: OnClockStop
// Description: Called when the presentation clock stops.
//
// Note: After this method is called, we stop accepting new data.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::OnClockStop(
/* [in] */ MFTIME hnsSystemTime)
{
CAutoLock lock(&m_csMediaSink);
HRESULT hr = CheckShutdown();
if (SUCCEEDED(hr))
{
hr = m_pStream->Stop();
}
if (SUCCEEDED(hr))
{
if (m_pScheduler != NULL)
{
// Stop the scheduler thread.
hr = m_pScheduler->StopScheduler();
}
}
return hr;
}
//-------------------------------------------------------------------------
// Name: GetService
// Description: IMFGetService
//-------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject)
{
HRESULT hr = S_OK;
if (guidService == MF_RATE_CONTROL_SERVICE)
{
hr = QueryInterface(riid, ppvObject);
}
else if (guidService == MR_VIDEO_RENDER_SERVICE)
{
hr = m_pPresenter->QueryInterface(riid, ppvObject);
}
else if (guidService == MR_VIDEO_ACCELERATION_SERVICE)
{
hr = m_pPresenter->GetService(guidService, riid, ppvObject);
}
else
{
hr = MF_E_UNSUPPORTED_SERVICE;
}
return hr;
}
STDMETHODIMP DX11VideoRenderer::CMediaSink::GetFastestRate(
MFRATE_DIRECTION eDirection,
BOOL fThin,
_Out_ float *pflRate
)
{
HRESULT hr = S_OK;
CAutoLock lock(&m_csMediaSink);
do
{
hr = CheckShutdown();
if (FAILED(hr))
{
break;
}
if (NULL == pflRate)
{
hr = E_POINTER;
break;
}
float rate;
hr = m_pStream->GetMaxRate(fThin, &rate);
if (FAILED(hr))
{
break;
}
if (MFRATE_FORWARD == eDirection)
{
*pflRate = rate;
}
else
{
*pflRate = -rate;
}
}
while (FALSE);
return hr;
}
//-------------------------------------------------------------------------
// Name: GetSlowestRate
// Description: IMFRateSupport
//-------------------------------------------------------------------------
STDMETHODIMP DX11VideoRenderer::CMediaSink::GetSlowestRate(
MFRATE_DIRECTION eDirection,
BOOL fThin,
_Out_ float* pflRate
)
{
HRESULT hr = S_OK;
CAutoLock lock(&m_csMediaSink);
do
{
hr = CheckShutdown();
if (FAILED(hr))
{
break;
}
if (NULL == pflRate)
{
hr = E_POINTER;
break;
}
if (SUCCEEDED(hr))
{
//
// We go as slow as you want!
//
*pflRate = 0;
}
}
while (FALSE);
return hr;
}
STDMETHODIMP DX11VideoRenderer::CMediaSink::IsRateSupported(BOOL fThin, float flRate, __RPC__inout_opt float* pflNearestSupportedRate)
{
HRESULT hr = S_OK;
float flNearestSupportedRate = flRate;
CAutoLock lock(&m_csMediaSink);
do
{
hr = CheckShutdown();
if (FAILED(hr))
{
break;
}
//
// Only support rates up to the refresh rate of the monitor.
// This check makes sense only if we're going to be receiving
// all frames
//
if ( !fThin )
{
float rate;
hr = m_pStream->GetMaxRate(fThin, &rate);
if (FAILED(hr))
{
break;
}
if ( (flRate > 0 && flRate > (float)rate) ||
(flRate < 0 && flRate < -(float)rate) )
{
hr = MF_E_UNSUPPORTED_RATE;
flNearestSupportedRate = ( flRate >= 0.0f ) ? rate : -rate;
break;
}
}
}
while (FALSE);
if ( NULL != pflNearestSupportedRate )
{
*pflNearestSupportedRate = flNearestSupportedRate;
}
return hr;
}
STDMETHODIMP DX11VideoRenderer::CMediaSink::NotifyPreroll(MFTIME hnsUpcomingStartTime)
{
HRESULT hr = S_OK;
CAutoLock lock(&m_csMediaSink);
hr = CheckShutdown();
if (SUCCEEDED(hr))
{
hr = m_pStream->Preroll();
}
return hr;
}
/// Private methods
//-------------------------------------------------------------------
// CMediaSink constructor.
//-------------------------------------------------------------------
DX11VideoRenderer::CMediaSink::CMediaSink(void) :
STREAM_ID(1),
m_nRefCount(1),
m_csMediaSink(), // default ctor
m_IsShutdown(FALSE),
m_pStream(NULL),
m_pClock(NULL),
m_pScheduler(NULL),
m_pPresenter(NULL)
{
}
//-------------------------------------------------------------------
// CMediaSink destructor.
//-------------------------------------------------------------------
DX11VideoRenderer::CMediaSink::~CMediaSink(void)
{
}
HRESULT DX11VideoRenderer::CMediaSink::CheckShutdown(void) const
{
if (m_IsShutdown)
{
return MF_E_SHUTDOWN;
}
else
{
return S_OK;
}
}
//-------------------------------------------------------------------
// Name: Initialize
// Description: Initializes the media sink.
//
// Note: This method is called once when the media sink is first
// initialized.
//-------------------------------------------------------------------
HRESULT DX11VideoRenderer::CMediaSink::Initialize(void)
{
HRESULT hr = S_OK;
IMFMediaSink* pSink = NULL;
do
{
m_pScheduler = new CScheduler(s_csStreamSinkAndScheduler);
if (m_pScheduler == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
m_pStream = new CStreamSink(STREAM_ID, s_csStreamSinkAndScheduler, m_pScheduler);
if (m_pStream == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
m_pPresenter = new CPresenter(); // Created with ref count = 1.
if (m_pPresenter == NULL)
{
hr = E_OUTOFMEMORY;
break;
}
hr = QueryInterface(IID_PPV_ARGS(&pSink));
if (FAILED(hr))
{
break;
}
hr = m_pStream->Initialize(pSink, m_pPresenter);
if (FAILED(hr))
{
break;
}
m_pScheduler->SetCallback(static_cast<SchedulerCallback*>(m_pStream));
}
while (FALSE);
if (FAILED(hr))
{
Shutdown();
}
SafeRelease(pSink);
return hr;
}

Просмотреть файл

@ -1,76 +0,0 @@
#pragma once
#include "Common.h"
#include "Presenter.h"
#include "Scheduler.h"
#include "StreamSink.h"
namespace DX11VideoRenderer
{
class CMediaSink :
public IMFMediaSink,
public IMFClockStateSink,
public IMFGetService,
public IMFRateSupport,
public IMFMediaSinkPreroll,
private CBase
{
public:
// Static method to create the object.
static HRESULT CreateInstance(_In_ REFIID iid, _COM_Outptr_ void** ppSink);
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
STDMETHODIMP_(ULONG) Release(void);
// IMFMediaSink methods
STDMETHODIMP AddStreamSink(DWORD dwStreamSinkIdentifier, __RPC__in_opt IMFMediaType* pMediaType, __RPC__deref_out_opt IMFStreamSink** ppStreamSink);
STDMETHODIMP GetCharacteristics(__RPC__out DWORD* pdwCharacteristics);
STDMETHODIMP GetPresentationClock(__RPC__deref_out_opt IMFPresentationClock** ppPresentationClock);
STDMETHODIMP GetStreamSinkById(DWORD dwIdentifier, __RPC__deref_out_opt IMFStreamSink** ppStreamSink);
STDMETHODIMP GetStreamSinkByIndex(DWORD dwIndex, __RPC__deref_out_opt IMFStreamSink** ppStreamSink);
STDMETHODIMP GetStreamSinkCount(__RPC__out DWORD* pcStreamSinkCount);
STDMETHODIMP RemoveStreamSink(DWORD dwStreamSinkIdentifier);
STDMETHODIMP SetPresentationClock(__RPC__in_opt IMFPresentationClock* pPresentationClock);
STDMETHODIMP Shutdown(void);
// IMFClockStateSink methods
STDMETHODIMP OnClockPause(MFTIME hnsSystemTime);
STDMETHODIMP OnClockRestart(MFTIME hnsSystemTime);
STDMETHODIMP OnClockSetRate(MFTIME hnsSystemTime, float flRate);
STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
STDMETHODIMP OnClockStop(MFTIME hnsSystemTime);
// IMFGetService
STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject);
// IMFRateSupport
STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, BOOL fThin, _Out_ float* pflRate);
STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, BOOL fThin, _Out_ float* pflRate);
STDMETHODIMP IsRateSupported(BOOL fThin, float flRate, __RPC__inout_opt float* pflNearestSupportedRate);
// IMFMediaSinkPreroll
STDMETHODIMP NotifyPreroll(MFTIME hnsUpcomingStartTime);
private:
static CCritSec s_csStreamSinkAndScheduler; // critical section for thread safety, used for CStreamSink and CScheduler
CMediaSink(void);
virtual ~CMediaSink(void);
HRESULT CheckShutdown(void) const;
HRESULT Initialize(void);
const DWORD STREAM_ID; // The stream ID of the one stream on the sink.
long m_nRefCount; // reference count
CCritSec m_csMediaSink; // critical section for thread safety, used for CMediaSink
BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called.
CStreamSink* m_pStream; // Byte stream
IMFPresentationClock* m_pClock; // Presentation clock.
CScheduler* m_pScheduler; // Manages scheduling of samples.
CPresenter* m_pPresenter;
};
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,704 +0,0 @@
#pragma once
#include "Common.h"
#include "display.h"
namespace DX11VideoRenderer
{
class CPresenter :
public IMFVideoDisplayControl,
public IMFGetService,
private CBase
{
public:
CPresenter(void);
virtual ~CPresenter(void);
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
STDMETHODIMP_(ULONG) Release(void);
// IMFVideoDisplayControl
STDMETHODIMP GetAspectRatioMode(__RPC__out DWORD* pdwAspectRatioMode) { return E_NOTIMPL; }
STDMETHODIMP GetBorderColor(__RPC__out COLORREF* pClr) { return E_NOTIMPL; }
STDMETHODIMP GetCurrentImage(__RPC__inout BITMAPINFOHEADER* pBih, __RPC__deref_out_ecount_full_opt(*pcbDib) BYTE** pDib, __RPC__out DWORD* pcbDib, __RPC__inout_opt LONGLONG* pTimestamp) { return E_NOTIMPL; }
STDMETHODIMP GetFullscreen(__RPC__out BOOL* pfFullscreen);
STDMETHODIMP GetIdealVideoSize(__RPC__inout_opt SIZE* pszMin, __RPC__inout_opt SIZE* pszMax) { return E_NOTIMPL; }
STDMETHODIMP GetNativeVideoSize(__RPC__inout_opt SIZE* pszVideo, __RPC__inout_opt SIZE* pszARVideo) { return E_NOTIMPL; }
STDMETHODIMP GetRenderingPrefs(__RPC__out DWORD* pdwRenderFlags) { return E_NOTIMPL; }
STDMETHODIMP GetVideoPosition(__RPC__out MFVideoNormalizedRect* pnrcSource, __RPC__out LPRECT prcDest) { return E_NOTIMPL; }
STDMETHODIMP GetVideoWindow(__RPC__deref_out_opt HWND* phwndVideo) { return E_NOTIMPL; }
STDMETHODIMP RepaintVideo(void) { return E_NOTIMPL; }
STDMETHODIMP SetAspectRatioMode(DWORD dwAspectRatioMode) { return E_NOTIMPL; }
STDMETHODIMP SetBorderColor(COLORREF Clr) { return E_NOTIMPL; }
STDMETHODIMP SetFullscreen(BOOL fFullscreen);
STDMETHODIMP SetRenderingPrefs(DWORD dwRenderingPrefs) { return E_NOTIMPL; }
STDMETHODIMP SetVideoPosition(__RPC__in_opt const MFVideoNormalizedRect* pnrcSource, __RPC__in_opt const LPRECT prcDest) { return E_NOTIMPL; }
STDMETHODIMP SetVideoWindow(__RPC__in HWND hwndVideo);
// IMFGetService
STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject);
BOOL CanProcessNextSample(void);
HRESULT Flush(void);
HRESULT GetMonitorRefreshRate(DWORD* pdwMonitorRefreshRate);
HRESULT IsMediaTypeSupported(IMFMediaType* pMediaType, DXGI_FORMAT dxgiFormat);
HRESULT PresentFrame(void);
HRESULT ProcessFrame(IMFMediaType* pCurrentType, IMFSample* pSample, UINT32* punInterlaceMode, BOOL* pbDeviceChanged, BOOL* pbProcessAgain, IMFSample** ppOutputSample = NULL);
HRESULT SetCurrentMediaType(IMFMediaType* pMediaType);
HRESULT Shutdown(void);
private:
void AspectRatioCorrectSize(
LPSIZE lpSizeImage, // size to be aspect ratio corrected
const SIZE& sizeAr, // aspect ratio of image
const SIZE& sizeOrig, // original image size
BOOL ScaleXorY // axis to correct in
);
void CheckDecodeSwitchRegKey(void);
HRESULT CheckDeviceState(BOOL* pbDeviceChanged);
BOOL CheckEmptyRect(RECT* pDst);
HRESULT CheckShutdown(void) const;
HRESULT CreateDCompDeviceAndVisual(void);
HRESULT CreateDXGIManagerAndDevice(D3D_DRIVER_TYPE DriverType=D3D_DRIVER_TYPE_HARDWARE);
HRESULT CreateXVP(void);
HRESULT FindBOBProcessorIndex(DWORD* pIndex);
HRESULT GetVideoDisplayArea(IMFMediaType* pType, MFVideoArea* pArea);
void LetterBoxDstRect(
LPRECT lprcLBDst, // output letterboxed rectangle
const RECT& rcSrc, // input source rectangle
const RECT& rcDst // input destination rectangle
);
void PixelAspectToPictureAspect(
int Width,
int Height,
int PixelAspectX,
int PixelAspectY,
int* pPictureAspectX,
int* pPictureAspectY
);
HRESULT ProcessFrameUsingD3D11( ID3D11Texture2D* pLeftTexture2D, ID3D11Texture2D* pRightTexture2D, UINT dwLeftViewIndex, UINT dwRightViewIndex, RECT rcDest, UINT32 unInterlaceMode, IMFSample** ppVideoOutFrame );
HRESULT ProcessFrameUsingXVP( IMFMediaType* pCurrentType, IMFSample* pVideoFrame, ID3D11Texture2D* pTexture2D, RECT rcDest, IMFSample** ppVideoOutFrame, BOOL* pbInputFrameUsed );
void ReduceToLowestTerms(
int NumeratorIn,
int DenominatorIn,
int* pNumeratorOut,
int* pDenominatorOut
);
HRESULT SetMonitor(UINT adapterID);
void SetVideoContextParameters(ID3D11VideoContext* pVideoContext, const RECT* pSRect, const RECT* pTRect, UINT32 unInterlaceMode);
HRESULT SetVideoMonitor(HWND hwndVideo);
HRESULT SetXVPOutputMediaType(IMFMediaType* pType, DXGI_FORMAT vpOutputFormat);
_Post_satisfies_(this->m_pSwapChain1 != NULL)
HRESULT UpdateDXGISwapChain(void);
void UpdateRectangles(RECT* pDst, RECT* pSrc);
long m_nRefCount; // reference count
CCritSec m_critSec; // critical section for thread safety
BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called.
IDXGIFactory2* m_pDXGIFactory2;
ID3D11Device* m_pD3D11Device;
ID3D11DeviceContext* m_pD3DImmediateContext;
IMFDXGIDeviceManager* m_pDXGIManager;
IDXGIOutput1* m_pDXGIOutput1;
IMFVideoSampleAllocatorEx* m_pSampleAllocatorEx;
IDCompositionDevice* m_pDCompDevice;
IDCompositionTarget* m_pHwndTarget;
IDCompositionVisual* m_pRootVisual;
BOOL m_bSoftwareDXVADeviceInUse;
HWND m_hwndVideo;
CMonitorArray* m_pMonitors;
CAMDDrawMonitorInfo* m_lpCurrMon;
UINT m_DeviceResetToken;
UINT m_ConnectionGUID;
UINT m_DXSWSwitch;
UINT m_useXVP;
UINT m_useDCompVisual;
UINT m_useDebugLayer;
ID3D11VideoDevice* m_pDX11VideoDevice;
ID3D11VideoProcessorEnumerator* m_pVideoProcessorEnum;
ID3D11VideoProcessor* m_pVideoProcessor;
IDXGISwapChain1* m_pSwapChain1;
BOOL m_bDeviceChanged;
BOOL m_bResize;
BOOL m_b3DVideo;
BOOL m_bStereoEnabled;
MFVideo3DFormat m_vp3DOutput;
BOOL m_bFullScreenState;
BOOL m_bCanProcessNextSample;
RECT m_displayRect;
UINT32 m_imageWidthInPixels;
UINT32 m_imageHeightInPixels;
UINT32 m_uiRealDisplayWidth;
UINT32 m_uiRealDisplayHeight;
RECT m_rcSrcApp;
RECT m_rcDstApp;
IMFTransform* m_pXVP;
IMFVideoProcessorControl* m_pXVPControl;
};
/////////////////////////////////////////////////////////////////////////////////////////////
// Wrapper class for D3D11 Device and D3D11 Video device used for DXVA to Software decode switch
class CPrivate_ID3D11VideoDevice : public ID3D11VideoDevice
{
private:
ID3D11VideoDevice* m_pReal;
ULONG m_cRef;
public:
CPrivate_ID3D11VideoDevice(ID3D11VideoDevice* pReal) :
m_pReal(pReal),
m_cRef(0)
{
}
virtual ~CPrivate_ID3D11VideoDevice(void)
{
}
STDMETHODIMP QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject)
{
if (__uuidof(ID3D11VideoDevice) == riid)
{
this->AddRef();
*ppvObject = this;
return S_OK;
}
else
{
return m_pReal->QueryInterface(riid,ppvObject);
}
}
STDMETHODIMP_(ULONG) AddRef(void)
{
InterlockedIncrement(&m_cRef);
return m_pReal->AddRef();
}
STDMETHODIMP_(ULONG) Release(void)
{
ULONG ulVal = m_pReal->Release();
if (0 == InterlockedDecrement(&m_cRef))
{
}
return ulVal;
}
STDMETHODIMP CreateVideoDecoder(
_In_ const D3D11_VIDEO_DECODER_DESC* pVideoDesc,
_In_ const D3D11_VIDEO_DECODER_CONFIG* pConfig,
_Out_ ID3D11VideoDecoder** ppDecoder)
{
return E_FAIL;
}
STDMETHODIMP CreateVideoProcessor(
_In_ ID3D11VideoProcessorEnumerator* pEnum,
_In_ UINT RateConversionIndex,
_Out_ ID3D11VideoProcessor** ppVideoProcessor)
{
return m_pReal->CreateVideoProcessor(pEnum,RateConversionIndex,ppVideoProcessor);
}
STDMETHODIMP CreateAuthenticatedChannel(
_In_ D3D11_AUTHENTICATED_CHANNEL_TYPE ChannelType,
_Out_ ID3D11AuthenticatedChannel** ppAuthenticatedChannel)
{
return m_pReal->CreateAuthenticatedChannel(ChannelType,ppAuthenticatedChannel);
}
STDMETHODIMP CreateCryptoSession(
_In_ const GUID* pCryptoType,
_In_opt_ const GUID* pDecoderProfile,
_In_ const GUID* pKeyExchangeType,
_Outptr_ ID3D11CryptoSession** ppCryptoSession)
{
return m_pReal->CreateCryptoSession(pCryptoType,pDecoderProfile,pKeyExchangeType,ppCryptoSession);
}
STDMETHODIMP CreateVideoDecoderOutputView(
_In_ ID3D11Resource* pResource,
_In_ const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC* pDesc,
_Out_opt_ ID3D11VideoDecoderOutputView** ppVDOVView)
{
return m_pReal->CreateVideoDecoderOutputView(pResource,pDesc,ppVDOVView);
}
STDMETHODIMP CreateVideoProcessorInputView(
_In_ ID3D11Resource* pResource,
_In_ ID3D11VideoProcessorEnumerator* pEnum,
_In_ const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC* pDesc,
_Out_opt_ ID3D11VideoProcessorInputView** ppVPIView)
{
return m_pReal->CreateVideoProcessorInputView(pResource,pEnum,pDesc,ppVPIView);
}
STDMETHODIMP CreateVideoProcessorOutputView(
_In_ ID3D11Resource* pResource,
_In_ ID3D11VideoProcessorEnumerator* pEnum,
_In_ const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC* pDesc,
_Out_opt_ ID3D11VideoProcessorOutputView** ppVPOView)
{
return m_pReal->CreateVideoProcessorOutputView(pResource,pEnum,pDesc,ppVPOView);
}
STDMETHODIMP CreateVideoProcessorEnumerator(
_In_ const D3D11_VIDEO_PROCESSOR_CONTENT_DESC* pDesc,
_Out_ ID3D11VideoProcessorEnumerator** ppEnum)
{
return m_pReal->CreateVideoProcessorEnumerator(pDesc,ppEnum);
}
STDMETHODIMP_(UINT) GetVideoDecoderProfileCount(void)
{
return m_pReal->GetVideoDecoderProfileCount();
}
STDMETHODIMP GetVideoDecoderProfile(
_In_ UINT Index,
_Out_ GUID* pDecoderProfile)
{
return m_pReal->GetVideoDecoderProfile(Index,pDecoderProfile);
}
STDMETHODIMP CheckVideoDecoderFormat(
_In_ const GUID* pDecoderProfile,
_In_ DXGI_FORMAT Format,
_Out_ BOOL* pSupported)
{
return m_pReal->CheckVideoDecoderFormat(pDecoderProfile,Format,pSupported);
}
STDMETHODIMP GetVideoDecoderConfigCount(
_In_ const D3D11_VIDEO_DECODER_DESC* pDesc,
_Out_ UINT* pCount)
{
return m_pReal->GetVideoDecoderConfigCount(pDesc,pCount);
}
STDMETHODIMP GetVideoDecoderConfig(
_In_ const D3D11_VIDEO_DECODER_DESC* pDesc,
_In_ UINT Index,
_Out_ D3D11_VIDEO_DECODER_CONFIG* pConfig)
{
return m_pReal->GetVideoDecoderConfig(pDesc,Index,pConfig);
}
STDMETHODIMP GetContentProtectionCaps(
_In_opt_ const GUID* pCryptoType,
_In_opt_ const GUID* pDecoderProfile,
_Out_ D3D11_VIDEO_CONTENT_PROTECTION_CAPS* pCaps)
{
return m_pReal->GetContentProtectionCaps(pCryptoType,pDecoderProfile,pCaps);
}
STDMETHODIMP CheckCryptoKeyExchange(
_In_ const GUID* pCryptoType,
_In_opt_ const GUID* pDecoderProfile,
_In_ UINT Index,
_Out_ GUID* pKeyExchangeType)
{
return m_pReal->CheckCryptoKeyExchange(pCryptoType,pDecoderProfile,Index,pKeyExchangeType);
}
STDMETHODIMP SetPrivateData(
_In_ REFGUID guid,
_In_ UINT DataSize,
_In_reads_bytes_opt_(DataSize) const void* pData)
{
return m_pReal->SetPrivateData(guid,DataSize,pData);
}
STDMETHODIMP SetPrivateDataInterface(
_In_ REFGUID guid,
_In_opt_ const IUnknown* pData)
{
return m_pReal->SetPrivateDataInterface(guid,pData);
}
};
class CPrivate_ID3D11Device : public ID3D11Device
{
private:
ID3D11Device* m_pReal;
ULONG m_cRef;
CPrivate_ID3D11VideoDevice* m_pVideoDevice;
public:
CPrivate_ID3D11Device(ID3D11Device* pReal) :
m_pReal(pReal),
m_cRef(1),
m_pVideoDevice(NULL)
{
ID3D11VideoDevice* pDevice;
m_pReal->QueryInterface(__uuidof(ID3D11VideoDevice),(void**)&pDevice);
m_pVideoDevice = new CPrivate_ID3D11VideoDevice(pDevice);
if (pDevice != NULL)
{
pDevice->Release();
}
}
virtual ~CPrivate_ID3D11Device(void)
{
SafeDelete(m_pVideoDevice);
}
STDMETHODIMP QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject)
{
if (__uuidof(ID3D11VideoDevice) == riid)
{
m_pVideoDevice->AddRef();
*ppvObject = m_pVideoDevice;
return S_OK;
}
else if (__uuidof(ID3D11Device) == riid)
{
this->AddRef();
*ppvObject = this;
return S_OK;
}
else
{
return m_pReal->QueryInterface(riid,ppvObject);
}
}
STDMETHODIMP_(ULONG) AddRef(void)
{
InterlockedIncrement(&m_cRef);
return m_pReal->AddRef();
}
STDMETHODIMP_(ULONG) Release(void)
{
ULONG ulVal = m_pReal->Release();
if (0 == InterlockedDecrement(&m_cRef))
{
delete this;
}
return ulVal;
}
STDMETHODIMP CreateBuffer(
_In_ const D3D11_BUFFER_DESC* pDesc,
_In_opt_ const D3D11_SUBRESOURCE_DATA* pInitialData,
_Out_opt_ ID3D11Buffer** ppBuffer)
{
return m_pReal->CreateBuffer(pDesc,pInitialData,ppBuffer);
}
STDMETHODIMP CreateTexture1D(
_In_ const D3D11_TEXTURE1D_DESC* pDesc,
_In_reads_opt_(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA* pInitialData,
_Out_opt_ ID3D11Texture1D** ppTexture1D)
{
return m_pReal->CreateTexture1D(pDesc,pInitialData,ppTexture1D);
}
STDMETHODIMP CreateTexture2D(
_In_ const D3D11_TEXTURE2D_DESC* pDesc,
_In_reads_opt_(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA* pInitialData,
_Out_opt_ ID3D11Texture2D** ppTexture2D)
{
return m_pReal->CreateTexture2D(pDesc,pInitialData,ppTexture2D);
}
STDMETHODIMP CreateTexture3D(
_In_ const D3D11_TEXTURE3D_DESC* pDesc,
_In_reads_opt_(pDesc->MipLevels) const D3D11_SUBRESOURCE_DATA* pInitialData,
_Out_opt_ ID3D11Texture3D** ppTexture3D)
{
return m_pReal->CreateTexture3D(pDesc,pInitialData,ppTexture3D);
}
STDMETHODIMP CreateShaderResourceView(
_In_ ID3D11Resource* pResource,
_In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
_Out_opt_ ID3D11ShaderResourceView** ppSRView)
{
return m_pReal->CreateShaderResourceView(pResource,pDesc,ppSRView);
}
STDMETHODIMP CreateUnorderedAccessView(
_In_ ID3D11Resource* pResource,
_In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
_Out_opt_ ID3D11UnorderedAccessView** ppUAView)
{
return m_pReal->CreateUnorderedAccessView(pResource,pDesc,ppUAView);
}
STDMETHODIMP CreateRenderTargetView(
_In_ ID3D11Resource* pResource,
_In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
_Out_opt_ ID3D11RenderTargetView** ppRTView)
{
return m_pReal->CreateRenderTargetView(pResource,pDesc,ppRTView);
}
STDMETHODIMP CreateDepthStencilView(
_In_ ID3D11Resource* pResource,
_In_opt_ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
_Out_opt_ ID3D11DepthStencilView** ppDepthStencilView)
{
return m_pReal->CreateDepthStencilView(pResource,pDesc,ppDepthStencilView);
}
STDMETHODIMP CreateInputLayout(
_In_reads_(NumElements) const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
_In_range_( 0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT ) UINT NumElements,
_In_ const void* pShaderBytecodeWithInputSignature,
_In_ SIZE_T BytecodeLength,
_Out_opt_ ID3D11InputLayout** ppInputLayout)
{
return m_pReal->CreateInputLayout(pInputElementDescs,NumElements,pShaderBytecodeWithInputSignature,BytecodeLength,ppInputLayout);
}
STDMETHODIMP CreateVertexShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11VertexShader** ppVertexShader)
{
return m_pReal->CreateVertexShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppVertexShader);
}
STDMETHODIMP CreateGeometryShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11GeometryShader** ppGeometryShader)
{
return m_pReal->CreateGeometryShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppGeometryShader);
}
STDMETHODIMP CreateGeometryShaderWithStreamOutput(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_reads_opt_(NumEntries) const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
_In_range_( 0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT ) UINT NumEntries,
_In_reads_opt_(NumStrides) const UINT* pBufferStrides,
_In_range_( 0, D3D11_SO_BUFFER_SLOT_COUNT ) UINT NumStrides,
_In_ UINT RasterizedStream,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11GeometryShader** ppGeometryShader)
{
return m_pReal->CreateGeometryShaderWithStreamOutput(pShaderBytecode,BytecodeLength,pSODeclaration,NumEntries,pBufferStrides,NumStrides,RasterizedStream,pClassLinkage,ppGeometryShader);
}
STDMETHODIMP CreatePixelShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11PixelShader** ppPixelShader)
{
return m_pReal->CreatePixelShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppPixelShader);
}
STDMETHODIMP CreateHullShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11HullShader** ppHullShader)
{
return m_pReal->CreateHullShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppHullShader);
}
STDMETHODIMP CreateDomainShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11DomainShader** ppDomainShader)
{
return m_pReal->CreateDomainShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppDomainShader);
}
STDMETHODIMP CreateComputeShader(
_In_ const void* pShaderBytecode,
_In_ SIZE_T BytecodeLength,
_In_opt_ ID3D11ClassLinkage* pClassLinkage,
_Out_opt_ ID3D11ComputeShader** ppComputeShader)
{
return m_pReal->CreateComputeShader(pShaderBytecode,BytecodeLength,pClassLinkage,ppComputeShader);
}
STDMETHODIMP CreateClassLinkage(
_Out_ ID3D11ClassLinkage** ppLinkage)
{
return m_pReal->CreateClassLinkage(ppLinkage);
}
STDMETHODIMP CreateBlendState(
_In_ const D3D11_BLEND_DESC* pBlendStateDesc,
_Out_opt_ ID3D11BlendState** ppBlendState)
{
return m_pReal->CreateBlendState(pBlendStateDesc,ppBlendState);
}
STDMETHODIMP CreateDepthStencilState(
_In_ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
_Out_opt_ ID3D11DepthStencilState** ppDepthStencilState)
{
return m_pReal->CreateDepthStencilState(pDepthStencilDesc,ppDepthStencilState);
}
STDMETHODIMP CreateRasterizerState(
_In_ const D3D11_RASTERIZER_DESC* pRasterizerDesc,
_Out_opt_ ID3D11RasterizerState** ppRasterizerState)
{
return m_pReal->CreateRasterizerState(pRasterizerDesc,ppRasterizerState);
}
STDMETHODIMP CreateSamplerState(
_In_ const D3D11_SAMPLER_DESC* pSamplerDesc,
_Out_opt_ ID3D11SamplerState** ppSamplerState)
{
return m_pReal->CreateSamplerState(pSamplerDesc,ppSamplerState);
}
STDMETHODIMP CreateQuery(
_In_ const D3D11_QUERY_DESC* pQueryDesc,
_Out_opt_ ID3D11Query** ppQuery)
{
return m_pReal->CreateQuery(pQueryDesc,ppQuery);
}
STDMETHODIMP CreatePredicate(
_In_ const D3D11_QUERY_DESC* pPredicateDesc,
_Out_opt_ ID3D11Predicate** ppPredicate)
{
return m_pReal->CreatePredicate(pPredicateDesc,ppPredicate);
}
STDMETHODIMP CreateCounter(
_In_ const D3D11_COUNTER_DESC* pCounterDesc,
_Out_opt_ ID3D11Counter** ppCounter)
{
return m_pReal->CreateCounter(pCounterDesc,ppCounter);
}
STDMETHODIMP CreateDeferredContext(
UINT ContextFlags,
_Out_opt_ ID3D11DeviceContext** ppDeferredContext)
{
return m_pReal->CreateDeferredContext(ContextFlags,ppDeferredContext);
}
STDMETHODIMP OpenSharedResource(
_In_ HANDLE hResource,
_In_ REFIID ReturnedInterface,
_Out_opt_ void** ppResource)
{
return m_pReal->OpenSharedResource(hResource,ReturnedInterface,ppResource);
}
STDMETHODIMP CheckFormatSupport(
_In_ DXGI_FORMAT Format,
_Out_ UINT* pFormatSupport)
{
return m_pReal->CheckFormatSupport(Format,pFormatSupport);
}
STDMETHODIMP CheckMultisampleQualityLevels(
_In_ DXGI_FORMAT Format,
_In_ UINT SampleCount,
_Out_ UINT* pNumQualityLevels)
{
return m_pReal->CheckMultisampleQualityLevels(Format,SampleCount,pNumQualityLevels);
}
STDMETHODIMP_(void) CheckCounterInfo(
_Out_ D3D11_COUNTER_INFO* pCounterInfo)
{
return m_pReal->CheckCounterInfo(pCounterInfo);
}
STDMETHODIMP CheckCounter(
_In_ const D3D11_COUNTER_DESC* pDesc,
_Out_ D3D11_COUNTER_TYPE* pType,
_Out_ UINT* pActiveCounters,
_Out_writes_opt_(*pNameLength) LPSTR szName,
_Inout_opt_ UINT* pNameLength,
_Out_writes_opt_(*pUnitsLength) LPSTR szUnits,
_Inout_opt_ UINT* pUnitsLength,
_Out_writes_opt_(*pDescriptionLength) LPSTR szDescription,
_Inout_opt_ UINT* pDescriptionLength)
{
return m_pReal->CheckCounter(pDesc,pType,pActiveCounters,szName,pNameLength,szUnits,pUnitsLength,szDescription,pDescriptionLength);
}
STDMETHODIMP CheckFeatureSupport(
D3D11_FEATURE Feature,
_Out_writes_bytes_(FeatureSupportDataSize) void* pFeatureSupportData,
UINT FeatureSupportDataSize)
{
return m_pReal->CheckFeatureSupport(Feature,pFeatureSupportData,FeatureSupportDataSize);
}
STDMETHODIMP GetPrivateData(
_In_ REFGUID guid,
_Inout_ UINT* pDataSize,
_Out_writes_bytes_opt_(*pDataSize) void* pData)
{
return m_pReal->GetPrivateData(guid,pDataSize,pData);
}
STDMETHODIMP SetPrivateData(
_In_ REFGUID guid,
_In_ UINT DataSize,
_In_reads_bytes_opt_(DataSize) const void* pData)
{
return m_pReal->SetPrivateData(guid,DataSize,pData);
}
STDMETHODIMP SetPrivateDataInterface(
_In_ REFGUID guid,
_In_opt_ const IUnknown* pData)
{
return m_pReal->SetPrivateDataInterface(guid,pData);
}
STDMETHODIMP_(D3D_FEATURE_LEVEL) GetFeatureLevel(void)
{
return m_pReal->GetFeatureLevel();
}
STDMETHODIMP_(UINT) GetCreationFlags(void)
{
return m_pReal->GetCreationFlags();
}
STDMETHODIMP GetDeviceRemovedReason(void)
{
return m_pReal->GetDeviceRemovedReason();
}
STDMETHODIMP_(void) GetImmediateContext(
_Out_ ID3D11DeviceContext** ppImmediateContext)
{
return m_pReal->GetImmediateContext(ppImmediateContext);
}
STDMETHODIMP SetExceptionMode(
UINT RaiseFlags)
{
return m_pReal->SetExceptionMode(RaiseFlags);
}
STDMETHODIMP_(UINT) GetExceptionMode(void)
{
return m_pReal->GetExceptionMode();
}
};
}

Просмотреть файл

@ -1,416 +0,0 @@
#include "Scheduler.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
DX11VideoRenderer::CScheduler::CScheduler(CCritSec& critSec) :
m_nRefCount(1),
m_critSec(critSec),
m_pCB(NULL),
m_ScheduledSamples(), // default ctor
m_pClock(NULL),
m_fRate(1.0f),
m_hWaitTimer(NULL),
m_LastSampleTime(0),
m_PerFrameInterval(0),
m_PerFrame_1_4th(0),
m_keyTimer(0)
{
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
DX11VideoRenderer::CScheduler::~CScheduler(void)
{
if (m_hWaitTimer != NULL)
{
CloseHandle(m_hWaitTimer);
m_hWaitTimer = NULL;
}
// Discard samples.
m_ScheduledSamples.Clear();
SafeRelease(m_pClock);
}
// IUnknown methods
ULONG DX11VideoRenderer::CScheduler::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
ULONG DX11VideoRenderer::CScheduler::Release()
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
// For thread safety, return a temporary variable.
return uCount;
}
HRESULT DX11VideoRenderer::CScheduler::QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv)
{
if (!ppv)
{
return E_POINTER;
}
if (iid == IID_IUnknown)
{
*ppv = static_cast<IUnknown*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
//-----------------------------------------------------------------------------
// SetFrameRate
// Specifies the frame rate of the video, in frames per second.
//-----------------------------------------------------------------------------
void DX11VideoRenderer::CScheduler::SetFrameRate(const MFRatio& fps)
{
UINT64 AvgTimePerFrame = 0;
// Convert to a duration.
MFFrameRateToAverageTimePerFrame(fps.Numerator, fps.Denominator, &AvgTimePerFrame);
m_PerFrameInterval = (MFTIME)AvgTimePerFrame;
// Calculate 1/4th of this value, because we use it frequently.
m_PerFrame_1_4th = m_PerFrameInterval / 4;
}
//-----------------------------------------------------------------------------
// StartScheduler
// Starts the scheduler's worker thread.
//
// IMFClock: Pointer to the DX11VideoRenderer's presentation clock. Can be NULL.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::StartScheduler(IMFClock* pClock)
{
HRESULT hr = S_OK;
SafeRelease(m_pClock);
m_pClock = pClock;
if (m_pClock != NULL)
{
m_pClock->AddRef();
}
// Set a high the timer resolution (ie, short timer period).
timeBeginPeriod(1);
// create the waitable timer
m_hWaitTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if (m_hWaitTimer == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
return hr;
}
//-----------------------------------------------------------------------------
// StopScheduler
//
// Stops the scheduler's worker thread.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::StopScheduler(void)
{
if (m_hWaitTimer != NULL)
{
CloseHandle(m_hWaitTimer);
m_hWaitTimer = NULL;
}
// Discard samples.
m_ScheduledSamples.Clear();
// Restore the timer resolution.
timeEndPeriod(1);
SafeRelease(m_pClock);
return S_OK;
}
//-----------------------------------------------------------------------------
// Flush
//
// Flushes all samples that are queued for presentation.
//
// Note: This method is synchronous; ie., it waits for the flush operation to
// complete on the worker thread.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::Flush(void)
{
CAutoLock lock(&m_critSec);
// Flushing: Clear the sample queue and set the event.
m_ScheduledSamples.Clear();
// Cancel timer callback
if (m_keyTimer != 0)
{
(void)MFCancelWorkItem(m_keyTimer);
m_keyTimer = 0;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// ScheduleSample
//
// Schedules a new sample for presentation.
//
// pSample: Pointer to the sample.
// bPresentNow: If TRUE, the sample is presented immediately. Otherwise, the
// sample's time stamp is used to schedule the sample.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::ScheduleSample(IMFSample* pSample, BOOL bPresentNow)
{
if (m_pCB == NULL)
{
return MF_E_NOT_INITIALIZED;
}
HRESULT hr = S_OK;
if (bPresentNow || (m_pClock == NULL))
{
// Present the sample immediately.
hr = m_pCB->PresentFrame();
}
else
{
// Queue the sample and ask the scheduler thread to wake up.
hr = m_ScheduledSamples.Queue(pSample);
if (SUCCEEDED(hr))
{
// process the frame asynchronously
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &m_xOnTimer, nullptr);
}
}
return hr;
}
//-----------------------------------------------------------------------------
// ProcessSamplesInQueue
//
// Processes all the samples in the queue.
//
// plNextSleep: Receives the length of time the scheduler thread should sleep
// before it calls ProcessSamplesInQueue again.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::ProcessSamplesInQueue(LONG* plNextSleep)
{
HRESULT hr = S_OK;
LONG lWait = 0;
IMFSample* pSample = NULL;
// Process samples until the queue is empty or until the wait time > 0.
// Note: Dequeue returns S_FALSE when the queue is empty.
while (m_ScheduledSamples.Dequeue(&pSample) == S_OK)
{
// Process the next sample in the queue. If the sample is not ready
// for presentation. the value returned in lWait is > 0, which
// means the scheduler should sleep for that amount of time.
hr = ProcessSample(pSample, &lWait);
SafeRelease(pSample);
if (FAILED(hr) || lWait > 0)
{
break;
}
}
// If the wait time is zero, it means we stopped because the queue is
// empty (or an error occurred). Set the wait time to infinite; this will
// make the scheduler thread sleep until it gets another thread message.
if (lWait == 0)
{
lWait = INFINITE;
}
*plNextSleep = lWait;
return hr;
}
//-----------------------------------------------------------------------------
// ProcessSample
//
// Processes a sample.
//
// plNextSleep: Receives the length of time the scheduler thread should sleep.
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::ProcessSample(IMFSample* pSample, LONG* plNextSleep)
{
HRESULT hr = S_OK;
LONGLONG hnsPresentationTime = 0;
LONGLONG hnsTimeNow = 0;
MFTIME hnsSystemTime = 0;
LONGLONG hnsDelta = 0;
BOOL bPresentNow = TRUE;
LONG lNextSleep = 0;
if (m_pClock)
{
// Get the sample's time stamp. It is valid for a sample to
// have no time stamp.
hr = pSample->GetSampleTime(&hnsPresentationTime);
// Get the clock time. (But if the sample does not have a time stamp,
// we don't need the clock time.)
if (SUCCEEDED(hr))
{
hr = m_pClock->GetCorrelatedTime(0, &hnsTimeNow, &hnsSystemTime);
}
if (SUCCEEDED(hr))
{
// Calculate the time until the sample's presentation time.
// A negative value means the sample is late.
hnsDelta = hnsPresentationTime - hnsTimeNow;
if (m_fRate < 0)
{
// For reverse playback, the clock runs backward. Therefore, the
// delta is reversed.
hnsDelta = - hnsDelta;
}
if (hnsDelta < - m_PerFrame_1_4th)
{
// This sample is late.
bPresentNow = TRUE;
}
else if (hnsDelta > (3 * m_PerFrame_1_4th))
{
// This sample is still too early. Go to sleep.
lNextSleep = static_cast<LONG>(TicksToMilliseconds(hnsDelta - (3 * m_PerFrame_1_4th)));
// Adjust the sleep time for the clock rate. (The presentation clock runs
// at m_fRate, but sleeping uses the system clock.)
lNextSleep = static_cast<LONG>(lNextSleep / fabsf(m_fRate));
// Don't present yet.
bPresentNow = FALSE;
}
}
}
if (bPresentNow)
{
hr = m_pCB->PresentFrame();
}
else
{
// The sample is not ready yet. Return it to the queue.
hr = m_ScheduledSamples.PutBack(pSample);
}
*plNextSleep = lNextSleep;
return hr;
}
//-----------------------------------------------------------------------------
// StartProcessSample
//
// Synopsis: Main entrypoint for the frame processing
//-----------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::StartProcessSample()
{
HRESULT hr = S_OK;
LONG lWait = INFINITE;
BOOL bExitThread = FALSE;
IMFAsyncResult *pAsyncResult = NULL;
hr = ProcessSamplesInQueue(&lWait);
if(SUCCEEDED(hr))
{
if(INFINITE != lWait && 0 < lWait)
{
// not time to process the frame yet, wait until the right time
LARGE_INTEGER llDueTime;
llDueTime.QuadPart = -1 * MillisecondsToTicks(lWait);
if (SetWaitableTimer(m_hWaitTimer, &llDueTime, 0, NULL, NULL, FALSE) == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
if(SUCCEEDED(hr))
{
// queue a waititem to wait for timer completion
hr = MFCreateAsyncResult(nullptr, &m_xOnTimer, nullptr, &pAsyncResult);
if(SUCCEEDED(hr))
{
hr = MFPutWaitingWorkItem(m_hWaitTimer, 0, pAsyncResult, &m_keyTimer);
}
}
}
}
SafeRelease(pAsyncResult);
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: OnTimer
//
// Synopsis: Callback fired when the timer expires. Used as entrypoint to
// check whether a frame should now be presented
//
//--------------------------------------------------------------------------
HRESULT DX11VideoRenderer::CScheduler::OnTimer(__RPC__in_opt IMFAsyncResult *pResult)
{
HRESULT hr = S_OK;
CAutoLock lock(&m_critSec);
m_keyTimer = 0;
// if we have a pending frame, process it
// it's possible that we don't have a frame at this point if the pending frame was cancelled
hr = StartProcessSample();
return hr;
}

Просмотреть файл

@ -1,89 +0,0 @@
#pragma once
#include "Common.h"
namespace DX11VideoRenderer
{
//-----------------------------------------------------------------------------
// SchedulerCallback
//
// Defines the callback method to present samples.
//-----------------------------------------------------------------------------
struct SchedulerCallback
{
virtual HRESULT PresentFrame(void) = 0;
};
//-----------------------------------------------------------------------------
// Scheduler class
//
// Schedules when a sample should be displayed.
//
// Note: Presentation of each sample is performed by another object which
// must implement SchedulerCallback::PresentSample.
//
// General design:
// The scheduler generally receives samples before their presentation time. It
// puts the samples on a queue and presents them in FIFO order on a worker
// thread. The scheduler communicates with the worker thread by posting thread
// messages.
//
// The caller has the option of presenting samples immediately (for example,
// for repaints).
//-----------------------------------------------------------------------------
class CScheduler:
public IUnknown,
private CBase
{
public:
CScheduler(CCritSec& critSec);
virtual ~CScheduler(void);
// IUnknown
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
void SetCallback(SchedulerCallback* pCB)
{
m_pCB = pCB;
}
void SetFrameRate(const MFRatio& fps);
void SetClockRate(float fRate) { m_fRate = fRate; }
const LONGLONG& LastSampleTime(void) const { return m_LastSampleTime; }
const LONGLONG& FrameDuration(void) const { return m_PerFrameInterval; }
HRESULT StartScheduler(IMFClock* pClock);
HRESULT StopScheduler(void);
HRESULT ScheduleSample(IMFSample* pSample, BOOL bPresentNow);
HRESULT ProcessSamplesInQueue(LONG* plNextSleep);
HRESULT ProcessSample(IMFSample* pSample, LONG* plNextSleep);
HRESULT Flush(void);
DWORD GetCount(void){ return m_ScheduledSamples.GetCount(); }
private:
HRESULT StartProcessSample();
HRESULT OnTimer(__RPC__in_opt IMFAsyncResult* pResult);
METHODASYNCCALLBACKEX(OnTimer, CScheduler, 0, MFASYNC_CALLBACK_QUEUE_MULTITHREADED);
long m_nRefCount;
CCritSec& m_critSec; // critical section for thread safety
SchedulerCallback* m_pCB; // Weak reference; do not delete.
ThreadSafeQueue<IMFSample> m_ScheduledSamples; // Samples waiting to be presented.
IMFClock* m_pClock; // Presentation clock. Can be NULL.
float m_fRate; // Playback rate.
HANDLE m_hWaitTimer; // Wait Timer after which frame is presented.
MFTIME m_LastSampleTime; // Most recent sample time.
MFTIME m_PerFrameInterval; // Duration of each frame.
LONGLONG m_PerFrame_1_4th; // 1/4th of the frame duration.
MFWORKITEM_KEY m_keyTimer;
};
}

Просмотреть файл

@ -1,116 +0,0 @@
#ifndef __STATICASYNCCALLBACK__
#define __STATICASYNCCALLBACK__
////////////////////////////////////////////////////////
//
#define STATICASYNCCALLBACK(Callback, Parent) \
class Callback##AsyncCallback; \
friend class Callback##AsyncCallback; \
class Callback##AsyncCallback : public IMFAsyncCallback \
{ \
public: \
STDMETHOD_( ULONG, AddRef )() \
{ \
Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
return pThis->AddRef(); \
} \
STDMETHOD_( ULONG, Release )() \
{ \
Parent * pThis = ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
return pThis->Release(); \
} \
STDMETHOD( QueryInterface )( REFIID riid, __RPC__deref_out _Result_nullonfailure_ void **ppvObject ) \
{ \
return E_NOINTERFACE; \
} \
STDMETHOD( GetParameters )( \
__RPC__out DWORD *pdwFlags, \
__RPC__out DWORD *pdwQueue) \
{ \
return S_OK; \
} \
STDMETHOD( Invoke )( __RPC__in_opt IMFAsyncResult * pResult ) \
{ \
Callback( pResult ); \
return S_OK; \
} \
} m_x##Callback;
////////////////////////////////////////////////////////
//
//
// We need to support QI interface so that DCOM is happy when it tries to marshal the interface pointer
//
#define METHODASYNCCALLBACKEX(Callback, Parent, Flag, Queue) \
class Callback##AsyncCallback; \
friend class Callback##AsyncCallback; \
class Callback##AsyncCallback : public IMFAsyncCallback \
{ \
public: \
STDMETHOD_( ULONG, AddRef )() \
{ \
return GetParent()->AddRef(); \
} \
STDMETHOD_( ULONG, Release )() \
{ \
return GetParent()->Release(); \
} \
STDMETHOD( QueryInterface )( REFIID riid, __RPC__deref_out _Result_nullonfailure_ void **ppvObject ) \
{ \
if(riid == IID_IMFAsyncCallback || riid == IID_IUnknown) \
{ \
(*ppvObject) = this; \
AddRef(); \
return S_OK; \
} \
(*ppvObject) = NULL; \
return E_NOINTERFACE; \
} \
STDMETHOD( GetParameters )( \
__RPC__out DWORD *pdwFlags, \
__RPC__out DWORD *pdwQueue) \
{ \
*pdwFlags = Flag; \
*pdwQueue = Queue; \
return S_OK; \
} \
STDMETHOD( Invoke )( __RPC__in_opt IMFAsyncResult * pResult ) \
{ \
GetParent()->Callback( pResult ); \
return S_OK; \
} \
protected: \
Parent* GetParent() \
{ \
return ((Parent*)((BYTE*)this - offsetof(Parent, m_x##Callback))); \
} \
} m_x##Callback;
////////////////////////////////////////////////////////
//
#define METHODFASTCALLBACK(Callback, Parent) \
METHODASYNCCALLBACKEX(Callback, Parent, MFASYNC_FAST_IO_PROCESSING_CALLBACK, MFASYNC_CALLBACK_QUEUE_STANDARD)
#define METHODASYNCCALLBACK(Callback, Parent) \
METHODASYNCCALLBACKEX(Callback, Parent, 0, MFASYNC_CALLBACK_QUEUE_STANDARD)
#define METHODASYNCRTCALLBACK(Callback, Parent) \
METHODASYNCCALLBACKEX(Callback, Parent, 0, MFASYNC_CALLBACK_QUEUE_RT)
#define METHODASYNCIOCALLBACK(Callback, Parent) \
METHODASYNCCALLBACKEX(Callback, Parent, MFASYNC_FAST_IO_PROCESSING_CALLBACK, MFASYNC_CALLBACK_QUEUE_IO)
////////////////////////////////////////////////////////
//
#define METHODASYNCCALLBACKEX2(Callback, Parent, GetQueue ) \
METHODASYNCCALLBACKEX(Callback, Parent, \
0, \
GetParent()->GetQueue() )
#define METHODASYNCCALLBACKEX3(Callback, Parent, GetFlags, GetQueue ) \
METHODASYNCCALLBACKEX(Callback, Parent, \
GetParent()->GetFlags(), GetParent()->GetQueue() )
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,186 +0,0 @@
#pragma once
#include "Common.h"
#include "display.h"
#include "MFAttributesImpl.h"
#include "Marker.h"
#include "Presenter.h"
#include "Scheduler.h"
namespace DX11VideoRenderer
{
class CStreamSink :
public IMFStreamSink,
public IMFMediaTypeHandler,
public IMFGetService,
public SchedulerCallback,
public CMFAttributesImpl<IMFAttributes>,
private CBase
{
public:
CStreamSink(DWORD dwStreamId, CCritSec& critSec, CScheduler* pScheduler);
virtual ~CStreamSink(void);
// IUnknown
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
STDMETHODIMP_(ULONG) Release(void);
// IMFStreamSink
STDMETHODIMP Flush(void);
STDMETHODIMP GetIdentifier(__RPC__out DWORD* pdwIdentifier);
STDMETHODIMP GetMediaSink(__RPC__deref_out_opt IMFMediaSink** ppMediaSink);
STDMETHODIMP GetMediaTypeHandler(__RPC__deref_out_opt IMFMediaTypeHandler** ppHandler);
STDMETHODIMP PlaceMarker(MFSTREAMSINK_MARKER_TYPE eMarkerType, __RPC__in const PROPVARIANT* pvarMarkerValue, __RPC__in const PROPVARIANT* pvarContextValue);
STDMETHODIMP ProcessSample(__RPC__in_opt IMFSample* pSample);
// IMFMediaEventGenerator (from IMFStreamSink)
STDMETHODIMP BeginGetEvent(IMFAsyncCallback* pCallback,IUnknown* punkState);
STDMETHODIMP EndGetEvent(IMFAsyncResult* pResult, _Out_ IMFMediaEvent** ppEvent);
STDMETHODIMP GetEvent(DWORD dwFlags, __RPC__deref_out_opt IMFMediaEvent** ppEvent);
STDMETHODIMP QueueEvent(MediaEventType met, __RPC__in REFGUID guidExtendedType, HRESULT hrStatus, __RPC__in_opt const PROPVARIANT* pvValue);
// IMFMediaTypeHandler
STDMETHODIMP GetCurrentMediaType(_Outptr_ IMFMediaType** ppMediaType);
STDMETHODIMP GetMajorType(__RPC__out GUID* pguidMajorType);
STDMETHODIMP GetMediaTypeByIndex(DWORD dwIndex, _Outptr_ IMFMediaType** ppType);
STDMETHODIMP GetMediaTypeCount(__RPC__out DWORD* pdwTypeCount);
STDMETHODIMP IsMediaTypeSupported(IMFMediaType* pMediaType, _Outptr_opt_result_maybenull_ IMFMediaType** ppMediaType);
STDMETHODIMP SetCurrentMediaType(IMFMediaType* pMediaType);
// IMFGetService
STDMETHODIMP GetService(__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID* ppvObject);
// SchedulerCallback
HRESULT PresentFrame(void);
HRESULT GetMaxRate(BOOL fThin, float* pflRate);
HRESULT Initialize(IMFMediaSink* pParent, CPresenter* pPresenter);
inline BOOL IsActive(void) const // IsActive: The "active" state is started or paused.
{
return ((m_state == State_Started) || (m_state == State_Paused));
}
HRESULT Pause(void);
HRESULT Preroll(void);
HRESULT Restart(void);
HRESULT Shutdown(void);
HRESULT Start(MFTIME start);
HRESULT Stop(void);
private:
// State enum: Defines the current state of the stream.
enum State
{
State_TypeNotSet = 0, // No media type is set
State_Ready, // Media type is set, Start has never been called.
State_Started,
State_Paused,
State_Stopped,
State_Count // Number of states
};
// StreamOperation: Defines various operations that can be performed on the stream.
enum StreamOperation
{
OpSetMediaType = 0,
OpStart,
OpRestart,
OpPause,
OpStop,
OpProcessSample,
OpPlaceMarker,
Op_Count // Number of operations
};
enum ConsumeState
{
DropFrames = 0,
ProcessFrames
};
// CAsyncOperation:
// Used to queue asynchronous operations. When we call MFPutWorkItem, we use this
// object for the callback state (pState). Then, when the callback is invoked,
// we can use the object to determine which asynchronous operation to perform.
// Optional data can include a sample (IMFSample) or a marker.
// When ProcessSample is called, we use it to queue a sample. When ProcessMarker is
// called, we use it to queue a marker. This way, samples and markers can live in
// the same queue. We need this because the sink has to serialize marker events
// with sample processing.
class CAsyncOperation : public IUnknown
{
public:
CAsyncOperation(StreamOperation op);
// IUnknown methods.
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void** ppv);
STDMETHODIMP_(ULONG) Release(void);
// Structure data.
StreamOperation m_op; // The operation to perform.
PROPVARIANT m_varDataWM; // Optional data, only used for water mark
private:
virtual ~CAsyncOperation(void);
long m_nRefCount;
};
static GUID const* const s_pVideoFormats[];
static const DWORD s_dwNumVideoFormats;
static const MFRatio s_DefaultFrameRate;
static const struct FormatEntry
{
GUID Subtype;
DXGI_FORMAT DXGIFormat;
} s_DXGIFormatMapping[];
static BOOL ValidStateMatrix[State_Count][Op_Count]; // Defines a look-up table that says which operations are valid from which states.
HRESULT DispatchProcessSample(CAsyncOperation* pOp);
HRESULT CheckShutdown(void) const;
HRESULT GetFrameRate(IMFMediaType* pType, MFRatio* pRatio);
BOOL NeedMoreSamples(void);
HRESULT OnDispatchWorkItem(IMFAsyncResult* pAsyncResult);
HRESULT ProcessSamplesFromQueue(ConsumeState bConsumeData);
HRESULT QueueAsyncOperation(StreamOperation op);
HRESULT RequestSamples(void);
HRESULT SendMarkerEvent(IMarker* pMarker, ConsumeState bConsumeData);
HRESULT ValidateOperation(StreamOperation op);
const DWORD STREAM_ID;
long m_nRefCount; // reference count
CCritSec& m_critSec; // critical section for thread safety
State m_state;
BOOL m_IsShutdown; // Flag to indicate if Shutdown() method was called.
DWORD m_WorkQueueId; // ID of the work queue for asynchronous operations.
CAsyncCallback<CStreamSink> m_WorkQueueCB; // Callback for the work queue.
ConsumeState m_ConsumeData; // Flag to indicate process or drop frames
MFTIME m_StartTime; // Presentation time when the clock started.
DWORD m_cbDataWritten; // How many bytes we have written so far.
DWORD m_cOutstandingSampleRequests; // Outstanding reuqests for samples.
IMFMediaSink* m_pSink; // Parent media sink
IMFMediaEventQueue* m_pEventQueue; // Event queue
IMFByteStream* m_pByteStream; // Bytestream where we write the data.
CPresenter* m_pPresenter;
CScheduler* m_pScheduler;
IMFMediaType* m_pCurrentType;
BOOL m_fPrerolling;
BOOL m_fWaitingForOnClockStart;
ThreadSafeQueue<IUnknown> m_SamplesToProcess; // Queue to hold samples and markers. Applies to: ProcessSample, PlaceMarker
UINT32 m_unInterlaceMode;
struct sFraction
{
DWORD Numerator;
DWORD Denominator;
} m_imageBytesPP;
DXGI_FORMAT m_dxgiFormat;
};
}

Просмотреть файл

@ -1,313 +0,0 @@
/******************************Module*Header*******************************\
* Module Name: display.cpp
*
* Support for DDraw device on Multiple Monitors.
*
*
* Created: Mon 01/24/2000
* Author: Stephen Estrop [StEstrop]
* Mod: KirtD - First integration into MF renderer model
*
* Copyright (c) Microsoft Corporation
\**************************************************************************/
#include <windows.h>
#include <unknwn.h>
#include "display.h"
#include <strsafe.h>
#ifndef DEFAULT_DENSITY_LIMIT
#define DEFAULT_DENSITY_LIMIT 60
#endif
#ifndef WIDTH
#define WIDTH(x) ((x)->right - (x)->left)
#endif
#ifndef HEIGHT
#define HEIGHT(x) ((x)->bottom - (x)->top)
#endif
/* -------------------------------------------------------------------------
** Structure use to pass info to the DDrawEnumEx callback
** -------------------------------------------------------------------------
*/
struct DDRAWINFO
{
DWORD dwCount;
DWORD dwPmiSize;
HRESULT hrCallback;
const GUID* pGUID;
CAMDDrawMonitorInfo* pmi;
HWND hwnd;
};
/******************************Public*Routine******************************\
* TermDDrawMonitorInfo
*
*
*
* History:
* 01-17-2000 - StEstrop - Created
*
\**************************************************************************/
void CMonitorArray::TermDDrawMonitorInfo(
_Inout_ CAMDDrawMonitorInfo* pmi
)
{
ZeroMemory(pmi, sizeof(CAMDDrawMonitorInfo));
}
/*****************************Private*Routine******************************\
* GetAMDDrawMonitorInfo
*
*
*
* History:
* Tue 08/17/1999 - StEstrop - Created
*
\**************************************************************************/
BOOL CMonitorArray::GetAMDDrawMonitorInfo(
UINT uDevID,
_Out_ CAMDDrawMonitorInfo* lpmi,
_In_ HMONITOR hm
)
{
MONITORINFOEX miInfoEx;
miInfoEx.cbSize = sizeof(miInfoEx);
lpmi->hMon = NULL;
lpmi->uDevID = 0;
lpmi->physMonDim.cx = 0;
lpmi->physMonDim.cy = 0;
lpmi->dwRefreshRate = DEFAULT_DENSITY_LIMIT;
if (GetMonitorInfo(hm, &miInfoEx))
{
HRESULT hr = StringCchCopy(lpmi->szDevice, sizeof(lpmi->szDevice)/sizeof(lpmi->szDevice[0]), miInfoEx.szDevice);
if ( FAILED( hr ) )
{
return FALSE;
}
lpmi->hMon = hm;
lpmi->uDevID = uDevID;
lpmi->physMonDim.cx = WIDTH(&miInfoEx.rcMonitor);
lpmi->physMonDim.cy = HEIGHT(&miInfoEx.rcMonitor);
int j = 0;
DISPLAY_DEVICE ddMonitor;
ddMonitor.cb = sizeof(ddMonitor);
while (EnumDisplayDevices(lpmi->szDevice, j, &ddMonitor, 0))
{
if (ddMonitor.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
{
DEVMODE dm;
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (EnumDisplaySettings(lpmi->szDevice, ENUM_CURRENT_SETTINGS, &dm))
{
lpmi->dwRefreshRate = dm.dmDisplayFrequency == 0 ? lpmi->dwRefreshRate : dm.dmDisplayFrequency;
}
// Remove registry snooping for monitor dimensions, as this is not supported by LDDM.
// if (!FindMonitorDimensions(ddMonitor.DeviceID, &lpmi->physMonDim.cx, &lpmi->physMonDim.cy))
{
lpmi->physMonDim.cx = WIDTH(&miInfoEx.rcMonitor);
lpmi->physMonDim.cy = HEIGHT(&miInfoEx.rcMonitor);
}
}
j++;
}
return TRUE;
}
return FALSE;
}
BOOL CMonitorArray::InitMonitor(
_In_ HMONITOR hMon,
BOOL fXclMode
)
{
if (GetAMDDrawMonitorInfo(m_dwNumMonitors, &m_DDMon[m_dwNumMonitors], hMon))
{
m_DDMon[m_dwNumMonitors].pDD = (IUnknown*)1; // make checks for pDD succeed.
m_dwNumMonitors++;
}
if (EVR_MAX_MONITORS >= m_dwNumMonitors)
{
// don't exceed array bounds
return TRUE;
}
return FALSE;
}
BOOL CALLBACK CMonitorArray::MonitorEnumProc(
_In_ HMONITOR hMon,
_In_opt_ HDC hDC,
_In_ LPRECT pRect,
LPARAM dwData
)
{
MonitorEnumProcInfo* info = (MonitorEnumProcInfo*)dwData;
if (!info)
{
return TRUE;
}
return info->pMonArray->InitMonitor(hMon, FALSE);
}
/*****************************Private*Routine******************************\
* InitializeDisplaySystem
*
*
*
* History:
* Mon 01/24/2000 - StEstrop - Created
*
\**************************************************************************/
HRESULT CMonitorArray::InitializeDisplaySystem(
_In_ HWND hwnd
)
{
HRESULT hr = S_OK;
MonitorEnumProcInfo info;
info.hwnd = hwnd;
info.pMonArray = this;
EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, (LPARAM)&info);
if (m_dwNumMonitors == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
return(hr);
}
return(hr);
}
/*****************************Private*Routine******************************\
* FindMonitor
*
* find the current monitor
*
* History:
* Fri 04/25/2000 - GlennE - Created
*
\**************************************************************************/
CAMDDrawMonitorInfo* CMonitorArray::FindMonitor(
_In_ HMONITOR hMon
)
{
for (DWORD i = 0; i < m_dwNumMonitors; i++)
{
if (hMon == m_DDMon[i].hMon)
{
return &m_DDMon[i];
}
}
return NULL;
}
/*****************************Private*Routine******************************\
* MatchGUID
*
*
*
* History:
* Fri 04/25/2000 - GlennE - Created
*
\**************************************************************************/
HRESULT CMonitorArray::MatchGUID(
UINT uDevID,
_Out_ DWORD* pdwMatchID
)
{
HRESULT hr = S_OK;
*pdwMatchID = 0;
for (DWORD i = 0; i < m_dwNumMonitors; i++)
{
UINT uMonDevID = m_DDMon[i].uDevID;
if (uDevID == uMonDevID)
{
*pdwMatchID = i;
hr = S_OK;
return( hr );
}
}
hr = S_FALSE;
return( hr );
}
/*****************************Private*Routine******************************\
* TerminateDisplaySystem
*
*
*
* History:
* Mon 01/24/2000 - StEstrop - Created
*
\**************************************************************************/
void CMonitorArray::TerminateDisplaySystem()
{
for (DWORD i = 0; i < m_dwNumMonitors; i++)
{
TermDDrawMonitorInfo(&m_DDMon[i]);
}
m_dwNumMonitors = 0;
}
/******************************Public*Routine******************************\
* Constructor and destructor
*
*
*
* History:
* Fri 11/17/2001 - StEstrop - Created
*
\**************************************************************************/
CMonitorArray::CMonitorArray()
: m_dwNumMonitors(0)
{
ZeroMemory(m_DDMon, sizeof(m_DDMon));
}
CMonitorArray::~CMonitorArray()
{
TerminateDisplaySystem();
}

Просмотреть файл

@ -1,73 +0,0 @@
/******************************Module*Header*******************************\
* Module Name: display.h
*
*
*
*
* Created: Mon 01/24/2000
* Author: Stephen Estrop [StEstrop]
*
* Copyright (c) Microsoft Corporation
\**************************************************************************/
#if !defined(__DISPLAY_H__)
#define __DISPLAY_H__
#define AMDDRAWMONITORINFO_PRIMARY_MONITOR 0x0001
struct CAMDDrawMonitorInfo
{
UINT uDevID;
HMONITOR hMon;
TCHAR szDevice[ 32 ];
LARGE_INTEGER liDriverVersion;
DWORD dwVendorId;
DWORD dwDeviceId;
DWORD dwSubSysId;
DWORD dwRevision;
SIZE physMonDim;
DWORD dwRefreshRate;
IUnknown *pDD;
};
#define EVR_MAX_MONITORS 16
class CMonitorArray
{
public:
CMonitorArray();
virtual ~CMonitorArray();
virtual HRESULT InitializeDisplaySystem(_In_ HWND hwnd);
virtual HRESULT InitializeXclModeDisplaySystem(_In_ IUnknown* lpDD, _Out_ UINT* pAdapterID) { return E_NOTIMPL; }
virtual void TerminateDisplaySystem();
CAMDDrawMonitorInfo* FindMonitor(_In_ HMONITOR hMon);
HRESULT MatchGUID(UINT uDevID, _Out_ DWORD* pdwMatchID );
CAMDDrawMonitorInfo& operator[](int i)
{ return m_DDMon[i]; }
DWORD Count() const
{ return m_dwNumMonitors; }
static BOOL CALLBACK MonitorEnumProc(_In_ HMONITOR hMon, _In_opt_ HDC hDC, _In_ LPRECT pRect, LPARAM dwData);
virtual BOOL InitMonitor(_In_ HMONITOR hMon, BOOL fXclMode);
protected:
BOOL GetAMDDrawMonitorInfo(UINT uDevID, _Out_ CAMDDrawMonitorInfo* lpmi, _In_ HMONITOR hm);
virtual void TermDDrawMonitorInfo(_Inout_ CAMDDrawMonitorInfo* pmi);
DWORD m_dwNumMonitors;
CAMDDrawMonitorInfo m_DDMon[EVR_MAX_MONITORS];
};
typedef struct {
HWND hwnd;
CMonitorArray* pMonArray;
} MonitorEnumProcInfo;
#endif // !defined(__DISPLAY_H__)

Просмотреть файл

@ -1,735 +0,0 @@
//-----------------------------------------------------------------------------
// File: Linklist.h
// Desc: Linked list class.
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
// Notes:
//
// This class template implements a simple double-linked list.
// Objects are held as pointers. (Does not use STL's copy semantics.)
// The Clear() method takes a functor object that releases the objects.
#pragma once
#include <new>
#include <assert.h>
#include <unknwn.h>
template <class T>
class List
{
protected:
// Nodes in the linked list
struct Node
{
Node *prev;
Node *next;
T *item;
Node() : prev(NULL), next(NULL), item(NULL)
{
}
Node(T* item) : prev(NULL), next(NULL)
{
this->item = item;
}
T* Item() const { return item; }
};
protected:
Node m_anchor; // Anchor node for the linked list.
DWORD m_count; // Number of items in the list
Node *m_pEnum; // Enumeration node
void InvalidateEnumerator()
{
m_pEnum = NULL;
}
Node* Front() const
{
return m_anchor.next;
}
Node* Back() const
{
return m_anchor.prev;
}
virtual HRESULT InsertAfter(T* item, Node *pBefore)
{
if (item == NULL || pBefore == NULL)
{
return E_POINTER;
}
Node *pNode = new Node(item);
if (pNode == NULL)
{
return E_OUTOFMEMORY;
}
Node *pAfter = pBefore->next;
pBefore->next = pNode;
pAfter->prev = pNode;
pNode->prev = pBefore;
pNode->next = pAfter;
m_count++;
InvalidateEnumerator();
return S_OK;
}
virtual HRESULT GetItem(Node *pNode, T** ppItem)
{
if (pNode == NULL || ppItem == NULL)
{
return E_POINTER;
}
if (pNode->item)
{
*ppItem = pNode->item;
return S_OK;
}
else
{
return E_INVALIDARG;
}
}
// RemoveItem:
// Removes a node and optionally returns the item.
// ppItem can be NULL.
virtual HRESULT RemoveItem(Node *pNode, T **ppItem)
{
if (pNode == NULL)
{
return E_POINTER;
}
if (pNode == &m_anchor)
{
return E_INVALIDARG;
}
T* item = NULL;
// anchor points back to the previous thing
m_anchor.prev = pNode->prev;
// the previous thing points to the anchor
pNode->prev->next = &m_anchor;
item = pNode->item;
delete pNode;
m_count--;
if (ppItem)
{
*ppItem = item;
}
InvalidateEnumerator();
return S_OK;
}
public:
List()
{
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
m_pEnum = NULL;
}
virtual ~List()
{
}
// Insertion functions
HRESULT InsertBack(T* item)
{
return InsertAfter(item, m_anchor.prev);
}
HRESULT InsertFront(T* item)
{
return InsertAfter(item, &m_anchor);
}
// RemoveBack: Removes the tail of the list and returns the value.
HRESULT RemoveBack(T **ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Back(), ppItem);
}
}
// RemoveFront: Removes the head of the list and returns the value.
HRESULT RemoveFront(T **ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Front(), ppItem);
}
}
HRESULT PopFront()
{
return RemoveFront(NULL);
}
HRESULT PopBack()
{
return RemoveBack(NULL);
}
HRESULT GetBack(T **ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Back(), ppItem);
}
}
HRESULT GetFront(T **ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Front(), ppItem);
}
}
// GetCount: Returns the number of items in the list.
DWORD GetCount() const { return m_count; }
bool IsEmpty() const
{
return (GetCount() == 0);
}
// Clear: Takes a functor object whose operator()
// frees the object on the list.
template <class FN>
void Clear(FN& clear_fn)
{
Node *n = m_anchor.next;
// Delete the nodes
while (n != &m_anchor)
{
clear_fn(n->item);
Node *tmp = n->next;
delete n;
n = tmp;
}
// Reset the anchor to point at itself
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
}
// Enumerator functions
void ResetEnumerator()
{
m_pEnum = Front();
}
HRESULT Next(T **ppItem)
{
if (ppItem == NULL)
{
return E_POINTER;
}
if (m_pEnum == NULL)
{
return E_FAIL; // Needs reset
}
if (m_pEnum == &m_anchor)
{
return __HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
}
HRESULT hr = GetItem(m_pEnum, ppItem);
if (SUCCEEDED(hr))
{
m_pEnum = m_pEnum->next;
}
return hr;
}
};
// Typical functors for Clear method.
// ComAutoRelease: Releases COM pointers.
// MemDelete: Deletes pointers to new'd memory.
class ComAutoRelease
{
public:
void operator()(IUnknown *p)
{
if (p)
{
p->Release();
}
}
};
class MemDelete
{
public:
void operator()(void *p)
{
if (p)
{
delete p;
}
}
};
//ComPtrList class
//Derived class that makes it safer to store COM pointers in the List<> class.
//It automatically AddRef's the pointers that are inserted onto the list
//(unless the insertion method fails).
//T must be a COM interface type.
template <class T>
class ComPtrList : public List<T>
{
public:
void Clear()
{
List<T>::Clear(ComAutoRelease());
}
protected:
HRESULT InsertAfter(T* item, typename List<T>::Node * pBefore)
{
item->AddRef();
HRESULT hr = List<T>::InsertAfter(item, pBefore);
if (FAILED(hr))
{
item->Release();
}
return hr;
}
HRESULT GetItem(typename List<T>::Node *pNode, T** ppItem)
{
HRESULT hr = List<T>::GetItem(pNode, ppItem);
if (SUCCEEDED(hr))
{
(*ppItem)->AddRef();
}
return hr;
}
HRESULT RemoveItem(typename List<T>::Node *pNode, T **ppItem)
{
// ppItem can be NULL, but we need to get the
// item so that we can release it.
// If ppItem is not NULL, we will AddRef it on the way out/
T* item = NULL;
HRESULT hr = List<T>::RemoveItem(pNode, &item);
if (SUCCEEDED(hr))
{
if (ppItem)
{
*ppItem = item;
(*ppItem)->AddRef();
}
item->Release();
}
return hr;
}
};
template <class T, bool NULLABLE = FALSE>
class ComPtrListEx
{
protected:
typedef T* Ptr;
// Nodes in the linked list
struct Node
{
Node *prev;
Node *next;
Ptr item;
Node() : prev(NULL), next(NULL), item(NULL)
{
}
Node(Ptr item) : prev(NULL), next(NULL)
{
this->item = item;
if (item)
{
item->AddRef();
}
}
~Node()
{
if (item)
{
item->Release();
}
}
Ptr Item() const { return item; }
};
public:
// Object for enumerating the list.
class POSITION
{
friend class ComPtrListEx<T>;
public:
POSITION() : pNode(NULL)
{
}
bool operator==(const POSITION &p) const
{
return pNode == p.pNode;
}
bool operator!=(const POSITION &p) const
{
return pNode != p.pNode;
}
private:
const Node *pNode;
POSITION(Node *p) : pNode(p)
{
}
};
protected:
Node m_anchor; // Anchor node for the linked list.
DWORD m_count; // Number of items in the list.
Node* Front() const
{
return m_anchor.next;
}
Node* Back() const
{
return m_anchor.prev;
}
virtual HRESULT InsertAfter(Ptr item, Node *pBefore)
{
if (pBefore == NULL)
{
return E_POINTER;
}
// Do not allow NULL item pointers unless NULLABLE is true.
if (!item && !NULLABLE)
{
return E_POINTER;
}
Node *pNode = new Node(item);
if (pNode == NULL)
{
return E_OUTOFMEMORY;
}
Node *pAfter = pBefore->next;
pBefore->next = pNode;
pAfter->prev = pNode;
pNode->prev = pBefore;
pNode->next = pAfter;
m_count++;
return S_OK;
}
virtual HRESULT GetItem(const Node *pNode, Ptr* ppItem)
{
if (pNode == NULL || ppItem == NULL)
{
return E_POINTER;
}
*ppItem = pNode->item;
if (*ppItem)
{
(*ppItem)->AddRef();
}
return S_OK;
}
// RemoveItem:
// Removes a node and optionally returns the item.
// ppItem can be NULL.
virtual HRESULT RemoveItem(Node *pNode, Ptr *ppItem)
{
if (pNode == NULL)
{
return E_POINTER;
}
assert(pNode != &m_anchor); // We should never try to remove the anchor node.
if (pNode == &m_anchor)
{
return E_INVALIDARG;
}
Ptr item;
// The next node's previous is this node's previous.
pNode->next->prev = pNode->prev;
// The previous node's next is this node's next.
pNode->prev->next = pNode->next;
item = pNode->item;
if (ppItem)
{
*ppItem = item;
if (*ppItem)
{
(*ppItem)->AddRef();
}
}
delete pNode;
m_count--;
return S_OK;
}
public:
ComPtrListEx()
{
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
}
virtual ~ComPtrListEx()
{
Clear();
}
void Clear()
{
Node *n = m_anchor.next;
// Delete the nodes
while (n != &m_anchor)
{
if (n->item)
{
n->item->Release();
n->item = NULL;
}
Node *tmp = n->next;
delete n;
n = tmp;
}
// Reset the anchor to point at itself
m_anchor.next = &m_anchor;
m_anchor.prev = &m_anchor;
m_count = 0;
}
// Insertion functions
HRESULT InsertBack(Ptr item)
{
return InsertAfter(item, m_anchor.prev);
}
HRESULT InsertFront(Ptr item)
{
return InsertAfter(item, &m_anchor);
}
// RemoveBack: Removes the tail of the list and returns the value.
// ppItem can be NULL if you don't want the item back.
HRESULT RemoveBack(Ptr *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Back(), ppItem);
}
}
// RemoveFront: Removes the head of the list and returns the value.
// ppItem can be NULL if you don't want the item back.
HRESULT RemoveFront(Ptr *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return RemoveItem(Front(), ppItem);
}
}
// GetBack: Gets the tail item.
HRESULT GetBack(Ptr *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Back(), ppItem);
}
}
// GetFront: Gets the front item.
HRESULT GetFront(Ptr *ppItem)
{
if (IsEmpty())
{
return E_FAIL;
}
else
{
return GetItem(Front(), ppItem);
}
}
// GetCount: Returns the number of items in the list.
DWORD GetCount() const { return m_count; }
bool IsEmpty() const
{
return (GetCount() == 0);
}
// Enumerator functions
POSITION FrontPosition()
{
if (IsEmpty())
{
return POSITION(NULL);
}
else
{
return POSITION(Front());
}
}
POSITION EndPosition() const
{
return POSITION();
}
HRESULT GetItemByPosition(POSITION pos, Ptr *ppItem)
{
if (pos.pNode)
{
return GetItem(pos.pNode, ppItem);
}
else
{
return E_FAIL;
}
}
POSITION Next(const POSITION pos)
{
if (pos.pNode && (pos.pNode->next != &m_anchor))
{
return POSITION(pos.pNode->next);
}
else
{
return POSITION(NULL);
}
}
};

Просмотреть файл

@ -12,9 +12,9 @@ const FOURCC FOURCC_RGB24 = 20;
const GUID* g_MediaSubtypes[] =
{
&MFVideoFormat_RGB24,
//&MEDIASUBTYPE_NV12,
//&MEDIASUBTYPE_YUY2,
//&MEDIASUBTYPE_UYVY
&MEDIASUBTYPE_NV12,
&MEDIASUBTYPE_YUY2,
&MEDIASUBTYPE_UYVY
};
// Number of media types in the aray.
@ -72,7 +72,9 @@ TransformBlur::TransformBlur(HRESULT& hr) :
m_cbImageSize(0),
m_pTransformFn(NULL),
m_pD3DDeviceManager(NULL),
m_pDecoderService(NULL)
m_pHandle(NULL),
m_pD3DDevice(NULL),
m_pD3DVideoDevice(NULL)
{
}
@ -84,8 +86,11 @@ TransformBlur::~TransformBlur()
SAFE_RELEASE(m_pInputType);
SAFE_RELEASE(m_pOutputType);
SAFE_RELEASE(m_pSample);
m_pD3DDeviceManager->CloseDeviceHandle(m_pHandle);
SAFE_RELEASE(m_pD3DDeviceManager);
SAFE_RELEASE(m_pDecoderService);
SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_pD3DVideoDevice);
}
// IUnknown methods
@ -492,44 +497,31 @@ HRESULT TransformBlur::SetInputType(
CHECK_HR(hr = OnCheckInputType(pType));
}
// Find a d3d decoder configuration, if have a video device to use
// TODO: Clear false if this is the way to go later
// TODO: Move to checkinputtype
if (m_pD3DDeviceManager && m_pDecoderService)
// Find a decoder configuration
if (m_pD3DDeviceManager)
{
UINT numDevices = 0;
UINT numFormats = 0;
GUID* pguids = NULL;
D3DFORMAT* d3dFormats = NULL;
m_pDecoderService->GetDecoderDeviceGuids(&numDevices, &pguids);
for (UINT i = 0; i < numDevices; i++)
UINT numProfiles = m_pD3DVideoDevice->GetVideoDecoderProfileCount();
for (UINT i = 0; i < numProfiles; i++)
{
g = pguids[i];
if (g == DXVA2_ModeH264_E || g == DXVA2_ModeH264_VLD_NoFGT)
{
OutputDebugString(L"Found h264 decoder E");
//break;
}
m_pDecoderService->GetDecoderRenderTargets(g, &numFormats, &d3dFormats);
for (UINT j = 0; j < numDevices; j++)
{
d = d3dFormats[j];
//(D3DFORMAT)subtype.Data1;
for (int k = 0; k < g_cNumSubtypes; k++)
{
GUID gtest = *g_MediaSubtypes[k];
if (d == (D3DFORMAT)(gtest.Data1))
{
OutputDebugString(L"Found a decoder with a supported format");
// pType = ;
break;
}
}
GUID pDecoderProfile = GUID_NULL;
CHECK_HR(hr = m_pD3DVideoDevice->GetVideoDecoderProfile(i, &pDecoderProfile));
BOOL rgbSupport;
hr = m_pD3DVideoDevice->CheckVideoDecoderFormat(&pDecoderProfile, DXGI_FORMAT_AYUV, &rgbSupport);
// IF H264 and supports a yuv/rgb format
if (rgbSupport) {
// D3D11_DECODER_PROFILE_H264_VLD_NOFGT
OutputDebugString(L"supports AYUV!");
}
}
// TODO: Move to done
CoTaskMemFree(pguids);
CoTaskMemFree(d3dFormats);
@ -854,14 +846,14 @@ HRESULT TransformBlur::OnSetD3DManager(ULONG_PTR ulParam)
}
// Get a handle to the DXVA decoder service
// TODO: Change to give to the field instead of local variable
hr = m_pD3DDeviceManager->OpenDeviceHandle(&p_deviceHandle);
// Get the d3d11 device
m_pD3DDeviceManager->GetVideoService(p_deviceHandle, IID_ID3D12Device, (void**) &pd3dDevice);
m_pD3DDeviceManager->GetVideoService(p_deviceHandle, IID_ID3D12Device, (void**) &m_pD3DDevice);
// Get the d3d11 video device
hr = m_pD3DDeviceManager->GetVideoService(p_deviceHandle, IID_ID3D11VideoDevice, (void**) &m_pDecoderService);
hr = m_pD3DDeviceManager->GetVideoService(p_deviceHandle, IID_ID3D11VideoDevice, (void**) &m_pD3DVideoDevice);
if (FAILED(hr))
{
@ -869,6 +861,8 @@ HRESULT TransformBlur::OnSetD3DManager(ULONG_PTR ulParam)
ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, NULL);
}
// TOOD: Get the ID3D11DeviceContext and use to add multi-thread protection on the device context
done:
//TODO: Safe release anything as needed
SAFE_RELEASE(ptr);
@ -888,7 +882,6 @@ HRESULT TransformBlur::ProcessInput(
)
{
AutoLock lock(m_critSec);
IDirect3DSurface11* ppSurface = NULL;
IMFMediaBuffer* pBuffer = NULL;
if (pSample == NULL)
@ -935,12 +928,12 @@ HRESULT TransformBlur::ProcessInput(
m_pSample = pSample;
// Check if for some reason already have d3dsurface
hr = pSample->GetBufferByIndex(0, &pBuffer);
/*hr = pSample->GetBufferByIndex(0, &pBuffer);
if (SUCCEEDED(hr))
{
HRESULT test = MFGetService(pBuffer, MR_BUFFER_SERVICE, IID_PPV_ARGS(ppSurface));
pBuffer->Release();
}
}*/
pSample->AddRef(); // Hold a reference count on the sample.
@ -1236,21 +1229,6 @@ HRESULT TransformBlur::OnSetInputType(IMFMediaType* pmt)
// Update the format information.
UpdateFormatInfo();
IDirect3DSurface9* ppSurfaces[4];
if (m_pDecoderService) {
hr = m_pDecoderService->CreateSurface(
m_imageWidthInPixels,
m_imageHeightInPixels,
3, // Number of backbuffers
des.Format, // D3DFORMAT
D3DPOOL_DEFAULT, // Memory pool to create the surfaces
0, // Reserved
DXVA2_VideoProcessorRenderTarget, //DXVATYPE Type of surface to make
ppSurfaces, // Out array of d3d9 surfaces
NULL
);
}
return S_OK;
}

Просмотреть файл

@ -19,7 +19,7 @@
#define USE_LOGGING
#include "common.h"
#include "common/common.h"
using namespace MediaFoundationSamples;
#include "SegmentModel.h"
@ -212,8 +212,12 @@ private:
IMAGE_TRANSFORM_FN m_pTransformFn;
// D3D fields
IMFDXGIDeviceManager* m_pD3DDeviceManager;
IDirectXVideoDecoderService* m_pDecoderService;
IMFDXGIDeviceManager* m_pD3DDeviceManager;
HANDLE m_pHandle; // Handle to the current device
// IDirectXVideoDecoderService*m_pDecoderService;
ID3D11Device* m_pD3DDevice;
ID3D11VideoDevice* m_pD3DVideoDevice;
// Model fields
SegmentModel m_segmentModel;
};

Просмотреть файл

@ -958,55 +958,6 @@ done:
return hr;
}
// Create an object for a renderer, based on the stream media type.
HRESULT CreateMediaSink(
IMFStreamDescriptor* pSourceSD, // Pointer to the stream descriptor.
HWND hVideoWindow, // Handle to the video clipping window.
IMFMediaSink** ppSink
)
{
IMFMediaTypeHandler* pHandler = NULL;
IMFMediaSink* pSink = NULL;
// Get the media type handler for the stream.
HRESULT hr = pSourceSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
// Get the major media type.
GUID guidMajorType;
hr = pHandler->GetMajorType(&guidMajorType);
if (FAILED(hr))
{
goto done;
}
if (MFMediaType_Video == guidMajorType)
{
hr = CreateDX11VideoRenderer(__uuidof(IMFMediaSink), (void**)&pSink);
}
else
{
// Unknown stream type.
hr = E_FAIL;
// Optionally, you could deselect this stream instead of failing.
}
if (FAILED(hr))
{
goto done;
}
// Return IMFMediaSink pointer to caller.
*ppSink = pSink;
(*ppSink)->AddRef();
done:
SafeRelease(&pHandler);
SafeRelease(&pSink);
return hr;
}
// Create an activation object for a renderer, based on the stream media type.
@ -1249,65 +1200,6 @@ done:
return hr;
}
// Add an output node to a topology.
HRESULT AddOutputNode(
IMFTopology* pTopology, // Topology.
IMFMediaSink* pSink, // Media sink activation object.
DWORD dwId, // Identifier of the stream sink.
IMFTopologyNode** ppNode) // Receives the node pointer.
{
IMFTopologyNode* pNode = NULL;
IDirect3DDeviceManager9* man = NULL;
IMFStreamSink* pStreamSink = NULL;
// Create the node.
HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
if (FAILED(hr))
{
goto done;
}
CHECK_HR(hr = pSink->GetStreamSinkByIndex(dwId, &pStreamSink));
// Set the object pointer.
hr = pNode->SetObject(pStreamSink);
if (FAILED(hr))
{
goto done;
}
// Set the stream sink ID attribute.
hr = pNode->SetUINT32(MF_TOPONODE_STREAMID, dwId);
if (FAILED(hr))
{
goto done;
}
hr = pNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
if (FAILED(hr))
{
goto done;
}
// Add the node to the topology.
hr = pTopology->AddNode(pNode);
if (FAILED(hr))
{
goto done;
}
BindOutputNode(pNode);
// Return the pointer to the caller.
*ppNode = pNode;
(*ppNode)->AddRef();
done:
SafeRelease(&pNode);
return hr;
}
//</SnippetPlayer.cpp>
HRESULT AddTransformNode(
IMFTopology* pTopology, // Topology.
IMFDXGIDeviceManager* d3dManager,
@ -1331,12 +1223,12 @@ HRESULT AddTransformNode(
{
hr = pNode->SetObject(pMFT);
//Determine if d3d-aware
//Determine if the MFT is d3d-aware
IMFAttributes* p_attr = NULL;
UINT32 p_aware = FALSE;
pMFT->GetAttributes(&p_attr);
hr = pMFT->GetAttributes(&p_attr);
UINT32 aware = MFGetAttributeUINT32(p_attr, MF_SA_D3D_AWARE, p_aware);
if (false && aware == TRUE && d3dManager) {
if (aware == TRUE && d3dManager) {
pMFT->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)d3dManager);
pNode->SetUINT32(MF_TOPONODE_D3DAWARE, TRUE);
}
@ -1404,8 +1296,6 @@ HRESULT AddBranchToPartialTopology(
goto done;
}
CHECK_HR(hr = CreateMediaSink(pSD, hVideoWnd, &pSink));
// Add a source node for this stream.
hr = AddSourceNode(pTopology, pSource, pPD, pSD, &pSourceNode);
if (FAILED(hr))
@ -1428,11 +1318,7 @@ HRESULT AddBranchToPartialTopology(
CHECK_HR(hr = pHandler->GetMajorType(&guidMajorType));
if (MFMediaType_Video == guidMajorType)
{
//TRACE((L"Adding MFT to video stream"));
class __declspec(uuid("{2F3DBC05-C011-4a8f-B264-E42E35C67BF4}")) ColorConverter; //"{98230571-0087-4204-b020-3282538e57d3}"
CLSID guid = __uuidof(ColorConverter);
// Query the output node for the d3d device manager
IUnknown* pNodeObject = NULL;
IMFDXGIDeviceManager* pD3DManager = NULL;
hr = pOutputNode->GetObject(&pNodeObject);