У меня есть код, основанный на этом образце; 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->Показать инструменты диагностики) удаленно на Surface Pro 4 (i5-6300U @2,4 ГГц) под управлением Windows 10 v 1903 (18362.175). Установите флажок «Показать кадр» и наблюдайте за памятью при нажатии кнопки GetPreviewFrameAsync. Память выглядит следующим образом: каждый тик вверх — это нажатие кнопки;
@NicoZhu-MSFT Конечно; Я добавил некоторую информацию, чтобы повторить проблему в основной части вопроса.
Интересно, что мой настольный ПК с тем же кодом и USB-камерой (которая также показывает проблему на Surface Pro 4) не показывает проблему — мой настольный ПК — Win 10 v1809 (17763.504)
Хорошо, я понял, я проверю это, если проблема действительно существует, я сообщу соответствующей команде
Пожалуйста, проверьте эту проблему отчет, которая размещена на Github.
@NicoZhu-MSFT: спасибо, мы уже видели это; но я не думаю, что видеокарта (которая кажется там решением) действительно является проблемой здесь, учитывая, что это происходит на Surface Pro 4, на котором мы не можем заменить видеокарту (и это происходит на моем рабочем столе с встроенная карта) Это также происходит только в последней версии Win10: v1903. v1809 вроде нормально. Мы вернули Surface Pro, и утечка исчезла.
Хорошо, я обсужу с командой.
Давайте продолжить обсуждение в чате.
Спасибо за сообщение об этой проблеме, наша команда инженеров исследует эту проблему, я обновлю ее здесь, как только появятся какие-либо обновления.





Использование API медиафреймреадера хорошо обходит эту ошибку в нашем коде и, возможно, немного более отзывчиво. Теперь Microsoft добавила примечание к Страница документации GetPreviewFrameAsync, чтобы указать на это.
Это работает для нас;
...
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);
...
}
}
...
}
}
Не могли бы вы рассказать больше о том, как проверить утечку памяти?