- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Windows Media Foundation 创建视频播放应用程序。
我使用 IMFTransform
接口(interface)和下面链接中提到的其他一些强制接口(interface)创建了自定义 EVR 混音器。
https://msdn.microsoft.com/en-us/library/windows/desktop/ms701624(v=vs.85).aspx
我已经将自定义混音器创建为 DLL,并且也成功注册了它。
然后我在 EVR 中使用以下代码添加了这个自定义混音器:
// Create the video renderer.
hr = MFCreateVideoRendererActivate(hVideoWindow, &pActivate);
// Add custom mixer
hr = pActivate->SetGUID(MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID, CLSID_CMyCustomMixerMFT);
EVR 正在我的自定义混音器中调用所需的方法,但最后我收到错误 MF_E_CANNOT_CREATE_SINK
。
对于自定义混音器,我指的是我的混音器的 MFT 实现,我指的是 Windows 媒体基础示例中的 mft_grayscale
示例应用程序。大部分 IMFTransform 实现都是从这个示例中复制的。
https://msdn.microsoft.com/en-us/library/windows/desktop/bb970487%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
我被这个错误困住了很长时间,找不到解决这个问题的方法。
根据方法的文档STDMETHODIMP GetDeviceID(IID *pDeviceID)
If a mixer or presenter uses Direct3D 9, it must return the value IID_IDirect3DDevice9 in pDeviceID.
The EVR's default mixer and presenter both return this value.
If you write a custom mixer or presenter, it can return some other value.
However, the mixer and presenter must use matching device identifiers.
自定义混音器应返回与演示者匹配的值。当我在我的代码中实现自定义混音器时,我将 deviceID 作为 IID_IDirect3DDevice9
返回。
我只有一个视频流,其中包含音频和视频。
GetStreamLimits
- 输入和输出流限制设置为 1GetStreamIDs
- 输入 ID 0 和输出 ID 0AddInputStreams
- 在我的混音器中,我没有调用此方法
按照建议,我将使用 MFTrace 进行调试。
最佳答案
这是一种实现自定义视频混合器的可能方法,它适用于 Windows 7 和 Microsoft MediaSession/Evr。
我发现 dxva2 可以与两种 NV12 流格式一起使用。当然,我们不能将流与 alpha 混合,但它可以工作。我的图形驱动程序告诉我 dxva2 子流只能处理 AYUV/AI44,但 NV12 也可以(奇怪地)。 NV12 没有 alpha,但如果我们不叠加它们,我们可以显示两个视频(也许更多)。我还发现 CLSID_CColorConvertDMO 无法为 AYUV 提供 MediaSession/Evr 和自定义视频混合器。颜色转换可以在自定义视频混合器中完成。
我会分几次贴出代码,请耐心等待。很难在这里格式化代码。对于代码的某些部分,您将需要来自 MFNode 的通用文件。
有些接口(interface)只是简单地返回E_NOTIMPL,它们只是在这里检查Evr 需要什么。所以我省略了使用 E_NOTIMPL 的代码。
自定义视频混合器类:
//----------------------------------------------------------------------------------------------
// CustomVideoMixer.h
//----------------------------------------------------------------------------------------------
#ifndef MFTCUSTOMVIDEOMIXER_H
#define MFTCUSTOMVIDEOMIXER_H
class CCustomVideoMixer :
BaseObject,
public IMFVideoDeviceID,
public IMFGetService,
public IMFTopologyServiceLookupClient,
public IMFTransform,
public IMFVideoMixerControl,
public IMFVideoProcessor,
public IMFAttributes,
public IMFVideoMixerBitmap,
public IMFVideoPositionMapper
{
public:
// CustomVideoMixer.cpp
static HRESULT CreateInstance(IUnknown*, REFIID, void**);
// IUnknown - CustomVideoMixer.cpp
STDMETHODIMP QueryInterface(REFIID, void**);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IMFVideoDeviceID - CustomVideoMixer.cpp
STDMETHODIMP GetDeviceID(IID*);
// IMFGetService - CustomVideoMixer.cpp
STDMETHODIMP GetService(REFGUID, REFIID, LPVOID*);
// IMFTopologyServiceLookupClient - CustomVideoMixer.cpp
STDMETHODIMP InitServicePointers(IMFTopologyServiceLookup*);
STDMETHODIMP ReleaseServicePointers();
// IMFTransform - CustomVideoMixer_Transform.cpp
STDMETHODIMP GetStreamLimits(DWORD*, DWORD*, DWORD*, DWORD*);
STDMETHODIMP GetStreamCount(DWORD*, DWORD*);
STDMETHODIMP GetStreamIDs(DWORD, DWORD*, DWORD, DWORD*);
STDMETHODIMP GetInputStreamInfo(DWORD, MFT_INPUT_STREAM_INFO*);
STDMETHODIMP GetOutputStreamInfo(DWORD, MFT_OUTPUT_STREAM_INFO*);
STDMETHODIMP GetAttributes(IMFAttributes**);
STDMETHODIMP GetInputStreamAttributes(DWORD, IMFAttributes**);
STDMETHODIMP GetOutputStreamAttributes(DWORD, IMFAttributes**);
STDMETHODIMP DeleteInputStream(DWORD);
STDMETHODIMP AddInputStreams(DWORD, DWORD*);
STDMETHODIMP GetInputAvailableType(DWORD, DWORD, IMFMediaType**);
STDMETHODIMP GetOutputAvailableType(DWORD, DWORD, IMFMediaType**);
STDMETHODIMP SetInputType(DWORD, IMFMediaType*, DWORD);
STDMETHODIMP SetOutputType(DWORD, IMFMediaType*, DWORD);
STDMETHODIMP GetInputCurrentType(DWORD, IMFMediaType**);
STDMETHODIMP GetOutputCurrentType(DWORD, IMFMediaType**);
STDMETHODIMP GetInputStatus(DWORD, DWORD*);
STDMETHODIMP GetOutputStatus(DWORD*);
STDMETHODIMP SetOutputBounds(LONGLONG, LONGLONG);
STDMETHODIMP ProcessEvent(DWORD, IMFMediaEvent*);
STDMETHODIMP ProcessMessage(MFT_MESSAGE_TYPE, ULONG_PTR);
STDMETHODIMP ProcessInput(DWORD, IMFSample*, DWORD);
STDMETHODIMP ProcessOutput(DWORD, DWORD, MFT_OUTPUT_DATA_BUFFER*, DWORD*);
// IMFVideoMixerControl - CustomVideoMixer_Mixer.cpp
STDMETHODIMP GetStreamOutputRect(DWORD, MFVideoNormalizedRect*);
STDMETHODIMP GetStreamZOrder(DWORD, DWORD*);
STDMETHODIMP SetStreamOutputRect(DWORD, const MFVideoNormalizedRect*);
STDMETHODIMP SetStreamZOrder(DWORD, DWORD);
// IMFVideoProcessor - CustomVideoMixer_Mixer.cpp
STDMETHODIMP GetAvailableVideoProcessorModes(UINT*, GUID**);
STDMETHODIMP GetBackgroundColor(COLORREF*);
STDMETHODIMP GetFilteringRange(DWORD, DXVA2_ValueRange*);
STDMETHODIMP GetFilteringValue(DWORD, DXVA2_Fixed32*);
STDMETHODIMP GetProcAmpRange(DWORD, DXVA2_ValueRange*);
STDMETHODIMP GetProcAmpValues(DWORD, DXVA2_ProcAmpValues*);
STDMETHODIMP GetVideoProcessorCaps(LPGUID, DXVA2_VideoProcessorCaps*);
STDMETHODIMP GetVideoProcessorMode(LPGUID);
STDMETHODIMP SetBackgroundColor(COLORREF);
STDMETHODIMP SetFilteringValue(DWORD, DXVA2_Fixed32*);
STDMETHODIMP SetProcAmpValues(DWORD, DXVA2_ProcAmpValues*);
STDMETHODIMP SetVideoProcessorMode(LPGUID);
// IMFAttributes - CustomVideoMixer_Attributes.cpp
STDMETHODIMP Compare(IMFAttributes*, MF_ATTRIBUTES_MATCH_TYPE, BOOL*);
STDMETHODIMP CompareItem(REFGUID, REFPROPVARIANT, BOOL*);
STDMETHODIMP CopyAllItems(IMFAttributes*);
STDMETHODIMP DeleteAllItems();
STDMETHODIMP DeleteItem(REFGUID);
STDMETHODIMP GetAllocatedBlob(REFGUID, UINT8**, UINT32*);
STDMETHODIMP GetAllocatedString(REFGUID, LPWSTR*, UINT32*);
STDMETHODIMP GetBlob(REFGUID, UINT8*, UINT32, UINT32*);
STDMETHODIMP GetBlobSize(REFGUID, UINT32*);
STDMETHODIMP GetCount(UINT32*);
STDMETHODIMP GetDouble(REFGUID, double*);
STDMETHODIMP GetGUID(REFGUID, GUID*);
STDMETHODIMP GetItem(REFGUID, PROPVARIANT*);
STDMETHODIMP GetItemByIndex(UINT32, GUID*, PROPVARIANT*);
STDMETHODIMP GetItemType(REFGUID, MF_ATTRIBUTE_TYPE*);
STDMETHODIMP GetString(REFGUID, LPWSTR, UINT32, UINT32*);
STDMETHODIMP GetStringLength(REFGUID, UINT32*);
STDMETHODIMP GetUINT32(REFGUID, UINT32*);
STDMETHODIMP GetUINT64(REFGUID, UINT64*);
STDMETHODIMP GetUnknown(REFGUID, REFIID, LPVOID*);
STDMETHODIMP LockStore();
STDMETHODIMP SetBlob(REFGUID, const UINT8*, UINT32);
STDMETHODIMP SetDouble(REFGUID, double);
STDMETHODIMP SetGUID(REFGUID, REFGUID);
STDMETHODIMP SetItem(REFGUID, REFPROPVARIANT);
STDMETHODIMP SetString(REFGUID, LPCWSTR);
STDMETHODIMP SetUINT32(REFGUID, UINT32);
STDMETHODIMP SetUINT64(REFGUID, UINT64);
STDMETHODIMP SetUnknown(REFGUID, IUnknown*);
STDMETHODIMP UnlockStore();
// IMFVideoMixerBitmap - CustomVideoMixer_Bitmap.cpp
STDMETHODIMP ClearAlphaBitmap();
STDMETHODIMP GetAlphaBitmapParameters(MFVideoAlphaBitmapParams*);
STDMETHODIMP SetAlphaBitmap(const MFVideoAlphaBitmap*);
STDMETHODIMP UpdateAlphaBitmapParameters(const MFVideoAlphaBitmapParams*);
// IMFVideoPositionMapper - CustomVideoMixer_Bitmap.cpp
STDMETHODIMP MapOutputCoordinateToInputStream(float, float, DWORD, DWORD, float*, float*);
private:
// CustomVideoMixer.cpp
CCustomVideoMixer();
virtual ~CCustomVideoMixer();
CriticSection m_CriticSection;
volatile long m_nRefCount;
CDxva2Manager m_cDxva2Manager;
IMediaEventSink* m_pMediaEventSink;
IMFMediaType* m_pRefInputType;
IMFMediaType* m_pSubInputType;
IMFMediaType* m_pOutputType;
BOOL m_bDraining;
DWORD m_dwInputStreamCount;
BOOL m_bHaveRefOuput;
BOOL m_bHaveSubOuput;
// CustomVideoMixer.cpp
HRESULT SetD3DManager(IDirect3DDeviceManager9*);
HRESULT BeginStreaming(ULONG_PTR);
HRESULT Flush();
// CustomVideoMixer_Type.cpp
HRESULT GetOutputType(IMFMediaType**);
};
#endif
自定义视频混合器.cpp :
//----------------------------------------------------------------------------------------------
// CustomVideoMixer.cpp
//----------------------------------------------------------------------------------------------
#include "StdAfx.h"
CCustomVideoMixer::CCustomVideoMixer()
: m_nRefCount(1),
m_pMediaEventSink(NULL),
m_pRefInputType(NULL),
m_pSubInputType(NULL),
m_pOutputType(NULL),
m_bDraining(FALSE),
m_dwInputStreamCount(1),
m_bHaveRefOuput(FALSE),
m_bHaveSubOuput(FALSE)
{
TRACE_TRANSFORM((L"CustomVideoMixer::CTOR"));
}
CCustomVideoMixer::~CCustomVideoMixer() {
TRACE_TRANSFORM((L"CustomVideoMixer::DTOR"));
AutoLock lock(m_CriticSection);
Flush();
m_cDxva2Manager.ReleaseDxva2();
SAFE_RELEASE(m_pMediaEventSink);
SAFE_RELEASE(m_pRefInputType);
SAFE_RELEASE(m_pSubInputType);
SAFE_RELEASE(m_pOutputType);
}
HRESULT CCustomVideoMixer::CreateInstance(IUnknown* pUnkOuter, REFIID iid, void** ppv) {
TRACE_TRANSFORM((L"CustomVideoMixer::CreateInstance"));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppv == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (pUnkOuter != NULL ? CLASS_E_NOAGGREGATION : S_OK));
CCustomVideoMixer* pMFT = new (std::nothrow)CCustomVideoMixer;
IF_FAILED_RETURN(pMFT == NULL ? E_OUTOFMEMORY : S_OK);
LOG_HRESULT(hr = pMFT->QueryInterface(iid, ppv));
SAFE_RELEASE(pMFT);
return hr;
}
ULONG CCustomVideoMixer::AddRef() {
LONG lRef = InterlockedIncrement(&m_nRefCount);
TRACE_REFCOUNT((L"CustomVideoMixer::AddRef m_nRefCount = %d", lRef));
return lRef;
}
ULONG CCustomVideoMixer::Release() {
ULONG uCount = InterlockedDecrement(&m_nRefCount);
TRACE_REFCOUNT((L"CustomVideoMixer::Release m_nRefCount = %d", uCount));
if (uCount == 0) {
delete this;
}
return uCount;
}
HRESULT CCustomVideoMixer::QueryInterface(REFIID riid, void** ppv) {
TRACE_TRANSFORM((L"CustomVideoMixer::QI : riid = %s", GetIIDString(riid)));
// IMFQualityAdvise
// IEVRTrustedVideoPlugin
static const QITAB qit[] = {
QITABENT(CCustomVideoMixer, IMFVideoDeviceID),
QITABENT(CCustomVideoMixer, IMFGetService),
QITABENT(CCustomVideoMixer, IMFTopologyServiceLookupClient),
QITABENT(CCustomVideoMixer, IMFTransform),
QITABENT(CCustomVideoMixer, IMFVideoMixerControl),
QITABENT(CCustomVideoMixer, IMFVideoProcessor),
QITABENT(CCustomVideoMixer, IMFAttributes),
QITABENT(CCustomVideoMixer, IMFVideoMixerBitmap),
QITABENT(CCustomVideoMixer, IMFVideoPositionMapper),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
HRESULT CCustomVideoMixer::GetDeviceID(IID* pDeviceID) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetDeviceID"));
HRESULT hr;
IF_FAILED_RETURN(hr = (pDeviceID == NULL ? E_POINTER : S_OK));
*pDeviceID = IID_IDirect3DDevice9;
return hr;
}
HRESULT CCustomVideoMixer::GetService(REFGUID guidService, REFIID riid, LPVOID* ppvObject) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetService : guidService = %s - riid = %s", MFServiceString(guidService), GetIIDString(riid)));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppvObject == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (guidService != MR_VIDEO_MIXER_SERVICE ? MF_E_UNSUPPORTED_SERVICE : S_OK));
if (riid == IID_IMFVideoMixerControl || riid == IID_IMFVideoProcessor || riid == IID_IMFTransform) {
hr = QueryInterface(riid, ppvObject);
}
else {
LOG_HRESULT(hr = MF_E_UNSUPPORTED_SERVICE);
}
return hr;
}
HRESULT CCustomVideoMixer::InitServicePointers(IMFTopologyServiceLookup* pLookup) {
TRACE_TRANSFORM((L"CustomVideoMixer::InitServicePointers"));
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd319606(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd406901(v=vs.85).aspx
HRESULT hr;
IF_FAILED_RETURN(hr = (pLookup == NULL ? E_POINTER : S_OK));
AutoLock lock(m_CriticSection);
//IF_FAILED_RETURN(hr = (IsActive() ? MF_E_INVALIDREQUEST : S_OK));
SAFE_RELEASE(m_pMediaEventSink);
DWORD dwObjectCount = 1;
(void)pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_pMediaEventSink), &dwObjectCount);
IF_FAILED_RETURN(hr = (m_pMediaEventSink == NULL ? E_POINTER : S_OK));
// IMFClock* pInterface = NULL;
// (void)pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pInterface), &dwObjectCount);
// SAFE_RELEASE(pInterface);
// IMFVideoPresenter* pInterface = NULL;
// (void)pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pInterface), &dwObjectCount);
// IF_FAILED_RETURN(hr = (pInterface == NULL ? E_POINTER : S_OK));
// SAFE_RELEASE(pInterface);
// IMFVideoRenderer* pInterface2 = NULL;
// (void)pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pInterface2), &dwObjectCount);
// IF_FAILED_RETURN(hr = (pInterface2 == NULL ? E_POINTER : S_OK));
// SAFE_RELEASE(pInterface2);
return hr;
}
HRESULT CCustomVideoMixer::ReleaseServicePointers() {
TRACE_TRANSFORM((L"CustomVideoMixer::ReleaseServicePointers"));
AutoLock lock(m_CriticSection);
SAFE_RELEASE(m_pMediaEventSink);
return S_OK;
}
HRESULT CCustomVideoMixer::SetD3DManager(IDirect3DDeviceManager9* pDeviceManager) {
TRACE_TRANSFORM((L"CustomVideoMixer::SetD3DManager"));
HRESULT hr = S_OK;
m_cDxva2Manager.ReleaseDxva2();
if (pDeviceManager != NULL) {
if (m_pRefInputType != NULL && m_pOutputType != NULL)
IF_FAILED_RETURN(hr = m_cDxva2Manager.InitDxva2(pDeviceManager, m_pOutputType, m_pRefInputType, m_pSubInputType));
}
return hr;
}
HRESULT CCustomVideoMixer::BeginStreaming(ULONG_PTR ulParam) {
TRACE_TRANSFORM((L"CustomVideoMixer::BeginStreaming"));
HRESULT hr;
IF_FAILED_RETURN(hr = (m_pMediaEventSink == NULL ? E_POINTER : S_OK));
//IF_FAILED_RETURN(hr = m_pMediaEventSink->Notify(EC_SAMPLE_NEEDED, ulParam, 0));
IF_FAILED_RETURN(hr = m_pMediaEventSink->Notify(EC_SAMPLE_NEEDED, 0, 0));
IF_FAILED_RETURN(hr = m_pMediaEventSink->Notify(EC_SAMPLE_NEEDED, 1, 0));
// MF_E_INVALIDSTREAMNUMBER
// MF_E_TRANSFORM_TYPE_NOT_SET
return hr;
}
HRESULT CCustomVideoMixer::Flush() {
TRACE_TRANSFORM((L"CustomVideoMixer::Flush"));
m_bDraining = FALSE;
m_bHaveRefOuput = FALSE;
m_bHaveSubOuput = FALSE;
return S_OK;
}
CustomVideoMixer_Transform.cpp :
//----------------------------------------------------------------------------------------------
// CustomVideoMixer_Transform.cpp
//----------------------------------------------------------------------------------------------
#include "StdAfx.h"
HRESULT CCustomVideoMixer::GetStreamLimits(DWORD* pdwInputMinimum, DWORD* pdwInputMaximum, DWORD* pdwOutputMinimum, DWORD* pdwOutputMaximum) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetStreamLimits"));
HRESULT hr;
IF_FAILED_RETURN(hr = ((pdwInputMinimum == NULL || pdwInputMaximum == NULL || pdwOutputMinimum == NULL || pdwOutputMaximum == NULL) ? E_POINTER : S_OK));
*pdwInputMinimum = 1;
*pdwInputMaximum = 16;
*pdwOutputMinimum = 1;
*pdwOutputMaximum = 1;
return hr;
}
HRESULT CCustomVideoMixer::GetStreamCount(DWORD* pcInputStreams, DWORD* pcOutputStreams) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetStreamCount"));
HRESULT hr;
IF_FAILED_RETURN(hr = ((pcInputStreams == NULL || pcOutputStreams == NULL) ? E_POINTER : S_OK));
*pcInputStreams = m_dwInputStreamCount;
*pcOutputStreams = 1;
return hr;
}
HRESULT CCustomVideoMixer::GetStreamIDs(DWORD dwInputIDArraySize, DWORD* pdwInputIDs, DWORD dwOutputIDArraySize, DWORD* pdwOutputIDs) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetStreamIDs"));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwInputIDArraySize == 0 || dwOutputIDArraySize == 0 ? MF_E_BUFFERTOOSMALL : S_OK));
IF_FAILED_RETURN(hr = (pdwInputIDs == NULL || pdwOutputIDs == NULL ? E_POINTER : S_OK));
*pdwOutputIDs = 0;
if (m_dwInputStreamCount == 1)
*pdwInputIDs = 0;
else
IF_FAILED_RETURN(hr = E_FAIL);
return hr;
}
HRESULT CCustomVideoMixer::GetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO* pStreamInfo) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetInputStreamInfo"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (pStreamInfo == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
pStreamInfo->dwFlags =
MFT_INPUT_STREAM_WHOLE_SAMPLES |
MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE |
MFT_INPUT_STREAM_DOES_NOT_ADDREF;
pStreamInfo->hnsMaxLatency = 0;
pStreamInfo->cbSize = 0;
pStreamInfo->cbMaxLookahead = 0;
pStreamInfo->cbAlignment = 0;
return hr;
}
HRESULT CCustomVideoMixer::GetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO* pStreamInfo) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputStreamInfo"));
TRACE_TRANSFORM((L"dwOutputStreamID = %d", dwOutputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (pStreamInfo == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwOutputStreamID != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
AutoLock lock(m_CriticSection);
pStreamInfo->dwFlags =
MFT_OUTPUT_STREAM_WHOLE_SAMPLES |
MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE |
MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
pStreamInfo->cbAlignment = 0;
pStreamInfo->cbSize = 0;
return hr;
}
HRESULT CCustomVideoMixer::GetAttributes(IMFAttributes** ppAttributes) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetAttributes"));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppAttributes == NULL ? E_POINTER : S_OK));
*ppAttributes = this;
(*ppAttributes)->AddRef();
return hr;
}
HRESULT CCustomVideoMixer::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes** ppAttributes) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetInputStreamAttributes"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (ppAttributes == NULL ? E_POINTER : S_OK));
*ppAttributes = this;
(*ppAttributes)->AddRef();
return hr;
}
HRESULT CCustomVideoMixer::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes** ppAttributes) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputStreamAttributes"));
TRACE_TRANSFORM((L"dwOutputStreamID = %d", dwOutputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwOutputStreamID != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (ppAttributes == NULL ? E_POINTER : S_OK));
*ppAttributes = this;
(*ppAttributes)->AddRef();
return hr;
}
HRESULT CCustomVideoMixer::DeleteInputStream(DWORD dwStreamID) {
TRACE_TRANSFORM((L"CustomVideoMixer::DeleteInputStream"));
TRACE_TRANSFORM((L"dwStreamID = %d", dwStreamID));
if (dwStreamID == 0)
return MF_E_INVALIDREQUEST;
else if (dwStreamID != 1)
return MF_E_INVALIDSTREAMNUMBER;
else if(m_dwInputStreamCount != 2)
return MF_E_INVALIDREQUEST;
//MF_E_TRANSFORM_INPUT_REMAINING
m_dwInputStreamCount--;
return S_OK;
}
HRESULT CCustomVideoMixer::AddInputStreams(DWORD cStreams, DWORD* adwStreamIDs) {
TRACE_TRANSFORM((L"CustomVideoMixer::AddInputStreams"));
HRESULT hr;
IF_FAILED_RETURN(hr = (cStreams != 1 ? E_INVALIDARG : S_OK));
IF_FAILED_RETURN(hr = (adwStreamIDs == NULL ? E_INVALIDARG : S_OK));
IF_FAILED_RETURN(hr = (*adwStreamIDs != 1 ? E_INVALIDARG : S_OK));
if (m_dwInputStreamCount == 1)
m_dwInputStreamCount++;
else
IF_FAILED_RETURN(hr = E_INVALIDARG);
return S_OK;
}
HRESULT CCustomVideoMixer::GetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType** ppType) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetInputAvailableType"));
TRACE_TRANSFORM((L"dwInputStreamID = %d - dwTypeIndex = %d", dwInputStreamID, dwTypeIndex));
return MF_E_NO_MORE_TYPES;
}
HRESULT CCustomVideoMixer::GetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType** ppType) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputAvailableType"));
TRACE_TRANSFORM((L"dwOutputStreamID = %d - dwTypeIndex = %d", dwOutputStreamID, dwTypeIndex));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppType == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwOutputStreamID != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (dwTypeIndex != 0 ? MF_E_NO_MORE_TYPES : S_OK));
AutoLock lock(m_CriticSection);
if (m_pRefInputType == NULL) {
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
}
else {
hr = GetOutputType(ppType);
}
return hr;
}
HRESULT CCustomVideoMixer::SetInputType(DWORD dwInputStreamID, IMFMediaType* pType, DWORD dwFlags) {
TRACE_TRANSFORM((L"CustomVideoMixer::SetInputType"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (dwFlags & ~MFT_SET_TYPE_TEST_ONLY ? E_INVALIDARG : S_OK));
BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
TRACE_TRANSFORM((L"bReallySet = %s", bReallySet ? L"TRUE" : L"FALSE"));
AutoLock lock(m_CriticSection);
if (pType) {
LogMediaType(pType);
}
else {
if (dwInputStreamID == 0)
SAFE_RELEASE(m_pRefInputType);
else
SAFE_RELEASE(m_pSubInputType);
return hr;
}
if (bReallySet) {
if (dwInputStreamID == 0) {
SAFE_RELEASE(m_pRefInputType);
m_pRefInputType = pType;
m_pRefInputType->AddRef();
}
else {
SAFE_RELEASE(m_pSubInputType);
m_pSubInputType = pType;
m_pSubInputType->AddRef();
}
}
return hr;
}
HRESULT CCustomVideoMixer::SetOutputType(DWORD dwOutputStreamID, IMFMediaType* pType, DWORD dwFlags) {
TRACE_TRANSFORM((L"CustomVideoMixer::SetOutputType"));
TRACE_TRANSFORM((L"dwOutputStreamID = %d", dwOutputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwOutputStreamID != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (dwFlags & ~MFT_SET_TYPE_TEST_ONLY ? E_INVALIDARG : S_OK));
BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
TRACE_TRANSFORM((L"bReallySet = %s", bReallySet ? L"TRUE" : L"FALSE"));
AutoLock lock(m_CriticSection);
if (pType) {
LogMediaType(pType);
}
else {
SAFE_RELEASE(m_pOutputType);
return hr;
}
if (bReallySet) {
SAFE_RELEASE(m_pOutputType);
m_pOutputType = pType;
m_pOutputType->AddRef();
}
return hr;
}
HRESULT CCustomVideoMixer::GetInputCurrentType(DWORD dwInputStreamID, IMFMediaType** ppType) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetInputCurrentType"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppType == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
AutoLock lock(m_CriticSection);
IMFMediaType* m_pInputType = dwInputStreamID == 0 ? m_pRefInputType : m_pSubInputType;
if (!m_pInputType) {
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
}
else {
// Todo : clone MediaType
*ppType = m_pInputType;
(*ppType)->AddRef();
}
return hr;
}
HRESULT CCustomVideoMixer::GetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType** ppType) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputCurrentType"));
TRACE_TRANSFORM((L"dwOutputStreamID = %d", dwOutputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (ppType == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwOutputStreamID != 0 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
AutoLock lock(m_CriticSection);
if (!m_pOutputType) {
hr = MF_E_TRANSFORM_TYPE_NOT_SET;
}
else {
// Todo : clone MediaType
*ppType = m_pOutputType;
(*ppType)->AddRef();
}
return hr;
}
HRESULT CCustomVideoMixer::GetInputStatus(DWORD dwInputStreamID, DWORD* pdwFlags) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetInputStatus"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (pdwFlags == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
AutoLock lock(m_CriticSection);
// I think we can always process
*pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
return hr;
}
HRESULT CCustomVideoMixer::GetOutputStatus(DWORD* pdwFlags) {
TRACE_TRANSFORM((L"CustomVideoMixer::GetOutputStatus"));
HRESULT hr;
IF_FAILED_RETURN(hr = (pdwFlags == NULL ? E_POINTER : S_OK));
AutoLock lock(m_CriticSection);
/*if (m_bHaveOuput) {
*pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
}
else {
*pdwFlags = 0;
}*/
return hr;
}
HRESULT CCustomVideoMixer::SetOutputBounds(LONGLONG /*hnsLowerBound*/, LONGLONG /*hnsUpperBound*/) {
TRACE_TRANSFORM((L"CustomVideoMixer::SetOutputBounds"));
return E_NOTIMPL;
}
HRESULT CCustomVideoMixer::ProcessEvent(DWORD /*dwInputStreamID*/, IMFMediaEvent* /*pEvent */) {
TRACE_TRANSFORM((L"CustomVideoMixer::ProcessEvent"));
return E_NOTIMPL;
}
HRESULT CCustomVideoMixer::ProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam) {
TRACE_TRANSFORM((L"CustomVideoMixer::ProcessMessage : %s (Param = %d)", MFTMessageString(eMessage), ulParam));
HRESULT hr = S_OK;
AutoLock lock(m_CriticSection);
switch (eMessage) {
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
//case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
hr = BeginStreaming(ulParam);
break;
case MFT_MESSAGE_COMMAND_FLUSH:
case MFT_MESSAGE_NOTIFY_END_STREAMING:
case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
hr = Flush();
break;
case MFT_MESSAGE_COMMAND_DRAIN:
m_bDraining = TRUE;
break;
case MFT_MESSAGE_SET_D3D_MANAGER:
hr = SetD3DManager(reinterpret_cast<IDirect3DDeviceManager9*>(ulParam));
// hr = MF_E_UNSUPPORTED_D3D_TYPE...
break;
}
return hr;
}
HRESULT CCustomVideoMixer::ProcessInput(DWORD dwInputStreamID, IMFSample* pSample, DWORD dwFlags) {
TRACE_TRANSFORM((L"CustomVideoMixer::ProcessInput"));
TRACE_TRANSFORM((L"dwInputStreamID = %d", dwInputStreamID));
HRESULT hr;
IF_FAILED_RETURN(hr = (pSample == NULL ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (dwInputStreamID > 1 ? MF_E_INVALIDSTREAMNUMBER : S_OK));
IF_FAILED_RETURN(hr = (dwFlags != 0 ? E_INVALIDARG : S_OK));
AutoLock lock(m_CriticSection);
if (m_bHaveRefOuput || m_bHaveSubOuput) {
return MF_E_NOTACCEPTING;
}
if (SUCCEEDED(hr = m_cDxva2Manager.ProcessInput(pSample, dwInputStreamID))) {
if (dwInputStreamID == 0) {
m_bHaveRefOuput = TRUE;
LOG_HRESULT(hr = m_pMediaEventSink->Notify(EC_SAMPLE_NEEDED, 0, 0));
}
else {
m_bHaveSubOuput = TRUE;
LOG_HRESULT(hr = m_pMediaEventSink->Notify(EC_SAMPLE_NEEDED, 1, 0));
}
}
return hr;
}
HRESULT CCustomVideoMixer::ProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER* pOutputSamples, DWORD* pdwStatus) {
TRACE_TRANSFORM((L"CustomVideoMixer::ProcessOutput"));
HRESULT hr;
IF_FAILED_RETURN(hr = (dwFlags != 0 ? E_INVALIDARG : S_OK));
IF_FAILED_RETURN(hr = (cOutputBufferCount != 1 ? E_INVALIDARG : S_OK));
IF_FAILED_RETURN(hr = ((pOutputSamples == NULL || pdwStatus == NULL) ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (pOutputSamples[0].dwStreamID != 0 ? E_POINTER : S_OK));
IF_FAILED_RETURN(hr = (pOutputSamples[0].pSample == NULL ? E_INVALIDARG : S_OK));
AutoLock lock(m_CriticSection);
if (m_bHaveRefOuput || m_bHaveSubOuput) {
IF_FAILED_RETURN(hr = m_cDxva2Manager.ProcessOutput(pOutputSamples[0].pSample));
if(m_bHaveRefOuput)
m_bHaveRefOuput = FALSE;
if (m_bHaveSubOuput)
m_bHaveSubOuput = FALSE;
}
else {
return MF_E_TRANSFORM_NEED_MORE_INPUT;
}
return hr;
}
关于c++ - 媒体基础自定义混合器 MFT 出现错误 MF_E_CANNOT_CREATE_SINK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42946608/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!