/// <summary>
        /// Start the video stream. This just prepares the stream for capture, and doesn't start collecting frames
        /// </summary>
        /// <param name="streamDesc">The description of the stream to start.</param>
        public async void Start(StreamDescription streamDesc)
        {
#if CAN_USE_UWP_TYPES
            lock (stateLock)
            {
                if (State != CameraState.Initialized)
                {
                    throw new InvalidOperationException("Start cannot be called until the camera is in the Initialized state");
                }

                State = CameraState.Starting;
            }

            Resolution = streamDesc.Resolution;
            CameraType = streamDesc.CameraType;

            StreamDescriptionInternal desc = streamDesc as StreamDescriptionInternal;

            MediaCaptureInitializationSettings initSettings = new MediaCaptureInitializationSettings()
            {
                SourceGroup          = desc.FrameSourceGroup,
                SharingMode          = MediaCaptureSharingMode.ExclusiveControl,
                MemoryPreference     = MediaCaptureMemoryPreference.Cpu,
                StreamingCaptureMode = StreamingCaptureMode.Video
            };

            // initialize the media device
            mediaCapture = new MediaCapture();

            try
            {
                await mediaCapture.InitializeAsync(initSettings);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"MediaCapture initialization failed: {ex.Message}");
                mediaCapture.Dispose();
                mediaCapture = null;
            }

            if (mediaCapture != null)
            {
                // get access to the video device controller for property settings
                videoDeviceController = mediaCapture.VideoDeviceController;

                // choose media source
                MediaFrameSource frameSource     = mediaCapture.FrameSources[desc.FrameSourceInfo.Id];
                MediaFrameFormat preferredFormat = null;

                foreach (MediaFrameFormat format in frameSource.SupportedFormats)
                {
                    if (format.VideoFormat.Width == desc.Resolution.Width && format.VideoFormat.Height == desc.Resolution.Height && Math.Abs((double)format.FrameRate.Numerator / (double)format.FrameRate.Denominator - desc.Resolution.Framerate) < epsilon)
                    {
                        preferredFormat = format;
                        break;
                    }
                }

                if (preferredFormat != null && preferredFormat != frameSource.CurrentFormat)
                {
                    await frameSource.SetFormatAsync(preferredFormat);
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine($"failed to set desired frame format");
                }

                // set up frame readercapture frame data
                frameReader = await mediaCapture.CreateFrameReaderAsync(frameSource);

                frameReader.FrameArrived += OnMediaFrameArrived;
                await frameReader.StartAsync();

                lock (stateLock)
                {
                    State = CameraState.Ready;
                    OnCameraStarted?.Invoke(this, true);
                }
            }
            else
            {
                lock (stateLock)
                {
                    // drop back to initialized when the camera doesn't initialize
                    State = CameraState.Initialized;
                    OnCameraStarted?.Invoke(this, false);
                }
            }
#else
            await Task.CompletedTask;
#endif
        }
        /// <summary>
        /// Initializes the camera
        /// </summary>
        /// <returns></returns>
        public async Task Initialize()
        {
            lock (stateLock)
            {
                State = CameraState.Initializing;
            }

#if CAN_USE_UWP_TYPES
            try
            {
                var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();

                StreamSelector = new StreamSelector();

                foreach (var sourceGroup in frameSourceGroups)
                {
                    string name = sourceGroup.DisplayName;
                    string id   = sourceGroup.Id;

                    foreach (var sourceInfo in sourceGroup.SourceInfos)
                    {
                        switch (CaptureMode)
                        {
                        case CaptureMode.Continuous:
                        case CaptureMode.SingleLowLatency:
                        {
                            if ((sourceInfo.MediaStreamType == MediaStreamType.VideoRecord || sourceInfo.MediaStreamType == MediaStreamType.VideoPreview) && sourceInfo.SourceKind == MediaFrameSourceKind.Color)
                            {
                                foreach (var setting in sourceInfo.VideoProfileMediaDescription)
                                {
                                    StreamDescriptionInternal desc = new StreamDescriptionInternal()
                                    {
                                        SourceName = sourceInfo.DeviceInformation.Name,
                                        SourceId   = sourceInfo.Id,
                                        Resolution = new CameraResolution()
                                        {
                                            Width = setting.Width, Height = setting.Height, Framerate = setting.FrameRate
                                        },
                                        FrameSourceInfo  = sourceInfo,
                                        FrameSourceGroup = sourceGroup,
                                        CameraType       = GetCameraType(sourceInfo.SourceKind)
                                    };

                                    StreamSelector.AddStream(desc);
                                }
                            }

                            break;
                        }

                        case CaptureMode.Single:
                        {
                            if (sourceInfo.MediaStreamType == MediaStreamType.Photo && sourceInfo.SourceKind == MediaFrameSourceKind.Color)
                            {
                                foreach (var setting in sourceInfo.VideoProfileMediaDescription)
                                {
                                    StreamDescriptionInternal desc = new StreamDescriptionInternal()
                                    {
                                        SourceName = sourceInfo.DeviceInformation.Name,
                                        SourceId   = sourceInfo.Id,
                                        Resolution = new CameraResolution()
                                        {
                                            Width = setting.Width, Height = setting.Height, Framerate = setting.FrameRate
                                        },
                                        FrameSourceInfo  = sourceInfo,
                                        FrameSourceGroup = sourceGroup,
                                        CameraType       = GetCameraType(sourceInfo.SourceKind)
                                    };

                                    StreamSelector.AddStream(desc);
                                }
                            }

                            break;
                        }
                        }
                    }
                }

                lock (stateLock)
                {
                    State = CameraState.Initialized;
                    OnCameraInitialized?.Invoke(this, true);
                }
            }
            catch
            {
                OnCameraInitialized?.Invoke(this, false);
            }
#else
            await Task.CompletedTask;
#endif
        }