- 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/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!