Path: blob/master/samples/winrt/ImageManipulations/AdvancedCapture.xaml.cpp
16337 views
//*********************************************************1//2// Copyright (c) Microsoft. All rights reserved.3// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF4// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY5// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR6// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.7//8//*********************************************************910//11// AdvancedCapture.xaml.cpp12// Implementation of the AdvancedCapture class13//1415#include "pch.h"16#include "AdvancedCapture.xaml.h"1718using namespace SDKSample::MediaCapture;1920using namespace Windows::UI::Xaml;21using namespace Windows::UI::Xaml::Navigation;22using namespace Windows::UI::Xaml::Data;23using namespace Windows::System;24using namespace Windows::Foundation;25using namespace Windows::Foundation::Collections;26using namespace Platform;27using namespace Windows::UI;28using namespace Windows::UI::Core;29using namespace Windows::UI::Xaml;30using namespace Windows::UI::Xaml::Controls;31using namespace Windows::UI::Xaml::Data;32using namespace Windows::UI::Xaml::Media;33using namespace Windows::Storage;34using namespace Windows::Media::MediaProperties;35using namespace Windows::Storage::Streams;36using namespace Windows::System;37using namespace Windows::UI::Xaml::Media::Imaging;38using namespace Windows::Devices::Enumeration;3940ref class ReencodeState sealed41{42public:43ReencodeState()44{45}4647virtual ~ReencodeState()48{49if (InputStream != nullptr)50{51delete InputStream;52}53if (OutputStream != nullptr)54{55delete OutputStream;56}57}5859internal:60Windows::Storage::Streams::IRandomAccessStream ^InputStream;61Windows::Storage::Streams::IRandomAccessStream ^OutputStream;62Windows::Storage::StorageFile ^PhotoStorage;63Windows::Graphics::Imaging::BitmapDecoder ^Decoder;64Windows::Graphics::Imaging::BitmapEncoder ^Encoder;65};6667AdvancedCapture::AdvancedCapture()68{69InitializeComponent();70ScenarioInit();71}7273/// <summary>74/// Invoked when this page is about to be displayed in a Frame.75/// </summary>76/// <param name="e">Event data that describes how this page was reached. The Parameter77/// property is typically used to configure the page.</param>78void AdvancedCapture::OnNavigatedTo(NavigationEventArgs^ e)79{80// A pointer back to the main page. This is needed if you want to call methods in MainPage such81// as NotifyUser()82rootPage = MainPage::Current;8384m_orientationChangedEventToken = Windows::Graphics::Display::DisplayProperties::OrientationChanged += ref new Windows::Graphics::Display::DisplayPropertiesEventHandler(this, &AdvancedCapture::DisplayProperties_OrientationChanged);85}8687void AdvancedCapture::OnNavigatedFrom(NavigationEventArgs^ e)88{89Windows::Media::MediaControl::SoundLevelChanged -= m_eventRegistrationToken;90Windows::Graphics::Display::DisplayProperties::OrientationChanged -= m_orientationChangedEventToken;91}9293void AdvancedCapture::ScenarioInit()94{95rootPage = MainPage::Current;96btnStartDevice2->IsEnabled = true;97btnStartPreview2->IsEnabled = false;98m_bRecording = false;99m_bPreviewing = false;100m_bEffectAdded = false;101previewElement2->Source = nullptr;102ShowStatusMessage("");103EffectTypeCombo->IsEnabled = false;104previewCanvas2->Visibility = Windows::UI::Xaml::Visibility::Collapsed;105EnumerateWebcamsAsync();106m_bSuspended = false;107}108109void AdvancedCapture::ScenarioReset()110{111previewCanvas2->Visibility = Windows::UI::Xaml::Visibility::Collapsed;112ScenarioInit();113}114115void AdvancedCapture::Failed(Windows::Media::Capture::MediaCapture ^currentCaptureObject, Windows::Media::Capture::MediaCaptureFailedEventArgs^ currentFailure)116{117String ^message = "Fatal error" + currentFailure->Message;118create_task(Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High,119ref new Windows::UI::Core::DispatchedHandler([this, message]()120{121ShowStatusMessage(message);122})));123}124125void AdvancedCapture::btnStartDevice_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)126{127try128{129EnableButton(false, "StartDevice");130ShowStatusMessage("Starting device");131auto mediaCapture = ref new Windows::Media::Capture::MediaCapture();132m_mediaCaptureMgr = mediaCapture;133auto settings = ref new Windows::Media::Capture::MediaCaptureInitializationSettings();134auto chosenDevInfo = m_devInfoCollection->GetAt(EnumedDeviceList2->SelectedIndex);135settings->VideoDeviceId = chosenDevInfo->Id;136if (chosenDevInfo->EnclosureLocation != nullptr && chosenDevInfo->EnclosureLocation->Panel == Windows::Devices::Enumeration::Panel::Back)137{138m_bRotateVideoOnOrientationChange = true;139m_bReversePreviewRotation = false;140}141else if (chosenDevInfo->EnclosureLocation != nullptr && chosenDevInfo->EnclosureLocation->Panel == Windows::Devices::Enumeration::Panel::Front)142{143m_bRotateVideoOnOrientationChange = true;144m_bReversePreviewRotation = true;145}146else147{148m_bRotateVideoOnOrientationChange = false;149}150151create_task(mediaCapture->InitializeAsync(settings)).then([this](task<void> initTask)152{153try154{155initTask.get();156157auto mediaCapture = m_mediaCaptureMgr.Get();158159DisplayProperties_OrientationChanged(nullptr);160161EnableButton(true, "StartPreview");162EnableButton(true, "StartStopRecord");163EnableButton(true, "TakePhoto");164ShowStatusMessage("Device initialized successful");165EffectTypeCombo->IsEnabled = true;166mediaCapture->Failed += ref new Windows::Media::Capture::MediaCaptureFailedEventHandler(this, &AdvancedCapture::Failed);167}168catch (Exception ^ e)169{170ShowExceptionMessage(e);171}172});173}174catch (Platform::Exception^ e)175{176ShowExceptionMessage(e);177}178}179180void AdvancedCapture::btnStartPreview_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)181{182m_bPreviewing = false;183try184{185ShowStatusMessage("Starting preview");186EnableButton(false, "StartPreview");187188auto mediaCapture = m_mediaCaptureMgr.Get();189previewCanvas2->Visibility = Windows::UI::Xaml::Visibility::Visible;190previewElement2->Source = mediaCapture;191create_task(mediaCapture->StartPreviewAsync()).then([this](task<void> previewTask)192{193try194{195previewTask.get();196m_bPreviewing = true;197ShowStatusMessage("Start preview successful");198}199catch (Exception ^e)200{201ShowExceptionMessage(e);202}203});204}205catch (Platform::Exception^ e)206{207m_bPreviewing = false;208previewElement2->Source = nullptr;209EnableButton(true, "StartPreview");210ShowExceptionMessage(e);211}212}213214void AdvancedCapture::lstEnumedDevices_SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e)215{216if ( m_bPreviewing )217{218create_task(m_mediaCaptureMgr->StopPreviewAsync()).then([this](task<void> previewTask)219{220try221{222previewTask.get();223m_bPreviewing = false;224}225catch (Exception ^e)226{227ShowExceptionMessage(e);228}229});230}231232btnStartDevice2->IsEnabled = true;233btnStartPreview2->IsEnabled = false;234m_bRecording = false;235previewElement2->Source = nullptr;236EffectTypeCombo->IsEnabled = false;237m_bEffectAdded = false;238m_bEffectAddedToRecord = false;239m_bEffectAddedToPhoto = false;240ShowStatusMessage("");241}242243void AdvancedCapture::EnumerateWebcamsAsync()244{245try246{247ShowStatusMessage("Enumerating Webcams...");248m_devInfoCollection = nullptr;249250EnumedDeviceList2->Items->Clear();251252task<DeviceInformationCollection^>(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture)).then([this](task<DeviceInformationCollection^> findTask)253{254try255{256m_devInfoCollection = findTask.get();257if (m_devInfoCollection == nullptr || m_devInfoCollection->Size == 0)258{259ShowStatusMessage("No WebCams found.");260}261else262{263for(unsigned int i = 0; i < m_devInfoCollection->Size; i++)264{265auto devInfo = m_devInfoCollection->GetAt(i);266EnumedDeviceList2->Items->Append(devInfo->Name);267}268EnumedDeviceList2->SelectedIndex = 0;269ShowStatusMessage("Enumerating Webcams completed successfully.");270btnStartDevice2->IsEnabled = true;271}272}273catch (Exception ^e)274{275ShowExceptionMessage(e);276}277});278}279catch (Platform::Exception^ e)280{281ShowExceptionMessage(e);282}283}284285void AdvancedCapture::AddEffectToImageStream()286{287auto mediaCapture = m_mediaCaptureMgr.Get();288Windows::Media::Capture::VideoDeviceCharacteristic charecteristic = mediaCapture->MediaCaptureSettings->VideoDeviceCharacteristic;289290if((charecteristic != Windows::Media::Capture::VideoDeviceCharacteristic::AllStreamsIdentical) &&291(charecteristic != Windows::Media::Capture::VideoDeviceCharacteristic::PreviewPhotoStreamsIdentical) &&292(charecteristic != Windows::Media::Capture::VideoDeviceCharacteristic::RecordPhotoStreamsIdentical))293{294Windows::Media::MediaProperties::IMediaEncodingProperties ^props = mediaCapture->VideoDeviceController->GetMediaStreamProperties(Windows::Media::Capture::MediaStreamType::Photo);295if(props->Type->Equals("Image"))296{297//Switch to a video media type instead since we can't add an effect to an image media type298Windows::Foundation::Collections::IVectorView<Windows::Media::MediaProperties::IMediaEncodingProperties^>^ supportedPropsList = mediaCapture->VideoDeviceController->GetAvailableMediaStreamProperties(Windows::Media::Capture::MediaStreamType::Photo);299{300unsigned int i = 0;301while (i < supportedPropsList->Size)302{303Windows::Media::MediaProperties::IMediaEncodingProperties^ props = supportedPropsList->GetAt(i);304305String^ s = props->Type;306if(props->Type->Equals("Video"))307{308task<void>(mediaCapture->VideoDeviceController->SetMediaStreamPropertiesAsync(Windows::Media::Capture::MediaStreamType::Photo,props)).then([this](task<void> changeTypeTask)309{310try311{312changeTypeTask.get();313ShowStatusMessage("Change type on photo stream successful");314//Now add the effect on the image pin315task<void>(m_mediaCaptureMgr->AddEffectAsync(Windows::Media::Capture::MediaStreamType::Photo,"OcvTransform.OcvImageManipulations", nullptr)).then([this](task<void> effectTask3)316{317try318{319effectTask3.get();320m_bEffectAddedToPhoto = true;321ShowStatusMessage("Adding effect to photo stream successful");322EffectTypeCombo->IsEnabled = true;323324}325catch(Exception ^e)326{327ShowExceptionMessage(e);328EffectTypeCombo->IsEnabled = true;329}330});331332}333catch(Exception ^e)334{335ShowExceptionMessage(e);336EffectTypeCombo->IsEnabled = true;337}338339});340break;341342}343i++;344}345}346}347else348{349//Add the effect to the image pin if the type is already "Video"350task<void>(mediaCapture->AddEffectAsync(Windows::Media::Capture::MediaStreamType::Photo,"OcvTransform.OcvImageManipulations", nullptr)).then([this](task<void> effectTask3)351{352try353{354effectTask3.get();355m_bEffectAddedToPhoto = true;356ShowStatusMessage("Adding effect to photo stream successful");357EffectTypeCombo->IsEnabled = true;358359}360catch(Exception ^e)361{362ShowExceptionMessage(e);363EffectTypeCombo->IsEnabled = true;364}365});366}367}368}369370void AdvancedCapture::ShowStatusMessage(Platform::String^ text)371{372rootPage->NotifyUser(text, NotifyType::StatusMessage);373}374375void AdvancedCapture::ShowExceptionMessage(Platform::Exception^ ex)376{377rootPage->NotifyUser(ex->Message, NotifyType::ErrorMessage);378}379380void AdvancedCapture::EnableButton(bool enabled, String^ name)381{382if (name->Equals("StartDevice"))383{384btnStartDevice2->IsEnabled = enabled;385}386else if (name->Equals("StartPreview"))387{388btnStartPreview2->IsEnabled = enabled;389}390}391392task<Windows::Storage::StorageFile^> AdvancedCapture::ReencodePhotoAsync(393Windows::Storage::StorageFile ^tempStorageFile,394Windows::Storage::FileProperties::PhotoOrientation photoRotation)395{396ReencodeState ^state = ref new ReencodeState();397398return create_task(tempStorageFile->OpenAsync(Windows::Storage::FileAccessMode::Read)).then([state](Windows::Storage::Streams::IRandomAccessStream ^stream)399{400state->InputStream = stream;401return Windows::Graphics::Imaging::BitmapDecoder::CreateAsync(state->InputStream);402}).then([state](Windows::Graphics::Imaging::BitmapDecoder ^decoder)403{404state->Decoder = decoder;405return Windows::Storage::KnownFolders::PicturesLibrary->CreateFileAsync(PHOTO_FILE_NAME, Windows::Storage::CreationCollisionOption::GenerateUniqueName);406}).then([state](Windows::Storage::StorageFile ^storageFile)407{408state->PhotoStorage = storageFile;409return state->PhotoStorage->OpenAsync(Windows::Storage::FileAccessMode::ReadWrite);410}).then([state](Windows::Storage::Streams::IRandomAccessStream ^stream)411{412state->OutputStream = stream;413state->OutputStream->Size = 0;414return Windows::Graphics::Imaging::BitmapEncoder::CreateForTranscodingAsync(state->OutputStream, state->Decoder);415}).then([state, photoRotation](Windows::Graphics::Imaging::BitmapEncoder ^encoder)416{417state->Encoder = encoder;418auto properties = ref new Windows::Graphics::Imaging::BitmapPropertySet();419properties->Insert("System.Photo.Orientation",420ref new Windows::Graphics::Imaging::BitmapTypedValue((unsigned short)photoRotation, Windows::Foundation::PropertyType::UInt16));421return create_task(state->Encoder->BitmapProperties->SetPropertiesAsync(properties));422}).then([state]()423{424return state->Encoder->FlushAsync();425}).then([tempStorageFile, state](task<void> previousTask)426{427auto result = state->PhotoStorage;428delete state;429430tempStorageFile->DeleteAsync(Windows::Storage::StorageDeleteOption::PermanentDelete);431432previousTask.get();433434return result;435});436}437438Windows::Storage::FileProperties::PhotoOrientation AdvancedCapture::GetCurrentPhotoRotation()439{440bool counterclockwiseRotation = m_bReversePreviewRotation;441442if (m_bRotateVideoOnOrientationChange)443{444return PhotoRotationLookup(Windows::Graphics::Display::DisplayProperties::CurrentOrientation, counterclockwiseRotation);445}446else447{448return Windows::Storage::FileProperties::PhotoOrientation::Normal;449}450}451452void AdvancedCapture::PrepareForVideoRecording()453{454Windows::Media::Capture::MediaCapture ^mediaCapture = m_mediaCaptureMgr.Get();455if (mediaCapture == nullptr)456{457return;458}459460bool counterclockwiseRotation = m_bReversePreviewRotation;461462if (m_bRotateVideoOnOrientationChange)463{464mediaCapture->SetRecordRotation(VideoRotationLookup(Windows::Graphics::Display::DisplayProperties::CurrentOrientation, counterclockwiseRotation));465}466else467{468mediaCapture->SetRecordRotation(Windows::Media::Capture::VideoRotation::None);469}470}471472void AdvancedCapture::DisplayProperties_OrientationChanged(Platform::Object^ sender)473{474Windows::Media::Capture::MediaCapture ^mediaCapture = m_mediaCaptureMgr.Get();475if (mediaCapture == nullptr)476{477return;478}479480bool previewMirroring = mediaCapture->GetPreviewMirroring();481bool counterclockwiseRotation = (previewMirroring && !m_bReversePreviewRotation) ||482(!previewMirroring && m_bReversePreviewRotation);483484if (m_bRotateVideoOnOrientationChange)485{486mediaCapture->SetPreviewRotation(VideoRotationLookup(Windows::Graphics::Display::DisplayProperties::CurrentOrientation, counterclockwiseRotation));487}488else489{490mediaCapture->SetPreviewRotation(Windows::Media::Capture::VideoRotation::None);491}492}493494Windows::Storage::FileProperties::PhotoOrientation AdvancedCapture::PhotoRotationLookup(495Windows::Graphics::Display::DisplayOrientations displayOrientation, bool counterclockwise)496{497switch (displayOrientation)498{499case Windows::Graphics::Display::DisplayOrientations::Landscape:500return Windows::Storage::FileProperties::PhotoOrientation::Normal;501502case Windows::Graphics::Display::DisplayOrientations::Portrait:503return (counterclockwise) ? Windows::Storage::FileProperties::PhotoOrientation::Rotate270:504Windows::Storage::FileProperties::PhotoOrientation::Rotate90;505506case Windows::Graphics::Display::DisplayOrientations::LandscapeFlipped:507return Windows::Storage::FileProperties::PhotoOrientation::Rotate180;508509case Windows::Graphics::Display::DisplayOrientations::PortraitFlipped:510return (counterclockwise) ? Windows::Storage::FileProperties::PhotoOrientation::Rotate90 :511Windows::Storage::FileProperties::PhotoOrientation::Rotate270;512513default:514return Windows::Storage::FileProperties::PhotoOrientation::Unspecified;515}516}517518Windows::Media::Capture::VideoRotation AdvancedCapture::VideoRotationLookup(519Windows::Graphics::Display::DisplayOrientations displayOrientation, bool counterclockwise)520{521switch (displayOrientation)522{523case Windows::Graphics::Display::DisplayOrientations::Landscape:524return Windows::Media::Capture::VideoRotation::None;525526case Windows::Graphics::Display::DisplayOrientations::Portrait:527return (counterclockwise) ? Windows::Media::Capture::VideoRotation::Clockwise270Degrees :528Windows::Media::Capture::VideoRotation::Clockwise90Degrees;529530case Windows::Graphics::Display::DisplayOrientations::LandscapeFlipped:531return Windows::Media::Capture::VideoRotation::Clockwise180Degrees;532533case Windows::Graphics::Display::DisplayOrientations::PortraitFlipped:534return (counterclockwise) ? Windows::Media::Capture::VideoRotation::Clockwise90Degrees:535Windows::Media::Capture::VideoRotation::Clockwise270Degrees ;536537default:538return Windows::Media::Capture::VideoRotation::None;539}540}541542void SDKSample::MediaCapture::AdvancedCapture::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)543{544try545{546create_task(m_mediaCaptureMgr->ClearEffectsAsync(Windows::Media::Capture::MediaStreamType::VideoPreview)).then([this](task<void> cleanTask)547{548m_bEffectAdded = true;549int index = EffectTypeCombo->SelectedIndex;550PropertySet^ props = ref new PropertySet();551props->Insert(L"{698649BE-8EAE-4551-A4CB-3EC98FBD3D86}", index);552create_task(m_mediaCaptureMgr->AddEffectAsync(Windows::Media::Capture::MediaStreamType::VideoPreview,"OcvTransform.OcvImageManipulations", props)).then([this](task<void> effectTask)553{554try555{556effectTask.get();557558auto mediaCapture = m_mediaCaptureMgr.Get();559Windows::Media::Capture::VideoDeviceCharacteristic charecteristic = mediaCapture->MediaCaptureSettings->VideoDeviceCharacteristic;560561ShowStatusMessage("Add effect successful to preview stream successful");562if((charecteristic != Windows::Media::Capture::VideoDeviceCharacteristic::AllStreamsIdentical) &&563(charecteristic != Windows::Media::Capture::VideoDeviceCharacteristic::PreviewRecordStreamsIdentical))564{565Windows::Media::MediaProperties::IMediaEncodingProperties ^props = mediaCapture->VideoDeviceController->GetMediaStreamProperties(Windows::Media::Capture::MediaStreamType::VideoRecord);566Windows::Media::MediaProperties::VideoEncodingProperties ^videoEncodingProperties = static_cast<Windows::Media::MediaProperties::VideoEncodingProperties ^>(props);567if(!videoEncodingProperties->Subtype->Equals("H264")) //Can't add an effect to an H264 stream568{569task<void>(mediaCapture->AddEffectAsync(Windows::Media::Capture::MediaStreamType::VideoRecord,"OcvTransform.OcvImageManipulations", nullptr)).then([this](task<void> effectTask2)570{571try572{573effectTask2.get();574ShowStatusMessage("Add effect successful to record stream successful");575m_bEffectAddedToRecord = true;576AddEffectToImageStream();577EffectTypeCombo->IsEnabled = true;578}579catch(Exception ^e)580{581ShowExceptionMessage(e);582EffectTypeCombo->IsEnabled = true;583}584});585}586else587{588AddEffectToImageStream();589EffectTypeCombo->IsEnabled = true;590}591592}593else594{595AddEffectToImageStream();596EffectTypeCombo->IsEnabled = true;597}598}599catch (Exception ^e)600{601ShowExceptionMessage(e);602EffectTypeCombo->IsEnabled = true;603}604});605});606}607catch (Platform::Exception ^e)608{609ShowExceptionMessage(e);610EffectTypeCombo->IsEnabled = true;611}612}613614615