WP8 AudioVideoCaptureDevice and PreviewBuffer

Apr 9, 2013 at 11:38 PM
Hi Michael,

Currently, I am working on an upgrade from a WP7 app where I use barcode scanning.
As the flash is not controllable enough on the Microsoft.Devices.PhotoCamera object,
I want to try using the AudioVideoCaptureDevice. This device includes the VideoTorch, so flash can be on constantly in stead of flashing when trying to focus.
I want to get an image from the previewbuffer by using this code:
Windows.Foundation.Size res = AudioVideoCaptureDevice.GetAvailablePreviewResolutions(CameraSensorLocation.Back).First();
this.CaptureDevice = await AudioVideoCaptureDevice.OpenForVideoOnlyAsync(CameraSensorLocation.Back, res);
this.CaptureDevice.PreviewFrameAvailable+=CaptureDevice_PreviewFramAvailable;
...

CaptureDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
    int frameWidth = (int)this.CaptureDevice.PreviewResolution.Width;
    int frameHeight = (int)this.CaptureDevice.PreviewResolution.Height;

    int[] ARGBPx = new int[frameWidth * frameHeight];
    this.CaptureDevice.GetPreviewBufferArgb(ARGBPx);

    ????
}
So, now I have an array of integers containing the ARGB values from the preview frame.
How can I let the BarcodeReader find a barcode in this array? The Decode method has an overload where you can place a byte array with raw RGB data. Also need a RGBLuminanceSource.BitmapFormat then.

Please be so kind to advice me on this.

Michel
Coordinator
Apr 10, 2013 at 8:05 PM
The following method should work:
CaptureDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
    int frameWidth = (int)this.CaptureDevice.PreviewResolution.Width;
    int frameHeight = (int)this.CaptureDevice.PreviewResolution.Height;

    byte[] YPx = new byte[frameWidth * frameHeight];
    this.CaptureDevice.GetPreviewBufferY(YPx);

    var barcodeReader = new BarcodeReader();
    barcodeReader.Decode(YPx, frameWidth, frameHeight, RGBLuminanceSource.BitmapFormat.Gray8);
}
Apr 10, 2013 at 10:47 PM
Thank you! This works.

However, creating the barcodeReader object on every PreviewFrameAvailable event blocks the UI, as well as it's Decode method.
So, I've created the Barcodereader in the OnNavigatedTo and let a Stopwatch run to 1500 milliseconds before trying again:
Stopwatch watch = new Stopwatch();

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    GetCaptureDevice();
    watch.Start();
}
CaptureDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
    if (watch.ElapsedMilliseconds < 1500)
        return;

    watch.Stop();
    watch.Reset();

    <code to decode barcode>
    if (result != null)
    {
        // Do something with the data
    }
    else
    {
        watch.Start();
    }
}