Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUnderground78 <underground78@users.sourceforge.net>2015-11-14 18:12:12 +0300
committerUnderground78 <underground78@users.sourceforge.net>2015-11-14 18:12:12 +0300
commitd911f14d5619d800819d6f4658e72236720b79af (patch)
tree62e98291589b13a60672bfa9f355df28442534df /src/filters/renderer
parent846eff07c13899dd7d3bf38251886b5263d41213 (diff)
parentf5d92cef4639bbe461bfc923ce2294df969a6d69 (diff)
Merge branch 'release-1.7.10'1.7.10
Diffstat (limited to 'src/filters/renderer')
-rw-r--r--src/filters/renderer/MpcAudioRenderer/IMpcAudioRendererFilter.h34
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.cpp1319
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.def5
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.h161
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.rc110
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj259
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj.filters58
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.cpp141
-rw-r--r--src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.h61
-rw-r--r--src/filters/renderer/MpcAudioRenderer/resource.h19
-rw-r--r--src/filters/renderer/MpcAudioRenderer/stdafx.cpp21
-rw-r--r--src/filters/renderer/MpcAudioRenderer/stdafx.h34
-rw-r--r--src/filters/renderer/VideoRenderers/AsyncCallback.h71
-rw-r--r--src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.cpp80
-rw-r--r--src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.h4
-rw-r--r--src/filters/renderer/VideoRenderers/DX9RenderingEngine.cpp7
-rw-r--r--src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.cpp212
-rw-r--r--src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.h24
-rw-r--r--src/filters/renderer/VideoRenderers/FocusThread.cpp31
-rw-r--r--src/filters/renderer/VideoRenderers/FocusThread.h9
-rw-r--r--src/filters/renderer/VideoRenderers/IPinHook.cpp67
-rw-r--r--src/filters/renderer/VideoRenderers/IPinHook.h4
-rw-r--r--src/filters/renderer/VideoRenderers/RenderersSettings.cpp18
-rw-r--r--src/filters/renderer/VideoRenderers/RenderersSettings.h1
-rw-r--r--src/filters/renderer/VideoRenderers/SyncRenderer.cpp487
-rw-r--r--src/filters/renderer/VideoRenderers/SyncRenderer.h28
-rw-r--r--src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj1
-rw-r--r--src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj.filters3
-rw-r--r--src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.cpp142
-rw-r--r--src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.h96
30 files changed, 750 insertions, 2757 deletions
diff --git a/src/filters/renderer/MpcAudioRenderer/IMpcAudioRendererFilter.h b/src/filters/renderer/MpcAudioRenderer/IMpcAudioRendererFilter.h
deleted file mode 100644
index a9e33ebf5..000000000
--- a/src/filters/renderer/MpcAudioRenderer/IMpcAudioRendererFilter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * (C) 2010-2013 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-interface __declspec(uuid("495D2C66-D430-439b-9DEE-40F9B7929BBA"))
-IMpcAudioRendererFilter :
-public IUnknown {
- STDMETHOD(Apply()) PURE;
-
- STDMETHOD(SetWasapiMode(BOOL nValue)) PURE;
- STDMETHOD_(BOOL, GetWasapiMode()) PURE;
- STDMETHOD(SetMuteFastForward(BOOL nValue)) PURE;
- STDMETHOD_(BOOL, GetMuteFastForward()) PURE;
- STDMETHOD(SetSoundDevice(CString nValue)) PURE;
- STDMETHOD_(CString, GetSoundDevice()) PURE;
-};
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.cpp b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.cpp
deleted file mode 100644
index 6d7498e21..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.cpp
+++ /dev/null
@@ -1,1319 +0,0 @@
-/*
- * (C) 2009-2014 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "stdafx.h"
-
-#ifdef STANDALONE_FILTER
-#include <InitGuid.h>
-#endif
-#include "moreuuids.h"
-#include "../../../DSUtil/DSUtil.h"
-#include <ks.h>
-#include <ksmedia.h>
-
-#include "MpcAudioRenderer.h"
-
-
-#ifdef STANDALONE_FILTER
-
-const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] = {
- {&GUID_NULL},
-};
-
-const AMOVIESETUP_PIN sudpPins[] = {
- {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, nullptr, _countof(sudPinTypesIn), sudPinTypesIn},
-};
-
-const AMOVIESETUP_FILTER sudFilter[] = {
- {&__uuidof(CMpcAudioRenderer), MpcAudioRendererName, 0x40000001, _countof(sudpPins), sudpPins, CLSID_AudioRendererCategory},
-};
-
-CFactoryTemplate g_Templates[] = {
- {sudFilter[0].strName, &__uuidof(CMpcAudioRenderer), CreateInstance<CMpcAudioRenderer>, nullptr, &sudFilter[0]},
- {L"CMpcAudioRendererPropertyPage", &__uuidof(CMpcAudioRendererSettingsWnd), CreateInstance<CInternalPropertyPageTempl<CMpcAudioRendererSettingsWnd>>},
-};
-
-int g_cTemplates = _countof(g_Templates);
-
-STDAPI DllRegisterServer()
-{
- return AMovieDllRegisterServer2(TRUE);
-}
-
-STDAPI DllUnregisterServer()
-{
- return AMovieDllRegisterServer2(FALSE);
-}
-
-#include "../../FilterApp.h"
-
-CFilterApp theApp;
-
-#endif
-
-static GUID lpSoundGUID = {0xdef00000, 0x9c6d, 0x47ed, {0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03}}; //DSDEVID_DefaultPlayback from dsound.h
-
-bool CALLBACK DSEnumProc2(LPGUID lpGUID,
- LPCTSTR lpszDesc,
- LPCTSTR lpszDrvName,
- LPVOID lpContext)
-{
- CString* pStr = (CString*)lpContext;
- ASSERT(pStr);
- CString strGUID = *pStr;
-
- if (lpGUID != nullptr) { // nullptr only for "Primary Sound Driver".
- if (strGUID == lpszDesc) {
- memcpy((void*)&lpSoundGUID, lpGUID, sizeof(GUID));
- }
- }
-
- return TRUE;
-}
-
-CMpcAudioRenderer::CMpcAudioRenderer(LPUNKNOWN punk, HRESULT* phr)
- : CBaseRenderer(__uuidof(this), MpcAudioRendererName, punk, phr)
- , m_pDS(nullptr)
- , m_pDSBuffer(nullptr)
- , m_dwDSWriteOff(0)
- , m_pWaveFileFormat(nullptr)
- , m_nDSBufSize(0)
- , m_pReferenceClock(nullptr)
- , m_dRate(1.0)
- , m_lVolume(DSBVOLUME_MIN)
- , m_pSoundTouch(nullptr)
- , m_useWASAPI(true)
- , m_bMuteFastForward(false)
- , m_pMMDevice(nullptr)
- , m_pAudioClient(nullptr)
- , m_pRenderClient(nullptr)
- , m_nFramesInBuffer(0)
- , m_hnsPeriod(0)
- , m_hnsActualDuration(0)
- , m_hTask(nullptr)
- , m_bufferSize(0)
- , m_isAudioClientStarted(false)
- , m_lastBufferTime(0)
- , m_pfAvSetMmThreadCharacteristicsW(nullptr)
- , m_pfAvRevertMmThreadCharacteristics(nullptr)
-{
-#ifdef STANDALONE_FILTER
- CRegKey key;
- ULONG len;
-
- if (ERROR_SUCCESS == key.Open(HKEY_CURRENT_USER, _T("Software\\MPC-HC\\Filters\\MPC-HC Audio Renderer"), KEY_READ)) {
- DWORD dw;
- TCHAR buff[256];
- if (ERROR_SUCCESS == key.QueryDWORDValue(_T("UseWasapi"), dw)) {
- m_useWASAPI = !!dw;
- }
- if (ERROR_SUCCESS == key.QueryDWORDValue(_T("MuteFastForward"), dw)) {
- m_bMuteFastForward = !!dw;
- }
- len = _countof(buff);
- ZeroMemory(buff, sizeof(buff));
- if (ERROR_SUCCESS == key.QueryStringValue(_T("SoundDevice"), buff, &len)) {
- m_csSound_Device = CString(buff);
- }
- }
-#else
- m_useWASAPI = !!AfxGetApp()->GetProfileInt(_T("Filters\\MPC-HC Audio Renderer"), _T("UseWasapi"), m_useWASAPI);
- m_bMuteFastForward = !!AfxGetApp()->GetProfileInt(_T("Filters\\MPC-HC Audio Renderer"), _T("MuteFastForward"), m_bMuteFastForward);
- m_csSound_Device = AfxGetApp()->GetProfileString(_T("Filters\\MPC-HC Audio Renderer"), _T("SoundDevice"));
-#endif
- m_useWASAPIAfterRestart = m_useWASAPI;
-
-
- // Load Vista+ specific DLLs
- m_hLibAVRT = LoadLibrary(L"avrt.dll");
- if (m_hLibAVRT != nullptr) {
- m_pfAvSetMmThreadCharacteristicsW = (PTR_AvSetMmThreadCharacteristicsW) GetProcAddress(m_hLibAVRT, "AvSetMmThreadCharacteristicsW");
- m_pfAvRevertMmThreadCharacteristics = (PTR_AvRevertMmThreadCharacteristics) GetProcAddress(m_hLibAVRT, "AvRevertMmThreadCharacteristics");
- } else {
- m_useWASAPI = false; // WASAPI is not available below Vista
- }
-
- TRACE(_T("CMpcAudioRenderer constructor\n"));
- if (!m_useWASAPI) {
- DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc2, (void*)&m_csSound_Device);
- m_pSoundTouch = DEBUG_NEW soundtouch::SoundTouch();
- *phr = DirectSoundCreate8(&lpSoundGUID, &m_pDS, nullptr);
- }
-}
-
-CMpcAudioRenderer::~CMpcAudioRenderer()
-{
- Stop();
-
- SAFE_DELETE(m_pSoundTouch);
- SAFE_RELEASE(m_pDSBuffer);
- SAFE_RELEASE(m_pDS);
-
- SAFE_RELEASE(m_pRenderClient);
- SAFE_RELEASE(m_pAudioClient);
- SAFE_RELEASE(m_pMMDevice);
-
- if (m_pReferenceClock) {
- SetSyncSource(nullptr);
- SAFE_RELEASE(m_pReferenceClock);
- }
-
- if (m_pWaveFileFormat) {
- BYTE* p = (BYTE*)m_pWaveFileFormat;
- SAFE_DELETE_ARRAY(p);
- }
-
- if (m_hTask != nullptr && m_pfAvRevertMmThreadCharacteristics != nullptr) {
- m_pfAvRevertMmThreadCharacteristics(m_hTask);
- }
-
- if (m_hLibAVRT) {
- FreeLibrary(m_hLibAVRT);
- }
-}
-
-HRESULT CMpcAudioRenderer::CheckInputType(const CMediaType* pmt)
-{
- return CheckMediaType(pmt);
-}
-
-HRESULT CMpcAudioRenderer::CheckMediaType(const CMediaType* pmt)
-{
- HRESULT hr = S_OK;
- if (pmt == nullptr) {
- return E_INVALIDARG;
- }
- TRACE(_T("CMpcAudioRenderer::CheckMediaType\n"));
- WAVEFORMATEX* pwfx = (WAVEFORMATEX*) pmt->Format();
-
- if (pwfx == nullptr) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
-
- if ((pmt->majortype != MEDIATYPE_Audio) ||
- (pmt->formattype != FORMAT_WaveFormatEx)) {
- TRACE(_T("CMpcAudioRenderer::CheckMediaType Not supported\n"));
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
-
- if (m_useWASAPI) {
- hr = CheckAudioClient((WAVEFORMATEX*)nullptr);
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::CheckMediaType Error on check audio client\n"));
- return hr;
- }
- if (!m_pAudioClient) {
- TRACE(_T("CMpcAudioRenderer::CheckMediaType Error, audio client not loaded\n"));
- return VFW_E_CANNOT_CONNECT;
- }
-
- if (m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, pwfx, nullptr) != S_OK) {
- TRACE(_T("CMpcAudioRenderer::CheckMediaType WASAPI client refused the format\n"));
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- TRACE(_T("CMpcAudioRenderer::CheckMediaType WASAPI client accepted the format\n"));
- } else if (pwfx->wFormatTag != WAVE_FORMAT_PCM) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- return S_OK;
-}
-
-void CMpcAudioRenderer::OnReceiveFirstSample(IMediaSample* pMediaSample)
-{
- if (!m_useWASAPI) {
- ClearBuffer();
- }
-}
-
-BOOL CMpcAudioRenderer::ScheduleSample(IMediaSample* pMediaSample)
-{
- REFERENCE_TIME StartSample;
- REFERENCE_TIME EndSample;
-
- // Is someone pulling our leg
- if (pMediaSample == nullptr) {
- return FALSE;
- }
-
- // Get the next sample due up for rendering. If there aren't any ready
- // then GetNextSampleTimes returns an error. If there is one to be done
- // then it succeeds and yields the sample times. If it is due now then
- // it returns S_OK other if it's to be done when due it returns S_FALSE
- HRESULT hr = GetSampleTimes(pMediaSample, &StartSample, &EndSample);
- if (FAILED(hr)) {
- return FALSE;
- }
-
- // If we don't have a reference clock then we cannot set up the advise
- // time so we simply set the event indicating an image to render. This
- // will cause us to run flat out without any timing or synchronization
- if (hr == S_OK) {
- EXECUTE_ASSERT(SetEvent((HANDLE) m_RenderEvent));
- return TRUE;
- }
-
- if (m_dRate <= 1.1) {
- ASSERT(m_dwAdvise == 0);
- ASSERT(m_pClock);
- WaitForSingleObject((HANDLE)m_RenderEvent, 0);
-
- hr = m_pClock->AdviseTime((REFERENCE_TIME) m_tStart, StartSample, (HEVENT)(HANDLE) m_RenderEvent, &m_dwAdvise);
- if (SUCCEEDED(hr)) {
- return TRUE;
- }
- } else {
- DoRenderSample(pMediaSample);
- }
-
- // We could not schedule the next sample for rendering despite the fact
- // we have a valid sample here. This is a fair indication that either
- // the system clock is wrong or the time stamp for the sample is duff
- ASSERT(m_dwAdvise == 0);
-
- return FALSE;
-}
-
-HRESULT CMpcAudioRenderer::DoRenderSample(IMediaSample* pMediaSample)
-{
- if (m_useWASAPI) {
- return DoRenderSampleWasapi(pMediaSample);
- } else {
- return DoRenderSampleDirectSound(pMediaSample);
- }
-}
-
-STDMETHODIMP CMpcAudioRenderer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
-{
- if (riid == IID_IReferenceClock) {
- return GetReferenceClockInterface(riid, ppv);
- } else if (riid == IID_IDispatch) {
- return GetInterface(static_cast<IDispatch*>(this), ppv);
- } else if (riid == IID_IBasicAudio) {
- return GetInterface(static_cast<IBasicAudio*>(this), ppv);
- } else if (riid == __uuidof(ISpecifyPropertyPages)) {
- return GetInterface(static_cast<ISpecifyPropertyPages*>(this), ppv);
- } else if (riid == __uuidof(ISpecifyPropertyPages2)) {
- return GetInterface(static_cast<ISpecifyPropertyPages2*>(this), ppv);
- } else if (riid == __uuidof(IMpcAudioRendererFilter)) {
- return GetInterface(static_cast<IMpcAudioRendererFilter*>(this), ppv);
- }
-
- return CBaseRenderer::NonDelegatingQueryInterface(riid, ppv);
-}
-
-HRESULT CMpcAudioRenderer::SetMediaType(const CMediaType* pmt)
-{
- CheckPointer(pmt, E_POINTER);
- TRACE(_T("CMpcAudioRenderer::SetMediaType\n"));
-
- if (m_useWASAPI) {
- // New media type set but render client already initialized => reset it
- if (m_pRenderClient != nullptr) {
- WAVEFORMATEX* pNewWf = (WAVEFORMATEX*) pmt->Format();
- TRACE(_T("CMpcAudioRenderer::SetMediaType Render client already initialized. Reinitialization...\n"));
- if (FAILED(CheckAudioClient(pNewWf))) {
- TRACE(_T("CMpcAudioRenderer::SetMediaType Error on check audio client\n"));
- return E_FAIL;
- }
- }
- }
-
- if (m_pWaveFileFormat) {
- BYTE* p = (BYTE*)m_pWaveFileFormat;
- SAFE_DELETE_ARRAY(p);
- }
- m_pWaveFileFormat = nullptr;
-
- WAVEFORMATEX* pwf = (WAVEFORMATEX*) pmt->Format();
- if (pwf != nullptr) {
- int size = sizeof(WAVEFORMATEX) + pwf->cbSize;
-
- m_pWaveFileFormat = (WAVEFORMATEX*)DEBUG_NEW BYTE[size];
- if (!m_pWaveFileFormat) {
- return E_OUTOFMEMORY;
- }
-
- memcpy(m_pWaveFileFormat, pwf, size);
-
-
- if (!m_useWASAPI && m_pSoundTouch && (pwf->nChannels <= 2)) {
- m_pSoundTouch->setSampleRate(pwf->nSamplesPerSec);
- m_pSoundTouch->setChannels(pwf->nChannels);
- m_pSoundTouch->setTempoChange(0);
- m_pSoundTouch->setPitchSemiTones(0);
- }
- }
-
- return CBaseRenderer::SetMediaType(pmt);
-}
-
-HRESULT CMpcAudioRenderer::CompleteConnect(IPin* pReceivePin)
-{
- HRESULT hr = S_OK;
- TRACE(_T("CMpcAudioRenderer::CompleteConnect\n"));
-
- if (!m_useWASAPI && !m_pDS) {
- return E_FAIL;
- }
-
- if (SUCCEEDED(hr)) {
- hr = CBaseRenderer::CompleteConnect(pReceivePin);
- }
- if (SUCCEEDED(hr)) {
- hr = InitCoopLevel();
- }
-
- if (!m_useWASAPI) {
- if (SUCCEEDED(hr)) {
- hr = CreateDSBuffer();
- }
- }
- if (SUCCEEDED(hr)) {
- TRACE(_T("CMpcAudioRenderer::CompleteConnect Success\n"));
- }
- return hr;
-}
-
-STDMETHODIMP CMpcAudioRenderer::Run(REFERENCE_TIME tStart)
-{
- HRESULT hr;
-
- if (m_State == State_Running) {
- return NOERROR;
- }
-
- if (m_useWASAPI) {
- hr = CheckAudioClient(m_pWaveFileFormat);
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::Run Error on check audio client\n"));
- return hr;
- }
- // Rather start the client at the last moment when the buffer is fed
- /*hr = pAudioClient->Start();
- if (FAILED (hr))
- {
- TRACE(_T("CMpcAudioRenderer::Run Start error"));
- return hr;
- }*/
- } else {
- if (m_pDSBuffer &&
- m_pPosition &&
- m_pWaveFileFormat &&
- SUCCEEDED(m_pPosition->GetRate(&m_dRate))) {
- if (m_dRate < 1.0) {
- hr = m_pDSBuffer->SetFrequency((long)(m_pWaveFileFormat->nSamplesPerSec * m_dRate));
- if (FAILED(hr)) {
- return hr;
- }
- } else {
- hr = m_pDSBuffer->SetFrequency((long)m_pWaveFileFormat->nSamplesPerSec);
- m_pSoundTouch->setRateChange((float)(m_dRate - 1.0) * 100);
-
- if (m_bMuteFastForward) {
- if (m_dRate == 1.0) {
- m_pDSBuffer->SetVolume(m_lVolume);
- } else {
- m_pDSBuffer->SetVolume(DSBVOLUME_MIN);
- }
- }
- }
- }
-
- ClearBuffer();
- }
- hr = CBaseRenderer::Run(tStart);
-
- return hr;
-}
-
-STDMETHODIMP CMpcAudioRenderer::Stop()
-{
- if (m_pDSBuffer) {
- m_pDSBuffer->Stop();
- }
- m_isAudioClientStarted = false;
-
- return CBaseRenderer::Stop();
-};
-
-STDMETHODIMP CMpcAudioRenderer::Pause()
-{
- if (m_pDSBuffer) {
- m_pDSBuffer->Stop();
- }
- if (m_pAudioClient && m_isAudioClientStarted) {
- m_pAudioClient->Stop();
- }
- m_isAudioClientStarted = false;
-
- return CBaseRenderer::Pause();
-};
-
-// === IDispatch
-STDMETHODIMP CMpcAudioRenderer::GetTypeInfoCount(UINT* pctinfo)
-{
- return E_NOTIMPL;
-}
-
-STDMETHODIMP CMpcAudioRenderer::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
-{
- return E_NOTIMPL;
-}
-
-STDMETHODIMP CMpcAudioRenderer::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
-{
- return E_NOTIMPL;
-}
-
-STDMETHODIMP CMpcAudioRenderer::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
-{
- return E_NOTIMPL;
-}
-
-// === IBasicAudio
-STDMETHODIMP CMpcAudioRenderer::put_Volume(long lVolume)
-{
- m_lVolume = lVolume;
- if (!m_useWASAPI && m_pDSBuffer) {
- return m_pDSBuffer->SetVolume(lVolume);
- }
-
- return S_OK;
-}
-
-STDMETHODIMP CMpcAudioRenderer::get_Volume(long* plVolume)
-{
- if (!m_useWASAPI && m_pDSBuffer) {
- return m_pDSBuffer->GetVolume(plVolume);
- }
-
- return S_OK;
-}
-
-STDMETHODIMP CMpcAudioRenderer::put_Balance(long lBalance)
-{
- if (!m_useWASAPI && m_pDSBuffer) {
- return m_pDSBuffer->SetPan(lBalance);
- }
-
- return S_OK;
-}
-
-STDMETHODIMP CMpcAudioRenderer::get_Balance(long* plBalance)
-{
- if (!m_useWASAPI && m_pDSBuffer) {
- return m_pDSBuffer->GetPan(plBalance);
- }
-
- return S_OK;
-}
-
-// === ISpecifyPropertyPages2
-STDMETHODIMP CMpcAudioRenderer::GetPages(CAUUID* pPages)
-{
- CheckPointer(pPages, E_POINTER);
-
- HRESULT hr = S_OK;
-
- pPages->cElems = 1;
- pPages->pElems = (GUID*)CoTaskMemAlloc(sizeof(GUID) * pPages->cElems);
- if (pPages->pElems != nullptr) {
- pPages->pElems[0] = __uuidof(CMpcAudioRendererSettingsWnd);
- } else {
- hr = E_OUTOFMEMORY;
- }
-
- return hr;
-}
-
-STDMETHODIMP CMpcAudioRenderer::CreatePage(const GUID& guid, IPropertyPage** ppPage)
-{
- CheckPointer(ppPage, E_POINTER);
-
- if (*ppPage != nullptr) {
- return E_INVALIDARG;
- }
-
- HRESULT hr;
-
- if (guid == __uuidof(CMpcAudioRendererSettingsWnd)) {
- (*ppPage = DEBUG_NEW CInternalPropertyPageTempl<CMpcAudioRendererSettingsWnd>(nullptr, &hr))->AddRef();
- }
-
- return *ppPage ? S_OK : E_FAIL;
-}
-
-// === IMpcAudioRendererFilter
-STDMETHODIMP CMpcAudioRenderer::Apply()
-{
-#ifdef STANDALONE_FILTER
- CRegKey key;
- if (ERROR_SUCCESS == key.Create(HKEY_CURRENT_USER, _T("Software\\MPC-HC\\Filters\\MPC-HC Audio Renderer"))) {
- key.SetDWORDValue(_T("UseWasapi"), m_useWASAPIAfterRestart);
- key.SetDWORDValue(_T("MuteFastForward"), m_bMuteFastForward);
- key.SetStringValue(_T("SoundDevice"), m_csSound_Device);
- }
-#else
- AfxGetApp()->WriteProfileInt(_T("Filters\\MPC-HC Audio Renderer"), _T("UseWasapi"), m_useWASAPI);
- AfxGetApp()->WriteProfileInt(_T("Filters\\MPC-HC Audio Renderer"), _T("MuteFastForward"), m_bMuteFastForward);
- AfxGetApp()->WriteProfileString(_T("Filters\\MPC-HC Audio Renderer"), _T("SoundDevice"), m_csSound_Device);
-#endif
-
- return S_OK;
-}
-
-STDMETHODIMP CMpcAudioRenderer::SetWasapiMode(BOOL nValue)
-{
- CAutoLock cAutoLock(&m_csProps);
- m_useWASAPIAfterRestart = !!nValue;
- return S_OK;
-}
-STDMETHODIMP_(BOOL) CMpcAudioRenderer::GetWasapiMode()
-{
- CAutoLock cAutoLock(&m_csProps);
- return m_useWASAPIAfterRestart;
-}
-
-STDMETHODIMP CMpcAudioRenderer::SetMuteFastForward(BOOL nValue)
-{
- CAutoLock cAutoLock(&m_csProps);
- m_bMuteFastForward = !!nValue;
- return S_OK;
-}
-STDMETHODIMP_(BOOL) CMpcAudioRenderer::GetMuteFastForward()
-{
- CAutoLock cAutoLock(&m_csProps);
- return m_bMuteFastForward;
-}
-
-STDMETHODIMP CMpcAudioRenderer::SetSoundDevice(CString nValue)
-{
- CAutoLock cAutoLock(&m_csProps);
- m_csSound_Device = nValue;
- return S_OK;
-}
-STDMETHODIMP_(CString) CMpcAudioRenderer::GetSoundDevice()
-{
- CAutoLock cAutoLock(&m_csProps);
- return m_csSound_Device;
-}
-
-HRESULT CMpcAudioRenderer::GetReferenceClockInterface(REFIID riid, void** ppv)
-{
- HRESULT hr = S_OK;
-
- if (m_pReferenceClock) {
- return m_pReferenceClock->NonDelegatingQueryInterface(riid, ppv);
- }
-
- m_pReferenceClock = DEBUG_NEW CBaseReferenceClock(NAME("MPC-HC Audio Clock"), nullptr, &hr);
- if (!m_pReferenceClock) {
- return E_OUTOFMEMORY;
- }
-
- m_pReferenceClock->AddRef();
-
- hr = SetSyncSource(m_pReferenceClock);
- if (FAILED(hr)) {
- SetSyncSource(nullptr);
- return hr;
- }
-
- return GetReferenceClockInterface(riid, ppv);
-}
-
-HRESULT CMpcAudioRenderer::EndOfStream()
-{
- if (m_pDSBuffer) {
- m_pDSBuffer->Stop();
- }
-#if !FILEWRITER
- if (m_pAudioClient && m_isAudioClientStarted) {
- m_pAudioClient->Stop();
- }
-#endif
- m_isAudioClientStarted = false;
-
- return CBaseRenderer::EndOfStream();
-}
-
-#pragma region DirectSound
-
-HRESULT CMpcAudioRenderer::CreateDSBuffer()
-{
- CheckPointer(m_pWaveFileFormat, E_POINTER);
-
- HRESULT hr = S_OK;
- LPDIRECTSOUNDBUFFER pDSBPrimary = nullptr;
- DSBUFFERDESC dsbd;
- DSBUFFERDESC cDSBufferDesc;
- DSBCAPS bufferCaps;
- DWORD dwDSBufSize = m_pWaveFileFormat->nAvgBytesPerSec * 4;
-
- ZeroMemory(&bufferCaps, sizeof(bufferCaps));
- ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
-
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
- dsbd.dwBufferBytes = 0;
- dsbd.lpwfxFormat = nullptr;
- if (SUCCEEDED(hr = m_pDS->CreateSoundBuffer(&dsbd, &pDSBPrimary, nullptr))) {
- hr = pDSBPrimary->SetFormat(m_pWaveFileFormat);
- ASSERT(SUCCEEDED(hr));
- SAFE_RELEASE(pDSBPrimary);
- }
-
-
- SAFE_RELEASE(m_pDSBuffer);
- cDSBufferDesc.dwSize = sizeof(DSBUFFERDESC);
- cDSBufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 |
- DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
- cDSBufferDesc.dwBufferBytes = dwDSBufSize;
- cDSBufferDesc.dwReserved = 0;
- cDSBufferDesc.lpwfxFormat = m_pWaveFileFormat;
- cDSBufferDesc.guid3DAlgorithm = GUID_NULL;
-
- hr = m_pDS->CreateSoundBuffer(&cDSBufferDesc, &m_pDSBuffer, nullptr);
-
- m_nDSBufSize = 0;
- if (SUCCEEDED(hr)) {
- bufferCaps.dwSize = sizeof(bufferCaps);
- hr = m_pDSBuffer->GetCaps(&bufferCaps);
- }
- if (SUCCEEDED(hr)) {
- m_nDSBufSize = bufferCaps.dwBufferBytes;
- hr = ClearBuffer();
- m_pDSBuffer->SetFrequency((long)(m_pWaveFileFormat->nSamplesPerSec * m_dRate));
- }
-
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::ClearBuffer()
-{
- HRESULT hr = S_FALSE;
- void* pDSLockedBuffer = nullptr;
- DWORD dwDSLockedSize = 0;
-
- if (m_pDSBuffer) {
- m_dwDSWriteOff = 0;
- m_pDSBuffer->SetCurrentPosition(0);
-
- hr = m_pDSBuffer->Lock(0, 0, &pDSLockedBuffer, &dwDSLockedSize, nullptr, nullptr, DSBLOCK_ENTIREBUFFER);
- if (SUCCEEDED(hr)) {
- ZeroMemory(pDSLockedBuffer, dwDSLockedSize);
- hr = m_pDSBuffer->Unlock(pDSLockedBuffer, dwDSLockedSize, nullptr, 0);
- }
- }
-
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::InitCoopLevel()
-{
- HRESULT hr;
- IVideoWindow* pVideoWindow = nullptr;
- HWND hWnd = nullptr;
-
- hr = m_pGraph->QueryInterface(IID_PPV_ARGS(&pVideoWindow));
- if (SUCCEEDED(hr)) {
- pVideoWindow->get_Owner((OAHWND*)&hWnd);
- SAFE_RELEASE(pVideoWindow);
- }
- if (!hWnd) {
- hWnd = GetTopWindow(nullptr);
- }
-
- ASSERT(hWnd != nullptr);
- if (!m_useWASAPI) {
- hr = m_pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
- } else if (m_hTask == nullptr) {
- // Ask MMCSS to temporarily boost the thread priority
- // to reduce glitches while the low-latency stream plays.
- DWORD taskIndex = 0;
-
- if (m_pfAvSetMmThreadCharacteristicsW) {
- m_hTask = m_pfAvSetMmThreadCharacteristicsW(_T("Pro Audio"), &taskIndex);
- TRACE(_T("CMpcAudioRenderer::InitCoopLevel Putting thread in higher priority for WASAPI mode (lowest latency)\n"));
- hr = GetLastError();
- if (m_hTask == nullptr) {
- return hr;
- }
- }
- }
-
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::DoRenderSampleDirectSound(IMediaSample* pMediaSample)
-{
- HRESULT hr;
- DWORD dwStatus = 0;
- const long lSize = pMediaSample->GetActualDataLength();
- DWORD dwPlayCursor = 0;
- DWORD dwWriteCursor = 0;
-
- hr = m_pDSBuffer->GetStatus(&dwStatus);
-
- if (SUCCEEDED(hr) && (dwStatus & DSBSTATUS_BUFFERLOST)) {
- hr = m_pDSBuffer->Restore();
- }
-
- if ((SUCCEEDED(hr)) && ((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)) {
- hr = m_pDSBuffer->Play(0, 0, DSBPLAY_LOOPING);
- ASSERT(SUCCEEDED(hr));
- }
-
- if (SUCCEEDED(hr)) {
- hr = m_pDSBuffer->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor);
- }
-
- if (SUCCEEDED(hr)) {
- if (((dwPlayCursor < dwWriteCursor) &&
- (
- ((m_dwDSWriteOff >= dwPlayCursor) && (m_dwDSWriteOff <= dwWriteCursor))
- ||
- ((m_dwDSWriteOff < dwPlayCursor) && (m_dwDSWriteOff + lSize >= dwPlayCursor))
- )
- )
- ||
- ((dwWriteCursor < dwPlayCursor) &&
- (
- (m_dwDSWriteOff >= dwPlayCursor) || (m_dwDSWriteOff < dwWriteCursor)
- ))) {
- m_dwDSWriteOff = dwWriteCursor;
- }
-
- if (m_dwDSWriteOff >= (DWORD)m_nDSBufSize) {
- m_dwDSWriteOff = 0;
- }
- }
-
- if (SUCCEEDED(hr)) {
- hr = WriteSampleToDSBuffer(pMediaSample, nullptr);
- }
-
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::WriteSampleToDSBuffer(IMediaSample* pMediaSample, bool* looped)
-{
- CheckPointer(m_pDSBuffer, E_POINTER);
-
- REFERENCE_TIME rtStart = 0;
- REFERENCE_TIME rtStop = 0;
- HRESULT hr;
- bool loop = false;
- void* pDSLockedBuffers[2] = { nullptr, nullptr };
- DWORD dwDSLockedSize[2] = { 0, 0 };
- BYTE* pMediaBuffer = nullptr;
- long lSize = pMediaSample->GetActualDataLength();
-
- hr = pMediaSample->GetPointer(&pMediaBuffer);
-
- if (m_dRate > 1.0) {
- int nBytePerSample = m_pWaveFileFormat->nChannels * (m_pWaveFileFormat->wBitsPerSample / 8);
- m_pSoundTouch->putSamples((const short*)pMediaBuffer, lSize / nBytePerSample);
- lSize = m_pSoundTouch->receiveSamples((short*)pMediaBuffer, lSize / nBytePerSample) * nBytePerSample;
- }
-
- pMediaSample->GetTime(&rtStart, &rtStop);
-
- if (rtStart < 0) {
- DWORD dwPercent = (DWORD)((-rtStart * 100) / (rtStop - rtStart));
- DWORD dwRemove = (lSize * dwPercent / 100);
-
- dwRemove = (dwRemove / m_pWaveFileFormat->nBlockAlign) * m_pWaveFileFormat->nBlockAlign;
- pMediaBuffer += dwRemove;
- lSize -= dwRemove;
- }
-
- if (SUCCEEDED(hr)) {
- hr = m_pDSBuffer->Lock(m_dwDSWriteOff, lSize, &pDSLockedBuffers[0], &dwDSLockedSize[0], &pDSLockedBuffers[1], &dwDSLockedSize[1], 0);
- }
- if (SUCCEEDED(hr)) {
- if (pDSLockedBuffers [0] != nullptr) {
- memcpy(pDSLockedBuffers[0], pMediaBuffer, dwDSLockedSize[0]);
- m_dwDSWriteOff += dwDSLockedSize[0];
- }
-
- if (pDSLockedBuffers [1] != nullptr) {
- memcpy(pDSLockedBuffers[1], &pMediaBuffer[dwDSLockedSize[0]], dwDSLockedSize[1]);
- m_dwDSWriteOff = dwDSLockedSize[1];
- loop = true;
- }
-
- hr = m_pDSBuffer->Unlock(pDSLockedBuffers[0], dwDSLockedSize[0], pDSLockedBuffers[1], dwDSLockedSize[1]);
- ASSERT(dwDSLockedSize [0] + dwDSLockedSize [1] == (DWORD)lSize);
- }
-
- if (SUCCEEDED(hr) && looped) {
- *looped = loop;
- }
-
- return hr;
-}
-
-#pragma endregion
-
-#pragma region WASAPI
-
-HRESULT CMpcAudioRenderer::DoRenderSampleWasapi(IMediaSample* pMediaSample)
-{
- HRESULT hr = S_OK;
- REFERENCE_TIME rtStart = 0;
- REFERENCE_TIME rtStop = 0;
- BYTE* pMediaBuffer = nullptr;
- BYTE* pInputBufferPointer = nullptr;
- BYTE* pInputBufferEnd = nullptr;
- BYTE* pData;
- m_bufferSize = pMediaSample->GetActualDataLength();
- const long lSize = m_bufferSize;
- pMediaSample->GetTime(&rtStart, &rtStop);
-
- AM_MEDIA_TYPE* pmt;
- if (SUCCEEDED(pMediaSample->GetMediaType(&pmt)) && pmt != nullptr) {
- CMediaType mt(*pmt);
- if ((WAVEFORMATEXTENSIBLE*)mt.Format() != nullptr) {
- hr = CheckAudioClient(&(((WAVEFORMATEXTENSIBLE*)mt.Format())->Format));
- } else {
- hr = CheckAudioClient((WAVEFORMATEX*)mt.Format());
- }
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::DoRenderSampleWasapi Error while checking audio client with input media type\n"));
- return hr;
- }
- DeleteMediaType(pmt);
- pmt = nullptr;
- }
-
- // Initialization
- hr = pMediaSample->GetPointer(&pMediaBuffer);
- if (FAILED(hr)) {
- return hr;
- }
-
- pInputBufferPointer = &pMediaBuffer[0];
- pInputBufferEnd = &pMediaBuffer[0] + lSize;
-
- WORD frameSize = m_pWaveFileFormat->nBlockAlign;
-
-
- // Sleep for half the buffer duration since last buffer feed
- DWORD currentTime = GetTickCount();
- if (m_lastBufferTime != 0 && m_hnsActualDuration != 0 && m_lastBufferTime < currentTime && (currentTime - m_lastBufferTime) < m_hnsActualDuration) {
- m_hnsActualDuration = m_hnsActualDuration - (currentTime - m_lastBufferTime);
- Sleep((DWORD)m_hnsActualDuration);
- }
-
- // Each loop fills one of the two buffers.
- while (pInputBufferPointer < pInputBufferEnd) {
- UINT32 numFramesPadding = 0;
- m_pAudioClient->GetCurrentPadding(&numFramesPadding);
- UINT32 numFramesAvailable = m_nFramesInBuffer - numFramesPadding;
-
- UINT32 nAvailableBytes = numFramesAvailable * frameSize;
- UINT32 nBytesToWrite = nAvailableBytes;
- // More room than enough in the output buffer
- if (pInputBufferPointer + nAvailableBytes > pInputBufferEnd) {
- nBytesToWrite = (UINT32)(pInputBufferEnd - pInputBufferPointer);
- numFramesAvailable = (UINT32)((float)nBytesToWrite / frameSize);
- }
-
- // Grab the next empty buffer from the audio device.
- hr = m_pRenderClient->GetBuffer(numFramesAvailable, &pData);
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::DoRenderSampleWasapi GetBuffer failed with size %ld : (error %lx)\n"), m_nFramesInBuffer, hr);
- return hr;
- }
-
- // Load the buffer with data from the audio source.
- if (pData != nullptr) {
-
- memcpy(&pData[0], pInputBufferPointer, nBytesToWrite);
- pInputBufferPointer += nBytesToWrite;
- } else {
- TRACE(_T("CMpcAudioRenderer::DoRenderSampleWasapi Output buffer is nullptr\n"));
- }
-
- hr = m_pRenderClient->ReleaseBuffer(numFramesAvailable, 0); // no flags
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::DoRenderSampleWasapi ReleaseBuffer failed with size %ld (error %lx)\n"), m_nFramesInBuffer, hr);
- return hr;
- }
-
- if (!m_isAudioClientStarted) {
- TRACE(_T("CMpcAudioRenderer::DoRenderSampleWasapi Starting audio client\n"));
- m_pAudioClient->Start();
- m_isAudioClientStarted = true;
- }
-
- if (pInputBufferPointer >= pInputBufferEnd) {
- m_lastBufferTime = GetTickCount();
- // This is the duration of the filled buffer
- m_hnsActualDuration = (REFERENCE_TIME)REFTIMES_PER_SEC * numFramesAvailable / m_pWaveFileFormat->nSamplesPerSec;
- // Sleep time is half this duration
- m_hnsActualDuration = (DWORD)(m_hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
- break;
- }
-
- // Buffer not completely filled, sleep for half buffer capacity duration
- m_hnsActualDuration = (REFERENCE_TIME)REFTIMES_PER_SEC * m_nFramesInBuffer / m_pWaveFileFormat->nSamplesPerSec;
- // Sleep time is half this duration
- m_hnsActualDuration = (DWORD)(m_hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
- Sleep((DWORD)m_hnsActualDuration);
- }
- return hr;
-}
-#pragma endregion
-
-HRESULT CMpcAudioRenderer::CheckAudioClient(WAVEFORMATEX* pWaveFormatEx)
-{
- HRESULT hr = S_OK;
- CAutoLock cAutoLock(&m_csCheck);
- TRACE(_T("CMpcAudioRenderer::CheckAudioClient\n"));
- if (!m_pMMDevice) {
- hr = GetAudioDevice(&m_pMMDevice);
- }
-
- // If no WAVEFORMATEX structure provided and client already exists, return it
- if (m_pAudioClient && !pWaveFormatEx) {
- return hr;
- }
-
- // Just create the audio client if no WAVEFORMATEX provided
- if (!m_pAudioClient && !pWaveFormatEx) {
- if (SUCCEEDED(hr)) {
- hr = CreateAudioClient(m_pMMDevice, &m_pAudioClient);
- }
- return hr;
- }
-
- // If we reach that point, m_pAudioClient should have been initialized
- ASSERT(m_pAudioClient);
- CheckPointer(m_pAudioClient, E_POINTER);
-
- // Compare the existing WAVEFORMATEX with the one provided
- WAVEFORMATEX* pNewWaveFormatEx = nullptr;
- if (CheckFormatChanged(pWaveFormatEx, &pNewWaveFormatEx)) {
- // Format has changed, audio client has to be reinitialized
- TRACE(_T("CMpcAudioRenderer::CheckAudioClient Format changed, reinitialize the audio client\n"));
- if (m_pWaveFileFormat) {
- BYTE* p = (BYTE*)m_pWaveFileFormat;
- SAFE_DELETE_ARRAY(p);
- }
- m_pWaveFileFormat = pNewWaveFormatEx;
- hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, pWaveFormatEx, nullptr);
- if (SUCCEEDED(hr)) {
- if (m_isAudioClientStarted) {
- m_pAudioClient->Stop();
- m_isAudioClientStarted = false;
- }
- SAFE_RELEASE(m_pRenderClient);
- SAFE_RELEASE(m_pAudioClient);
-
- hr = CreateAudioClient(m_pMMDevice, &m_pAudioClient);
- } else {
- TRACE(_T("CMpcAudioRenderer::CheckAudioClient New format not supported, accept it anyway\n"));
- return S_OK;
- }
- } else if (!m_pRenderClient) {
- TRACE(_T("CMpcAudioRenderer::CheckAudioClient First initialization of the audio renderer\n"));
- } else {
- return hr;
- }
-
- SAFE_RELEASE(m_pRenderClient);
- if (SUCCEEDED(hr)) {
- hr = InitAudioClient(pWaveFormatEx, m_pAudioClient, &m_pRenderClient);
- }
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::GetAvailableAudioDevices(IMMDeviceCollection** ppMMDevices)
-{
- HRESULT hr;
-
- CComPtr<IMMDeviceEnumerator> enumerator;
- TRACE(_T("CMpcAudioRenderer::GetAvailableAudioDevices\n"));
- hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
-
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::GetAvailableAudioDevices - failed to get MMDeviceEnumerator\n"));
- return S_FALSE;
- }
-
- //IMMDevice* pEndpoint = nullptr;
- //IPropertyStore* pProps = nullptr;
- //LPWSTR pwszID = nullptr;
-
- enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, ppMMDevices);
- UINT count = 0;
- hr = (*ppMMDevices)->GetCount(&count);
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::GetAudioDevice(IMMDevice** ppMMDevice)
-{
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice\n"));
-
- CComPtr<IMMDeviceEnumerator> enumerator;
- IMMDeviceCollection* devices = nullptr;
- IPropertyStore* pProps = nullptr;
- HRESULT hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
-
- if (hr != S_OK) {
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - failed to create MMDeviceEnumerator!\n"));
- return hr;
- }
-
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - Target end point: %s\n"), m_csSound_Device);
-
- if (GetAvailableAudioDevices(&devices) == S_OK && devices) {
- UINT count = 0;
- hr = devices->GetCount(&count);
- if (hr != S_OK) {
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetCount failed: (0x%08x)\n"), hr);
- return hr;
- }
-
- for (ULONG i = 0 ; i < count ; i++) {
- LPWSTR pwszID = nullptr;
- IMMDevice* endpoint = nullptr;
- hr = devices->Item(i, &endpoint);
- if (hr == S_OK) {
- hr = endpoint->GetId(&pwszID);
- if (hr == S_OK) {
- if (endpoint->OpenPropertyStore(STGM_READ, &pProps) == S_OK) {
-
- PROPVARIANT varName;
- PropVariantInit(&varName);
-
- // Found the configured audio endpoint
- if ((pProps->GetValue(PKEY_Device_FriendlyName, &varName) == S_OK) && (m_csSound_Device == varName.pwszVal)) {
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetId OK, num: (%u), pwszVal: %s, pwszID: %s\n"), i, varName.pwszVal, pwszID);
- enumerator->GetDevice(pwszID, ppMMDevice);
- SAFE_RELEASE(devices);
- *(ppMMDevice) = endpoint;
- CoTaskMemFree(pwszID);
- pwszID = nullptr;
- PropVariantClear(&varName);
- SAFE_RELEASE(pProps);
- return S_OK;
- } else {
- PropVariantClear(&varName);
- SAFE_RELEASE(pProps);
- SAFE_RELEASE(endpoint);
- CoTaskMemFree(pwszID);
- pwszID = nullptr;
- }
- }
- } else {
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->GetId failed: (0x%08x)\n"), hr);
- }
- } else {
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - devices->Item failed: (0x%08x)\n"), hr);
- }
-
- CoTaskMemFree(pwszID);
- pwszID = nullptr;
- }
- }
-
- TRACE(_T("CMpcAudioRenderer::GetAudioDevice - Unable to find selected audio device, using the default end point!\n"));
- hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, ppMMDevice);
-
- SAFE_RELEASE(devices);
-
- return hr;
-}
-
-bool CMpcAudioRenderer::CheckFormatChanged(const WAVEFORMATEX* pWaveFormatEx, WAVEFORMATEX** ppNewWaveFormatEx)
-{
- bool formatChanged = false;
- if (m_pWaveFileFormat == nullptr) {
- formatChanged = true;
- } else if (pWaveFormatEx->wFormatTag != m_pWaveFileFormat->wFormatTag
- || pWaveFormatEx->nChannels != m_pWaveFileFormat->nChannels
- || pWaveFormatEx->wBitsPerSample != m_pWaveFileFormat->wBitsPerSample) { // TODO : improve the checks
- formatChanged = true;
- }
-
-
- if (!formatChanged) {
- return false;
- }
-
- int size = sizeof(WAVEFORMATEX) + pWaveFormatEx->cbSize; // Always true, even for WAVEFORMATEXTENSIBLE and WAVEFORMATEXTENSIBLE_IEC61937
- *ppNewWaveFormatEx = (WAVEFORMATEX*)DEBUG_NEW BYTE[size];
- if (!*ppNewWaveFormatEx) {
- return false;
- }
- memcpy(*ppNewWaveFormatEx, pWaveFormatEx, size);
- return true;
-}
-
-HRESULT CMpcAudioRenderer::GetBufferSize(WAVEFORMATEX* pWaveFormatEx, REFERENCE_TIME* pHnsBufferPeriod)
-{
- if (pWaveFormatEx == nullptr) {
- return S_OK;
- }
- if (pWaveFormatEx->cbSize < 22) { //WAVEFORMATEX
- return S_OK;
- }
-
- WAVEFORMATEXTENSIBLE* wfext = (WAVEFORMATEXTENSIBLE*)pWaveFormatEx;
-
- if (m_bufferSize == 0)
- if (wfext->SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP) {
- m_bufferSize = 61440;
- } else if (wfext->SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD) {
- m_bufferSize = 32768;
- } else if (wfext->SubFormat == KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS) {
- m_bufferSize = 24576;
- } else if (wfext->Format.wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF) {
- m_bufferSize = 6144;
- } else {
- return S_OK;
- }
-
- const double dBitrate = (double)pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample * pWaveFormatEx->nSamplesPerSec;
- *pHnsBufferPeriod = REFERENCE_TIME(m_bufferSize * 10000000i64 * 8 / dBitrate);
-
- TRACE(_T("CMpcAudioRenderer::GetBufferSize set a %I64d period for a %ld buffer size\n"), *pHnsBufferPeriod, m_bufferSize);
-
- return S_OK;
-}
-
-HRESULT CMpcAudioRenderer::InitAudioClient(WAVEFORMATEX* pWaveFormatEx, IAudioClient* pAudioClient, IAudioRenderClient** ppRenderClient)
-{
- TRACE(_T("CMpcAudioRenderer::InitAudioClient\n"));
-
- ASSERT(pAudioClient && ppRenderClient);
- CheckPointer(pAudioClient, E_POINTER);
- CheckPointer(ppRenderClient, E_POINTER);
-
- HRESULT hr;
- // Initialize the stream to play at the minimum latency.
- //if (SUCCEEDED (hr)) hr = pAudioClient->GetDevicePeriod(nullptr, &hnsPeriod);
- m_hnsPeriod = 500000; //50 ms is the best according to James @Slysoft
-
- hr = pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, pWaveFormatEx, nullptr);
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient not supported (0x%08x)\n"), hr);
- } else {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient format supported\n"));
- }
-
- GetBufferSize(pWaveFormatEx, &m_hnsPeriod);
-
- if (SUCCEEDED(hr)) {
- hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, 0/*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/,
- m_hnsPeriod, m_hnsPeriod, pWaveFormatEx, nullptr);
- }
- if (FAILED(hr) && hr != AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient failed (0x%08x)\n"), hr);
- return hr;
- }
-
- if (AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED == hr) {
- // if the buffer size was not aligned, need to do the alignment dance
- TRACE(_T("CMpcAudioRenderer::InitAudioClient Buffer size not aligned. Realigning\n"));
-
- // get the buffer size, which will be aligned
- hr = pAudioClient->GetBufferSize(&m_nFramesInBuffer);
-
- // throw away this IAudioClient
- SAFE_RELEASE(pAudioClient);
-
- // calculate the new aligned periodicity
- m_hnsPeriod = // hns =
- (REFERENCE_TIME)(
- 10000.0 * // (hns / ms) *
- 1000 * // (ms / s) *
- m_nFramesInBuffer / // frames /
- pWaveFormatEx->nSamplesPerSec // (frames / s)
- + 0.5 // rounding
- );
-
- if (SUCCEEDED(hr)) {
- hr = CreateAudioClient(m_pMMDevice, &pAudioClient);
- }
- TRACE(_T("CMpcAudioRenderer::InitAudioClient Trying again with periodicity of %I64u hundred-nanoseconds, or %u frames.\n"), m_hnsPeriod, m_nFramesInBuffer);
- if (SUCCEEDED(hr)) {
- hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, 0/*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/,
- m_hnsPeriod, m_hnsPeriod, pWaveFormatEx, nullptr);
- }
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient Failed to reinitialize the audio client\n"));
- return hr;
- }
- } // if (AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED == hr)
-
- // get the buffer size, which is aligned
- if (SUCCEEDED(hr)) {
- hr = pAudioClient->GetBufferSize(&m_nFramesInBuffer);
- }
-
- // calculate the new period
- if (SUCCEEDED(hr)) {
- hr = pAudioClient->GetService(IID_PPV_ARGS(ppRenderClient));
- }
-
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient service initialization failed (0x%08x)\n"), hr);
- } else {
- TRACE(_T("CMpcAudioRenderer::InitAudioClient service initialization success\n"));
- }
-
- return hr;
-}
-
-HRESULT CMpcAudioRenderer::CreateAudioClient(IMMDevice* pMMDevice, IAudioClient** ppAudioClient)
-{
- HRESULT hr = S_OK;
- m_hnsPeriod = 0;
-
- TRACE(_T("CMpcAudioRenderer::CreateAudioClient\n"));
-
- ASSERT(ppAudioClient);
- CheckPointer(ppAudioClient, E_POINTER);
-
- if (*ppAudioClient) {
- if (m_isAudioClientStarted) {
- (*ppAudioClient)->Stop();
- }
- SAFE_RELEASE(*ppAudioClient);
- m_isAudioClientStarted = false;
- }
-
- if (!pMMDevice) {
- TRACE(_T("CMpcAudioRenderer::CreateAudioClient failed, device not loaded\n"));
- return E_FAIL;
- }
-
- hr = pMMDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, reinterpret_cast<void**>(ppAudioClient));
- if (FAILED(hr)) {
- TRACE(_T("CMpcAudioRenderer::CreateAudioClient activation failed (0x%08x)\n"), hr);
- } else {
- TRACE(_T("CMpcAudioRenderer::CreateAudioClient success\n"));
- }
- return hr;
-}
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.def b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.def
deleted file mode 100644
index 6492e5cd6..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.def
+++ /dev/null
@@ -1,5 +0,0 @@
-EXPORTS
- DllCanUnloadNow PRIVATE
- DllGetClassObject PRIVATE
- DllRegisterServer PRIVATE
- DllUnregisterServer PRIVATE
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.h b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.h
deleted file mode 100644
index b71c03537..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * (C) 2009-2014 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include "BaseClasses/streams.h"
-#include <dsound.h>
-
-#include <MMReg.h> //must be before other WASAPI headers
-#include <strsafe.h>
-#include <mmdeviceapi.h>
-#include <avrt.h>
-#include <audioclient.h>
-#include <endpointvolume.h>
-#include <FunctionDiscoveryKeys_devpkey.h>
-
-#include "MpcAudioRendererSettingsWnd.h"
-#include "SoundTouch/include/SoundTouch.h"
-
-#define MpcAudioRendererName L"MPC-HC Audio Renderer"
-
-// REFERENCE_TIME time units per second and per millisecond
-#define REFTIMES_PER_SEC 10000000.0
-#define REFTIMES_PER_MILLISEC 10000.0
-
-// if you get a compilation error on AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED,
-// uncomment the #define below
-#define AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED AUDCLNT_ERR(0x019)
-
-class __declspec(uuid("601D2A2B-9CDE-40bd-8650-0485E3522727"))
- CMpcAudioRenderer : public CBaseRenderer
- , public IBasicAudio
- , public ISpecifyPropertyPages2
- , public IMpcAudioRendererFilter
-{
-public:
- CMpcAudioRenderer(LPUNKNOWN punk, HRESULT* phr);
- virtual ~CMpcAudioRenderer();
-
- static const AMOVIESETUP_FILTER sudASFilter;
-
- HRESULT CheckInputType(const CMediaType* mtIn);
- virtual HRESULT CheckMediaType(const CMediaType* pmt);
- virtual HRESULT DoRenderSample(IMediaSample* pMediaSample);
- virtual void OnReceiveFirstSample(IMediaSample* pMediaSample);
- BOOL ScheduleSample(IMediaSample* pMediaSample);
- virtual HRESULT SetMediaType(const CMediaType* pmt);
- virtual HRESULT CompleteConnect(IPin* pReceivePin);
-
- HRESULT EndOfStream();
-
-
- DECLARE_IUNKNOWN
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
-
- // === IMediaFilter
- STDMETHOD(Run)(REFERENCE_TIME tStart);
- STDMETHOD(Stop)();
- STDMETHOD(Pause)();
-
- // === IDispatch (pour IBasicAudio)
- STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
- STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
- STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid);
- STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr);
-
- // === IBasicAudio
- STDMETHOD(put_Volume)(long lVolume);
- STDMETHOD(get_Volume)(long* plVolume);
- STDMETHOD(put_Balance)(long lBalance);
- STDMETHOD(get_Balance)(long* plBalance);
-
- // === ISpecifyPropertyPages2
- STDMETHODIMP GetPages(CAUUID* pPages);
- STDMETHODIMP CreatePage(const GUID& guid, IPropertyPage** ppPage);
-
- // === IMpcAudioRendererFilter
- STDMETHODIMP Apply();
- STDMETHODIMP SetWasapiMode(BOOL nValue);
- STDMETHODIMP_(BOOL) GetWasapiMode();
- STDMETHODIMP SetMuteFastForward(BOOL nValue);
- STDMETHODIMP_(BOOL) GetMuteFastForward();
- STDMETHODIMP SetSoundDevice(CString nValue);
- STDMETHODIMP_(CString) GetSoundDevice();
-
- // CMpcAudioRenderer
-private:
-
- HRESULT DoRenderSampleDirectSound(IMediaSample* pMediaSample);
-
- HRESULT InitCoopLevel();
- HRESULT ClearBuffer();
- HRESULT CreateDSBuffer();
- HRESULT GetReferenceClockInterface(REFIID riid, void** ppv);
- HRESULT WriteSampleToDSBuffer(IMediaSample* pMediaSample, bool* looped);
-
- LPDIRECTSOUND8 m_pDS;
- LPDIRECTSOUNDBUFFER m_pDSBuffer;
- DWORD m_dwDSWriteOff;
- WAVEFORMATEX* m_pWaveFileFormat;
- int m_nDSBufSize;
- CBaseReferenceClock* m_pReferenceClock;
- double m_dRate;
- long m_lVolume;
- soundtouch::SoundTouch* m_pSoundTouch;
- CCritSec m_csProps;
-
- // CMpcAudioRenderer WASAPI methods
- HRESULT GetAvailableAudioDevices(IMMDeviceCollection** ppMMDevices);
- HRESULT GetAudioDevice(IMMDevice** ppMMDevice);
- HRESULT CreateAudioClient(IMMDevice* pMMDevice, IAudioClient** ppAudioClient);
- HRESULT InitAudioClient(WAVEFORMATEX* pWaveFormatEx, IAudioClient* pAudioClient, IAudioRenderClient** ppRenderClient);
- HRESULT CheckAudioClient(WAVEFORMATEX* pWaveFormatEx);
- bool CheckFormatChanged(const WAVEFORMATEX* pWaveFormatEx, WAVEFORMATEX** ppNewWaveFormatEx);
- HRESULT DoRenderSampleWasapi(IMediaSample* pMediaSample);
- HRESULT GetBufferSize(WAVEFORMATEX* pWaveFormatEx, REFERENCE_TIME* pHnsBufferPeriod);
-
-
- // WASAPI variables
- bool m_useWASAPI;
- bool m_useWASAPIAfterRestart;
- bool m_bMuteFastForward;
- CString m_csSound_Device;
- IMMDevice* m_pMMDevice;
- IAudioClient* m_pAudioClient;
- IAudioRenderClient* m_pRenderClient;
- UINT32 m_nFramesInBuffer;
- REFERENCE_TIME m_hnsPeriod, m_hnsActualDuration;
- HANDLE m_hTask;
- CCritSec m_csCheck;
- UINT32 m_bufferSize;
- bool m_isAudioClientStarted;
- DWORD m_lastBufferTime;
-
- // avrt.dll (Vista or greater)
- typedef HANDLE(__stdcall* PTR_AvSetMmThreadCharacteristicsW)(LPCWSTR TaskName, LPDWORD TaskIndex);
- typedef BOOL (__stdcall* PTR_AvRevertMmThreadCharacteristics)(HANDLE AvrtHandle);
-
- HMODULE m_hLibAVRT;
- PTR_AvSetMmThreadCharacteristicsW m_pfAvSetMmThreadCharacteristicsW;
- PTR_AvRevertMmThreadCharacteristics m_pfAvRevertMmThreadCharacteristics;
-
-};
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.rc b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.rc
deleted file mode 100644
index 78030895a..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.rc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-#include "version.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION MPC_VERSION_NUM
- PRODUCTVERSION MPC_VERSION_NUM
- FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-#ifdef _DEBUG
- FILEFLAGS VS_FF_DEBUG
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS VOS_NT_WINDOWS32
- FILETYPE VFT_DLL
- FILESUBTYPE VFT2_UNKNOWN
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "Comments", MPC_VERSION_COMMENTS
- VALUE "CompanyName", MPC_COMP_NAME_STR
- VALUE "FileDescription", "Audio Renderer, based on SoundTouch"
- VALUE "FileVersion", MPC_VERSION_STR_FULL
- VALUE "InternalName", "MpcAudioRenderer Filter"
- VALUE "LegalCopyright", MPC_COPYRIGHT_STR
- VALUE "OriginalFilename", "MpcAudioRenderer.ax"
- VALUE "ProductName", "MpcAudioRenderer Filter"
- VALUE "ProductVersion", MPC_VERSION_STR_FULL
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-STRINGTABLE
-BEGIN
- IDS_FILTER_SETTINGS_CAPTION "Settings"
- IDS_ARS_WASAPI_MODE "Use WASAPI (restart playback)"
- IDS_ARS_MUTE_FAST_FORWARD "Mute on fast forward"
- IDS_ARS_SOUND_DEVICE "Sound Device:"
-END
-
-#endif // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj
deleted file mode 100644
index d14f4d2f9..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj
+++ /dev/null
@@ -1,259 +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 Filter|Win32">
- <Configuration>Debug Filter</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug Filter|x64">
- <Configuration>Debug Filter</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <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 Filter|Win32">
- <Configuration>Release Filter</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release Filter|x64">
- <Configuration>Release Filter</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>{D0620EF4-1313-40D5-9069-A82F6FE26994}</ProjectGuid>
- <RootNamespace>MpcAudioRenderer</RootNamespace>
- <Keyword>MFCProj</Keyword>
- <ProjectName>MpcAudioRenderer</ProjectName>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <Import Project="..\..\..\platform.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>Static</UseOfMfc>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </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" />
- <Import Project="..\..\..\common.props" />
- </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" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|x64'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\common.props" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug Filter|Win32'">.ax</TargetExt>
- <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release Filter|Win32'">.ax</TargetExt>
- <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug Filter|x64'">.ax</TargetExt>
- <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release Filter|x64'">.ax</TargetExt>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|Win32'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <AdditionalDependencies>dsound.lib;Vfw32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ModuleDefinitionFile>MpcAudioRenderer.def</ModuleDefinitionFile>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Filter|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <AdditionalDependencies>dsound.lib;Vfw32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ModuleDefinitionFile>MpcAudioRenderer.def</ModuleDefinitionFile>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|Win32'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <AdditionalDependencies>dsound.lib;Vfw32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ModuleDefinitionFile>MpcAudioRenderer.def</ModuleDefinitionFile>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Filter|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <AdditionalDependencies>dsound.lib;Vfw32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <ModuleDefinitionFile>MpcAudioRenderer.def</ModuleDefinitionFile>
- </Link>
- <ResourceCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Lib>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Lib>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Lib>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- </ClCompile>
- <Lib>
- <AdditionalDependencies>dsound.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Lib>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\..\FilterApp.cpp" />
- <ClCompile Include="MpcAudioRenderer.cpp" />
- <ClCompile Include="MpcAudioRendererSettingsWnd.cpp" />
- <ClCompile Include="stdafx.cpp">
- <PrecompiledHeader>Create</PrecompiledHeader>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <None Include="MpcAudioRenderer.def" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="IMpcAudioRendererFilter.h" />
- <ClInclude Include="MpcAudioRenderer.h" />
- <ClInclude Include="MpcAudioRendererSettingsWnd.h" />
- <ClInclude Include="resource.h">
- <ExcludedFromBuild Condition="'$(Configuration)'=='Debug' or '$(Configuration)'=='Release'">true</ExcludedFromBuild>
- </ClInclude>
- <ClInclude Include="stdafx.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="MpcAudioRenderer.rc">
- <ExcludedFromBuild Condition="'$(Configuration)'=='Debug' or '$(Configuration)'=='Release'">true</ExcludedFromBuild>
- </ResourceCompile>
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\..\DSUtil\DSUtil.vcxproj">
- <Project>{fc70988b-1ae5-4381-866d-4f405e28ac42}</Project>
- </ProjectReference>
- <ProjectReference Include="..\..\..\thirdparty\SoundTouch\source\SoundTouch.vcxproj">
- <Project>{68a5dd20-7057-448b-8fe0-b6ac8d205509}</Project>
- </ProjectReference>
- <ProjectReference Include="..\..\..\thirdparty\BaseClasses\BaseClasses.vcxproj">
- <Project>{e8a3f6fa-ae1c-4c8e-a0b6-9c8480324eaa}</Project>
- </ProjectReference>
- <ProjectReference Include="..\..\..\thirdparty\VirtualDub\Kasumi\Kasumi.vcxproj">
- <Project>{0d252872-7542-4232-8d02-53f9182aee15}</Project>
- </ProjectReference>
- <ProjectReference Include="..\..\..\thirdparty\VirtualDub\system\system.vcxproj">
- <Project>{c2082189-3ecb-4079-91fa-89d3c8a305c0}</Project>
- </ProjectReference>
- <ProjectReference Include="..\..\Filters.vcxproj">
- <Project>{273b3149-3192-4b75-a791-470320b90812}</Project>
- </ProjectReference>
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj.filters b/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj.filters
deleted file mode 100644
index 02f8239d5..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRenderer.vcxproj.filters
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{9788c006-0809-4532-aa20-b51ed992525a}</UniqueIdentifier>
- <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{4d561854-929b-492e-9fba-c2cebb7cc3d4}</UniqueIdentifier>
- <Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{addff0d6-0d94-4e4c-b5ea-b7d5b330fd45}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\..\FilterApp.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="MpcAudioRenderer.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="stdafx.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="MpcAudioRendererSettingsWnd.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <None Include="MpcAudioRenderer.def">
- <Filter>Source Files</Filter>
- </None>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="MpcAudioRenderer.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="resource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="stdafx.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="IMpcAudioRendererFilter.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="MpcAudioRendererSettingsWnd.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="MpcAudioRenderer.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.cpp b/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.cpp
deleted file mode 100644
index 4b925fe97..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * (C) 2010-2014 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "stdafx.h"
-#include "resource.h"
-#include "MpcAudioRendererSettingsWnd.h"
-#include "../../../DSUtil/DSUtil.h"
-
-#include "../../../mpc-hc/InternalFiltersConfig.h"
-
-
-CMpcAudioRendererSettingsWnd::CMpcAudioRendererSettingsWnd()
-{
-}
-
-bool CMpcAudioRendererSettingsWnd::OnConnect(const CInterfaceList<IUnknown, &IID_IUnknown>& pUnks)
-{
- ASSERT(!m_pMAR);
-
- m_pMAR.Release();
-
- POSITION pos = pUnks.GetHeadPosition();
- while (pos && !(m_pMAR = pUnks.GetNext(pos))) {
- ;
- }
-
- if (!m_pMAR) {
- return false;
- }
-
- return true;
-}
-
-void CMpcAudioRendererSettingsWnd::OnDisconnect()
-{
- m_pMAR.Release();
-}
-
-bool CALLBACK DSEnumProc(LPGUID lpGUID,
- LPCTSTR lpszDesc,
- LPCTSTR lpszDrvName,
- LPVOID lpContext)
-{
- CComboBox* pCombo = (CComboBox*)lpContext;
- ASSERT(pCombo);
- LPGUID lpTemp = nullptr;
-
- if (lpGUID != nullptr) { // nullptr only for "Primary Sound Driver".
- if ((lpTemp = (LPGUID)malloc(sizeof(GUID))) == nullptr) {
- return TRUE;
- }
- memcpy(lpTemp, lpGUID, sizeof(GUID));
- }
- pCombo->AddString(lpszDesc);
- free(lpTemp);
- return TRUE;
-}
-
-bool CMpcAudioRendererSettingsWnd::OnActivate()
-{
- ASSERT(IPP_FONTSIZE == 13);
- DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
- CPoint p(10, 10);
-
- m_cbWasapiMode.Create(ResStr(IDS_ARS_WASAPI_MODE), dwStyle | BS_AUTOCHECKBOX | BS_LEFTTEXT, CRect(p, CSize(IPP_SCALE(320), m_fontheight)), this, IDC_PP_WASAPI_MODE);
-
- p.y += IPP_SCALE(20);
- m_cbMuteFastForward.Create(ResStr(IDS_ARS_MUTE_FAST_FORWARD), dwStyle | BS_AUTOCHECKBOX | BS_LEFTTEXT, CRect(p, CSize(IPP_SCALE(320), m_fontheight)), this, IDC_PP_MUTE_FAST_FORWARD);
-
- p.y += IPP_SCALE(25);
- m_txtSoundDevice.Create(ResStr(IDS_ARS_SOUND_DEVICE), WS_VISIBLE | WS_CHILD, CRect(p, CSize(IPP_SCALE(115), m_fontheight)), this, (UINT)IDC_STATIC);
- m_cbSoundDevice.Create(dwStyle | CBS_DROPDOWNLIST | WS_VSCROLL, CRect(p + CPoint(IPP_SCALE(120), -4), CSize(IPP_SCALE(200), 200)), this, IDC_PP_SOUND_DEVICE);
-
- SetClassLongPtr(GetDlgItem(IDC_PP_SOUND_DEVICE)->m_hWnd, GCLP_HCURSOR, (LONG_PTR)AfxGetApp()->LoadStandardCursor(IDC_HAND));
-
- DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc, (void*)&m_cbSoundDevice);
-
- if (m_cbSoundDevice.GetCount() > 0) {
- int idx = m_cbSoundDevice.FindString(0, m_pMAR->GetSoundDevice());
- if (idx < 0) {
- m_cbSoundDevice.SetCurSel(0);
- } else {
- m_cbSoundDevice.SetCurSel(m_cbSoundDevice.FindString(0, m_pMAR->GetSoundDevice()));
- }
- }
-
- m_cbWasapiMode.SetCheck(m_pMAR->GetWasapiMode());
- m_cbMuteFastForward.SetCheck(m_pMAR->GetMuteFastForward());
-
- for (CWnd* pWnd = GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow()) {
- pWnd->SetFont(&m_font, FALSE);
- }
-
- CorrectComboListWidth(m_cbSoundDevice);
-
- return true;
-}
-
-void CMpcAudioRendererSettingsWnd::OnDeactivate()
-{
-}
-
-bool CMpcAudioRendererSettingsWnd::OnApply()
-{
- OnDeactivate();
-
- if (m_pMAR) {
- m_pMAR->SetWasapiMode(m_cbWasapiMode.GetCheck());
- m_pMAR->SetMuteFastForward(m_cbMuteFastForward.GetCheck());
- CString str;
- int idx = m_cbSoundDevice.GetCurSel();
- if (!(idx < 0)) {
- m_cbSoundDevice.GetLBText(idx, str);
- m_pMAR->SetSoundDevice(str);
- }
- m_pMAR->Apply();
- }
-
- return true;
-}
-
-
-BEGIN_MESSAGE_MAP(CMpcAudioRendererSettingsWnd, CInternalPropertyPageWnd)
-END_MESSAGE_MAP()
diff --git a/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.h b/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.h
deleted file mode 100644
index 54491b922..000000000
--- a/src/filters/renderer/MpcAudioRenderer/MpcAudioRendererSettingsWnd.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * (C) 2010-2012 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include "../../InternalPropertyPage.h"
-#include "IMpcAudioRendererFilter.h"
-#include <afxcmn.h>
-
-class __declspec(uuid("1E53BA32-3BCC-4dff-9342-34E46BE3F5A5"))
- CMpcAudioRendererSettingsWnd : public CInternalPropertyPageWnd
-{
-private:
- CComQIPtr<IMpcAudioRendererFilter> m_pMAR;
-
- CStatic m_txtWasapiMode;
- CButton m_cbWasapiMode;
- CButton m_cbMuteFastForward;
-
- CStatic m_txtSoundDevice;
- CComboBox m_cbSoundDevice;
-
- enum {
- IDC_PP_WASAPI_MODE = 10000,
- IDC_PP_MUTE_FAST_FORWARD,
- IDC_PP_SOUND_DEVICE
- };
-
-public:
- CMpcAudioRendererSettingsWnd();
-
- bool OnConnect(const CInterfaceList<IUnknown, &IID_IUnknown>& pUnks);
- void OnDisconnect();
- bool OnActivate();
- void OnDeactivate();
- bool OnApply();
-
- HRESULT GetAvailableAudioDevices();
-
- static LPCTSTR GetWindowTitle() { return _T("Settings"); }
- static CSize GetWindowSize() { return CSize(340, 82); }
-
- DECLARE_MESSAGE_MAP()
-};
diff --git a/src/filters/renderer/MpcAudioRenderer/resource.h b/src/filters/renderer/MpcAudioRenderer/resource.h
deleted file mode 100644
index e813a13b9..000000000
--- a/src/filters/renderer/MpcAudioRenderer/resource.h
+++ /dev/null
@@ -1,19 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by MpcAudioRenderer.rc
-//
-#define IDS_FILTER_SETTINGS_CAPTION 7000
-#define IDS_ARS_WASAPI_MODE 7100
-#define IDS_ARS_MUTE_FAST_FORWARD 7101
-#define IDS_ARS_SOUND_DEVICE 7102
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 103
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1001
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/src/filters/renderer/MpcAudioRenderer/stdafx.cpp b/src/filters/renderer/MpcAudioRenderer/stdafx.cpp
deleted file mode 100644
index 42728ce2e..000000000
--- a/src/filters/renderer/MpcAudioRenderer/stdafx.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * (C) 2009-2012 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "stdafx.h"
diff --git a/src/filters/renderer/MpcAudioRenderer/stdafx.h b/src/filters/renderer/MpcAudioRenderer/stdafx.h
deleted file mode 100644
index 7c436e070..000000000
--- a/src/filters/renderer/MpcAudioRenderer/stdafx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * (C) 2009-2013 see Authors.txt
- *
- * This file is part of MPC-HC.
- *
- * MPC-HC is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * MPC-HC is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include "../../../DSUtil/SharedInclude.h"
-
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
-#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
-#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
-
-#include <afx.h>
-#include <afxwin.h> // MFC core and standard components
-
-#include "BaseClasses/streams.h"
-#include <dvdmedia.h>
-#include <dsound.h>
diff --git a/src/filters/renderer/VideoRenderers/AsyncCallback.h b/src/filters/renderer/VideoRenderers/AsyncCallback.h
new file mode 100644
index 000000000..d49645582
--- /dev/null
+++ b/src/filters/renderer/VideoRenderers/AsyncCallback.h
@@ -0,0 +1,71 @@
+/*
+* (C) 2015 see Authors.txt
+*
+* This file is part of MPC-HC.
+*
+* MPC-HC is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+*
+* MPC-HC is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+#pragma once
+
+#include <mfobjects.h>
+
+// T: Type of the parent object
+template <class T>
+class AsyncCallback : public IMFAsyncCallback
+{
+public:
+ typedef HRESULT(T::*InvokeFn)(IMFAsyncResult* pAsyncResult);
+
+ AsyncCallback(T* pParent, InvokeFn fn) : m_pParent(pParent), m_pInvokeFn(fn) {}
+ virtual ~AsyncCallback() = default;
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override {
+ 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 = nullptr;
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef() override {
+ return m_pParent->AddRef();
+ }
+
+ STDMETHODIMP_(ULONG) Release() override {
+ return m_pParent->Release();
+ }
+
+ // IMFAsyncCallback
+ STDMETHODIMP GetParameters(DWORD*, DWORD*) override {
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult) override {
+ return (m_pParent->*m_pInvokeFn)(pAsyncResult);
+ }
+
+ T* m_pParent;
+ InvokeFn m_pInvokeFn;
+};
diff --git a/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.cpp b/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.cpp
index 46e650176..b49a0364b 100644
--- a/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.cpp
+++ b/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.cpp
@@ -144,6 +144,7 @@ CDX9AllocatorPresenter::CDX9AllocatorPresenter(HWND hWnd, bool bFullscreen, HRES
, m_LastFrameDuration(0)
, m_LastSampleTime(0)
, m_FocusThread(nullptr)
+ , m_hFocusWindow(nullptr)
{
ZeroMemory(&m_VMR9AlphaBitmap, sizeof(m_VMR9AlphaBitmap));
@@ -623,8 +624,11 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
m_bCompositionEnabled = !!bCompositionEnabled;
m_bAlternativeVSync = r.m_AdvRendSets.bVMR9AlterativeVSync;
- // detect FP textures support
- rd->m_bFP16Support = SUCCEEDED(m_pD3D->CheckDeviceFormat(m_CurrentAdapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, D3DRTYPE_VOLUMETEXTURE, D3DFMT_A32B32G32R32F));
+ // detect FP16 textures support
+ rd->m_bFP16Support = SUCCEEDED(m_pD3D->CheckDeviceFormat(m_CurrentAdapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, D3DRTYPE_VOLUMETEXTURE, D3DFMT_A16B16G16R16F));
+
+ // detect FP32 textures support
+ rd->m_bFP32Support = SUCCEEDED(m_pD3D->CheckDeviceFormat(m_CurrentAdapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, D3DRTYPE_VOLUMETEXTURE, D3DFMT_A32B32G32R32F));
// detect 10-bit textures support
rd->m_b10bitSupport = SUCCEEDED(m_pD3D->CheckDeviceFormat(m_CurrentAdapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A2R10G10B10));
@@ -635,7 +639,7 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
// set settings that depend on hardware feature support
m_bForceInputHighColorResolution = r.m_AdvRendSets.bEVRForceInputHighColorResolution && m_bIsEVR && rd->m_b10bitSupport;
m_bHighColorResolution = r.m_AdvRendSets.bEVRHighColorResolution && m_bIsEVR && rd->m_b10bitSupport && bHighColorSupport;
- m_bFullFloatingPointProcessing = r.m_AdvRendSets.bVMR9FullFloatingPointProcessing && rd->m_bFP16Support;
+ m_bFullFloatingPointProcessing = r.m_AdvRendSets.bVMR9FullFloatingPointProcessing && rd->m_bFP32Support;
m_bHalfFloatingPointProcessing = r.m_AdvRendSets.bVMR9HalfFloatingPointProcessing && rd->m_bFP16Support && !m_bFullFloatingPointProcessing;
// set color formats
@@ -678,6 +682,10 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
m_FocusThread = (CFocusThread*)AfxBeginThread(RUNTIME_CLASS(CFocusThread), 0, 0, 0);
}
+ HWND hFocusWindow = m_FocusThread->GetFocusWindow();
+ bTryToReset &= m_hFocusWindow == hFocusWindow;
+ m_hFocusWindow = hFocusWindow;
+
if (m_pD3DEx) {
m_pD3DEx->GetAdapterDisplayModeEx(m_CurrentAdapter, &DisplayMode, nullptr);
@@ -687,16 +695,13 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
pp.BackBufferWidth = m_ScreenSize.cx;
pp.BackBufferHeight = m_ScreenSize.cy;
- if (bTryToReset) {
- if (!m_pD3DDevEx || FAILED(hr = m_pD3DDevEx->ResetEx(&pp, &DisplayMode))) {
- bTryToReset = false;
- m_pD3DDev = nullptr;
- m_pD3DDevEx = nullptr;
- }
- }
+ bTryToReset = bTryToReset && m_pD3DDevEx && SUCCEEDED(hr = m_pD3DDevEx->ResetEx(&pp, &DisplayMode));
+
if (!bTryToReset) {
+ m_pD3DDev = nullptr;
+ m_pD3DDevEx = nullptr;
hr = m_pD3DEx->CreateDeviceEx(
- m_CurrentAdapter, D3DDEVTYPE_HAL, m_FocusThread->GetFocusWindow(),
+ m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
GetVertexProcessing() | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_ENABLE_PRESENTSTATS | D3DCREATE_NOWINDOWCHANGES, //D3DCREATE_MANAGED
&pp, &DisplayMode, &m_pD3DDevEx);
}
@@ -722,7 +727,7 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
pp.BackBufferHeight = m_ScreenSize.cy;
hr = m_pD3D->CreateDevice(
- m_CurrentAdapter, D3DDEVTYPE_HAL, m_FocusThread->GetFocusWindow(),
+ m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
GetVertexProcessing() | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_NOWINDOWCHANGES, //D3DCREATE_MANAGED
&pp, &m_pD3DDev);
m_DisplayType = d3ddm.Format;
@@ -744,6 +749,9 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}
+ bTryToReset &= m_hFocusWindow == m_hWnd;
+ m_hFocusWindow = m_hWnd;
+
if (m_pD3DEx) {
m_pD3DEx->GetAdapterDisplayModeEx(m_CurrentAdapter, &DisplayMode, nullptr);
m_ScreenSize.SetSize(DisplayMode.Width, DisplayMode.Height);
@@ -751,18 +759,15 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
pp.BackBufferWidth = szDesktopSize.cx;
pp.BackBufferHeight = szDesktopSize.cy;
- if (bTryToReset) {
- if (!m_pD3DDevEx || FAILED(hr = m_pD3DDevEx->ResetEx(&pp, nullptr))) {
- bTryToReset = false;
- m_pD3DDev = nullptr;
- m_pD3DDevEx = nullptr;
- }
- }
+ bTryToReset = bTryToReset && m_pD3DDevEx && SUCCEEDED(hr = m_pD3DDevEx->ResetEx(&pp, nullptr));
+
if (!bTryToReset) {
+ m_pD3DDev = nullptr;
+ m_pD3DDevEx = nullptr;
// We can get 0x8876086a here when switching from two displays to one display using Win + P (Windows 7)
// Cause: We might not reinitialize dx correctly during the switch
hr = m_pD3DEx->CreateDeviceEx(
- m_CurrentAdapter, D3DDEVTYPE_HAL, m_hWnd,
+ m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
GetVertexProcessing() | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_ENABLE_PRESENTSTATS, //D3DCREATE_MANAGED
&pp, nullptr, &m_pD3DDevEx);
}
@@ -784,7 +789,7 @@ HRESULT CDX9AllocatorPresenter::CreateDevice(CString& _Error)
pp.BackBufferHeight = szDesktopSize.cy;
hr = m_pD3D->CreateDevice(
- m_CurrentAdapter, D3DDEVTYPE_HAL, m_hWnd,
+ m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
GetVertexProcessing() | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED, //D3DCREATE_MANAGED
&pp, &m_pD3DDev);
m_DisplayType = d3ddm.Format;
@@ -1127,7 +1132,7 @@ bool CDX9AllocatorPresenter::WaitForVBlankRange(int& _RasterStart, int _RasterSi
if (!GetVBlank(ScanLine, InVBlank, _bMeasure)) {
break;
}
- int ScanLineDiff = long(ScanLine) - _RasterStart;
+ ScanLineDiff = long(ScanLine) - _RasterStart;
if (ScanLineDiff > m_ScreenSize.cy / 2) {
ScanLineDiff -= m_ScreenSize.cy;
} else if (ScanLineDiff < -m_ScreenSize.cy / 2) {
@@ -1189,7 +1194,7 @@ bool CDX9AllocatorPresenter::WaitForVBlankRange(int& _RasterStart, int _RasterSi
if (!GetVBlank(ScanLine, InVBlank, _bMeasure)) {
break;
}
- int ScanLineDiff = long(ScanLine) - _RasterStart;
+ ScanLineDiff = long(ScanLine) - _RasterStart;
if (ScanLineDiff > m_ScreenSize.cy / 2) {
ScanLineDiff -= m_ScreenSize.cy;
} else if (ScanLineDiff < -m_ScreenSize.cy / 2) {
@@ -1203,7 +1208,7 @@ bool CDX9AllocatorPresenter::WaitForVBlankRange(int& _RasterStart, int _RasterSi
bWaited = true;
- int ScanLineDiffLock = long(ScanLine) - D3DDevLockStart;
+ ScanLineDiffLock = long(ScanLine) - D3DDevLockStart;
if (ScanLineDiffLock > m_ScreenSize.cy / 2) {
ScanLineDiffLock -= m_ScreenSize.cy;
} else if (ScanLineDiffLock < -m_ScreenSize.cy / 2) {
@@ -1220,7 +1225,7 @@ bool CDX9AllocatorPresenter::WaitForVBlankRange(int& _RasterStart, int _RasterSi
LastLineDiffLock = ScanLineDiffLock;
- int ScanLineDiffSleep = long(ScanLine) - NoSleepStart;
+ ScanLineDiffSleep = long(ScanLine) - NoSleepStart;
if (ScanLineDiffSleep > m_ScreenSize.cy / 2) {
ScanLineDiffSleep -= m_ScreenSize.cy;
} else if (ScanLineDiffSleep < -m_ScreenSize.cy / 2) {
@@ -1456,19 +1461,18 @@ STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool bAll)
bool bDoVSyncInPresent = (!bCompositionEnabled && !m_bAlternativeVSync) || !r.m_AdvRendSets.bVMR9VSync;
- CComPtr<IDirect3DQuery9> pEventQuery;
-
- m_pD3DDev->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
- if (pEventQuery) {
- pEventQuery->Issue(D3DISSUE_END);
+ CComPtr<IDirect3DQuery9> pEventQueryFlushBeforeVSync;
+ m_pD3DDev->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQueryFlushBeforeVSync);
+ if (pEventQueryFlushBeforeVSync) {
+ pEventQueryFlushBeforeVSync->Issue(D3DISSUE_END);
}
- if (r.m_AdvRendSets.bVMRFlushGPUBeforeVSync && pEventQuery) {
+ if (r.m_AdvRendSets.bVMRFlushGPUBeforeVSync && pEventQueryFlushBeforeVSync) {
LONGLONG llPerf = rd->GetPerfCounter();
BOOL Data;
//Sleep(5);
LONGLONG FlushStartTime = rd->GetPerfCounter();
- while (S_FALSE == pEventQuery->GetData(&Data, sizeof(Data), D3DGETDATA_FLUSH)) {
+ while (S_FALSE == pEventQueryFlushBeforeVSync->GetData(&Data, sizeof(Data), D3DGETDATA_FLUSH)) {
if (!r.m_AdvRendSets.bVMRFlushGPUWait) {
break;
}
@@ -1511,8 +1515,8 @@ STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool bAll)
// Create a query object
{
- CComPtr<IDirect3DQuery9> pEventQuery;
- m_pD3DDev->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQuery);
+ CComPtr<IDirect3DQuery9> pEventQueryFlushAfterVSync;
+ m_pD3DDev->CreateQuery(D3DQUERYTYPE_EVENT, &pEventQueryFlushAfterVSync);
LONGLONG llPerf = rd->GetPerfCounter();
CRect presentationSrcRect(rDstPri), presentationDestRect(m_windowRect);
@@ -1533,15 +1537,15 @@ STDMETHODIMP_(bool) CDX9AllocatorPresenter::Paint(bool bAll)
}
}
// Issue an End event
- if (pEventQuery) {
- pEventQuery->Issue(D3DISSUE_END);
+ if (pEventQueryFlushAfterVSync) {
+ pEventQueryFlushAfterVSync->Issue(D3DISSUE_END);
}
BOOL Data;
- if (r.m_AdvRendSets.bVMRFlushGPUAfterPresent && pEventQuery) {
+ if (r.m_AdvRendSets.bVMRFlushGPUAfterPresent && pEventQueryFlushAfterVSync) {
LONGLONG FlushStartTime = rd->GetPerfCounter();
- while (S_FALSE == pEventQuery->GetData(&Data, sizeof(Data), D3DGETDATA_FLUSH)) {
+ while (S_FALSE == pEventQueryFlushAfterVSync->GetData(&Data, sizeof(Data), D3DGETDATA_FLUSH)) {
if (!r.m_AdvRendSets.bVMRFlushGPUWait) {
break;
}
diff --git a/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.h b/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.h
index 6dd983bd9..a7eefc80e 100644
--- a/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.h
+++ b/src/filters/renderer/VideoRenderers/DX9AllocatorPresenter.h
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2014 see Authors.txt
+ * (C) 2006-2015 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -288,6 +288,8 @@ namespace DSObjects
CString m_Decoder;
CFocusThread* m_FocusThread;
+ HWND m_hFocusWindow;
+
public:
CDX9AllocatorPresenter(HWND hWnd, bool bFullscreen, HRESULT& hr, bool bIsEVR, CString& _Error);
~CDX9AllocatorPresenter();
diff --git a/src/filters/renderer/VideoRenderers/DX9RenderingEngine.cpp b/src/filters/renderer/VideoRenderers/DX9RenderingEngine.cpp
index 4f4704c6d..c350d92df 100644
--- a/src/filters/renderer/VideoRenderers/DX9RenderingEngine.cpp
+++ b/src/filters/renderer/VideoRenderers/DX9RenderingEngine.cpp
@@ -25,6 +25,9 @@
#include "Dither.h"
#include "DX9RenderingEngine.h"
+// UUID for vorpX hack
+static const IID IID_D3D9VorpVideoCaptureTexture = { 0x8a49d79, 0x8646, 0x4867, { 0xb9, 0x34, 0x13, 0x12, 0xe4, 0x4b, 0x23, 0xdb } };
+
#pragma pack(push, 1)
template<int texcoords>
struct MYD3DVERTEX {
@@ -435,6 +438,10 @@ HRESULT CDX9RenderingEngine::RenderVideoDrawPath(IDirect3DSurface9* pRenderTarge
pVideoTexture = m_pTemporaryVideoTextures[src];
}
+ // Hack to send the pre-resize video texture to vorpX.
+ void* pVorpTex = pVideoTexture; // Prevent the pointer being overwritten.
+ m_pD3DDev->QueryInterface(IID_D3D9VorpVideoCaptureTexture, (void**)&pVorpTex);
+
// Resize the frame
Vector dst[4];
Transform(destRect, dst);
diff --git a/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.cpp b/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.cpp
index b391bd4b3..1842bd5d2 100644
--- a/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.cpp
+++ b/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.cpp
@@ -41,6 +41,8 @@ enum EVR_STATS_MSG {
MSG_MIXEROUT
};
+// Guid to tag IMFSample with a group id
+static const GUID GUID_GROUP_ID = { 0x309e32cc, 0x9b23, 0x4c6c, { 0x86, 0x63, 0xcd, 0xd9, 0xad, 0x49, 0x7f, 0x8a } };
// Guid to tag IMFSample with DirectX surface index
static const GUID GUID_SURFACE_INDEX = { 0x30c8e9f6, 0x415, 0x4b81, { 0xa3, 0x15, 0x1, 0xa, 0xc6, 0xa9, 0xda, 0x19 } };
@@ -89,8 +91,7 @@ CEVRAllocatorPresenter::CEVRAllocatorPresenter(HWND hWnd, bool bFullscreen, HRES
, m_hGetMixerThread(nullptr)
, m_hVSyncThread(nullptr)
, m_nRenderState(Shutdown)
- , m_pCurrentDisplaydSample(nullptr)
- , m_bWaitingSample(false)
+ , m_nCurrentGroupId(0)
, m_bLastSampleOffsetValid(false)
, m_LastScheduledSampleTime(-1)
, m_LastScheduledSampleTimeFP(-1)
@@ -103,6 +104,7 @@ CEVRAllocatorPresenter::CEVRAllocatorPresenter(HWND hWnd, bool bFullscreen, HRES
, m_nStepCount(0)
, m_bSignaledStarvation(false)
, m_StarvationClock(0)
+ , m_SampleFreeCallback(this, &CEVRAllocatorPresenter::OnSampleFree)
, fnDXVA2CreateDirect3DDeviceManager9("dxva2.dll", "DXVA2CreateDirect3DDeviceManager9")
, fnMFCreateDXSurfaceBuffer("evr.dll", "MFCreateDXSurfaceBuffer")
, fnMFCreateVideoSampleFromSurface("evr.dll", "MFCreateVideoSampleFromSurface")
@@ -311,6 +313,22 @@ STDMETHODIMP_(bool) CEVRAllocatorPresenter::Paint(bool bAll)
return __super::Paint(bAll);
}
+STDMETHODIMP_(bool) CEVRAllocatorPresenter::Paint(IMFSample* pMFSample)
+{
+ CAutoLock lock(&m_RenderLock);
+
+ m_pCurrentlyDisplayedSample = pMFSample;
+ pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
+
+ auto sampleHasCurrentGroupId = [this](IMFSample * pSample) {
+ UINT32 nGroupId;
+ return (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId);
+ };
+ ASSERT(sampleHasCurrentGroupId(pMFSample));
+
+ return Paint(true);
+}
+
STDMETHODIMP CEVRAllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
HRESULT hr;
@@ -350,6 +368,9 @@ STDMETHODIMP CEVRAllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, vo
// IMFClockStateSink
STDMETHODIMP CEVRAllocatorPresenter::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
+
m_nRenderState = Started;
TRACE_EVR("EVR: OnClockStart hnsSystemTime = %I64d, llClockStartOffset = %I64d\n", hnsSystemTime, llClockStartOffset);
@@ -361,6 +382,9 @@ STDMETHODIMP CEVRAllocatorPresenter::OnClockStart(MFTIME hnsSystemTime, LONGLONG
STDMETHODIMP CEVRAllocatorPresenter::OnClockStop(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
+
TRACE_EVR("EVR: OnClockStop hnsSystemTime = %I64d\n", hnsSystemTime);
m_nRenderState = Stopped;
@@ -371,6 +395,9 @@ STDMETHODIMP CEVRAllocatorPresenter::OnClockStop(MFTIME hnsSystemTime)
STDMETHODIMP CEVRAllocatorPresenter::OnClockPause(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
+
TRACE_EVR("EVR: OnClockPause hnsSystemTime = %I64d\n", hnsSystemTime);
if (!m_bSignaledStarvation) {
m_nRenderState = Paused;
@@ -382,6 +409,9 @@ STDMETHODIMP CEVRAllocatorPresenter::OnClockPause(MFTIME hnsSystemTime)
STDMETHODIMP CEVRAllocatorPresenter::OnClockRestart(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
+
m_nRenderState = Started;
m_ModeratedTimeLast = -1;
@@ -559,6 +589,7 @@ void CEVRAllocatorPresenter::CompleteFrameStep(bool bCancel)
STDMETHODIMP CEVRAllocatorPresenter::ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
{
HRESULT hr = S_OK;
+ CHECK_HR(CheckShutdown());
switch (eMessage) {
case MFVP_MESSAGE_BEGINSTREAMING: // The EVR switched from stopped to paused. The presenter should allocate resources
@@ -752,11 +783,27 @@ HRESULT CEVRAllocatorPresenter::CreateOptimalOutputType(IMFMediaType* pMixerProp
HRESULT CEVRAllocatorPresenter::SetMediaType(IMFMediaType* pType)
{
- HRESULT hr;
+ HRESULT hr = S_OK;
AM_MEDIA_TYPE* pAMMedia = nullptr;
CString strTemp, strTemp1;
- CheckPointer(pType, E_POINTER);
+ CHECK_HR(CheckShutdown());
+
+ if (!pType) {
+ // Release
+ RemoveAllSamples();
+ DeleteSurfaces();
+ CAutoLock lock(&m_MediaTypeLock);
+ m_pMediaType = nullptr;
+ return hr;
+ }
+
+ DWORD dwFlags = 0;
+ if (m_pMediaType && m_pMediaType->IsEqual(pType, &dwFlags) == S_OK) {
+ // Nothing to do
+ return hr;
+ }
+
CHECK_HR(pType->GetRepresentation(FORMAT_VideoInfo2, (void**)&pAMMedia));
hr = InitializeDevice(pType);
@@ -1053,17 +1100,22 @@ bool CEVRAllocatorPresenter::GetImageFromMixer()
bool bDoneSomething = false;
+ auto sampleHasCurrentGroupId = [this](IMFSample * pSample) {
+ UINT32 nGroupId;
+ return (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId);
+ };
+
while (SUCCEEDED(hr)) {
CComPtr<IMFSample> pSample;
if (FAILED(GetFreeSample(&pSample))) {
- m_bWaitingSample = true;
break;
}
ZeroMemory(&dataBuffer, sizeof(dataBuffer));
dataBuffer.pSample = pSample;
pSample->GetUINT32(GUID_SURFACE_INDEX, &dwSurface);
+ ASSERT(sampleHasCurrentGroupId(pSample));
{
llClockBefore = GetRenderersData()->GetPerfCounter();
@@ -1072,7 +1124,8 @@ bool CEVRAllocatorPresenter::GetImageFromMixer()
}
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
- MoveToFreeList(pSample, false);
+ AddToFreeList(pSample, false);
+ pSample = nullptr; // The sample should not be used after being queued
// Important: Release any events returned from the ProcessOutput method.
SAFE_RELEASE(dataBuffer.pEvents);
break;
@@ -1105,8 +1158,13 @@ bool CEVRAllocatorPresenter::GetImageFromMixer()
TRACE_EVR("EVR: Get from Mixer : %u (%I64d) (%I64d)\n", dwSurface, nsSampleTime, m_rtTimePerFrame ? nsSampleTime / m_rtTimePerFrame : 0);
- MoveToScheduledList(pSample, false);
- bDoneSomething = true;
+ if (SUCCEEDED(TrackSample(pSample))) {
+ AddToScheduledList(pSample, false);
+ pSample = nullptr; // The sample should not be used after being queued
+ bDoneSomething = true;
+ } else {
+ ASSERT(FALSE);
+ }
// Important: Release any events returned from the ProcessOutput method.
SAFE_RELEASE(dataBuffer.pEvents);
@@ -1472,9 +1530,11 @@ STDMETHODIMP CEVRAllocatorPresenter::InitializeDevice(IMFMediaType* pMediaType)
hr = fnMFCreateVideoSampleFromSurface(m_pVideoSurface[i], &pMFSample);
if (SUCCEEDED(hr)) {
+ pMFSample->SetUINT32(GUID_GROUP_ID, m_nCurrentGroupId);
pMFSample->SetUINT32(GUID_SURFACE_INDEX, i);
CAutoLock sampleQueueLock(&m_SampleQueueLock);
m_FreeSamples.AddTail(pMFSample);
+ pMFSample = nullptr; // The sample should not be used after being queued
}
ASSERT(SUCCEEDED(hr));
}
@@ -1499,14 +1559,6 @@ DWORD WINAPI CEVRAllocatorPresenter::PresentThread(LPVOID lpParam)
return 0;
}
-void CEVRAllocatorPresenter::CheckWaitingSampleFromMixer()
-{
- if (m_bWaitingSample) {
- m_bWaitingSample = false;
- //GetImageFromMixer(); // Do this in processing thread instead
- }
-}
-
bool ExtractInterlaced(const AM_MEDIA_TYPE* pmt)
{
if (pmt->formattype == FORMAT_VideoInfo) {
@@ -1787,7 +1839,9 @@ LONGLONG CEVRAllocatorPresenter::GetClockTime(LONGLONG PerformanceCounter)
void CEVRAllocatorPresenter::OnVBlankFinished(bool bAll, LONGLONG PerformanceCounter)
{
- if (!m_pCurrentDisplaydSample || !m_OrderedPaint || !bAll) {
+ // This function is meant to be called only from the rendering function
+ // so with the ownership on m_RenderLock.
+ if (!m_pCurrentlyDisplayedSample || !m_OrderedPaint || !bAll) {
return;
}
@@ -1806,14 +1860,14 @@ void CEVRAllocatorPresenter::OnVBlankFinished(bool bAll, LONGLONG PerformanceCou
llClockTime = m_StarvationClock;
}
- if (SUCCEEDED(m_pCurrentDisplaydSample->GetSampleDuration(&SampleDuration))) {
+ if (SUCCEEDED(m_pCurrentlyDisplayedSample->GetSampleDuration(&SampleDuration))) {
// Some filters return invalid values, ignore them
if (SampleDuration > MIN_FRAME_TIME) {
TimePerFrame = SampleDuration;
}
}
- if (FAILED(m_pCurrentDisplaydSample->GetSampleTime(&nsSampleTime))) {
+ if (FAILED(m_pCurrentlyDisplayedSample->GetSampleTime(&nsSampleTime))) {
nsSampleTime = llClockTime;
}
@@ -1845,7 +1899,6 @@ void CEVRAllocatorPresenter::OnVBlankFinished(bool bAll, LONGLONG PerformanceCou
m_fSyncOffsetAvr = MeanOffset;
m_bSyncStatsAvailable = true;
m_fSyncOffsetStdDev = StdDev;
-
}
}
@@ -1866,9 +1919,11 @@ STDMETHODIMP_(bool) CEVRAllocatorPresenter::ResetDevice()
HRESULT hr = fnMFCreateVideoSampleFromSurface(m_pVideoSurface[i], &pMFSample);
if (SUCCEEDED(hr)) {
+ pMFSample->SetUINT32(GUID_GROUP_ID, m_nCurrentGroupId);
pMFSample->SetUINT32(GUID_SURFACE_INDEX, i);
CAutoLock sampleQueueLock(&m_SampleQueueLock);
m_FreeSamples.AddTail(pMFSample);
+ pMFSample = nullptr; // The sample should not be used after being queued
}
ASSERT(SUCCEEDED(hr));
}
@@ -1939,6 +1994,17 @@ void CEVRAllocatorPresenter::RenderThread()
timeGetDevCaps(&tc, sizeof(TIMECAPS));
DWORD dwResolution = std::min(std::max(tc.wPeriodMin, 0u), tc.wPeriodMax);
VERIFY(timeBeginPeriod(dwResolution) == 0);
+
+ auto checkPendingMediaFinished = [this]() {
+ if (m_bPendingMediaFinished) {
+ CAutoLock lock(&m_SampleQueueLock);
+ if (m_ScheduledSamples.IsEmpty()) {
+ m_bPendingMediaFinished = false;
+ m_pSink->Notify(EC_COMPLETE, 0, 0);
+ }
+ }
+ };
+
const CRenderersSettings& r = GetRenderersSettings();
int NextSleepTime = 1;
@@ -1993,12 +2059,12 @@ void CEVRAllocatorPresenter::RenderThread()
//if (WaitForMultipleObjects (_countof(hEvtsBuff), hEvtsBuff, FALSE, INFINITE) == WAIT_OBJECT_0+2)
{
CComPtr<IMFSample> pMFSample;
- LONGLONG llPerf = GetRenderersData()->GetPerfCounter();
- UNREFERENCED_PARAMETER(llPerf);
+ //LONGLONG llPerf2 = GetRenderersData()->GetPerfCounter();
+ //UNREFERENCED_PARAMETER(llPerf2);
int nSamplesLeft = 0;
if (SUCCEEDED(GetScheduledSample(&pMFSample, nSamplesLeft))) {
- //pMFSample->GetUINT32 (GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
- m_pCurrentDisplaydSample = pMFSample;
+ //UINT32 nSurface;
+ //pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&nSurface);
bool bValidSampleTime = true;
HRESULT hrGetSampleTime = pMFSample->GetSampleTime(&nsSampleTime);
@@ -2014,7 +2080,7 @@ void CEVRAllocatorPresenter::RenderThread()
bValidSampleDuration = false;
}
- //TRACE_EVR ("EVR: RenderThread ==>> Presenting surface %d (%I64d)\n", m_nCurSurface, nsSampleTime);
+ //TRACE_EVR("EVR: RenderThread ==>> Presenting surface %d (%I64d)\n", nSurface, nsSampleTime);
bool bStepForward = false;
@@ -2026,14 +2092,13 @@ void CEVRAllocatorPresenter::RenderThread()
m_nStepCount = 0;
/*
} else if (m_nStepCount > 0) {
- pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32 *)&m_nCurSurface);
++m_OrderedPaint;
if (!g_bExternalSubtitleTime) {
__super::SetTime (g_tSegmentStart + nsSampleTime);
}
- Paint(true);
+ Paint(pMFSample);
m_nDroppedUpdate = 0;
- CompleteFrameStep (false);
+ CompleteFrameStep(false);
bStepForward = true;
*/
} else if (m_nRenderState == Started) {
@@ -2049,18 +2114,13 @@ void CEVRAllocatorPresenter::RenderThread()
if (!bValidSampleTime) {
// Just play as fast as possible
bStepForward = true;
- pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
++m_OrderedPaint;
if (!g_bExternalSubtitleTime) {
__super::SetTime(g_tSegmentStart + nsSampleTime);
}
- Paint(true);
+ Paint(pMFSample);
} else {
LONGLONG TimePerFrame = (LONGLONG)(GetFrameTime() * 10000000.0);
- LONGLONG DrawTime = m_PaintTime * 9 / 10 - 20000; // 2 ms offset (= m_PaintTime * 0.9 - 20000)
- //if (!r.bVMR9VSync)
- DrawTime = 0;
-
LONGLONG SyncOffset = 0;
LONGLONG VSyncTime = 0;
LONGLONG TimeToNextVSync = -1;
@@ -2168,7 +2228,6 @@ void CEVRAllocatorPresenter::RenderThread()
TRACE_EVR("EVR: Normalframe\n");
m_nDroppedUpdate = 0;
bStepForward = true;
- pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
m_LastFrameDuration = nsSampleTime - m_LastSampleTime;
m_LastSampleTime = nsSampleTime;
m_LastPredictedSync = VSyncOffset0;
@@ -2182,7 +2241,7 @@ void CEVRAllocatorPresenter::RenderThread()
if (!g_bExternalSubtitleTime) {
__super::SetTime(g_tSegmentStart + nsSampleTime);
}
- Paint(true);
+ Paint(pMFSample);
NextSleepTime = 0;
m_pcFramesDrawn++;
@@ -2249,18 +2308,17 @@ void CEVRAllocatorPresenter::RenderThread()
if (!g_bExternalSubtitleTime) {
__super::SetTime(g_tSegmentStart + nsSampleTime);
}
- Paint(false);
+ Paint(pMFSample);
}
NextSleepTime = int(SampleDuration / 10000 - 2);
}
- m_pCurrentDisplaydSample = nullptr;
if (bStepForward) {
- MoveToFreeList(pMFSample, true);
- CheckWaitingSampleFromMixer();
m_MaxSampleDuration = std::max(SampleDuration, m_MaxSampleDuration);
+ checkPendingMediaFinished();
} else {
- MoveToScheduledList(pMFSample, true);
+ AddToScheduledList(pMFSample, true);
+ pMFSample = nullptr; // The sample should not be used after being queued
}
bForcePaint = false;
@@ -2269,8 +2327,9 @@ void CEVRAllocatorPresenter::RenderThread()
m_pSink->Notify(EC_STARVATION, 0, 0);
m_bSignaledStarvation = true;
}
+ } else {
+ checkPendingMediaFinished();
}
- //GetImageFromMixer();
}
//else
//{
@@ -2485,6 +2544,8 @@ void CEVRAllocatorPresenter::RemoveAllSamples()
m_LastScheduledSampleTime = -1;
m_LastScheduledUncorrectedSampleTime = -1;
m_nUsedBuffer = 0;
+ // Increment the group id to make sure old samples will really be deleted
+ m_nCurrentGroupId++;
}
HRESULT CEVRAllocatorPresenter::GetFreeSample(IMFSample** ppSample)
@@ -2492,7 +2553,7 @@ HRESULT CEVRAllocatorPresenter::GetFreeSample(IMFSample** ppSample)
CAutoLock lock(&m_SampleQueueLock);
HRESULT hr = S_OK;
- if (m_FreeSamples.GetCount() > 1) { // <= Cannot use first free buffer (can be currently displayed)
+ if (!m_FreeSamples.IsEmpty()) {
m_nUsedBuffer++;
*ppSample = m_FreeSamples.RemoveHead().Detach();
} else {
@@ -2502,15 +2563,15 @@ HRESULT CEVRAllocatorPresenter::GetFreeSample(IMFSample** ppSample)
return hr;
}
-HRESULT CEVRAllocatorPresenter::GetScheduledSample(IMFSample** ppSample, int& _Count)
+HRESULT CEVRAllocatorPresenter::GetScheduledSample(IMFSample** ppSample, int& count)
{
CAutoLock lock(&m_SampleQueueLock);
HRESULT hr = S_OK;
- _Count = (int)m_ScheduledSamples.GetCount();
- if (_Count > 0) {
+ count = (int)m_ScheduledSamples.GetCount();
+ if (count > 0) {
*ppSample = m_ScheduledSamples.RemoveHead().Detach();
- --_Count;
+ --count;
} else {
hr = MF_E_SAMPLEALLOCATOR_EMPTY;
}
@@ -2518,15 +2579,11 @@ HRESULT CEVRAllocatorPresenter::GetScheduledSample(IMFSample** ppSample, int& _C
return hr;
}
-void CEVRAllocatorPresenter::MoveToFreeList(IMFSample* pSample, bool bTail)
+void CEVRAllocatorPresenter::AddToFreeList(IMFSample* pSample, bool bTail)
{
CAutoLock lock(&m_SampleQueueLock);
m_nUsedBuffer--;
- if (m_bPendingMediaFinished && m_nUsedBuffer == 0) {
- m_bPendingMediaFinished = false;
- m_pSink->Notify(EC_COMPLETE, 0, 0);
- }
if (bTail) {
m_FreeSamples.AddTail(pSample);
} else {
@@ -2534,11 +2591,11 @@ void CEVRAllocatorPresenter::MoveToFreeList(IMFSample* pSample, bool bTail)
}
}
-void CEVRAllocatorPresenter::MoveToScheduledList(IMFSample* pSample, bool _bSorted)
+void CEVRAllocatorPresenter::AddToScheduledList(IMFSample* pSample, bool bSorted)
{
+ CAutoLock lock(&m_SampleQueueLock);
- if (_bSorted) {
- CAutoLock lock(&m_SampleQueueLock);
+ if (bSorted) {
// Insert sorted
/*POSITION Iterator = m_ScheduledSamples.GetHeadPosition();
@@ -2560,9 +2617,6 @@ void CEVRAllocatorPresenter::MoveToScheduledList(IMFSample* pSample, bool _bSort
m_ScheduledSamples.AddHead(pSample);
} else {
-
- CAutoLock lock(&m_SampleQueueLock);
-
const CRenderersSettings& r = GetRenderersSettings();
double ForceFPS = 0.0;
//double ForceFPS = 59.94;
@@ -2594,7 +2648,7 @@ void CEVRAllocatorPresenter::MoveToScheduledList(IMFSample* pSample, bool _bSort
}
if (Diff < m_rtTimePerFrame * 8 && m_rtTimePerFrame && Diff2 < m_rtTimePerFrame * 8) { // Detect seeking
int iPos = (m_DetectedFrameTimePos++) % 60;
- LONGLONG Diff = Time - PrevTime;
+ Diff = Time - PrevTime;
if (PrevTime == -1) {
Diff = 0;
}
@@ -2762,7 +2816,6 @@ void CEVRAllocatorPresenter::MoveToScheduledList(IMFSample* pSample, bool _bSort
m_LastScheduledSampleTime = Time;
m_ScheduledSamples.AddTail(pSample);
-
}
}
@@ -2770,21 +2823,40 @@ void CEVRAllocatorPresenter::FlushSamples()
{
CAutoLock lock(this);
CAutoLock lock2(&m_SampleQueueLock);
+ CAutoLock lock3(&m_RenderLock);
+
+ m_pCurrentlyDisplayedSample = nullptr;
+ m_ScheduledSamples.RemoveAll();
- FlushSamplesInternal();
+ m_LastSampleOffset = 0;
+ m_bLastSampleOffsetValid = false;
+ m_bSignaledStarvation = false;
m_LastScheduledSampleTime = -1;
}
-void CEVRAllocatorPresenter::FlushSamplesInternal()
+HRESULT CEVRAllocatorPresenter::TrackSample(IMFSample* pSample)
{
- while (!m_ScheduledSamples.IsEmpty()) {
- CComPtr<IMFSample> pMFSample;
-
- pMFSample = m_ScheduledSamples.RemoveHead();
- MoveToFreeList(pMFSample, true);
+ HRESULT hr = E_FAIL;
+ if (CComQIPtr<IMFTrackedSample> pTracked = pSample) {
+ hr = pTracked->SetAllocator(&m_SampleFreeCallback, nullptr);
}
+ return hr;
+}
- m_LastSampleOffset = 0;
- m_bLastSampleOffsetValid = false;
- m_bSignaledStarvation = false;
+HRESULT CEVRAllocatorPresenter::OnSampleFree(IMFAsyncResult* pResult)
+{
+ CComPtr<IUnknown> pObject;
+ HRESULT hr = pResult->GetObject(&pObject);
+ if (SUCCEEDED(hr)) {
+ if (CComQIPtr<IMFSample> pSample = pObject) {
+ // Ignore the sample if it is from an old group
+ UINT32 nGroupId;
+ CAutoLock sampleQueueLock(&m_SampleQueueLock);
+ if (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId) {
+ AddToFreeList(pSample, true);
+ pSample = nullptr; // The sample should not be used after being queued
+ }
+ }
+ }
+ return hr;
}
diff --git a/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.h b/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.h
index 292b7a4e1..cbb8f22d9 100644
--- a/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.h
+++ b/src/filters/renderer/VideoRenderers/EVRAllocatorPresenter.h
@@ -24,6 +24,7 @@
#include <mfapi.h> // API Media Foundation
#include <evr9.h>
#include "../../../DSUtil/WinapiFunc.h"
+#include "AsyncCallback.h"
namespace DSObjects
{
@@ -144,6 +145,7 @@ namespace DSObjects
STDMETHODIMP GetVideoService(HANDLE hDevice, REFIID riid, void** ppService);
protected:
+ STDMETHODIMP_(bool) Paint(IMFSample* pMFSample);
void OnResetDevice();
virtual void OnVBlankFinished(bool bAll, LONGLONG PerformanceCounter);
@@ -193,10 +195,10 @@ namespace DSObjects
CCritSec m_ImageProcessingLock;
CCritSec m_MediaTypeLock;
- CInterfaceList<IMFSample, &IID_IMFSample> m_FreeSamples;
- CInterfaceList<IMFSample, &IID_IMFSample> m_ScheduledSamples;
- IMFSample* m_pCurrentDisplaydSample;
- bool m_bWaitingSample;
+ UINT32 m_nCurrentGroupId;
+ CInterfaceList<IMFSample> m_FreeSamples;
+ CInterfaceList<IMFSample> m_ScheduledSamples;
+ CComPtr<IMFSample> m_pCurrentlyDisplayedSample;
bool m_bLastSampleOffsetValid;
LONGLONG m_LastScheduledSampleTime;
double m_LastScheduledSampleTimeFP;
@@ -232,17 +234,21 @@ namespace DSObjects
void StopWorkerThreads();
HRESULT CheckShutdown() const;
void CompleteFrameStep(bool bCancel);
- void CheckWaitingSampleFromMixer();
static DWORD WINAPI VSyncThreadStatic(LPVOID lpParam);
void VSyncThread();
void RemoveAllSamples();
HRESULT GetFreeSample(IMFSample** ppSample);
- HRESULT GetScheduledSample(IMFSample** ppSample, int& _Count);
- void MoveToFreeList(IMFSample* pSample, bool bTail);
- void MoveToScheduledList(IMFSample* pSample, bool _bSorted);
+ HRESULT GetScheduledSample(IMFSample** ppSample, int& count);
+ void AddToFreeList(IMFSample* pSample, bool bTail);
+ void AddToScheduledList(IMFSample* pSample, bool bSorted);
void FlushSamples();
- void FlushSamplesInternal();
+
+ HRESULT TrackSample(IMFSample* pSample);
+
+ // Callback when a video sample is released.
+ HRESULT OnSampleFree(IMFAsyncResult* pResult);
+ AsyncCallback<CEVRAllocatorPresenter> m_SampleFreeCallback;
// === Media type negotiation functions
HRESULT RenegotiateMediaType();
diff --git a/src/filters/renderer/VideoRenderers/FocusThread.cpp b/src/filters/renderer/VideoRenderers/FocusThread.cpp
index 73620ea98..c71365d5f 100644
--- a/src/filters/renderer/VideoRenderers/FocusThread.cpp
+++ b/src/filters/renderer/VideoRenderers/FocusThread.cpp
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2014 see Authors.txt
+ * (C) 2006-2015 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -39,18 +39,18 @@ CFocusThread::CFocusThread()
: m_hWnd(nullptr)
, m_hEvtInit(nullptr)
{
- WNDCLASS wndclass;
-
- wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
- wndclass.lpfnWndProc = FocusWndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = nullptr;
- wndclass.hIcon = nullptr;
- wndclass.hCursor = nullptr;
- wndclass.hbrBackground = nullptr;
- wndclass.lpszMenuName = nullptr;
- wndclass.lpszClassName = _T("D3DFocusClass");
+ WNDCLASS wndclass {
+ CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE,
+ FocusWndProc,
+ 0,
+ 0,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ _T("D3DFocusClass")
+ };
if (!RegisterClass(&wndclass)) {
TRACE("Registering focus window failed");
@@ -82,6 +82,11 @@ int CFocusThread::ExitInstance()
if (m_hWnd) {
DestroyWindow(m_hWnd);
m_hWnd = nullptr;
+
+ CWnd* pMainWnd = AfxGetApp()->GetMainWnd();
+ if (pMainWnd) {
+ pMainWnd->SetActiveWindow();
+ }
}
return __super::ExitInstance();
}
diff --git a/src/filters/renderer/VideoRenderers/FocusThread.h b/src/filters/renderer/VideoRenderers/FocusThread.h
index 7d4d9f837..17701f088 100644
--- a/src/filters/renderer/VideoRenderers/FocusThread.h
+++ b/src/filters/renderer/VideoRenderers/FocusThread.h
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
- * (C) 2006-2013 see Authors.txt
+ * (C) 2006-2013, 2015 see Authors.txt
*
* This file is part of MPC-HC.
*
@@ -32,13 +32,16 @@ private:
HANDLE m_hEvtInit;
protected:
- CFocusThread(void); // protected constructor used by dynamic creation
- ~CFocusThread(void);
+ CFocusThread(); // protected constructor used by dynamic creation
+ ~CFocusThread();
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
HWND GetFocusWindow();
+
+protected:
+ afx_msg void OnDestroy();
};
diff --git a/src/filters/renderer/VideoRenderers/IPinHook.cpp b/src/filters/renderer/VideoRenderers/IPinHook.cpp
index e445a0e5b..2e85648a9 100644
--- a/src/filters/renderer/VideoRenderers/IPinHook.cpp
+++ b/src/filters/renderer/VideoRenderers/IPinHook.cpp
@@ -29,6 +29,8 @@
#include "IPinHook.h"
#include "AllocatorCommon.h"
+#include "../../../mpc-hc/FGFilterLAV.h"
+
#define DXVA_LOGFILE_A 0 // set to 1 for logging DXVA data to a file
#define LOG_BITSTREAM 0 // set to 1 for logging DXVA bitstream data to a file
#define LOG_MATRIX 0 // set to 1 for logging DXVA matrix data to a file
@@ -47,7 +49,7 @@ GUID g_guidDXVADecoder = GUID_NULL;
int g_nDXVAVersion = 0;
IPinCVtbl* g_pPinCVtbl = nullptr;
-IPinCVtbl* g_pPinCVtblVideoDriverWorkAround = nullptr;
+IPinCVtbl* g_pPinCVtbl10BitWorkAround = nullptr;
IMemInputPinCVtbl* g_pMemInputPinCVtbl = nullptr;
struct D3DFORMAT_TYPE {
@@ -153,12 +155,15 @@ static HRESULT(STDMETHODCALLTYPE* ReceiveConnectionOrg)(IPinC* This, /* [in] */
static HRESULT STDMETHODCALLTYPE ReceiveConnectionMine(IPinC* This, /* [in] */ IPinC* pConnector, /* [in] */ const AM_MEDIA_TYPE* pmt)
{
- // Force the renderer to always reject the P010 and P016 pixel formats
+ // Force-reject P010 and P016 pixel formats due to Microsoft bug ...
if (pmt && (pmt->subtype == MEDIASUBTYPE_P010 || pmt->subtype == MEDIASUBTYPE_P016)) {
- return VFW_E_TYPE_NOT_ACCEPTED;
- } else {
- return ReceiveConnectionOrg(This, pConnector, pmt);
+ // ... but allow LAV Video Decoder to do that itself in order to support 10bit DXVA.
+ if (GetCLSID((IPin*)pConnector) != GUID_LAVVideo) {
+ return VFW_E_TYPE_NOT_ACCEPTED;
+ }
}
+
+ return ReceiveConnectionOrg(This, pConnector, pmt);
}
@@ -184,26 +189,20 @@ static HRESULT STDMETHODCALLTYPE ReceiveMine(IMemInputPinC* This, IMediaSample*
return ReceiveMineI(This, pSample);
}
-void HookWorkAroundVideoDriversBug(IBaseFilter* pBF)
+void HookWorkAround10BitBug(IBaseFilter* pBF)
{
- // Work-around a bug in some video drivers: some drivers mistakenly
- // accepts P010 and P016 pixel formats as input for VMR/EVR renderers
- // so use the pin hook to add our own level of verification.
-#if MPC_VERSION_MAJOR > 1 || MPC_VERSION_MINOR > 7 || MPC_VERSION_PATCH > 9
-#pragma message("WARNING: Check if this bug is fixed in currently distributed drivers")
-#endif
-
if (CComPtr<IPin> pPin = GetFirstPin(pBF)) {
IPinC* pPinC = (IPinC*)(IPin*)pPin;
DWORD flOldProtect = 0;
- if (VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (ReceiveConnectionOrg == nullptr) {
ReceiveConnectionOrg = pPinC->lpVtbl->ReceiveConnection;
}
pPinC->lpVtbl->ReceiveConnection = ReceiveConnectionMine;
+ FlushInstructionCache(GetCurrentProcess(), pPinC->lpVtbl, sizeof(IPinCVtbl));
VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
- g_pPinCVtblVideoDriverWorkAround = pPinC->lpVtbl;
+ g_pPinCVtbl10BitWorkAround = pPinC->lpVtbl;
} else {
TRACE(_T("HookWorkAroundVideoDriversBug: Could not hook the VTable"));
ASSERT(FALSE);
@@ -211,18 +210,19 @@ void HookWorkAroundVideoDriversBug(IBaseFilter* pBF)
}
}
-void UnhookWorkAroundVideoDriversBug()
+void UnhookWorkAround10BitBug()
{
// Unhook previous VTable
- if (g_pPinCVtblVideoDriverWorkAround) {
+ if (g_pPinCVtbl10BitWorkAround) {
DWORD flOldProtect = 0;
- if (VirtualProtect(g_pPinCVtblVideoDriverWorkAround, sizeof(IPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
- if (g_pPinCVtblVideoDriverWorkAround->ReceiveConnection == ReceiveConnectionMine) {
- g_pPinCVtblVideoDriverWorkAround->ReceiveConnection = ReceiveConnectionOrg;
+ if (VirtualProtect(g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
+ if (g_pPinCVtbl10BitWorkAround->ReceiveConnection == ReceiveConnectionMine) {
+ g_pPinCVtbl10BitWorkAround->ReceiveConnection = ReceiveConnectionOrg;
}
ReceiveConnectionOrg = nullptr;
- VirtualProtect(g_pPinCVtblVideoDriverWorkAround, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
- g_pPinCVtblVideoDriverWorkAround = nullptr;
+ FlushInstructionCache(GetCurrentProcess(), g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl));
+ VirtualProtect(g_pPinCVtbl10BitWorkAround, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
+ g_pPinCVtbl10BitWorkAround = nullptr;
} else {
TRACE(_T("UnhookWorkAroundVideoDriversBug: Could not unhook previous VTable"));
ASSERT(FALSE);
@@ -236,10 +236,11 @@ void UnhookNewSegmentAndReceive()
// Unhook previous VTables
if (g_pPinCVtbl) {
- if (VirtualProtect(g_pPinCVtbl, sizeof(IPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(g_pPinCVtbl, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (g_pPinCVtbl->NewSegment == NewSegmentMine) {
g_pPinCVtbl->NewSegment = NewSegmentOrg;
}
+ FlushInstructionCache(GetCurrentProcess(), g_pPinCVtbl, sizeof(IPinCVtbl));
VirtualProtect(g_pPinCVtbl, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
g_pPinCVtbl = nullptr;
NewSegmentOrg = nullptr;
@@ -250,10 +251,11 @@ void UnhookNewSegmentAndReceive()
}
if (g_pMemInputPinCVtbl) {
- if (VirtualProtect(g_pMemInputPinCVtbl, sizeof(IMemInputPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(g_pMemInputPinCVtbl, sizeof(IMemInputPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (g_pMemInputPinCVtbl->Receive == ReceiveMine) {
g_pMemInputPinCVtbl->Receive = ReceiveOrg;
}
+ FlushInstructionCache(GetCurrentProcess(), g_pMemInputPinCVtbl, sizeof(IMemInputPinCVtbl));
VirtualProtect(g_pMemInputPinCVtbl, sizeof(IMemInputPinCVtbl), flOldProtect, &flOldProtect);
g_pMemInputPinCVtbl = nullptr;
ReceiveOrg = nullptr;
@@ -278,11 +280,12 @@ bool HookNewSegmentAndReceive(IPinC* pPinC, IMemInputPinC* pMemInputPinC)
DWORD flOldProtect = 0;
if (!g_pPinCVtbl) {
- if (VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (NewSegmentOrg == nullptr) {
NewSegmentOrg = pPinC->lpVtbl->NewSegment;
}
pPinC->lpVtbl->NewSegment = NewSegmentMine; // Function sets global variable(s)
+ FlushInstructionCache(GetCurrentProcess(), pPinC->lpVtbl, sizeof(IPinCVtbl));
VirtualProtect(pPinC->lpVtbl, sizeof(IPinCVtbl), flOldProtect, &flOldProtect);
g_pPinCVtbl = pPinC->lpVtbl;
} else {
@@ -292,11 +295,12 @@ bool HookNewSegmentAndReceive(IPinC* pPinC, IMemInputPinC* pMemInputPinC)
}
if (!g_pMemInputPinCVtbl) {
- if (VirtualProtect(pMemInputPinC->lpVtbl, sizeof(IMemInputPinCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(pMemInputPinC->lpVtbl, sizeof(IMemInputPinCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (ReceiveOrg == nullptr) {
ReceiveOrg = pMemInputPinC->lpVtbl->Receive;
}
pMemInputPinC->lpVtbl->Receive = ReceiveMine; // Function sets global variable(s)
+ FlushInstructionCache(GetCurrentProcess(), pMemInputPinC->lpVtbl, sizeof(IMemInputPinCVtbl));
VirtualProtect(pMemInputPinC->lpVtbl, sizeof(IMemInputPinCVtbl), flOldProtect, &flOldProtect);
g_pMemInputPinCVtbl = pMemInputPinC->lpVtbl;
} else {
@@ -1052,7 +1056,7 @@ void HookAMVideoAccelerator(IAMVideoAcceleratorC* pAMVideoAcceleratorC)
g_nDXVAVersion = 0;
DWORD flOldProtect = 0;
- if (VirtualProtect(pAMVideoAcceleratorC->lpVtbl, sizeof(IAMVideoAcceleratorC), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(pAMVideoAcceleratorC->lpVtbl, sizeof(IAMVideoAcceleratorCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
#ifdef _DEBUG
if (GetVideoAcceleratorGUIDsOrg == nullptr) {
@@ -1110,7 +1114,8 @@ void HookAMVideoAccelerator(IAMVideoAcceleratorC* pAMVideoAcceleratorC)
pAMVideoAcceleratorC->lpVtbl->DisplayFrame = DisplayFrameMine;
#endif
- VirtualProtect(pAMVideoAcceleratorC->lpVtbl, sizeof(IAMVideoAcceleratorC), PAGE_EXECUTE, &flOldProtect);
+ FlushInstructionCache(GetCurrentProcess(), pAMVideoAcceleratorC->lpVtbl, sizeof(IAMVideoAcceleratorCVtbl));
+ VirtualProtect(pAMVideoAcceleratorC->lpVtbl, sizeof(IAMVideoAcceleratorCVtbl), flOldProtect, &flOldProtect);
} else {
TRACE(_T("HookAMVideoAccelerator: Could not hook the VTable"));
ASSERT(FALSE);
@@ -1559,7 +1564,7 @@ void HookDirectXVideoDecoderService(void* pIDirectXVideoDecoderService)
// Unhook previous VTable
if (g_pIDirectXVideoDecoderServiceCVtbl) {
- if (VirtualProtect(g_pIDirectXVideoDecoderServiceCVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(g_pIDirectXVideoDecoderServiceCVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
if (g_pIDirectXVideoDecoderServiceCVtbl->CreateVideoDecoder == CreateVideoDecoderMine) {
g_pIDirectXVideoDecoderServiceCVtbl->CreateVideoDecoder = CreateVideoDecoderOrg;
}
@@ -1574,6 +1579,7 @@ void HookDirectXVideoDecoderService(void* pIDirectXVideoDecoderService)
//}
#endif
+ FlushInstructionCache(GetCurrentProcess(), g_pIDirectXVideoDecoderServiceCVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl));
VirtualProtect(g_pIDirectXVideoDecoderServiceCVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), flOldProtect, &flOldProtect);
g_pIDirectXVideoDecoderServiceCVtbl = nullptr;
@@ -1597,7 +1603,7 @@ void HookDirectXVideoDecoderService(void* pIDirectXVideoDecoderService)
#endif
if (!g_pIDirectXVideoDecoderServiceCVtbl && pIDirectXVideoDecoderService) {
- if (VirtualProtect(pIDirectXVideoDecoderServiceC->lpVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), PAGE_WRITECOPY, &flOldProtect)) {
+ if (VirtualProtect(pIDirectXVideoDecoderServiceC->lpVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), PAGE_EXECUTE_WRITECOPY, &flOldProtect)) {
CreateVideoDecoderOrg = pIDirectXVideoDecoderServiceC->lpVtbl->CreateVideoDecoder;
pIDirectXVideoDecoderServiceC->lpVtbl->CreateVideoDecoder = CreateVideoDecoderMine;
@@ -1610,6 +1616,7 @@ void HookDirectXVideoDecoderService(void* pIDirectXVideoDecoderService)
//pIDirectXVideoDecoderServiceC->lpVtbl->GetDecoderDeviceGuids = GetDecoderDeviceGuidsMine;
#endif
+ FlushInstructionCache(GetCurrentProcess(), pIDirectXVideoDecoderServiceC->lpVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl));
VirtualProtect(pIDirectXVideoDecoderServiceC->lpVtbl, sizeof(IDirectXVideoDecoderServiceCVtbl), flOldProtect, &flOldProtect);
g_pIDirectXVideoDecoderServiceCVtbl = pIDirectXVideoDecoderServiceC->lpVtbl;
diff --git a/src/filters/renderer/VideoRenderers/IPinHook.h b/src/filters/renderer/VideoRenderers/IPinHook.h
index adb5f8d83..7425224a9 100644
--- a/src/filters/renderer/VideoRenderers/IPinHook.h
+++ b/src/filters/renderer/VideoRenderers/IPinHook.h
@@ -76,8 +76,8 @@ extern bool HookNewSegmentAndReceive(IPinC* pPinC, IMemInputPinC* pMemInputPin);
extern void UnhookNewSegmentAndReceive();
extern REFERENCE_TIME g_tSegmentStart, g_tSampleStart, g_rtTimePerFrame;
-extern void HookWorkAroundVideoDriversBug(IBaseFilter* pBF);
-extern void UnhookWorkAroundVideoDriversBug();
+extern void HookWorkAround10BitBug(IBaseFilter* pBF);
+extern void UnhookWorkAround10BitBug();
//
diff --git a/src/filters/renderer/VideoRenderers/RenderersSettings.cpp b/src/filters/renderer/VideoRenderers/RenderersSettings.cpp
index 3f04ec596..461eb5175 100644
--- a/src/filters/renderer/VideoRenderers/RenderersSettings.cpp
+++ b/src/filters/renderer/VideoRenderers/RenderersSettings.cpp
@@ -98,16 +98,16 @@ void CRenderersSettings::CAdvRendererSettings::SetOptimal()
// CRenderersData construction
CRenderersData::CRenderersData()
+ : m_hD3DX9Dll(nullptr)
+ , m_nDXSdkRelease(0)
+ , m_bTearingTest(false)
+ , m_iDisplayStats(0)
+ , m_bResetStats(false)
+ // Don't disable hardware features before initializing a renderer
+ , m_bFP16Support(true)
+ , m_bFP32Support(true)
+ , m_b10bitSupport(true)
{
- m_bTearingTest = false;
- m_iDisplayStats = 0;
- m_bResetStats = false;
- m_hD3DX9Dll = nullptr;
- m_nDXSdkRelease = 0;
-
- // Don't disable hardware features before initializing a renderer
- m_bFP16Support = true;
- m_b10bitSupport = true;
QueryPerformanceFrequency(&llPerfFrequency);
}
diff --git a/src/filters/renderer/VideoRenderers/RenderersSettings.h b/src/filters/renderer/VideoRenderers/RenderersSettings.h
index 2e57c929a..9f658cba4 100644
--- a/src/filters/renderer/VideoRenderers/RenderersSettings.h
+++ b/src/filters/renderer/VideoRenderers/RenderersSettings.h
@@ -145,6 +145,7 @@ public:
// Hardware feature support
bool m_bFP16Support;
+ bool m_bFP32Support;
bool m_b10bitSupport;
CString m_strDXVAInfo;
diff --git a/src/filters/renderer/VideoRenderers/SyncRenderer.cpp b/src/filters/renderer/VideoRenderers/SyncRenderer.cpp
index e4c13b406..ecb328db6 100644
--- a/src/filters/renderer/VideoRenderers/SyncRenderer.cpp
+++ b/src/filters/renderer/VideoRenderers/SyncRenderer.cpp
@@ -56,84 +56,85 @@ extern bool LoadResource(UINT resid, CStringA& str, LPCTSTR restype);
CBaseAP::CBaseAP(HWND hWnd, bool bFullscreen, HRESULT& hr, CString& _Error)
: CSubPicAllocatorPresenterImpl(hWnd, hr, &_Error)
- , m_ScreenSize(0, 0)
+ , m_hDWMAPI(nullptr)
+ , m_pDwmIsCompositionEnabled(nullptr)
+ , m_pDwmEnableComposition(nullptr)
+ , m_hD3D9(nullptr)
+ , m_pDirect3DCreate9Ex(nullptr)
+ , m_pOuterEVR(nullptr)
+ , m_SurfaceType(D3DFMT_UNKNOWN)
+ , m_BackbufferType(D3DFMT_UNKNOWN)
+ , m_DisplayType(D3DFMT_UNKNOWN)
+ , m_filter(D3DTEXF_NONE)
+ , m_LastAdapterCheck(0)
+ , m_CurrentAdapter(UINT_ERROR)
, m_bicubicA(0)
, m_nTearingPos(0)
, m_VMR9AlphaBitmapWidthBytes()
+ , m_pD3DXLoadSurfaceFromMemory(nullptr)
+ , m_pD3DXCreateLine(nullptr)
+ , m_pD3DXCreateFont(nullptr)
+ , m_pD3DXCreateSprite(nullptr)
, m_nDXSurface(1)
, m_nVMR9Surfaces(0)
, m_iVMR9Surface(0)
, m_nCurSurface(0)
- , m_bSnapToVSync(false)
- , m_rtTimePerFrame(0)
- , m_bInterlaced(false)
, m_nUsedBuffer(0)
- , m_TextScale(1.0)
- , m_dMainThreadId(0)
- , m_bNeedCheckSample(true)
- , m_bIsFullscreen(bFullscreen)
- , m_uSyncGlitches(0)
- , m_pGenlock(nullptr)
- , m_lAudioLag(0)
- , m_lAudioLagMin(10000)
- , m_lAudioLagMax(-10000)
- , m_pAudioStats(nullptr)
- , m_nNextJitter(0)
- , m_nNextSyncOffset(0)
- , m_llLastSyncTime(LONGLONG_ERROR)
+ , m_lNextSampleWait(1)
+ , m_bSnapToVSync(false)
+ , m_uScanLineEnteringPaint(0)
+ , m_llEstVBlankTime(0)
, m_fAvrFps(0.0)
, m_fJitterStdDev(0.0)
- , m_fSyncOffsetStdDev(0.0)
+ , m_fJitterMean(0)
, m_fSyncOffsetAvr(0.0)
- , m_llHysteresis(0)
- , m_dD3DRefreshCycle(0)
+ , m_fSyncOffsetStdDev(0.0)
+ , m_bHighColorResolution(false)
+ , m_bCompositionEnabled(false)
+ , m_bDesktopCompositionDisabled(false)
+ , m_bIsFullscreen(bFullscreen)
+ , m_bNeedCheckSample(true)
+ , m_dMainThreadId(0)
+ , m_ScreenSize(0, 0)
, m_dDetectedScanlineTime(0.0)
+ , m_dD3DRefreshCycle(0)
, m_dEstRefreshCycle(0.0)
, m_dFrameCycle(0.0)
, m_dOptimumDisplayCycle(0.0)
, m_dCycleDifference(1.0)
- , m_llEstVBlankTime(0)
- , m_LastAdapterCheck(0)
- , m_CurrentAdapter(UINT_ERROR)
- , m_FocusThread(nullptr)
- , m_lNextSampleWait(1)
- , m_MinJitter(MAXLONG64)
- , m_MaxJitter(MINLONG64)
- , m_MinSyncOffset(MAXLONG64)
- , m_MaxSyncOffset(MINLONG64)
, m_pcFramesDropped(0)
, m_pcFramesDuplicated(0)
, m_pcFramesDrawn(0)
- , m_uScanLineEnteringPaint(0)
+ , m_nNextJitter(0)
+ , m_nNextSyncOffset(0)
, m_JitterStdDev(0)
- , m_fJitterMean(0)
- , m_bHighColorResolution(false)
- , m_bCompositionEnabled(false)
- , m_bDesktopCompositionDisabled(false)
+ , m_llLastSyncTime(LONGLONG_ERROR)
+ , m_MaxJitter(MINLONG64)
+ , m_MinJitter(MAXLONG64)
+ , m_MaxSyncOffset(MINLONG64)
+ , m_MinSyncOffset(MAXLONG64)
+ , m_uSyncGlitches(0)
, m_llSampleTime(0)
, m_llLastSampleTime(0)
+ , m_llHysteresis(0)
, m_lShiftToNearest(0)
, m_lShiftToNearestPrev(0)
, m_bVideoSlowerThanDisplay(0)
+ , m_rtTimePerFrame(0)
+ , m_bInterlaced(false)
+ , m_TextScale(1.0)
+ , m_pGenlock(nullptr)
+ , m_pAudioStats(nullptr)
+ , m_lAudioLag(0)
+ , m_lAudioLagMin(10000)
+ , m_lAudioLagMax(-10000)
, m_lAudioSlaveMode(0)
- , m_pD3DXLoadSurfaceFromMemory(nullptr)
- , m_pD3DXCreateLine(nullptr)
- , m_pD3DXCreateFont(nullptr)
- , m_pD3DXCreateSprite(nullptr)
- , m_pDwmIsCompositionEnabled(nullptr)
- , m_pDwmEnableComposition(nullptr)
- , m_pDirect3DCreate9Ex(nullptr)
- , m_hDWMAPI(nullptr)
- , m_hD3D9(nullptr)
- , m_pOuterEVR(nullptr)
- , m_SurfaceType(D3DFMT_UNKNOWN)
- , m_BackbufferType(D3DFMT_UNKNOWN)
- , m_DisplayType(D3DFMT_UNKNOWN)
- , m_filter(D3DTEXF_NONE)
+ , m_FocusThread(nullptr)
+ , m_hFocusWindow(nullptr)
{
ZeroMemory(&m_VMR9AlphaBitmap, sizeof(m_VMR9AlphaBitmap));
ZeroMemory(&m_caps, sizeof(m_caps));
- ZeroMemory(&pp, sizeof(pp));
+ ZeroMemory(&m_pp, sizeof(m_pp));
if (FAILED(hr)) {
_Error += _T("ISubPicAllocatorPresenterImpl failed\n");
@@ -485,17 +486,17 @@ HRESULT CBaseAP::CreateDXDevice(CString& _Error)
}
m_bCompositionEnabled = bCompositionEnabled != 0;
- ZeroMemory(&pp, sizeof(pp));
+ ZeroMemory(&m_pp, sizeof(m_pp));
if (m_bIsFullscreen) { // Exclusive mode fullscreen
- pp.Windowed = FALSE;
- pp.BackBufferWidth = d3ddm.Width;
- pp.BackBufferHeight = d3ddm.Height;
- pp.hDeviceWindow = m_hWnd;
+ m_pp.Windowed = FALSE;
+ m_pp.BackBufferWidth = d3ddm.Width;
+ m_pp.BackBufferHeight = d3ddm.Height;
+ m_pp.hDeviceWindow = m_hWnd;
TRACE(_T("Wnd in CreateDXDevice: %p\n"), m_hWnd);
- pp.BackBufferCount = 3;
- pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
- pp.Flags = D3DPRESENTFLAG_VIDEO;
+ m_pp.BackBufferCount = 3;
+ m_pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ m_pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ m_pp.Flags = D3DPRESENTFLAG_VIDEO;
m_bHighColorResolution = r.m_AdvRendSets.bEVRHighColorResolution;
if (m_bHighColorResolution) {
if (FAILED(m_pD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DFMT_A2R10G10B10, false))) {
@@ -505,67 +506,67 @@ HRESULT CBaseAP::CreateDXDevice(CString& _Error)
}
if (m_bHighColorResolution) {
- pp.BackBufferFormat = D3DFMT_A2R10G10B10;
+ m_pp.BackBufferFormat = D3DFMT_A2R10G10B10;
} else {
- pp.BackBufferFormat = d3ddm.Format;
+ m_pp.BackBufferFormat = d3ddm.Format;
}
if (!m_FocusThread) {
m_FocusThread = (CFocusThread*)AfxBeginThread(RUNTIME_CLASS(CFocusThread), 0, 0, 0);
}
+ HWND hFocusWindow = m_FocusThread->GetFocusWindow();
+ bTryToReset &= m_hFocusWindow == hFocusWindow;
+ m_hFocusWindow = hFocusWindow;
+
if (m_pD3DEx) {
D3DDISPLAYMODEEX DisplayMode;
ZeroMemory(&DisplayMode, sizeof(DisplayMode));
DisplayMode.Size = sizeof(DisplayMode);
m_pD3DEx->GetAdapterDisplayModeEx(m_CurrentAdapter, &DisplayMode, nullptr);
- DisplayMode.Format = pp.BackBufferFormat;
- pp.FullScreen_RefreshRateInHz = DisplayMode.RefreshRate;
+ DisplayMode.Format = m_pp.BackBufferFormat;
+ m_pp.FullScreen_RefreshRateInHz = DisplayMode.RefreshRate;
+
+ bTryToReset = bTryToReset && m_pD3DDevEx && SUCCEEDED(hr = m_pD3DDevEx->ResetEx(&m_pp, &DisplayMode));
- if (bTryToReset) {
- if (!m_pD3DDevEx || FAILED(hr = m_pD3DDevEx->ResetEx(&pp, &DisplayMode))) {
- bTryToReset = false;
- m_pD3DDev = nullptr;
- m_pD3DDevEx = nullptr;
- }
- }
if (!bTryToReset) {
+ m_pD3DDev = nullptr;
+ m_pD3DDevEx = nullptr;
hr = m_pD3DEx->CreateDeviceEx(m_CurrentAdapter, D3DDEVTYPE_HAL, m_FocusThread->GetFocusWindow(),
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_ENABLE_PRESENTSTATS | D3DCREATE_NOWINDOWCHANGES,
- &pp, &DisplayMode, &m_pD3DDevEx);
+ &m_pp, &DisplayMode, &m_pD3DDevEx);
}
if (m_pD3DDevEx) {
m_pD3DDev = m_pD3DDevEx;
- m_BackbufferType = pp.BackBufferFormat;
+ m_BackbufferType = m_pp.BackBufferFormat;
m_DisplayType = DisplayMode.Format;
}
} else {
- if (bTryToReset) {
- if (!m_pD3DDev || FAILED(hr = m_pD3DDev->Reset(&pp))) {
- bTryToReset = false;
- }
- }
+ bTryToReset = bTryToReset && m_pD3DDev && SUCCEEDED(hr = m_pD3DDev->Reset(&m_pp));
+
if (!bTryToReset) {
+ m_pD3DDev = nullptr;
+ m_pD3DDevEx = nullptr;
hr = m_pD3D->CreateDevice(m_CurrentAdapter, D3DDEVTYPE_HAL, m_FocusThread->GetFocusWindow(),
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_NOWINDOWCHANGES,
- &pp, &m_pD3DDev);
+ &m_pp, &m_pD3DDev);
}
TRACE(_T("Created full-screen device\n"));
if (m_pD3DDev) {
- m_BackbufferType = pp.BackBufferFormat;
+ m_BackbufferType = m_pp.BackBufferFormat;
m_DisplayType = d3ddm.Format;
}
}
} else { // Windowed
- pp.Windowed = TRUE;
- pp.hDeviceWindow = m_hWnd;
- pp.SwapEffect = D3DSWAPEFFECT_COPY;
- pp.Flags = D3DPRESENTFLAG_VIDEO;
- pp.BackBufferCount = 1;
- pp.BackBufferWidth = szDesktopSize.cx;
- pp.BackBufferHeight = szDesktopSize.cy;
+ m_pp.Windowed = TRUE;
+ m_pp.hDeviceWindow = m_hWnd;
+ m_pp.SwapEffect = D3DSWAPEFFECT_COPY;
+ m_pp.Flags = D3DPRESENTFLAG_VIDEO;
+ m_pp.BackBufferCount = 1;
+ m_pp.BackBufferWidth = szDesktopSize.cx;
+ m_pp.BackBufferHeight = szDesktopSize.cy;
m_BackbufferType = d3ddm.Format;
m_DisplayType = d3ddm.Format;
m_bHighColorResolution = r.m_AdvRendSets.bEVRHighColorResolution;
@@ -578,26 +579,27 @@ HRESULT CBaseAP::CreateDXDevice(CString& _Error)
if (m_bHighColorResolution) {
m_BackbufferType = D3DFMT_A2R10G10B10;
- pp.BackBufferFormat = D3DFMT_A2R10G10B10;
+ m_pp.BackBufferFormat = D3DFMT_A2R10G10B10;
}
if (bCompositionEnabled) {
// Desktop composition presents the whole desktop
- pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ m_pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
} else {
- pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ m_pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
+
+ bTryToReset &= m_hFocusWindow == m_hWnd;
+ m_hFocusWindow = m_hWnd;
+
if (m_pD3DEx) {
- if (bTryToReset) {
- if (!m_pD3DDevEx || FAILED(hr = m_pD3DDevEx->ResetEx(&pp, nullptr))) {
- bTryToReset = false;
- m_pD3DDev = nullptr;
- m_pD3DDevEx = nullptr;
- }
- }
+ bTryToReset = bTryToReset && m_pD3DDevEx && SUCCEEDED(hr = m_pD3DDevEx->ResetEx(&m_pp, nullptr));
+
if (!bTryToReset) {
- hr = m_pD3DEx->CreateDeviceEx(m_CurrentAdapter, D3DDEVTYPE_HAL, m_hWnd,
+ m_pD3DDev = nullptr;
+ m_pD3DDevEx = nullptr;
+ hr = m_pD3DEx->CreateDeviceEx(m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED | D3DCREATE_ENABLE_PRESENTSTATS,
- &pp, nullptr, &m_pD3DDevEx);
+ &m_pp, nullptr, &m_pD3DDevEx);
}
if (m_pD3DDevEx) {
@@ -605,14 +607,14 @@ HRESULT CBaseAP::CreateDXDevice(CString& _Error)
}
} else {
if (bTryToReset) {
- if (!m_pD3DDev || FAILED(hr = m_pD3DDev->Reset(&pp))) {
+ if (!m_pD3DDev || FAILED(hr = m_pD3DDev->Reset(&m_pp))) {
bTryToReset = false;
}
}
if (!bTryToReset) {
- hr = m_pD3D->CreateDevice(m_CurrentAdapter, D3DDEVTYPE_HAL, m_hWnd,
+ hr = m_pD3D->CreateDevice(m_CurrentAdapter, D3DDEVTYPE_HAL, m_hFocusWindow,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE | D3DCREATE_MULTITHREADED,
- &pp, &m_pD3DDev);
+ &m_pp, &m_pD3DDev);
}
TRACE(_T("Created windowed device\n"));
}
@@ -625,7 +627,7 @@ HRESULT CBaseAP::CreateDXDevice(CString& _Error)
}
if (hr == D3DERR_DEVICENOTRESET) {
TRACE(_T("D3DERR_DEVICENOTRESET\n"));
- hr = m_pD3DDev->Reset(&pp);
+ hr = m_pD3DDev->Reset(&m_pp);
}
if (m_pD3DDevEx) {
@@ -783,8 +785,7 @@ HRESULT CBaseAP::ResetDXDevice(CString& _Error)
m_pGenlock->SetDisplayResolution(d3ddm.Width, d3ddm.Height);
CSize szDesktopSize(GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN));
- D3DPRESENT_PARAMETERS pp;
- ZeroMemory(&pp, sizeof(pp));
+ ZeroMemory(&m_pp, sizeof(m_pp));
BOOL bCompositionEnabled = false;
if (m_pDwmIsCompositionEnabled) {
@@ -794,14 +795,14 @@ HRESULT CBaseAP::ResetDXDevice(CString& _Error)
m_bHighColorResolution = r.m_AdvRendSets.bEVRHighColorResolution;
if (m_bIsFullscreen) { // Exclusive mode fullscreen
- pp.BackBufferWidth = d3ddm.Width;
- pp.BackBufferHeight = d3ddm.Height;
+ m_pp.BackBufferWidth = d3ddm.Width;
+ m_pp.BackBufferHeight = d3ddm.Height;
if (m_bHighColorResolution) {
- pp.BackBufferFormat = D3DFMT_A2R10G10B10;
+ m_pp.BackBufferFormat = D3DFMT_A2R10G10B10;
} else {
- pp.BackBufferFormat = d3ddm.Format;
+ m_pp.BackBufferFormat = d3ddm.Format;
}
- if (FAILED(m_pD3DEx->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pp.BackBufferFormat, pp.BackBufferFormat, false))) {
+ if (FAILED(m_pD3DEx->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_pp.BackBufferFormat, m_pp.BackBufferFormat, false))) {
_Error += L"10 bit RGB is not supported by this graphics device in exclusive mode fullscreen.\n";
return hr;
}
@@ -811,14 +812,14 @@ HRESULT CBaseAP::ResetDXDevice(CString& _Error)
DisplayMode.Size = sizeof(DisplayMode);
if (m_pD3DDevEx) {
m_pD3DEx->GetAdapterDisplayModeEx(GetAdapter(m_pD3DEx, m_hWnd), &DisplayMode, nullptr);
- DisplayMode.Format = pp.BackBufferFormat;
- pp.FullScreen_RefreshRateInHz = DisplayMode.RefreshRate;
- if (FAILED(m_pD3DDevEx->Reset(&pp))) {
+ DisplayMode.Format = m_pp.BackBufferFormat;
+ m_pp.FullScreen_RefreshRateInHz = DisplayMode.RefreshRate;
+ if (FAILED(m_pD3DDevEx->Reset(&m_pp))) {
_Error += GetWindowsErrorMessage(hr, m_hD3D9);
return hr;
}
} else if (m_pD3DDev) {
- if (FAILED(m_pD3DDev->Reset(&pp))) {
+ if (FAILED(m_pD3DDev->Reset(&m_pp))) {
_Error += GetWindowsErrorMessage(hr, m_hD3D9);
return hr;
}
@@ -826,33 +827,33 @@ HRESULT CBaseAP::ResetDXDevice(CString& _Error)
_Error += L"No device.\n";
return hr;
}
- m_BackbufferType = pp.BackBufferFormat;
+ m_BackbufferType = m_pp.BackBufferFormat;
m_DisplayType = d3ddm.Format;
} else { // Windowed
- pp.BackBufferWidth = szDesktopSize.cx;
- pp.BackBufferHeight = szDesktopSize.cy;
+ m_pp.BackBufferWidth = szDesktopSize.cx;
+ m_pp.BackBufferHeight = szDesktopSize.cy;
m_BackbufferType = d3ddm.Format;
m_DisplayType = d3ddm.Format;
if (m_bHighColorResolution) {
m_BackbufferType = D3DFMT_A2R10G10B10;
- pp.BackBufferFormat = D3DFMT_A2R10G10B10;
+ m_pp.BackBufferFormat = D3DFMT_A2R10G10B10;
}
- if (FAILED(m_pD3DEx->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pp.BackBufferFormat, pp.BackBufferFormat, false))) {
+ if (FAILED(m_pD3DEx->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_pp.BackBufferFormat, m_pp.BackBufferFormat, false))) {
_Error += L"10 bit RGB is not supported by this graphics device in windowed mode.\n";
return hr;
}
if (bCompositionEnabled) {
// Desktop composition presents the whole desktop
- pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ m_pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
} else {
- pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ m_pp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
if (m_pD3DDevEx)
- if (FAILED(m_pD3DDevEx->Reset(&pp))) {
+ if (FAILED(m_pD3DDevEx->Reset(&m_pp))) {
_Error += GetWindowsErrorMessage(hr, m_hD3D9);
return hr;
} else if (m_pD3DDev)
- if (FAILED(m_pD3DDevEx->Reset(&pp))) {
+ if (FAILED(m_pD3DDevEx->Reset(&m_pp))) {
_Error += GetWindowsErrorMessage(hr, m_hD3D9);
return hr;
} else {
@@ -1719,7 +1720,7 @@ STDMETHODIMP_(bool) CBaseAP::Paint(bool bAll)
hr = m_pD3DDev->SetPixelShaderConstantF(0, (float*)fConstData, _countof(fConstData));
- int src = 1, dst = 0;
+ int srcTexture = 1, dstTexture = 0;
POSITION pos = m_pPixelShadersScreenSpace.GetHeadPosition();
while (pos) {
@@ -1727,7 +1728,7 @@ STDMETHODIMP_(bool) CBaseAP::Paint(bool bAll)
m_pD3DDev->SetRenderTarget(0, pBackBuffer);
} else {
CComPtr<IDirect3DSurface9> pRT;
- hr = m_pScreenSizeTemporaryTexture[dst]->GetSurfaceLevel(0, &pRT);
+ hr = m_pScreenSizeTemporaryTexture[dstTexture]->GetSurfaceLevel(0, &pRT);
m_pD3DDev->SetRenderTarget(0, pRT);
}
@@ -1736,9 +1737,9 @@ STDMETHODIMP_(bool) CBaseAP::Paint(bool bAll)
Shader.Compile(m_pPSC);
}
hr = m_pD3DDev->SetPixelShader(Shader.m_pPixelShader);
- TextureCopy(m_pScreenSizeTemporaryTexture[src]);
+ TextureCopy(m_pScreenSizeTemporaryTexture[srcTexture]);
- std::swap(src, dst);
+ std::swap(srcTexture, dstTexture);
}
hr = m_pD3DDev->SetPixelShader(nullptr);
@@ -2404,28 +2405,29 @@ STDMETHODIMP CBaseAP::SetPixelShader2(LPCSTR pSrcData, LPCSTR pTarget, bool bScr
CSyncAP::CSyncAP(HWND hWnd, bool bFullscreen, HRESULT& hr, CString& _Error)
: CBaseAP(hWnd, bFullscreen, hr, _Error)
- , m_nResetToken(0)
- , m_hRenderThread(nullptr)
- , m_hMixerThread(nullptr)
- , m_hEvtFlush(nullptr)
+ , m_LastClockState(MFCLOCK_STATE_INVALID)
+ , m_dwVideoAspectRatioMode(MFVideoARMode_PreservePicture)
+ , m_dwVideoRenderPrefs((MFVideoRenderPrefs)0)
+ , m_BorderColor(RGB(0, 0, 0))
, m_hEvtQuit(nullptr)
- , m_hEvtSkip(nullptr)
, m_bEvtQuit(0)
+ , m_hEvtFlush(nullptr)
, m_bEvtFlush(0)
- , m_nRenderState(Shutdown)
- , m_bStepping(false)
+ , m_hEvtSkip(nullptr)
+ , m_bEvtSkip(false)
, m_bUseInternalTimer(false)
, m_LastSetOutputRange(-1)
, m_bPendingRenegotiate(false)
, m_bPendingMediaFinished(false)
- , m_pCurrentDisplaydSample(nullptr)
- , m_nStepCount(0)
- , m_dwVideoAspectRatioMode(MFVideoARMode_PreservePicture)
- , m_dwVideoRenderPrefs((MFVideoRenderPrefs)0)
- , m_BorderColor(RGB(0, 0, 0))
, m_bPrerolled(false)
- , m_LastClockState(MFCLOCK_STATE_INVALID)
- , m_bEvtSkip(false)
+ , m_hRenderThread(nullptr)
+ , m_hMixerThread(nullptr)
+ , m_nRenderState(Shutdown)
+ , m_bStepping(false)
+ , m_nCurrentGroupId(0)
+ , m_nResetToken(0)
+ , m_nStepCount(0)
+ , m_SampleFreeCallback(this, &CSyncAP::OnSampleFree)
, fnDXVA2CreateDirect3DDeviceManager9("dxva2.dll", "DXVA2CreateDirect3DDeviceManager9")
, fnMFCreateDXSurfaceBuffer("evr.dll", "MFCreateDXSurfaceBuffer")
, fnMFCreateVideoSampleFromSurface("evr.dll", "MFCreateVideoSampleFromSurface")
@@ -2612,6 +2614,20 @@ STDMETHODIMP_(bool) CSyncAP::Paint(bool bAll)
return __super::Paint(bAll);
}
+STDMETHODIMP_(bool) CSyncAP::Paint(IMFSample* pMFSample)
+{
+ m_pCurrentlyDisplayedSample = pMFSample;
+ pMFSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
+
+ auto sampleHasCurrentGroupId = [this](IMFSample * pSample) {
+ UINT32 nGroupId;
+ return (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId);
+ };
+ ASSERT(sampleHasCurrentGroupId(pMFSample));
+
+ return Paint(true);
+}
+
STDMETHODIMP CSyncAP::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
HRESULT hr;
@@ -2651,24 +2667,32 @@ STDMETHODIMP CSyncAP::NonDelegatingQueryInterface(REFIID riid, void** ppv)
// IMFClockStateSink
STDMETHODIMP CSyncAP::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
m_nRenderState = Started;
return S_OK;
}
STDMETHODIMP CSyncAP::OnClockStop(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
m_nRenderState = Stopped;
return S_OK;
}
STDMETHODIMP CSyncAP::OnClockPause(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
m_nRenderState = Paused;
return S_OK;
}
STDMETHODIMP CSyncAP::OnClockRestart(MFTIME hnsSystemTime)
{
+ HRESULT hr;
+ CHECK_HR(CheckShutdown());
m_nRenderState = Started;
return S_OK;
}
@@ -2838,6 +2862,7 @@ void CSyncAP::CompleteFrameStep(bool bCancel)
STDMETHODIMP CSyncAP::ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
{
HRESULT hr = S_OK;
+ CHECK_HR(CheckShutdown());
switch (eMessage) {
case MFVP_MESSAGE_BEGINSTREAMING:
@@ -2998,11 +3023,27 @@ HRESULT CSyncAP::CreateOptimalOutputType(IMFMediaType* pMixerProposedType, IMFMe
HRESULT CSyncAP::SetMediaType(IMFMediaType* pType)
{
- HRESULT hr;
+ HRESULT hr = S_OK;
AM_MEDIA_TYPE* pAMMedia = nullptr;
CString strTemp;
- CheckPointer(pType, E_POINTER);
+ CHECK_HR(CheckShutdown());
+
+ if (pType == nullptr) {
+ // Release
+ RemoveAllSamples();
+ DeleteSurfaces();
+ CAutoLock lock(this);
+ m_pMediaType = nullptr;
+ return hr;
+ }
+
+ DWORD dwFlags = 0;
+ if (m_pMediaType && m_pMediaType->IsEqual(pType, &dwFlags) == S_OK) {
+ // Nothing to do
+ return hr;
+ }
+
CHECK_HR(pType->GetRepresentation(FORMAT_VideoInfo2, (void**)&pAMMedia));
hr = InitializeDevice(pAMMedia);
@@ -3158,9 +3199,13 @@ bool CSyncAP::GetSampleFromMixer()
UINT dwSurface;
bool newSample = false;
+ auto sampleHasCurrentGroupId = [this](IMFSample * pSample) {
+ UINT32 nGroupId;
+ return (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId);
+ };
+
while (SUCCEEDED(hr)) { // Get as many frames as there are and that we have samples for
CComPtr<IMFSample> pSample;
- CComPtr<IMFSample> pNewSample;
if (FAILED(GetFreeSample(&pSample))) { // All samples are taken for the moment. Better luck next time
break;
}
@@ -3168,6 +3213,8 @@ bool CSyncAP::GetSampleFromMixer()
ZeroMemory(&dataBuffer, sizeof(dataBuffer));
dataBuffer.pSample = pSample;
pSample->GetUINT32(GUID_SURFACE_INDEX, &dwSurface);
+ ASSERT(sampleHasCurrentGroupId(pSample));
+
{
llClockBefore = GetRenderersData()->GetPerfCounter();
hr = m_pMixer->ProcessOutput(0 , 1, &dataBuffer, &dwStatus);
@@ -3175,11 +3222,13 @@ bool CSyncAP::GetSampleFromMixer()
}
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { // There are no samples left in the mixer
- MoveToFreeList(pSample, false);
+ AddToFreeList(pSample, false);
+ pSample = nullptr; // The sample should not be used after being queued
// Important: Release any events returned from the ProcessOutput method.
SAFE_RELEASE(dataBuffer.pEvents);
break;
}
+
if (m_pSink) {
llMixerLatency = llClockAfter - llClockBefore;
m_pSink->Notify(EC_PROCESSING_LATENCY, (LONG_PTR)&llMixerLatency, 0);
@@ -3201,7 +3250,14 @@ bool CSyncAP::GetSampleFromMixer()
m_pD3DDev->ColorFill(m_pVideoSurface[dwSurface], &rcTearing, D3DCOLOR_ARGB(255, 255, 0, 0));
m_nTearingPos = (m_nTearingPos + 7) % m_nativeVideoSize.cx;
}
- MoveToScheduledList(pSample, false); // Schedule, then go back to see if there is more where that came from
+
+ if (SUCCEEDED(TrackSample(pSample))) {
+ AddToScheduledList(pSample, false); // Schedule, then go back to see if there is more where that came from
+ pSample = nullptr; // The sample should not be used after being queued
+ } else {
+ ASSERT(FALSE);
+ }
+
// Important: Release any events returned from the ProcessOutput method.
SAFE_RELEASE(dataBuffer.pEvents);
}
@@ -3535,9 +3591,11 @@ STDMETHODIMP CSyncAP::InitializeDevice(AM_MEDIA_TYPE* pMediaType)
CComPtr<IMFSample> pMFSample;
hr = fnMFCreateVideoSampleFromSurface(m_pVideoSurface[i], &pMFSample);
if (SUCCEEDED(hr)) {
+ pMFSample->SetUINT32(GUID_GROUP_ID, m_nCurrentGroupId);
pMFSample->SetUINT32(GUID_SURFACE_INDEX, i);
CAutoLock sampleQueueLock(&m_SampleQueueLock);
m_FreeSamples.AddTail(pMFSample);
+ pMFSample = nullptr; // The sample should not be used after being queued
}
ASSERT(SUCCEEDED(hr));
}
@@ -3615,7 +3673,7 @@ void CSyncAP::RenderThread()
HANDLE hEvts[] = {m_hEvtQuit, m_hEvtFlush, m_hEvtSkip};
bool bQuit = false;
TIMECAPS tc;
- CComPtr<IMFSample>pNewSample = nullptr; // The sample next in line to be presented
+ CComPtr<IMFSample> pNewSample; // The sample next in line to be presented
// Tell Multimedia Class Scheduler we are doing threaded playback (increase priority)
HANDLE hAvrt = 0;
@@ -3631,7 +3689,16 @@ void CSyncAP::RenderThread()
timeGetDevCaps(&tc, sizeof(TIMECAPS));
DWORD dwResolution = std::min(std::max(tc.wPeriodMin, 0u), tc.wPeriodMax);
VERIFY(timeBeginPeriod(dwResolution) == 0);
- pNewSample = nullptr;
+
+ auto checkPendingMediaFinished = [this]() {
+ if (m_bPendingMediaFinished) {
+ CAutoLock lock(&m_SampleQueueLock);
+ if (m_ScheduledSamples.IsEmpty()) {
+ m_bPendingMediaFinished = false;
+ m_pSink->Notify(EC_COMPLETE, 0, 0);
+ }
+ }
+ };
while (!bQuit) {
m_lNextSampleWait = 1; // Default value for running this loop
@@ -3652,7 +3719,7 @@ void CSyncAP::RenderThread()
m_lNextSampleWait = 0; // Present immediately
} else if (SUCCEEDED(pNewSample->GetSampleTime(&m_llSampleTime))) { // Get zero-based sample due time
if (m_llLastSampleTime == m_llSampleTime) { // In the rare case there are duplicate frames in the movie. There really shouldn't be but it happens.
- MoveToFreeList(pNewSample, true);
+ checkPendingMediaFinished();
pNewSample = nullptr;
m_lNextSampleWait = 0;
} else {
@@ -3729,6 +3796,8 @@ void CSyncAP::RenderThread()
}
}
} // if got new sample
+ } else {
+ checkPendingMediaFinished();
}
}
// Wait for the next presentation time (m_lNextSampleWait) or some other event.
@@ -3739,9 +3808,7 @@ void CSyncAP::RenderThread()
break;
case WAIT_OBJECT_0 + 1: // Flush
- if (pNewSample) {
- MoveToFreeList(pNewSample, true);
- }
+ checkPendingMediaFinished();
pNewSample = nullptr;
FlushSamples();
m_bEvtFlush = false;
@@ -3761,9 +3828,7 @@ void CSyncAP::RenderThread()
case WAIT_TIMEOUT: // Time to show the sample or something
if (m_LastSetOutputRange != -1 && m_LastSetOutputRange != r.m_AdvRendSets.iEVROutputRange || m_bPendingRenegotiate) {
- if (pNewSample) {
- MoveToFreeList(pNewSample, true);
- }
+ checkPendingMediaFinished();
pNewSample = nullptr;
FlushSamples();
RenegotiateMediaType();
@@ -3771,9 +3836,7 @@ void CSyncAP::RenderThread()
}
if (m_bPendingResetDevice) {
- if (pNewSample) {
- MoveToFreeList(pNewSample, true);
- }
+ checkPendingMediaFinished();
pNewSample = nullptr;
SendResetRequest();
} else if (m_nStepCount < 0) {
@@ -3781,34 +3844,26 @@ void CSyncAP::RenderThread()
m_pcFramesDropped++;
stepForward = true;
} else if (pNewSample && (m_nStepCount > 0)) {
- pNewSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
- if (!g_bExternalSubtitleTime) {
- __super::SetTime(g_tSegmentStart + m_llSampleTime);
- }
- Paint(true);
+ Paint(pNewSample);
CompleteFrameStep(false);
m_pcFramesDrawn++;
stepForward = true;
} else if (pNewSample && !m_bStepping) { // When a stepped frame is shown, a new one is fetched that we don't want to show here while stepping
- pNewSample->GetUINT32(GUID_SURFACE_INDEX, (UINT32*)&m_nCurSurface);
if (!g_bExternalSubtitleTime) {
__super::SetTime(g_tSegmentStart + m_llSampleTime);
}
- Paint(true);
+ Paint(pNewSample);
m_pcFramesDrawn++;
stepForward = true;
}
break;
} // switch
- if (pNewSample && stepForward) {
- MoveToFreeList(pNewSample, true);
+ if (stepForward) {
+ checkPendingMediaFinished();
pNewSample = nullptr;
}
} // while
- if (pNewSample) {
- MoveToFreeList(pNewSample, true);
- pNewSample = nullptr;
- }
+ pNewSample = nullptr;
timeEndPeriod(dwResolution);
if (fnAvRevertMmThreadCharacteristics) {
fnAvRevertMmThreadCharacteristics(hAvrt);
@@ -3829,9 +3884,11 @@ STDMETHODIMP_(bool) CSyncAP::ResetDevice()
CComPtr<IMFSample> pMFSample;
HRESULT hr = fnMFCreateVideoSampleFromSurface(m_pVideoSurface[i], &pMFSample);
if (SUCCEEDED(hr)) {
+ pMFSample->SetUINT32(GUID_GROUP_ID, m_nCurrentGroupId);
pMFSample->SetUINT32(GUID_SURFACE_INDEX, i);
CAutoLock sampleQueueLock(&m_SampleQueueLock);
m_FreeSamples.AddTail(pMFSample);
+ pMFSample = nullptr; // The sample should not be used after being queued
}
ASSERT(SUCCEEDED(hr));
}
@@ -3860,6 +3917,8 @@ void CSyncAP::RemoveAllSamples()
m_ScheduledSamples.RemoveAll();
m_FreeSamples.RemoveAll();
m_nUsedBuffer = 0;
+ // Increment the group id to make sure old samples will really be deleted
+ m_nCurrentGroupId++;
}
HRESULT CSyncAP::GetFreeSample(IMFSample** ppSample)
@@ -3867,7 +3926,7 @@ HRESULT CSyncAP::GetFreeSample(IMFSample** ppSample)
CAutoLock lock(&m_SampleQueueLock);
HRESULT hr = S_OK;
- if (m_FreeSamples.GetCount() > 1) { // Cannot use first free buffer (can be currently displayed)
+ if (!m_FreeSamples.IsEmpty()) {
m_nUsedBuffer++;
*ppSample = m_FreeSamples.RemoveHead().Detach();
} else {
@@ -3877,15 +3936,15 @@ HRESULT CSyncAP::GetFreeSample(IMFSample** ppSample)
return hr;
}
-HRESULT CSyncAP::GetScheduledSample(IMFSample** ppSample, int& _Count)
+HRESULT CSyncAP::GetScheduledSample(IMFSample** ppSample, int& count)
{
CAutoLock lock(&m_SampleQueueLock);
HRESULT hr = S_OK;
- _Count = (int)m_ScheduledSamples.GetCount();
- if (_Count > 0) {
+ count = (int)m_ScheduledSamples.GetCount();
+ if (count > 0) {
*ppSample = m_ScheduledSamples.RemoveHead().Detach();
- --_Count;
+ --count;
} else {
hr = MF_E_SAMPLEALLOCATOR_EMPTY;
}
@@ -3893,15 +3952,11 @@ HRESULT CSyncAP::GetScheduledSample(IMFSample** ppSample, int& _Count)
return hr;
}
-void CSyncAP::MoveToFreeList(IMFSample* pSample, bool bTail)
+void CSyncAP::AddToFreeList(IMFSample* pSample, bool bTail)
{
CAutoLock lock(&m_SampleQueueLock);
m_nUsedBuffer--;
- if (m_bPendingMediaFinished && m_nUsedBuffer == 0) {
- m_bPendingMediaFinished = false;
- m_pSink->Notify(EC_COMPLETE, 0, 0);
- }
if (bTail) {
m_FreeSamples.AddTail(pSample);
} else {
@@ -3909,11 +3964,11 @@ void CSyncAP::MoveToFreeList(IMFSample* pSample, bool bTail)
}
}
-void CSyncAP::MoveToScheduledList(IMFSample* pSample, bool _bSorted)
+void CSyncAP::AddToScheduledList(IMFSample* pSample, bool bSorted)
{
CAutoLock lock(&m_SampleQueueLock);
- if (_bSorted) {
+ if (bSorted) {
m_ScheduledSamples.AddHead(pSample);
} else {
m_ScheduledSamples.AddTail(pSample);
@@ -3924,17 +3979,37 @@ void CSyncAP::FlushSamples()
{
CAutoLock lock(this);
CAutoLock lock2(&m_SampleQueueLock);
- FlushSamplesInternal();
+
+ m_bPrerolled = false;
+ m_pCurrentlyDisplayedSample = nullptr;
+ m_ScheduledSamples.RemoveAll();
}
-void CSyncAP::FlushSamplesInternal()
+HRESULT CSyncAP::TrackSample(IMFSample* pSample)
{
- m_bPrerolled = false;
- while (!m_ScheduledSamples.IsEmpty()) {
- CComPtr<IMFSample> pMFSample;
- pMFSample = m_ScheduledSamples.RemoveHead();
- MoveToFreeList(pMFSample, true);
+ HRESULT hr = E_FAIL;
+ if (CComQIPtr<IMFTrackedSample> pTracked = pSample) {
+ hr = pTracked->SetAllocator(&m_SampleFreeCallback, nullptr);
+ }
+ return hr;
+}
+
+HRESULT CSyncAP::OnSampleFree(IMFAsyncResult* pResult)
+{
+ CComPtr<IUnknown> pObject;
+ HRESULT hr = pResult->GetObject(&pObject);
+ if (SUCCEEDED(hr)) {
+ if (CComQIPtr<IMFSample> pSample = pObject) {
+ // Ignore the sample if it is from an old group
+ UINT32 nGroupId;
+ CAutoLock sampleQueueLock(&m_SampleQueueLock);
+ if (SUCCEEDED(pSample->GetUINT32(GUID_GROUP_ID, &nGroupId)) && nGroupId == m_nCurrentGroupId) {
+ AddToFreeList(pSample, true);
+ pSample = nullptr; // The sample should not be used after being queued
+ }
+ }
}
+ return hr;
}
HRESULT CSyncAP::AdviseSyncClock(ISyncClock* sC)
@@ -4172,30 +4247,20 @@ STDMETHODIMP CSyncRenderer::NonDelegatingQueryInterface(REFIID riid, void** ppv)
}
CGenlock::CGenlock(double target, double limit, int lineD, int colD, double clockD, UINT mon)
- : targetSyncOffset(target) // Target sync offset, typically around 10 ms
- , controlLimit(limit) // How much sync offset is allowed to drift from target sync offset before control kicks in
- , lineDelta(lineD) // Number of rows used in display frequency adjustment, typically 1 (one)
- , columnDelta(colD) // Number of columns used in display frequency adjustment, typically 1 - 2
- , cycleDelta(clockD) // Delta used in clock speed adjustment. In fractions of 1.0. Typically around 0.001
- , monitor(mon) // The monitor to be adjusted if the display refresh rate is the controlled parameter
- , lowSyncOffset(target - limit)
- , highSyncOffset(target + limit)
- , adjDelta(0)
+ : powerstripTimingExists(false)
+ , liveSource(false)
+ , adjDelta(0) // Number of rows used in display frequency adjustment, typically 1 (one)
+ , lineDelta(lineD) // Number of columns used in display frequency adjustment, typically 1 - 2
+ , columnDelta(colD) // Delta used in clock speed adjustment. In fractions of 1.0. Typically around 0.001
+ , cycleDelta(clockD) // The monitor to be adjusted if the display refresh rate is the controlled parameter
, displayAdjustmentsMade(0)
, clockAdjustmentsMade(0)
- , displayFreqCruise(0.0)
- , displayFreqFaster(0.0)
- , displayFreqSlower(0.0)
- , curDisplayFreq(0.0)
- , psWnd(nullptr)
- , liveSource(false)
- , powerstripTimingExists(false)
- , syncOffsetFifo(64)
- , frameCycleFifo(4)
, totalLines(0)
, totalColumns(0)
, visibleLines(0)
, visibleColumns(0)
+ , syncOffsetFifo(64)
+ , frameCycleFifo(4)
, minSyncOffset(DBL_MAX)
, maxSyncOffset(DBL_MIN)
, syncOffsetAvg(0.0)
@@ -4203,8 +4268,18 @@ CGenlock::CGenlock(double target, double limit, int lineD, int colD, double cloc
, maxFrameCycle(DBL_MIN)
, frameCycleAvg(0.0)
, pixelClock(0)
+ , displayFreqCruise(0.0)
+ , displayFreqSlower(0.0)
+ , displayFreqFaster(0.0)
+ , curDisplayFreq(0.0)
+ , controlLimit(limit) // How much sync offset is allowed to drift from target sync offset before control kicks in
+ , monitor(mon)
+ , psWnd(nullptr)
, displayTiming()
, displayTimingSave()
+ , lowSyncOffset(target - limit)
+ , targetSyncOffset(target) // Target sync offset, typically around 10 ms
+ , highSyncOffset(target + limit)
{
ZeroMemory(faster, MAX_LOADSTRING);
ZeroMemory(cruise, MAX_LOADSTRING);
diff --git a/src/filters/renderer/VideoRenderers/SyncRenderer.h b/src/filters/renderer/VideoRenderers/SyncRenderer.h
index 7455e0e0c..f10fcc8fb 100644
--- a/src/filters/renderer/VideoRenderers/SyncRenderer.h
+++ b/src/filters/renderer/VideoRenderers/SyncRenderer.h
@@ -30,6 +30,7 @@
#define VMRBITMAP_UPDATE 0x80000000
#define MAX_PICTURE_SLOTS (60 + 2) // Last 2 for pixels shader!
#define NB_JITTER 126
+#include "AsyncCallback.h"
extern bool g_bNoDuration; // Defined in MainFrm.cpp
extern bool g_bExternalSubtitleTime;
@@ -68,6 +69,8 @@ class CFocusThread;
#define PIXELCLOCK 8
#define UNKNOWN 9
+// Guid to tag IMFSample with a group id
+static const GUID GUID_GROUP_ID = { 0x309e32cc, 0x9b23, 0x4c6c, { 0x86, 0x63, 0xcd, 0xd9, 0xad, 0x49, 0x7f, 0x8a } };
// Guid to tag IMFSample with DirectX surface index
static const GUID GUID_SURFACE_INDEX = { 0x30c8e9f6, 0x415, 0x4b81, { 0xa3, 0x15, 0x1, 0xa, 0xc6, 0xa9, 0xda, 0x19 } };
@@ -154,7 +157,7 @@ namespace GothSync
D3DFORMAT m_DisplayType;
D3DTEXTUREFILTERTYPE m_filter;
D3DCAPS9 m_caps;
- D3DPRESENT_PARAMETERS pp;
+ D3DPRESENT_PARAMETERS m_pp;
bool SettingsNeedResetDevice();
void SendResetRequest();
@@ -315,6 +318,8 @@ namespace GothSync
bool ExtractInterlaced(const AM_MEDIA_TYPE* pmt);
CFocusThread* m_FocusThread;
+ HWND m_hFocusWindow;
+
public:
CBaseAP(HWND hWnd, bool bFullscreen, HRESULT& hr, CString& _Error);
~CBaseAP();
@@ -446,6 +451,7 @@ namespace GothSync
STDMETHODIMP GetD3DFullscreen(bool* pfEnabled);
protected:
+ STDMETHODIMP_(bool) Paint(IMFSample* pMFSample);
void OnResetDevice();
MFCLOCK_STATE m_LastClockState;
@@ -487,9 +493,10 @@ namespace GothSync
CCritSec m_SampleQueueLock;
CCritSec m_ImageProcessingLock;
- CInterfaceList<IMFSample, &IID_IMFSample> m_FreeSamples;
- CInterfaceList<IMFSample, &IID_IMFSample> m_ScheduledSamples;
- IMFSample* m_pCurrentDisplaydSample;
+ UINT32 m_nCurrentGroupId;
+ CInterfaceList<IMFSample> m_FreeSamples;
+ CInterfaceList<IMFSample> m_ScheduledSamples;
+ CComPtr<IMFSample> m_pCurrentlyDisplayedSample;
UINT m_nResetToken;
int m_nStepCount;
@@ -508,11 +515,16 @@ namespace GothSync
STDMETHODIMP AdviseSyncClock(ISyncClock* sC);
HRESULT BeginStreaming();
HRESULT GetFreeSample(IMFSample** ppSample);
- HRESULT GetScheduledSample(IMFSample** ppSample, int& _Count);
- void MoveToFreeList(IMFSample* pSample, bool bTail);
- void MoveToScheduledList(IMFSample* pSample, bool _bSorted);
+ HRESULT GetScheduledSample(IMFSample** ppSample, int& count);
+ void AddToFreeList(IMFSample* pSample, bool bTail);
+ void AddToScheduledList(IMFSample* pSample, bool bSorted);
void FlushSamples();
- void FlushSamplesInternal();
+
+ HRESULT TrackSample(IMFSample* pSample);
+
+ // Callback when a video sample is released.
+ HRESULT OnSampleFree(IMFAsyncResult* pResult);
+ AsyncCallback<CSyncAP> m_SampleFreeCallback;
LONGLONG GetMediaTypeMerit(IMFMediaType* pMediaType);
HRESULT RenegotiateMediaType();
diff --git a/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj b/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj
index c709d4564..0c6973d05 100644
--- a/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj
+++ b/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj
@@ -138,6 +138,7 @@
<ItemGroup>
<ClInclude Include="AllocatorCommon.h" />
<ClInclude Include="AllocatorCommon7.h" />
+ <ClInclude Include="AsyncCallback.h" />
<ClInclude Include="D3DFont.h" />
<ClInclude Include="Dither.h" />
<ClInclude Include="DX7AllocatorPresenter.h" />
diff --git a/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj.filters b/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj.filters
index 9a21a9b7d..2c606a773 100644
--- a/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj.filters
+++ b/src/filters/renderer/VideoRenderers/VideoRenderers.vcxproj.filters
@@ -169,5 +169,8 @@
<ClInclude Include="FocusThread.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="AsyncCallback.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.cpp b/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.cpp
index 3faf3784d..04eef572b 100644
--- a/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.cpp
+++ b/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.cpp
@@ -28,19 +28,10 @@
using namespace DSObjects;
-#define ShaderStage_PreScale 0
-#define ShaderStage_PostScale 1
-
extern bool g_bExternalSubtitleTime;
-//
-// CmadVRAllocatorPresenter
-//
-
CmadVRAllocatorPresenter::CmadVRAllocatorPresenter(HWND hWnd, HRESULT& hr, CString& _Error)
: CSubPicAllocatorPresenterImpl(hWnd, hr, &_Error)
- , m_ScreenSize(0, 0)
- , m_bIsFullscreen(false)
{
if (FAILED(hr)) {
_Error += L"ISubPicAllocatorPresenterImpl failed\n";
@@ -52,41 +43,28 @@ CmadVRAllocatorPresenter::CmadVRAllocatorPresenter(HWND hWnd, HRESULT& hr, CStri
CmadVRAllocatorPresenter::~CmadVRAllocatorPresenter()
{
- if (m_pSRCB) {
- // nasty, but we have to let it know about our death somehow
- ((CSubRenderCallback*)(ISubRenderCallback2*)m_pSRCB)->SetDXRAP(nullptr);
- }
-
// the order is important here
m_pSubPicQueue = nullptr;
m_pAllocator = nullptr;
- m_pDXR = nullptr;
+ m_pMVR = nullptr;
}
STDMETHODIMP CmadVRAllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
- /*
- if (riid == __uuidof(IVideoWindow))
- return GetInterface((IVideoWindow*)this, ppv);
- if (riid == __uuidof(IBasicVideo))
- return GetInterface((IBasicVideo*)this, ppv);
- if (riid == __uuidof(IBasicVideo2))
- return GetInterface((IBasicVideo2*)this, ppv);
- */
- /*
- if (riid == __uuidof(IVMRWindowlessControl))
- return GetInterface((IVMRWindowlessControl*)this, ppv);
- */
-
- if (riid != IID_IUnknown && m_pDXR) {
- if (SUCCEEDED(m_pDXR->QueryInterface(riid, ppv))) {
+ if (riid != IID_IUnknown && m_pMVR) {
+ if (SUCCEEDED(m_pMVR->QueryInterface(riid, ppv))) {
return S_OK;
}
}
- return __super::NonDelegatingQueryInterface(riid, ppv);
+ return QI(ISubRenderCallback)
+ QI(ISubRenderCallback2)
+ QI(ISubRenderCallback3)
+ __super::NonDelegatingQueryInterface(riid, ppv);
}
+// ISubRenderCallback
+
HRESULT CmadVRAllocatorPresenter::SetDevice(IDirect3DDevice9* pD3DDev)
{
if (!pD3DDev) {
@@ -96,8 +74,14 @@ HRESULT CmadVRAllocatorPresenter::SetDevice(IDirect3DDevice9* pD3DDev)
return S_OK;
}
+ CSize screenSize;
+ MONITORINFO mi = { sizeof(MONITORINFO) };
+ if (GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi)) {
+ screenSize.SetSize(mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top);
+ }
+
const CRenderersSettings& r = GetRenderersSettings();
- InitMaxSubtitleTextureSize(r.subPicQueueSettings.nMaxRes, m_ScreenSize);
+ InitMaxSubtitleTextureSize(r.subPicQueueSettings.nMaxRes, screenSize);
if (m_pAllocator) {
m_pAllocator->ChangeDevice(pD3DDev);
@@ -122,21 +106,27 @@ HRESULT CmadVRAllocatorPresenter::SetDevice(IDirect3DDevice9* pD3DDev)
return hr;
}
-HRESULT CmadVRAllocatorPresenter::Render(
- REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME atpf,
- int left, int top, int right, int bottom, int width, int height)
+// ISubRenderCallback3
+
+HRESULT CmadVRAllocatorPresenter::RenderEx2(REFERENCE_TIME rtStart,
+ REFERENCE_TIME /*rtStop*/,
+ REFERENCE_TIME atpf,
+ RECT croppedVideoRect,
+ RECT /*originalVideoRect*/,
+ RECT viewportRect,
+ const double videoStretchFactor)
{
- CRect wndRect(0, 0, width, height);
- CRect videoRect(left, top, right, bottom);
- __super::SetPosition(wndRect, videoRect); // needed? should be already set by the player
+ CheckPointer(m_pSubPicQueue, E_UNEXPECTED);
+
+ __super::SetPosition(viewportRect, croppedVideoRect);
if (!g_bExternalSubtitleTime) {
SetTime(rtStart);
}
- if (atpf > 0 && m_pSubPicQueue) {
+ if (atpf > 0) {
m_fps = 10000000.0 / atpf;
m_pSubPicQueue->SetFPS(m_fps);
}
- AlphaBltSubPic(wndRect, videoRect);
+ AlphaBltSubPic(viewportRect, croppedVideoRect, nullptr, videoStretchFactor);
return S_OK;
}
@@ -145,46 +135,29 @@ HRESULT CmadVRAllocatorPresenter::Render(
STDMETHODIMP CmadVRAllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
{
CheckPointer(ppRenderer, E_POINTER);
+ ASSERT(!m_pMVR);
- if (m_pDXR) {
- return E_UNEXPECTED;
- }
- m_pDXR.CoCreateInstance(CLSID_madVR, GetOwner());
- if (!m_pDXR) {
- return E_FAIL;
- }
+ HRESULT hr = S_FALSE;
- CComQIPtr<ISubRender> pSR = m_pDXR;
- if (!pSR) {
- m_pDXR = nullptr;
- return E_FAIL;
- }
+ CHECK_HR(m_pMVR.CoCreateInstance(CLSID_madVR, GetOwner()));
- m_pSRCB = DEBUG_NEW CSubRenderCallback(this);
- if (FAILED(pSR->SetCallback(m_pSRCB))) {
- m_pDXR = nullptr;
- return E_FAIL;
+ if (CComQIPtr<ISubRender> pSR = m_pMVR) {
+ VERIFY(SUCCEEDED(pSR->SetCallback(this)));
}
(*ppRenderer = (IUnknown*)(INonDelegatingUnknown*)(this))->AddRef();
- MONITORINFO mi;
- mi.cbSize = sizeof(MONITORINFO);
- if (GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi)) {
- m_ScreenSize.SetSize(mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top);
- }
-
return S_OK;
}
STDMETHODIMP_(void) CmadVRAllocatorPresenter::SetPosition(RECT w, RECT v)
{
- if (CComQIPtr<IBasicVideo> pBV = m_pDXR) {
+ if (CComQIPtr<IBasicVideo> pBV = m_pMVR) {
pBV->SetDefaultSourcePosition();
pBV->SetDestinationPosition(v.left, v.top, v.right - v.left, v.bottom - v.top);
}
- if (CComQIPtr<IVideoWindow> pVW = m_pDXR) {
+ if (CComQIPtr<IVideoWindow> pVW = m_pMVR) {
pVW->SetWindowPosition(w.left, w.top, w.right - w.left, w.bottom - w.top);
}
@@ -193,14 +166,14 @@ STDMETHODIMP_(void) CmadVRAllocatorPresenter::SetPosition(RECT w, RECT v)
STDMETHODIMP_(SIZE) CmadVRAllocatorPresenter::GetVideoSize(bool bCorrectAR) const
{
- SIZE size = {0, 0};
+ CSize size;
if (!bCorrectAR) {
- if (CComQIPtr<IBasicVideo> pBV = m_pDXR) {
+ if (CComQIPtr<IBasicVideo> pBV = m_pMVR) {
pBV->GetVideoSize(&size.cx, &size.cy);
}
} else {
- if (CComQIPtr<IBasicVideo2> pBV2 = m_pDXR) {
+ if (CComQIPtr<IBasicVideo2> pBV2 = m_pMVR) {
pBV2->GetPreferredAspectRatio(&size.cx, &size.cy);
}
}
@@ -208,42 +181,47 @@ STDMETHODIMP_(SIZE) CmadVRAllocatorPresenter::GetVideoSize(bool bCorrectAR) cons
return size;
}
-STDMETHODIMP_(bool) CmadVRAllocatorPresenter::Paint(bool bAll)
+STDMETHODIMP_(bool) CmadVRAllocatorPresenter::Paint(bool /*bAll*/)
{
- return false; // TODO
+ if (CComQIPtr<IMadVRCommand> pMVRC = m_pMVR) {
+ return SUCCEEDED(pMVRC->SendCommand("redraw"));
+ }
+ return false;
}
STDMETHODIMP CmadVRAllocatorPresenter::GetDIB(BYTE* lpDib, DWORD* size)
{
HRESULT hr = E_NOTIMPL;
- if (CComQIPtr<IBasicVideo> pBV = m_pDXR) {
+ if (CComQIPtr<IBasicVideo> pBV = m_pMVR) {
hr = pBV->GetCurrentImage((long*)size, (long*)lpDib);
}
return hr;
}
-STDMETHODIMP CmadVRAllocatorPresenter::SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget)
+STDMETHODIMP CmadVRAllocatorPresenter::SetPixelShader2(LPCSTR pSrcData, LPCSTR pTarget, bool bScreenSpace)
{
HRESULT hr = E_NOTIMPL;
- if (CComQIPtr<IMadVRExternalPixelShaders> pEPS = m_pDXR) {
+
+ if (CComQIPtr<IMadVRExternalPixelShaders> pMVREPS = m_pMVR) {
if (!pSrcData && !pTarget) {
- hr = pEPS->ClearPixelShaders(false);
+ hr = pMVREPS->ClearPixelShaders(bScreenSpace ? ShaderStage_PostScale : ShaderStage_PreScale);
} else {
- hr = pEPS->AddPixelShader(pSrcData, pTarget, ShaderStage_PreScale, nullptr);
+ hr = pMVREPS->AddPixelShader(pSrcData, pTarget, bScreenSpace ? ShaderStage_PostScale : ShaderStage_PreScale, nullptr);
}
}
+
return hr;
}
-STDMETHODIMP CmadVRAllocatorPresenter::SetPixelShader2(LPCSTR pSrcData, LPCSTR pTarget, bool bScreenSpace)
+// ISubPicAllocatorPresenter2
+
+STDMETHODIMP_(bool) CmadVRAllocatorPresenter::IsRendering()
{
- HRESULT hr = E_NOTIMPL;
- if (CComQIPtr<IMadVRExternalPixelShaders> pEPS = m_pDXR) {
- if (!pSrcData && !pTarget) {
- hr = pEPS->ClearPixelShaders(bScreenSpace);
- } else {
- hr = pEPS->AddPixelShader(pSrcData, pTarget, bScreenSpace ? ShaderStage_PostScale : ShaderStage_PreScale, nullptr);
+ if (CComQIPtr<IMadVRInfo> pMVRI = m_pMVR) {
+ int playbackState;
+ if (SUCCEEDED(pMVRI->GetInt("playbackState", &playbackState))) {
+ return playbackState == State_Running;
}
}
- return hr;
+ return false;
}
diff --git a/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.h b/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.h
index 2bbf45e06..443f9fbf9 100644
--- a/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.h
+++ b/src/filters/renderer/VideoRenderers/madVRAllocatorPresenter.h
@@ -25,81 +25,49 @@
namespace DSObjects
{
- class CmadVRAllocatorPresenter
- : public CSubPicAllocatorPresenterImpl
+ class CmadVRAllocatorPresenter : public CSubPicAllocatorPresenterImpl, ISubRenderCallback3
{
- class CSubRenderCallback : public CUnknown, public ISubRenderCallback2, public CCritSec
- {
- CmadVRAllocatorPresenter* m_pDXRAP;
-
- public:
- CSubRenderCallback(CmadVRAllocatorPresenter* pDXRAP)
- : CUnknown(_T("CSubRender"), nullptr)
- , m_pDXRAP(pDXRAP) {
- }
-
- DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) {
- return
- QI(ISubRenderCallback)
- QI(ISubRenderCallback2)
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
-
- void SetDXRAP(CmadVRAllocatorPresenter* pDXRAP) {
- CAutoLock cAutoLock(this);
- m_pDXRAP = pDXRAP;
- }
-
- // ISubRenderCallback
-
- STDMETHODIMP SetDevice(IDirect3DDevice9* pD3DDev) {
- CAutoLock cAutoLock(this);
- return m_pDXRAP ? m_pDXRAP->SetDevice(pD3DDev) : E_UNEXPECTED;
- }
-
- STDMETHODIMP Render(REFERENCE_TIME rtStart, int left, int top, int right, int bottom, int width, int height) {
- CAutoLock cAutoLock(this);
- return m_pDXRAP ? m_pDXRAP->Render(rtStart, 0, 0, left, top, right, bottom, width, height) : E_UNEXPECTED;
- }
-
- // ISubRendererCallback2
-
- STDMETHODIMP RenderEx(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME AvgTimePerFrame, int left, int top, int right, int bottom, int width, int height) {
- CAutoLock cAutoLock(this);
- return m_pDXRAP ? m_pDXRAP->Render(rtStart, rtStop, AvgTimePerFrame, left, top, right, bottom, width, height) : E_UNEXPECTED;
- }
- };
-
- CComPtr<IUnknown> m_pDXR;
- CComPtr<ISubRenderCallback2> m_pSRCB;
- CSize m_ScreenSize;
- bool m_bIsFullscreen;
+ CComPtr<IUnknown> m_pMVR;
public:
CmadVRAllocatorPresenter(HWND hWnd, HRESULT& hr, CString& _Error);
virtual ~CmadVRAllocatorPresenter();
DECLARE_IUNKNOWN
- STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv) override;
- HRESULT SetDevice(IDirect3DDevice9* pD3DDev);
- HRESULT Render(
- REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME atpf,
- int left, int top, int bottom, int right, int width, int height);
+ // ISubRenderCallback
+ STDMETHODIMP SetDevice(IDirect3DDevice9* pD3DDev) override;
+ STDMETHODIMP Render(REFERENCE_TIME rtStart, int left, int top, int right,
+ int bottom, int width, int height) override {
+ return RenderEx(rtStart, 0, 0, left, top, right, bottom, width, height);
+ };
+
+ // ISubRenderCallback2
+ STDMETHODIMP RenderEx(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, REFERENCE_TIME atpf,
+ int left, int top, int right, int bottom, int width, int height) override {
+ return RenderEx2(rtStart, rtStop, atpf, { left, top, right, bottom },
+ { left, top, right, bottom }, { 0, 0, width, height });
+ };
+
+ // ISubRenderCallback3
+ STDMETHODIMP RenderEx2(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop,
+ REFERENCE_TIME atpf, RECT croppedVideoRect,
+ RECT originalVideoRect, RECT viewportRect,
+ const double videoStretchFactor = 1.0) override;
// ISubPicAllocatorPresenter
- STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
- STDMETHODIMP_(void) SetPosition(RECT w, RECT v);
- STDMETHODIMP_(SIZE) GetVideoSize(bool bCorrectAR = true) const;
- STDMETHODIMP_(bool) Paint(bool bAll);
- STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size);
- STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget);
- STDMETHODIMP SetPixelShader2(LPCSTR pSrcData, LPCSTR pTarget, bool bScreenSpace);
+ STDMETHODIMP CreateRenderer(IUnknown** ppRenderer) override;
+ STDMETHODIMP_(void) SetPosition(RECT w, RECT v) override;
+ STDMETHODIMP_(SIZE) GetVideoSize(bool bCorrectAR = true) const override;
+ STDMETHODIMP_(bool) Paint(bool bAll) override;
+ STDMETHODIMP GetDIB(BYTE* lpDib, DWORD* size) override;
+ STDMETHODIMP SetPixelShader(LPCSTR pSrcData, LPCSTR pTarget) override {
+ return SetPixelShader2(pSrcData, pTarget, false);
+ };
+ STDMETHODIMP SetPixelShader2(LPCSTR pSrcData, LPCSTR pTarget, bool bScreenSpace) override;
// ISubPicAllocatorPresenter2
- STDMETHODIMP_(bool) IsRendering() {
- return false; // For testing
- }
+ STDMETHODIMP_(bool) IsRendering() override;
};
}