我遭遇了一次内存泄漏,到目前为止,我追踪它的运气是零。它似乎与释放拓扑有关。
基本上我有一个视频播放器,可以有多种拓扑连接到它。每次调用play时,我都会重新创建拓扑(使用activate objects for audio and video),如下所示:
private Topology BuildTopology( TimeSpan startTime, TimeSpan endTime, IntPtr hWnd )
{
if ( _topology != null )
{
_topology.Dispose();
_topology = null;
}
MediaFactory.CreateTopology( out _topology );
SharpDX.MediaFoundation.MediaSource mediaSource;
{
SourceResolver resolver = new SourceResolver();
ObjectType otype;
ComObject source = (ComObject)resolver.CreateObjectFromURL(FileName, SourceResolverFlags.MediaSource, null, out otype);
mediaSource = source.QueryInterface<SharpDX.MediaFoundation.MediaSource>();
resolver.Dispose();
source.Dispose();
}
PresentationDescriptor presDesc;
mediaSource.CreatePresentationDescriptor(out presDesc);
for (var i = 0; i < presDesc.StreamDescriptorCount; i++)
{
SharpDX.Mathematics.Interop.RawBool selected;
StreamDescriptor desc;
presDesc.GetStreamDescriptorByIndex(i, out selected, out desc);
if (selected)
{
var majorType = desc.MediaTypeHandler.MajorType;
TopologyNode sourceNode;
MediaFactory.CreateTopologyNode( TopologyType.SourceStreamNode, out sourceNode );
sourceNode.Set( TopologyNodeAttributeKeys.Source, mediaSource );
sourceNode.Set( TopologyNodeAttributeKeys.PresentationDescriptor, presDesc );
sourceNode.Set( TopologyNodeAttributeKeys.StreamDescriptor, desc );
if ( startTime != TimeSpan.Zero )
sourceNode.Set( TopologyNodeAttributeKeys.Mediastart, startTime.Ticks );
if ( endTime != TimeSpan.Zero )
sourceNode.Set( TopologyNodeAttributeKeys.Mediastop, endTime.Ticks );
TopologyNode outputNode;
MediaFactory.CreateTopologyNode(TopologyType.OutputNode, out outputNode);
if (majorType == MediaTypeGuids.Video)
{
Activate activate;
MediaFactory.CreateVideoRendererActivate( hWnd, out activate );
outputNode.Object = activate;
IsVideo = true;
}
if (majorType == MediaTypeGuids.Audio)
{
Activate activate;
MediaFactory.CreateAudioRendererActivate( out activate );
//activate.Dispose();
outputNode.Object = activate;
}
outputNode.Set( TopologyNodeAttributeKeys.NoshutdownOnRemove, false );
_topology.AddNode( sourceNode );
_topology.AddNode( outputNode );
sourceNode.ConnectOutput( 0, outputNode, 0 );
sourceNode.Dispose();
outputNode.Dispose();
}
desc.Dispose();
}
presDesc.Dispose();
mediaSource.Dispose();
return _topology;
}
奇怪的是,尽管每次确保前一个拓扑已被释放,但我都会得到一个内存泄漏,这个泄漏会慢慢累积,直到我的应用程序抛出内存不足错误。
我的游戏功能如下:
private void Play( TimeSpan ts )
{
if (State != MediaState.Stopped)
{
_session.Stop();
_clock.Dispose();
}
// Set the new song.
_session.SetTopology( SessionSetTopologyFlags.ClearCurrent, null );
//_session.ClearTopologies();
_session.SetTopology( SessionSetTopologyFlags.Immediate, _currentVideo.Topology );
// Get the clock.
_clock = _session.Clock.QueryInterface< PresentationClock >();
// Start playing.
var varStart = new Variant();
varStart.Value = (long)ts.Ticks;
_session.Start( null, varStart );
}
我已经打开了“EnableObjectTracking”和“UseThreadStaticObjectTracking”,但是没有对象的生成。只有我的会话和上次播放的拓扑出现过。
有趣的是,在我打开“EnableReleaseOnFinalizer”之前,内存leajk要快得多。现在它需要几百个播放周期来耗尽内存,这是一个巨大的进步,但仍然对我没有好处。
有人知道我做错了什么吗?这让我有点发疯。应用程序已经准备好,除了这个内存泄漏,我不能释放与这个问题在那里。
编辑
:我应该补充一点,这似乎与视频有关,因为当我播放音频文件而不是视频时,似乎没有内存泄漏(或者相比之下它非常小)。