У меня утечка памяти, и до сих пор мне не повезло отследить ее.Похоже, это связано с освобождением топологии.
По сути, у меня есть видеоплеер, к которому можно подключить несколько топологий.Каждый раз, когда я вызываю play, я воссоздаю топологию (используя объекты активации для аудио и видео) следующим образом:
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».Теперь требуется несколько сотен игровых циклов, чтобы исчерпать память, что является огромным улучшением, но все еще бесполезно для меня.
Кто-нибудь понял, что я делаю неправильно?Это сводит меня с ума.Приложение готово, кроме этой утечки памяти, и я не могу выпустить эту проблему там.
Редактировать : я должен добавить, что это, похоже, связанок видео, поскольку при воспроизведении аудиофайлов вместо видео не возникает утечка памяти (или она ОЧЕНЬ мала).