Я работаю над добавлением простого предварительного просмотра веб-камеры в приложение UWP. Подготовка и запуск предварительного просмотра работают нормально, поэтому я работаю над правильной обработкой исключений, генерируемых InitializeAsync()
и StartPreviewAsync()
, и не могу правильно перехватить исключения для второго.
Я основываю свой кодoff of Отобразите предварительный просмотр камеры , и он говорит, что, если приложению не предоставлен доступ к устройству захвата, оно вызовет UnauthorizedAccessException
при вызове InitializeAsync()
. Для C ++ / WinRT это, кажется, работает для перехвата hresult_error
кода E_ACCESSDENIED
, как показано ниже. Я проверил это, отключив доступ к веб-камере в настройках приложения, и блок try / catch работает точно так же, как и следовало ожидать, когда всплыло диалоговое окно с содержимым, объясняющее проблему пользователю.
Ссылкатакже говорит, что если другое приложение имеет исключительный контроль над устройством захвата, то StartPreviewAsync()
должно выдать FileLoadException
. Для начала я не могу понять, что такое эквивалент C ++ / WinRT для этого исключения. Во-вторых, я не могу поймать никаких исключений вообще. Я попытался использовать тот же тип блока перехвата, который я использовал для InitializeAsync()
, поскольку это то, что описано в Перехват исключений , но когда это не сработало, я прибег к попытке перехватить что-нибудь с помощью блока ниже. В документах говорится, что вы можете зарегистрироваться на событие CaptureDeviceExclusiveControlStatusChanged
, когда вы поймаете исключение, но так как я не могу поймать исключение, я не уверен, где будет подходящее место для этого или если событие сработает, если мое приложение запущенопосле того, как другое приложение уже имеет контроль над устройством захвата. Я никогда не вижу текст из OutputDebugString()
в блоке catch, но я получаю следующее сообщение (дважды) в окне вывода отладки:
Исключение, сгенерированное в 0x00007FFC7114A839 (KernelBase.dll) в DBRacing. exe: ошибка инициализации WinRT - 0xC00D3704: «Аппаратному MFT не удалось начать потоковую передачу из-за нехватки аппаратных ресурсов.».
Похоже, генерируется исключение, я просто не могу уловитьпо какой-то причине.
В приведенном ниже коде методы, используемые с моей ViewModel (), просто для обеспечения доступа к локальным настройкам, где я храню последний использованный идентификатор устройства, и все работает нормально, когда мое приложение имеет эксклюзивный контрольвеб-камеры.
Итак, мой вопрос: как правильно определить, когда другое приложение имеет исключительный контроль над устройством захвата?
У меня есть переменная класса приватной страницы для объекта MediaCapture:
private:
Windows::Media::Capture::MediaCapture m_mediaCapture;
Предварительный просмотр камеры начинается при переходе на страницу:
void VideoPage::OnNavigatedTo(NavigationEventArgs /*e*/) {
StartPreviewAsync();
}
StartPreviewAsync () определяется какэто:
Windows::Foundation::IAsyncAction VideoPage::StartPreviewAsync() {
// if we have a previously used device, then we should check if it's valid and use it
if (!ViewModel().hasDeviceID()) {
// device picker to choose camera
DevicePicker picker;
// create a filter that only looks for video capture devices
picker.Filter().SupportedDeviceClasses().Append(DeviceClass::VideoCapture);
// show the picker below the button that opens it and get the chosen device
DeviceInformation device = co_await picker.PickSingleDeviceAsync({ 0,0,100,100 });
// the user can cancel the dialog before picking something
if (!device)
return;
// store the device ID
ViewModel().deviceID(device.Id());
// store the device name
ViewModel().deviceName(device.Name());
}
// settings for the media capture object (such as which camera to use)
MediaCaptureInitializationSettings settings;
// add the chosen device to the settings so we initialize on that camera
settings.VideoDeviceId(ViewModel().deviceID());
try {
// initialize the mediacapture object using the chosen camera
co_await m_mediaCapture.InitializeAsync(settings);
// dont let the screen go to sleep while the preview is active
m_displayRequest.RequestActive();
}
// an exception is thrown if the user does not allow access to the camera
catch (winrt::hresult_error const& ex) {
winrt::hresult hr = ex.to_abi();
if (hr == E_ACCESSDENIED) {
ContentDialog msg;
// set all the options for the dialog
msg.Title(box_value(L"Access Denied"));
msg.Content(box_value(L"This App has not been given permission to use the Camera and/or Microphone.\nPlease go to the settings in Windows for this App to allow access."));
msg.CloseButtonText(L"OK");
// Show the message dialog.
msg.ShowAsync();
}
return;
}
try {
// assign the source to the Capture Element on the XAML page
capturePreview().Source(m_mediaCapture);
co_await m_mediaCapture.StartPreviewAsync();
}
// This method should throw a FileLoadException (0x80070020) if another app has exclusive control of the capture device
catch(...) {
OutputDebugString(L"Exception Message\n");
return;
}
}