Я пытаюсь настроить объект топологии в моей оболочке C # для MMF, чтобы начать захват с устройства захвата в качестве источника.У меня есть существующий и активированный объект IMFMediaSource
, поэтому я создаю узел топологии, добавляю узел в топологию и пытаюсь установить топологию.Во время вызова IMFMediaSession::SetTopology
выдается следующее исключение:
System.Runtime.InteropServices.COMException: узел потока источника в топологии не имеет источника.(Исключение из HRESULT: 0xC00D521A)
Ранее я использовал SourceReader для извлечения сэмплов из источника мультимедиа, поэтому я знаю, что источник мультимедиа работает.Я читал в нескольких разных местах, что если я на самом деле хочу отобразить что-то на экране с видеоустройства, я не могу использовать SourceReader и SinkWriter, поэтому я пытаюсь создатьТопология для использования.Я также могу создать дескриптор презентации и получить дескрипторы потока из дескриптора презентации, созданного из медиаисточника.В ходе этого процесса я также проверяю, что подтип - это то, что я действительно могу использовать.
У меня также есть выходной узел приемника мультимедиа как часть топологии.Это, кажется, не имеет никаких проблем или вызывает исключения.Я удалил узел исходного потока и оставил приемник мультимедиа, и он не аварийно завершился.
Я попытался найти дополнительную информацию об этом исключении, но единственные результаты поиска, которые я нашел, - это то, чтоHResult, о котором у меня уже есть эта информация.
Вот как я создаю узел топологии (источник, дескриптор представления и потоковый дескриптор не равны NULL):
if (sourcePresentationDescriptor == null || videoStreamDescriptor == null || !isSelectedStream)
{
return false;
}
status = NativeMethods.MFCreateTopologyNode(MFTopologyType.TopologySourcestreamNode, out videoSourceNode);
if (status < 0) { throw new Exception("Not able to create topology node for source."); }
// Finish instantiating source node
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodeSource, mediaSource);
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodePresentationDescriptor, sourcePresentationDescriptor);
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodeStreamDescriptor, videoStreamDescriptor);
topology.AddNode(videoSourceNode);
MediaSession.SetTopology(0, topology); // <-- Exception thrown here
Запуск MFTraceЯ получаю следующее:
CTopologyHelpers::Trace @05114468 >>>>>>>>>>>>> input topology
CTopologyHelpers::TraceNode @ Node 0 @050EDFD8 ID:7FC400000001, 0 inputs, 0 outputs, type 1, MF_TOPONODE_SOURCE=@050E3E68;MF_TOPONODE_STREAM_DESCRIPTOR=@050FE9B0
CMFTopologyNodeDetours::GetGUID @050EDFD8 attribute not found guidKey = MF_TOPONODE_TRANSFORM_OBJECTID
CTopologyHelpers::TraceObject @ UnknownType @00000000 {00000000-0000-0000-0000-000000000000} ((null)), (null)
CMFTopologyDetours::GetUINT32 @05114468 attribute not found guidKey = MF_TOPOLOGY_RESOLUTION_STATUS
CTopologyHelpers::Trace @05114468 MF_TOPOLOGY_RESOLUTION_STATUS = NOT FOUND!!!
CTopologyHelpers::Trace @05114468 <<<<<<<<<<<<< input topology
Я думаю, что это должно создать правильный узел топологии, но я очень новичок в этом.Если это проблема с моей оболочкой COM, я бы не ожидал такого конкретного исключения, хотя я не против исключить это как проблему.Вместо установки топологии он просто выдает это исключение.
UPDATE
Вот полный код, который я использую для создания топологии:
private bool CreateMediaSessionAndTopology(IMFMediaSource mediaSource, IntPtr videoHWnd, string uniqueDeviceName)
{
IMFTopology topology;
IMFTopologyNode videoSourceNode;
IMFTopologyNode outputVideoSinkNode;
//IMFTopologyNode transformNode;
IMFPresentationDescriptor sourcePresentationDescriptor = null;
IMFStreamDescriptor videoStreamDescriptor = null;
IMFMediaTypeHandler mediaTypeHandler;
IMFMediaType captureMediaType;
IMFActivate rendererActivator;
uint sourceStreamCount;
bool isSelectedStream = false;
Guid majorMediaType;
Guid[] subTypes =
{
MFMediaTypeGuids.NV12,
MFMediaTypeGuids.YUY2,
MFMediaTypeGuids.UYVY,
MFMediaTypeGuids.RGB32,
MFMediaTypeGuids.RGB24,
MFMediaTypeGuids.IYUV
};
try
{
// Create the topology
uint status = NativeMethods.MFCreateTopology(out topology);
if (status < 0) { throw new Exception("Couldn't create topology"); }
sourcePresentationDescriptor = mediaSource.CreatePresentationDescriptor();
sourceStreamCount = sourcePresentationDescriptor.GetStreamDescriptorCount();
for (uint i = 0; i < sourceStreamCount; i++)
{
videoStreamDescriptor = sourcePresentationDescriptor.GetStreamDescriptorByIndex(i, out isSelectedStream);
if (videoStreamDescriptor != null)
{
mediaTypeHandler = videoStreamDescriptor.GetMediaTypeHandler();
majorMediaType = mediaTypeHandler.GetMajorType();
if (majorMediaType != MFMediaTypeGuids.Video) { continue; }
if (!isSelectedStream) { continue; }
uint MaxSubTypes = 250; //magic number for now;
for (uint j = 0; j < MaxSubTypes; j++)
{
captureMediaType = mediaTypeHandler.GetMediaTypeByIndex(j);
if (captureMediaType == null) { continue; }
Guid subtype = captureMediaType.GetGuid(CLSIDsMFMediaTypeAttributes.SubType);
for (int k = 0; k < subTypes.Length; k++)
{
if (subtype == subTypes[k])
{
mediaTypeHandler.SetCurrentMediaType(captureMediaType);
break;
}
}
break;
}
break;
}
}
if (sourcePresentationDescriptor == null || videoStreamDescriptor == null || !isSelectedStream)
{
return false;
}
status = NativeMethods.MFCreateTopologyNode(MFTopologyType.TopologySourcestreamNode, out videoSourceNode);
if (status < 0) { throw new Exception("Not able to create topology node for source."); }
// Finish instantiating source node
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodeSource, mediaSource);
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodePresentationDescriptor, sourcePresentationDescriptor);
videoSourceNode.SetUnknown(CLSIDsMFMediaTypeAttributes.TopoNodeStreamDescriptor, videoStreamDescriptor);
topology.AddNode(videoSourceNode);
// Create Video Sink node
status = NativeMethods.MFCreateTopologyNode(MFTopologyType.TopologyOutputNode, out outputVideoSinkNode);
if (status < 0) { throw new Exception("Couldn't create output node."); }
status = NativeMethods.MFCreateVideoRendererActivate(videoHWnd, out rendererActivator);
if (status < 0) { throw new Exception("Couldn't create renderer activator"); }
outputVideoSinkNode.SetObject(rendererActivator);
topology.AddNode(outputVideoSinkNode);
videoSourceNode.ConnectOutput(0, outputVideoSinkNode, 0);
// Create the session
status = NativeMethods.MFCreateMediaSession(null, out _mediaSession);
if (status < 0) { throw new Exception("Not able to create media session."); }
_mediaSessionCallbackHandler = new DeviceCaptureCallbackHandler();
_mediaSessionCallbackHandler.MediaSession = _mediaSession;
_mediaSessionCallbackHandler.MediaSessionAsyncCallbackEvent = HandleMediaSessionCallbackEvent;
_mediaSessionCallbackHandler.MediaSessionAsyncCallbackError = HandleMediaSessionCallbackErrors;
_mediaSession.BeginGetEvent(_mediaSessionCallbackHandler, null);
_mediaSession.SetTopology(0, topology);
}
catch (Exception ex)
{
throw new Exception("Failed to create topology", ex);
}
return true;
}
Вот как устройство активируется:
public Device(IMFActivate activator)
{
string friendlyName;
string symbolicLinkName;
_activator = activator;
activator.GetAllocatedString(MfAttributeSourceTypeGuids.MfDevsourceAttributeFriendlyName, out friendlyName);
FriendlyName = friendlyName;
activator.GetAllocatedString(MfAttributeSourceTypeGuids.MfDevsourceAttributeSourceTypeVidcapSymbolicLink, out symbolicLinkName);
SymbolicLinkName = symbolicLinkName;
}
На самом деле с помощью активатора:
public bool ActivateDevice()
{
object source;
try
{
source = _activator.ActivateObject(typeof(IMFMediaSource).GUID);
MediaSource = source as IMFMediaSource;
}
catch (System.Exception ex)
{
throw new System.Exception("Couldn't activate object", ex);
}
return true;
Я думаю, что здесь я совершаю простую ошибку,испортить это.