3

I am trying to operate a flashlight app through TorchControl Class in Windows Phone application: Here is my code

private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel desiredCamera)
    {
        DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
            .FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredCamera);
        if (deviceID != null) return deviceID;
        else throw new Exception(string.Format("Camera {0} doesn't exist", desiredCamera));
    }


    async private void Button_Click(object sender, RoutedEventArgs e)
   {
       var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
       var mediaDev = new MediaCapture();
       await mediaDev.InitializeAsync(new MediaCaptureInitializationSettings
       {
           StreamingCaptureMode = StreamingCaptureMode.Video,
           PhotoCaptureSource = PhotoCaptureSource.VideoPreview,
           AudioDeviceId = String.Empty,
           VideoDeviceId = cameraID.Id
       });
       var videoDev = mediaDev.VideoDeviceController;
       var tc = videoDev.TorchControl;
       if (tc.Supported)         
           tc.Enabled = true;
       mediaDev.Dispose();          
   }

But the problem is that the app crashes everytime i click on the button second time. I have been told to use the mediaDev.Dispose() method but it is also not working. Here's the exception:

A first chance exception of type 'System.Exception' occurred in mscorlib.ni.dll WinRT information: The text associated with this error code could not be found.

  • This is showing while the text in "initializeasync" is highlighted
Cœur
  • 37,241
  • 25
  • 195
  • 267
Prajjwal
  • 49
  • 2
  • 10

2 Answers2

2

MediaCapture will throw exception when it is re-initialized. To solve this issue, Just make sure you do not initialize MediaCapture twice when you navigate back to Camera page, or when you click the camera button.

    MediaCapture mediacapture = new MediaCapture();
    bool initialized;
    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        if (initialized == false)
        {
            var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
            await mediacapture.InitializeAsync(new MediaCaptureInitializationSettings
            {
                StreamingCaptureMode = StreamingCaptureMode.Video,
                PhotoCaptureSource = PhotoCaptureSource.Photo,
                AudioDeviceId = string.Empty,
                VideoDeviceId = cameraID.Id
            });
        }
        //Selecting Maximum resolution for Video Preview
        var maxPreviewResolution = mediacapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview).Aggregate((i1, i2) => (i1 as VideoEncodingProperties).Height > (i2 as VideoEncodingProperties).Height ? i1 : i2);
        //Selecting 4rd resolution setting
        var selectedPhotoResolution = mediacapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).ElementAt(3);
        await mediacapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, selectedPhotoResolution);
        await mediacapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, maxPreviewResolution);
        // in my .xaml <CaptureElement Name="viewfinder" />
        viewfinder.Source = mediacapture;
        mediacapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
        await mediacapture.StartPreviewAsync(); 
        initialized = true;
    }

Also, make sure the camera stops previewing before you navigate to other page, or before camera starts preview again. There's no need to dispose MediaCapture.

    private async void GoBack_Click(object sender, RoutedEventArgs e)
    {     
        await mediacapture.StopPreviewAsync();
        this.Frame.Navigate(typeof(MainPage));
        //Not needed
        //mediacapture.Dispose();
    }

GetCameraID method credit to Romasz's blog. http://www.romasz.net/how-to-take-a-photo-in-windows-runtime/

Amjay
  • 81
  • 6
1

This issue may be related to multithreading: using the defaults (ie not changing the SynchronizationContext) calls to await will continue methods on another thread, something which is not always supported by graphics and media libraries (I have firsthand experience with SFML, WPF, and AutoCAD getting very crash-happy, to name a few). While the presence of an InitializeAsync method indicates otherwise, make sure disposal doesn't need to happen on the main thread or such.

David
  • 10,458
  • 1
  • 28
  • 40