【问题标题】:How to fix memory leak in GetPreviewFrameAsync如何修复 GetPreviewFrameAsync 中的内存泄漏
【发布时间】:2019-06-18 11:02:01
【问题描述】:

我有基于此示例的代码; https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/CameraGetPreviewFrame。每次都行;

await _mediaCapture.GetPreviewFrameAsync(_currentVideoFrame);

被击中我们似乎泄漏了内存。我没有收拾什么?我也尝试过每次创建模板框架并在每个循环中处理和归零它 - 这似乎也不起作用。

我已返回 Microsoft 的原始示例,它似乎也泄漏了。这是我的代码;

await Task.Run(async () =>
{
    try
    {
        var videoEncodingProperties = 
            _mediaCapture.VideoDeviceController.GetMediaStreamProperties
                (MediaStreamType.VideoPreview) as VideoEncodingProperties;

        Debug.Assert(videoEncodingProperties != null, nameof(videoEncodingProperties) + " != null");

        _currentVideoFrame = new VideoFrame(BitmapPixelFormat.Gray8,
            (int) videoEncodingProperties.Width,
            (int) videoEncodingProperties.Height);

        TimeSpan? lastFrameTime = null;

        while (_mediaCapture.CameraStreamState == CameraStreamState.Streaming)
        {
            token.ThrowIfCancellationRequested();

            await _mediaCapture.GetPreviewFrameAsync(_currentVideoFrame);

            if (!lastFrameTime.HasValue ||
                lastFrameTime != _currentVideoFrame.RelativeTime)
            {
                await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync
                    (CoreDispatcherPriority.Normal,
                    () =>
                    {
                        try
                        {
                            Debug.Assert(_currentVideoFrame != null,
                                        $"{nameof(_currentVideoFrame)} != null");

                            var bitmap = _currentVideoFrame.SoftwareBitmap.AsBitmap();

                            float focalLength = _cameraOptions == CameraOptions.Front ? AppSettings.FrontCameraFocalLength : AppSettings.RearCameraFocalLength;

                            _frameProcessor.ProcessFrame(bitmap, focalLength);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"Exception: {ex}");
                        }
                    });

                lastFrameTime = _currentVideoFrame.RelativeTime;
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Exception: {ex}");
    }
},
token);

这应该只是获取帧并将它们通过_frameProcessor.ProcessFrame() 调用,但即使它什么都不做(我删除了除 GetPreviewFrameAsync 之外的所有内容)它也会泄漏。

要重复该问题,请从以下位置下载示例; https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/CameraGetPreviewFrame。在 Windows 10 v 1903 (18362.175) 下使用诊断工具 (Debug->Windows->Show Diagnostic tools) 远程运行调试器中的示例到 Surface Pro 4 (i5-6300U @2.4GHz)。打开显示帧复选框并在按下 GetPreviewFrameAsync 按钮时观察内存。记忆如下所示,每次上升都是我按下按钮;

【问题讨论】:

  • 你能分享更多关于如何检查内存泄漏的信息吗?
  • @NicoZhu-MSFT 当然;我添加了一些信息以在问题的主体中重复问题
  • 有趣的是我的台式电脑运行相同的代码和一个 USB 摄像头(这也显示了 Surface Pro 4 上的问题)没有显示问题 - 我的台式电脑是 Win 10 v1809 (17763.504)跨度>
  • 好的,我知道了,我去测试一下,如果问题真的存在,我会向相关团队报告
  • 请检查这个问题report Github 中的主机。

标签: uwp mediacapture


【解决方案1】:

在我们的代码中使用MediaFrameReader API 可以很好地解决这个错误,而且响应速度可能会稍微快一些。微软现在已经在GetPreviewFrameAsync documentation page 中添加了一条注释来指出这一点。

这对我们有用;

...
private MediaFrameReader _mediaFrameReader;
...

private async Task InitializeCameraAsync()
{
    if (_mediaCapture == null)
    {
         _mediaCapture = new MediaCapture();
         var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
         var selectedGroup = frameSourceGroups.FirstOrDefault(x => x.Id.Equals(_camera.UwpDeviceInfo.Id));

         try
         {
             var mediaInitSettings = new MediaCaptureInitializationSettings
             {
                 SourceGroup = selectedGroup,
                 VideoDeviceId = _camera.UwpDeviceInfo.Id,
                 AudioDeviceId = string.Empty,
                 StreamingCaptureMode = StreamingCaptureMode.Video,
                 MemoryPreference = MediaCaptureMemoryPreference.Cpu
             };

             await _mediaCapture.InitializeAsync(mediaInitSettings);

             _isInitialized = true;
         }
         catch (UnauthorizedAccessException)
         {
...
         }
         catch (Exception ex)
         {
...
         }
...

         // Set-up for frameProcessing
         var sourceInfo = selectedGroup?.SourceInfos.FirstOrDefault(info =>
             info.SourceKind == MediaFrameSourceKind.Color);
...                   
         var colorFrameSource = _mediaCapture.FrameSources[sourceInfo.Id];
         var preferredFormat = colorFrameSource.SupportedFormats
             .OrderByDescending(x => x.VideoFormat.Width)
             .FirstOrDefault(x => x.VideoFormat.Width <= 1920 &&
                  x.Subtype.Equals(MediaEncodingSubtypes.Nv12, StringComparison.OrdinalIgnoreCase));

         await colorFrameSource.SetFormatAsync(preferredFormat);

         _mediaFrameReader = await _mediaCapture.CreateFrameReaderAsync(colorFrameSource);
     }
...
}

...

private void _mediaFrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
...
        var mediaFrameReference = sender.TryAcquireLatestFrame();
        var videoMediaFrame = mediaFrameReference?.VideoMediaFrame;
        var softwareBitmap = videoMediaFrame?.SoftwareBitmap;

        if (softwareBitmap != null && _frameProcessor != null)
        {
            if (_mediaCapture.CameraStreamState == CameraStreamState.Streaming)
            {
...
                _frameProcessor.ProcessFrame(SoftwareBitmap.Convert(softwareBitmap, 
                        BitmapPixelFormat.Gray8).AsBitmap(), _camera);
...
            }
        }
...
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 2018-05-09
    • 2018-07-12
    • 2012-09-14
    • 2020-05-24
    相关资源
    最近更新 更多