Утечка памяти при воспроизведении видео с помощью MediaSession с использованием SharpDX - PullRequest
0 голосов
/ 30 января 2019

У меня утечка памяти, и до сих пор мне не повезло отследить ее.Похоже, это связано с освобождением топологии.

По сути, у меня есть видеоплеер, к которому можно подключить несколько топологий.Каждый раз, когда я вызываю 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».Теперь требуется несколько сотен игровых циклов, чтобы исчерпать память, что является огромным улучшением, но все еще бесполезно для меня.

Кто-нибудь понял, что я делаю неправильно?Это сводит меня с ума.Приложение готово, кроме этой утечки памяти, и я не могу выпустить эту проблему там.

Редактировать : я должен добавить, что это, похоже, связанок видео, поскольку при воспроизведении аудиофайлов вместо видео не возникает утечка памяти (или она ОЧЕНЬ мала).

...