代码之家  ›  专栏  ›  技术社区  ›  Goz

内存泄漏使用SharpDX使用MediaSession播放视频

  •  0
  • Goz  · 技术社区  · 6 年前

    我遭遇了一次内存泄漏,到目前为止,我追踪它的运气是零。它似乎与释放拓扑有关。

    基本上我有一个视频播放器,可以有多种拓扑连接到它。每次调用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要快得多。现在它需要几百个播放周期来耗尽内存,这是一个巨大的进步,但仍然对我没有好处。

    有人知道我做错了什么吗?这让我有点发疯。应用程序已经准备好,除了这个内存泄漏,我不能释放与这个问题在那里。

    编辑 :我应该补充一点,这似乎与视频有关,因为当我播放音频文件而不是视频时,似乎没有内存泄漏(或者相比之下它非常小)。

    0 回复  |  直到 6 年前