Beispiel #1
0
        public void StartScanning(MobileBarcodeScanningOptions options, Action <Result> callback)
        {
            this.callback = callback;
            this.options  = options;

            lastPreviewAnalysis = DateTime.UtcNow.AddMilliseconds(options.InitialDelayBeforeAnalyzingFrames);
            isAnalyzing         = true;

            Console.WriteLine("StartScanning");

            CheckPermissions();

            var perf = PerformanceCounter.Start();

            GetExclusiveAccess();

            try
            {
                var version = Build.VERSION.SdkInt;

                if (version >= BuildVersionCodes.Gingerbread)
                {
                    Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Checking Number of cameras...");

                    var numCameras = Android.Hardware.Camera.NumberOfCameras;
                    var camInfo    = new Android.Hardware.Camera.CameraInfo();
                    var found      = false;
                    Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Found " + numCameras + " cameras...");

                    var whichCamera = CameraFacing.Back;

                    if (options.UseFrontCameraIfAvailable.HasValue && options.UseFrontCameraIfAvailable.Value)
                    {
                        whichCamera = CameraFacing.Front;
                    }

                    for (int i = 0; i < numCameras; i++)
                    {
                        Android.Hardware.Camera.GetCameraInfo(i, camInfo);
                        if (camInfo.Facing == whichCamera)
                        {
                            Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Found " + whichCamera + " Camera, opening...");
                            camera = Android.Hardware.Camera.Open(i);
                            found  = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Finding " + whichCamera + " camera failed, opening camera 0...");
                        camera = Android.Hardware.Camera.Open(0);
                    }
                }
                else
                {
                    camera = Android.Hardware.Camera.Open();
                }

                if (camera == null)
                {
                    Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Camera is null :(");
                }

                camera.SetPreviewCallback(this);
            } catch (Exception ex) {
                ShutdownCamera();

                Console.WriteLine("Setup Error: " + ex);
            }

            PerformanceCounter.Stop(perf, "SurfaceCreated took {0}ms");
        }
Beispiel #2
0
        public void SurfaceChanged(ISurfaceHolder holder, Format format, int w, int h)
        {
            if (camera == null)
            {
                return;
            }

            var perf = PerformanceCounter.Start();

            var parameters = camera.GetParameters();

            parameters.PreviewFormat = ImageFormatType.Nv21;


            var availableResolutions = new List <CameraResolution> ();

            foreach (var sps in parameters.SupportedPreviewSizes)
            {
                availableResolutions.Add(new CameraResolution {
                    Width  = sps.Width,
                    Height = sps.Height
                });
            }

            // Try and get a desired resolution from the options selector
            var resolution = options.GetResolution(availableResolutions);

            // If the user did not specify a resolution, let's try and find a suitable one
            if (resolution == null)
            {
                // Loop through all supported sizes
                foreach (var sps in parameters.SupportedPreviewSizes)
                {
                    // Find one that's >= 640x360 but <= 1000x1000
                    // This will likely pick the *smallest* size in that range, which should be fine
                    if (sps.Width >= 640 && sps.Width <= 1000 && sps.Height >= 360 && sps.Height <= 1000)
                    {
                        resolution = new CameraResolution {
                            Width  = sps.Width,
                            Height = sps.Height
                        };
                        break;
                    }
                }
            }

            // Google Glass requires this fix to display the camera output correctly
            if (Build.Model.Contains("Glass"))
            {
                resolution = new CameraResolution {
                    Width  = 640,
                    Height = 360
                };
                // Glass requires 30fps
                parameters.SetPreviewFpsRange(30000, 30000);
            }

            // Hopefully a resolution was selected at some point
            if (resolution != null)
            {
                Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Selected Resolution: " + resolution.Width + "x" + resolution.Height);
                parameters.SetPreviewSize(resolution.Width, resolution.Height);
            }

            camera.SetParameters(parameters);

            SetCameraDisplayOrientation(this.activity);

            camera.SetPreviewDisplay(holder);
            camera.StartPreview();

            //cameraResolution = new Size(parameters.PreviewSize.Width, parameters.PreviewSize.Height);

            PerformanceCounter.Stop(perf, "SurfaceChanged took {0}ms");

            AutoFocus();
        }
Beispiel #3
0
        public void OnPreviewFrame(byte [] bytes, Android.Hardware.Camera camera)
        {
            if (!isAnalyzing)
            {
                return;
            }

            //Check and see if we're still processing a previous frame
            if (processingTask != null && !processingTask.IsCompleted)
            {
                return;
            }

            if ((DateTime.UtcNow - lastPreviewAnalysis).TotalMilliseconds < options.DelayBetweenAnalyzingFrames)
            {
                return;
            }

            // Delay a minimum between scans
            if (wasScanned && ((DateTime.UtcNow - lastPreviewAnalysis).TotalMilliseconds < options.DelayBetweenContinuousScans))
            {
                return;
            }

            wasScanned = false;

            var cameraParameters = camera.GetParameters();
            var width            = cameraParameters.PreviewSize.Width;
            var height           = cameraParameters.PreviewSize.Height;

            //var img = new YuvImage(bytes, ImageFormatType.Nv21, cameraParameters.PreviewSize.Width, cameraParameters.PreviewSize.Height, null);
            lastPreviewAnalysis = DateTime.UtcNow;

            processingTask = Task.Factory.StartNew(() =>
            {
                try
                {
                    if (barcodeReader == null)
                    {
                        barcodeReader = new BarcodeReader(null, null, null, (p, w, h, f) =>
                                                          new PlanarYUVLuminanceSource(p, w, h, 0, 0, w, h, false));
                        //new PlanarYUVLuminanceSource(p, w, h, dataRect.Left, dataRect.Top, dataRect.Width(), dataRect.Height(), false))

                        if (this.options.TryHarder.HasValue)
                        {
                            barcodeReader.Options.TryHarder = this.options.TryHarder.Value;
                        }
                        if (this.options.PureBarcode.HasValue)
                        {
                            barcodeReader.Options.PureBarcode = this.options.PureBarcode.Value;
                        }
                        if (!string.IsNullOrEmpty(this.options.CharacterSet))
                        {
                            barcodeReader.Options.CharacterSet = this.options.CharacterSet;
                        }
                        if (this.options.TryInverted.HasValue)
                        {
                            barcodeReader.TryInverted = this.options.TryInverted.Value;
                        }

                        if (this.options.PossibleFormats != null && this.options.PossibleFormats.Count > 0)
                        {
                            barcodeReader.Options.PossibleFormats = new List <BarcodeFormat> ();

                            foreach (var pf in this.options.PossibleFormats)
                            {
                                barcodeReader.Options.PossibleFormats.Add(pf);
                            }
                        }
                    }

                    bool rotate   = false;
                    int newWidth  = width;
                    int newHeight = height;

                    var cDegrees = getCameraDisplayOrientation(this.activity);

                    if (cDegrees == 90 || cDegrees == 270)
                    {
                        rotate    = true;
                        newWidth  = height;
                        newHeight = width;
                    }

                    var start = PerformanceCounter.Start();

                    if (rotate)
                    {
                        bytes = rotateCounterClockwise(bytes, width, height);
                    }

                    var result = barcodeReader.Decode(bytes, newWidth, newHeight, RGBLuminanceSource.BitmapFormat.Unknown);

                    PerformanceCounter.Stop(start, "Decode Time: {0} ms (width: " + width + ", height: " + height + ", degrees: " + cDegrees + ", rotate: " + rotate + ")");

                    if (result == null || string.IsNullOrEmpty(result.Text))
                    {
                        return;
                    }

                    Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "Barcode Found: " + result.Text);

                    wasScanned = true;
                    callback(result);
                }
                catch (ReaderException)
                {
                    Android.Util.Log.Debug(MobileBarcodeScanner.TAG, "No barcode Found");
                    // ignore this exception; it happens every time there is a failed scan
                }
                catch (Exception)
                {
                    // TODO: this one is unexpected.. log or otherwise handle it
                    throw;
                }
            });
        }
        public void SurfaceCreated(ISurfaceHolder holder)
        {
            CheckPermissions();

            var perf = PerformanceCounter.Start();

            try
            {
                var version = Android.OS.Build.VERSION.SdkInt;

                if (version >= BuildVersionCodes.Gingerbread)
                {
                    Android.Util.Log.Debug("ZXing.Net.Mobile", "Checking Number of cameras...");

                    var numCameras = Android.Hardware.Camera.NumberOfCameras;
                    var camInfo    = new Android.Hardware.Camera.CameraInfo();
                    var found      = false;
                    Android.Util.Log.Debug("ZXing.Net.Mobile", "Found " + numCameras + " cameras...");

                    var whichCamera = CameraFacing.Back;

                    if (options.UseFrontCameraIfAvailable.HasValue && options.UseFrontCameraIfAvailable.Value)
                    {
                        whichCamera = CameraFacing.Front;
                    }

                    for (int i = 0; i < numCameras; i++)
                    {
                        Android.Hardware.Camera.GetCameraInfo(i, camInfo);
                        if (camInfo.Facing == whichCamera)
                        {
                            Android.Util.Log.Debug("ZXing.Net.Mobile", "Found " + whichCamera + " Camera, opening...");
                            camera = Android.Hardware.Camera.Open(i);
                            found  = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        Android.Util.Log.Debug("ZXing.Net.Mobile", "Finding " + whichCamera + " camera failed, opening camera 0...");
                        camera = Android.Hardware.Camera.Open(0);
                    }
                }
                else
                {
                    camera = Android.Hardware.Camera.Open();
                }
                if (camera == null)
                {
                    Android.Util.Log.Debug("ZXing.Net.Mobile", "Camera is null :(");
                }


                //camera = Android.Hardware.Camera.Open ();
                camera.SetPreviewDisplay(holder);
                camera.SetPreviewCallback(this);
            } catch (Exception ex) {
                ShutdownCamera();

                // TODO: log or otherwise handle this exception
                Console.WriteLine("Setup Error: " + ex);
                //throw;
            }

            PerformanceCounter.Stop(perf, "SurfaceCreated took {0}ms");
        }
        bool SetupCaptureSession()
        {
            var started = DateTime.UtcNow;

            var availableResolutions = new List <CameraResolution>();

            var consideredResolutions = new Dictionary <NSString, CameraResolution> {
                { AVCaptureSession.Preset352x288, new CameraResolution   {
                      Width = 352, Height = 288
                  } },
                { AVCaptureSession.PresetMedium, new CameraResolution    {
                      Width = 480, Height = 360
                  } },                                                                                                          //480x360
                { AVCaptureSession.Preset640x480, new CameraResolution   {
                      Width = 640, Height = 480
                  } },
                { AVCaptureSession.Preset1280x720, new CameraResolution  {
                      Width = 1280, Height = 720
                  } },
                { AVCaptureSession.Preset1920x1080, new CameraResolution {
                      Width = 1920, Height = 1080
                  } }
            };

            // configure the capture session for low resolution, change this if your code
            // can cope with more data or volume
            session = new AVCaptureSession()
            {
                SessionPreset = AVCaptureSession.Preset640x480
            };

            // create a device input and attach it to the session
            var devices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);

            foreach (var device in devices)
            {
                captureDevice = device;
                if (ScanningOptions.UseFrontCameraIfAvailable.HasValue &&
                    ScanningOptions.UseFrontCameraIfAvailable.Value &&
                    device.Position == AVCaptureDevicePosition.Front)
                {
                    break;                     //Front camera successfully set
                }
                else if (device.Position == AVCaptureDevicePosition.Back && (!ScanningOptions.UseFrontCameraIfAvailable.HasValue || !ScanningOptions.UseFrontCameraIfAvailable.Value))
                {
                    break;                     //Back camera succesfully set
                }
            }
            if (captureDevice == null)
            {
                Console.WriteLine("No captureDevice - this won't work on the simulator, try a physical device");
                if (overlayView != null)
                {
                    AddSubview(overlayView);
                    BringSubviewToFront(overlayView);
                }
                return(false);
            }

            CameraResolution resolution = null;

            // Find resolution
            // Go through the resolutions we can even consider
            foreach (var cr in consideredResolutions)
            {
                // Now check to make sure our selected device supports the resolution
                // so we can add it to the list to pick from
                if (captureDevice.SupportsAVCaptureSessionPreset(cr.Key))
                {
                    availableResolutions.Add(cr.Value);
                }
            }

            resolution = ScanningOptions.GetResolution(availableResolutions);

            // See if the user selected a resolution
            if (resolution != null)
            {
                // Now get the preset string from the resolution chosen
                var preset = (from c in consideredResolutions
                              where c.Value.Width == resolution.Width &&
                              c.Value.Height == resolution.Height
                              select c.Key).FirstOrDefault();

                // If we found a matching preset, let's set it on the session
                if (!string.IsNullOrEmpty(preset))
                {
                    session.SessionPreset = preset;
                }
            }

            var input = AVCaptureDeviceInput.FromDevice(captureDevice);

            if (input == null)
            {
                Console.WriteLine("No input - this won't work on the simulator, try a physical device");
                if (overlayView != null)
                {
                    AddSubview(overlayView);
                    BringSubviewToFront(overlayView);
                }
                return(false);
            }
            else
            {
                session.AddInput(input);
            }


            var startedAVPreviewLayerAlloc = PerformanceCounter.Start();

            previewLayer = new AVCaptureVideoPreviewLayer(session);

            PerformanceCounter.Stop(startedAVPreviewLayerAlloc, "Alloc AVCaptureVideoPreviewLayer took {0} ms.");

            var perf2 = PerformanceCounter.Start();

            previewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
            previewLayer.Frame        = new CGRect(0, 0, Frame.Width, Frame.Height);
            previewLayer.Position     = new CGPoint(Layer.Bounds.Width / 2, (Layer.Bounds.Height / 2));

            layerView = new UIView(new CGRect(0, 0, Frame.Width, Frame.Height));
            layerView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
            layerView.Layer.AddSublayer(previewLayer);

            AddSubview(layerView);

            ResizePreview(UIApplication.SharedApplication.StatusBarOrientation);

            if (overlayView != null)
            {
                AddSubview(overlayView);
                BringSubviewToFront(overlayView);
            }

            PerformanceCounter.Stop(perf2, "PERF: Setting up layers took {0} ms");

            var perf3 = PerformanceCounter.Start();

            session.StartRunning();

            PerformanceCounter.Stop(perf3, "PERF: session.StartRunning() took {0} ms");

            var perf4 = PerformanceCounter.Start();

            var videoSettings = NSDictionary.FromObjectAndKey(new NSNumber((int)CVPixelFormatType.CV32BGRA),
                                                              CVPixelBuffer.PixelFormatTypeKey);

            // create a VideoDataOutput and add it to the sesion
            output = new AVCaptureVideoDataOutput
            {
                WeakVideoSettings = videoSettings
            };

            // configure the output
            queue = new DispatchQueue("ZxingScannerView");             // (Guid.NewGuid().ToString());

            var barcodeReader = ScanningOptions.BuildBarcodeReader();

            outputRecorder = new OutputRecorder(this, img =>
            {
                var ls = img;

                if (!IsAnalyzing)
                {
                    return(false);
                }

                try
                {
                    var perfDecode = PerformanceCounter.Start();

                    if (shouldRotatePreviewBuffer)
                    {
                        ls = ls.rotateCounterClockwise();
                    }

                    var result = barcodeReader.Decode(ls);

                    PerformanceCounter.Stop(perfDecode, "Decode Time: {0} ms");

                    if (result != null)
                    {
                        resultCallback(result);
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DECODE FAILED: " + ex);
                }

                return(false);
            });

            output.AlwaysDiscardsLateVideoFrames = true;
            output.SetSampleBufferDelegate(outputRecorder, queue);

            PerformanceCounter.Stop(perf4, "PERF: SetupCamera Finished.  Took {0} ms.");

            session.AddOutput(output);

            var perf5 = PerformanceCounter.Start();

            if (captureDevice.LockForConfiguration(out var err))
            {
                captureDeviceOriginalConfig = new AVConfigs
                {
                    FocusMode                 = captureDevice.FocusMode,
                    ExposureMode              = captureDevice.ExposureMode,
                    WhiteBalanceMode          = captureDevice.WhiteBalanceMode,
                    AutoFocusRangeRestriction = captureDevice.AutoFocusRangeRestriction,
                };

                if (captureDevice.HasFlash)
                {
                    captureDeviceOriginalConfig.FlashMode = captureDevice.FlashMode;
                }
                if (captureDevice.HasTorch)
                {
                    captureDeviceOriginalConfig.TorchMode = captureDevice.TorchMode;
                }
                if (captureDevice.FocusPointOfInterestSupported)
                {
                    captureDeviceOriginalConfig.FocusPointOfInterest = captureDevice.FocusPointOfInterest;
                }
                if (captureDevice.ExposurePointOfInterestSupported)
                {
                    captureDeviceOriginalConfig.ExposurePointOfInterest = captureDevice.ExposurePointOfInterest;
                }

                if (ScanningOptions.DisableAutofocus)
                {
                    captureDevice.FocusMode = AVCaptureFocusMode.Locked;
                }
                else
                {
                    if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus))
                    {
                        captureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus;
                    }
                    else if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.AutoFocus))
                    {
                        captureDevice.FocusMode = AVCaptureFocusMode.AutoFocus;
                    }
                }

                if (captureDevice.IsExposureModeSupported(AVCaptureExposureMode.ContinuousAutoExposure))
                {
                    captureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure;
                }
                else if (captureDevice.IsExposureModeSupported(AVCaptureExposureMode.AutoExpose))
                {
                    captureDevice.ExposureMode = AVCaptureExposureMode.AutoExpose;
                }

                if (captureDevice.IsWhiteBalanceModeSupported(AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance))
                {
                    captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance;
                }
                else if (captureDevice.IsWhiteBalanceModeSupported(AVCaptureWhiteBalanceMode.AutoWhiteBalance))
                {
                    captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.AutoWhiteBalance;
                }

                if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0) && captureDevice.AutoFocusRangeRestrictionSupported)
                {
                    captureDevice.AutoFocusRangeRestriction = AVCaptureAutoFocusRangeRestriction.Near;
                }

                if (captureDevice.FocusPointOfInterestSupported)
                {
                    captureDevice.FocusPointOfInterest = new PointF(0.5f, 0.5f);
                }

                if (captureDevice.ExposurePointOfInterestSupported)
                {
                    captureDevice.ExposurePointOfInterest = new PointF(0.5f, 0.5f);
                }

                captureDevice.UnlockForConfiguration();
            }
            else
            {
                Console.WriteLine("Failed to Lock for Config: " + err.Description);
            }

            PerformanceCounter.Stop(perf5, "PERF: Setup Focus in {0} ms.");

            return(true);
        }
		bool SetupCaptureSession ()
		{
			// configure the capture session for low resolution, change this if your code
			// can cope with more data or volume
			session = new AVCaptureSession () {
				SessionPreset = AVCaptureSession.Preset640x480
			};

			// create a device input and attach it to the session
			//			var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
			AVCaptureDevice captureDevice = null;
			var devices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);
			foreach (var device in devices)
			{
				captureDevice = device;
				if (options.UseFrontCameraIfAvailable.HasValue &&
					options.UseFrontCameraIfAvailable.Value &&
					device.Position == AVCaptureDevicePosition.Front)

					break; //Front camera successfully set
				else if (device.Position == AVCaptureDevicePosition.Back && (!options.UseFrontCameraIfAvailable.HasValue || !options.UseFrontCameraIfAvailable.Value))
					break; //Back camera succesfully set
			}
			if (captureDevice == null){
				Console.WriteLine ("No captureDevice - this won't work on the simulator, try a physical device");
				if (overlayView != null)
				{
					this.AddSubview (overlayView);
					this.BringSubviewToFront (overlayView);
				}
				return false;
			}

			var input = AVCaptureDeviceInput.FromDevice (captureDevice);
			if (input == null){
				Console.WriteLine ("No input - this won't work on the simulator, try a physical device");
				if (overlayView != null)
				{
					this.AddSubview (overlayView);
					this.BringSubviewToFront (overlayView);
				}				
				return false;
			}
			else
				session.AddInput (input);


			foundResult = false;
			//Detect barcodes with built in avcapture stuff
			AVCaptureMetadataOutput metadataOutput = new AVCaptureMetadataOutput();

			var dg = new CaptureDelegate (metaDataObjects =>
				{
					if (foundResult)
						return;

					//Console.WriteLine("Found MetaData Objects");

					var mdo = metaDataObjects.FirstOrDefault();

					if (mdo == null)
						return;

					var readableObj = mdo as AVMetadataMachineReadableCodeObject;

					if (readableObj == null)
						return;

					foundResult = true;

					//Console.WriteLine("Barcode: " + readableObj.StringValue);

					var zxingFormat = ZXingBarcodeFormatFromAVCaptureBarcodeFormat(readableObj.Type.ToString());

					var rs = new ZXing.Result(readableObj.StringValue, null, null, zxingFormat);

					resultCallback(rs);
				});

			metadataOutput.SetDelegate (dg, DispatchQueue.MainQueue);
			session.AddOutput (metadataOutput);

			//Setup barcode formats
			if (ScanningOptions.PossibleFormats != null && ScanningOptions.PossibleFormats.Count > 0)
			{
				var formats = AVMetadataObjectType.None;

				foreach (var f in ScanningOptions.PossibleFormats)
					formats |= AVCaptureBarcodeFormatFromZXingBarcodeFormat (f);

				formats &= ~AVMetadataObjectType.None;

				metadataOutput.MetadataObjectTypes = formats;
			}
			else
				metadataOutput.MetadataObjectTypes = metadataOutput.AvailableMetadataObjectTypes;





			previewLayer = new AVCaptureVideoPreviewLayer(session);

			//Framerate set here (15 fps)
			if (previewLayer.RespondsToSelector(new Selector("connection")))
			{
				if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0))
				{
					var perf1 = PerformanceCounter.Start ();

					NSError lockForConfigErr = null;

					captureDevice.LockForConfiguration (out lockForConfigErr);
					if (lockForConfigErr == null)
					{
						captureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 10);
						captureDevice.UnlockForConfiguration ();
					}

					PerformanceCounter.Stop (perf1, "PERF: ActiveVideoMinFrameDuration Took {0} ms");
				}
				else
					previewLayer.Connection.VideoMinFrameDuration = new CMTime(1, 10);
			}

			#if __UNIFIED__
			previewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
			#else
			previewLayer.LayerVideoGravity = AVLayerVideoGravity.ResizeAspectFill;
			#endif
			previewLayer.Frame = new CGRect(0, 0, this.Frame.Width, this.Frame.Height);
			previewLayer.Position = new CGPoint(this.Layer.Bounds.Width / 2, (this.Layer.Bounds.Height / 2));

			layerView = new UIView(new CGRect(0, 0, this.Frame.Width, this.Frame.Height));
			layerView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
			layerView.Layer.AddSublayer(previewLayer);

			this.AddSubview(layerView);

			ResizePreview(UIApplication.SharedApplication.StatusBarOrientation);

			if (overlayView != null)
			{
				this.AddSubview (overlayView);
				this.BringSubviewToFront (overlayView);

				//overlayView.LayoutSubviews ();
			}

			session.StartRunning ();

			Console.WriteLine ("RUNNING!!!");



			//output.AlwaysDiscardsLateVideoFrames = true;


			Console.WriteLine("SetupCamera Finished");

			//session.AddOutput (output);
			//session.StartRunning ();


			if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus))
			{
				NSError err = null;
				if (captureDevice.LockForConfiguration(out err))
				{
					if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus))
						captureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus;
					else if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.AutoFocus))
						captureDevice.FocusMode = AVCaptureFocusMode.AutoFocus;

					if (captureDevice.IsExposureModeSupported (AVCaptureExposureMode.ContinuousAutoExposure))
						captureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure;
					else if (captureDevice.IsExposureModeSupported(AVCaptureExposureMode.AutoExpose))
						captureDevice.ExposureMode = AVCaptureExposureMode.AutoExpose;

					if (captureDevice.IsWhiteBalanceModeSupported (AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance))
						captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance;
					else if (captureDevice.IsWhiteBalanceModeSupported (AVCaptureWhiteBalanceMode.AutoWhiteBalance))
						captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.AutoWhiteBalance;

					if (UIDevice.CurrentDevice.CheckSystemVersion (7, 0) && captureDevice.AutoFocusRangeRestrictionSupported)
						captureDevice.AutoFocusRangeRestriction = AVCaptureAutoFocusRangeRestriction.Near;

					if (captureDevice.FocusPointOfInterestSupported)
						captureDevice.FocusPointOfInterest = new CGPoint(0.5f, 0.5f);

					if (captureDevice.ExposurePointOfInterestSupported)
						captureDevice.ExposurePointOfInterest = new CGPoint (0.5f, 0.5f);

					captureDevice.UnlockForConfiguration();
				}
				else
					Console.WriteLine("Failed to Lock for Config: " + err.Description);
			}

			return true;
		}
        bool SetupCaptureSession()
        {
            var started = DateTime.UtcNow;

            var availableResolutions = new List <CameraResolution> ();

            var consideredResolutions = new Dictionary <NSString, CameraResolution> {
                { AVCaptureSession.Preset352x288, new CameraResolution   {
                      Width = 352, Height = 288
                  } },
                { AVCaptureSession.PresetMedium, new CameraResolution    {
                      Width = 480, Height = 360
                  } },                                                                                                          //480x360
                { AVCaptureSession.Preset640x480, new CameraResolution   {
                      Width = 640, Height = 480
                  } },
                { AVCaptureSession.Preset1280x720, new CameraResolution  {
                      Width = 1280, Height = 720
                  } },
                { AVCaptureSession.Preset1920x1080, new CameraResolution {
                      Width = 1920, Height = 1080
                  } }
            };

            // configure the capture session for low resolution, change this if your code
            // can cope with more data or volume
            session = new AVCaptureSession()
            {
                SessionPreset = AVCaptureSession.Preset640x480
            };

            // create a device input and attach it to the session
//			var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
            AVCaptureDevice captureDevice = null;
            var             devices       = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);

            foreach (var device in devices)
            {
                captureDevice = device;
                if (options.UseFrontCameraIfAvailable.HasValue &&
                    options.UseFrontCameraIfAvailable.Value &&
                    device.Position == AVCaptureDevicePosition.Front)
                {
                    break;                     //Front camera successfully set
                }
                else if (device.Position == AVCaptureDevicePosition.Back && (!options.UseFrontCameraIfAvailable.HasValue || !options.UseFrontCameraIfAvailable.Value))
                {
                    break;                     //Back camera succesfully set
                }
            }
            if (captureDevice == null)
            {
                Console.WriteLine("No captureDevice - this won't work on the simulator, try a physical device");
                if (overlayView != null)
                {
                    this.AddSubview(overlayView);
                    this.BringSubviewToFront(overlayView);
                }
                return(false);
            }

            CameraResolution resolution = null;

            // Find resolution
            // Go through the resolutions we can even consider
            foreach (var cr in consideredResolutions)
            {
                // Now check to make sure our selected device supports the resolution
                // so we can add it to the list to pick from
                if (captureDevice.SupportsAVCaptureSessionPreset(cr.Key))
                {
                    availableResolutions.Add(cr.Value);
                }
            }

            resolution = options.GetResolution(availableResolutions);

            // See if the user selected a resolution
            if (resolution != null)
            {
                // Now get the preset string from the resolution chosen
                var preset = (from c in consideredResolutions
                              where c.Value.Width == resolution.Width &&
                              c.Value.Height == resolution.Height
                              select c.Key).FirstOrDefault();

                // If we found a matching preset, let's set it on the session
                if (!string.IsNullOrEmpty(preset))
                {
                    session.SessionPreset = preset;
                }
            }

            var input = AVCaptureDeviceInput.FromDevice(captureDevice);

            if (input == null)
            {
                Console.WriteLine("No input - this won't work on the simulator, try a physical device");
                if (overlayView != null)
                {
                    this.AddSubview(overlayView);
                    this.BringSubviewToFront(overlayView);
                }
                return(false);
            }
            else
            {
                session.AddInput(input);
            }


            var startedAVPreviewLayerAlloc = DateTime.UtcNow;

            previewLayer = new AVCaptureVideoPreviewLayer(session);

            var totalAVPreviewLayerAlloc = DateTime.UtcNow - startedAVPreviewLayerAlloc;

            Console.WriteLine("PERF: Alloc AVCaptureVideoPreviewLayer took {0} ms.", totalAVPreviewLayerAlloc.TotalMilliseconds);


            //Framerate set here (15 fps)
            if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0))
            {
                var perf1 = PerformanceCounter.Start();

                NSError lockForConfigErr = null;

                captureDevice.LockForConfiguration(out lockForConfigErr);
                if (lockForConfigErr == null)
                {
                    captureDevice.ActiveVideoMinFrameDuration = new CMTime(1, 10);
                    captureDevice.UnlockForConfiguration();
                }

                PerformanceCounter.Stop(perf1, "PERF: ActiveVideoMinFrameDuration Took {0} ms");
            }
            else
            {
                previewLayer.Connection.VideoMinFrameDuration = new CMTime(1, 10);
            }


            var perf2 = PerformanceCounter.Start();

                        #if __UNIFIED__
            previewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
                        #else
            previewLayer.LayerVideoGravity = AVLayerVideoGravity.ResizeAspectFill;
                        #endif
            previewLayer.Frame    = new CGRect(0, 0, this.Frame.Width, this.Frame.Height);
            previewLayer.Position = new CGPoint(this.Layer.Bounds.Width / 2, (this.Layer.Bounds.Height / 2));

            layerView = new UIView(new CGRect(0, 0, this.Frame.Width, this.Frame.Height));
            layerView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
            layerView.Layer.AddSublayer(previewLayer);

            this.AddSubview(layerView);

            ResizePreview(UIApplication.SharedApplication.StatusBarOrientation);

            if (overlayView != null)
            {
                this.AddSubview(overlayView);
                this.BringSubviewToFront(overlayView);

                //overlayView.LayoutSubviews ();
            }

            PerformanceCounter.Stop(perf2, "PERF: Setting up layers took {0} ms");

            var perf3 = PerformanceCounter.Start();

            session.StartRunning();

            PerformanceCounter.Stop(perf3, "PERF: session.StartRunning() took {0} ms");

            var perf4 = PerformanceCounter.Start();

            var videoSettings = NSDictionary.FromObjectAndKey(new NSNumber((int)CVPixelFormatType.CV32BGRA),
                                                              CVPixelBuffer.PixelFormatTypeKey);


            // create a VideoDataOutput and add it to the sesion
            output = new AVCaptureVideoDataOutput {
                WeakVideoSettings = videoSettings
            };

            // configure the output
            queue = new DispatchQueue("ZxingScannerView");             // (Guid.NewGuid().ToString());

            var barcodeReader = new BarcodeReader(null, (img) =>
            {
                var src = new RGBLuminanceSource(img);                 //, bmp.Width, bmp.Height);

                //Don't try and rotate properly if we're autorotating anyway
                if (ScanningOptions.AutoRotate.HasValue && ScanningOptions.AutoRotate.Value)
                {
                    return(src);
                }

                var tmpInterfaceOrientation = UIInterfaceOrientation.Portrait;
                InvokeOnMainThread(() => tmpInterfaceOrientation = UIApplication.SharedApplication.StatusBarOrientation);

                switch (tmpInterfaceOrientation)
                {
                case UIInterfaceOrientation.Portrait:
                    return(src.rotateCounterClockwise().rotateCounterClockwise().rotateCounterClockwise());

                case UIInterfaceOrientation.PortraitUpsideDown:
                    return(src.rotateCounterClockwise().rotateCounterClockwise().rotateCounterClockwise());

                case UIInterfaceOrientation.LandscapeLeft:
                    return(src);

                case UIInterfaceOrientation.LandscapeRight:
                    return(src);
                }

                return(src);
            }, null, null);             //(p, w, h, f) => new RGBLuminanceSource(p, w, h, RGBLuminanceSource.BitmapFormat.Unknown));

            if (ScanningOptions.TryHarder.HasValue)
            {
                Console.WriteLine("TRY_HARDER: " + ScanningOptions.TryHarder.Value);
                barcodeReader.Options.TryHarder = ScanningOptions.TryHarder.Value;
            }
            if (ScanningOptions.PureBarcode.HasValue)
            {
                barcodeReader.Options.PureBarcode = ScanningOptions.PureBarcode.Value;
            }
            if (ScanningOptions.AutoRotate.HasValue)
            {
                Console.WriteLine("AUTO_ROTATE: " + ScanningOptions.AutoRotate.Value);
                barcodeReader.AutoRotate = ScanningOptions.AutoRotate.Value;
            }
            if (!string.IsNullOrEmpty(ScanningOptions.CharacterSet))
            {
                barcodeReader.Options.CharacterSet = ScanningOptions.CharacterSet;
            }
            if (ScanningOptions.TryInverted.HasValue)
            {
                barcodeReader.TryInverted = ScanningOptions.TryInverted.Value;
            }

            if (ScanningOptions.PossibleFormats != null && ScanningOptions.PossibleFormats.Count > 0)
            {
                barcodeReader.Options.PossibleFormats = new List <BarcodeFormat>();

                foreach (var pf in ScanningOptions.PossibleFormats)
                {
                    barcodeReader.Options.PossibleFormats.Add(pf);
                }
            }

            outputRecorder = new OutputRecorder(ScanningOptions, img =>
            {
                if (!IsAnalyzing)
                {
                    return;
                }

                try
                {
                    //var sw = new System.Diagnostics.Stopwatch();
                    //sw.Start();

                    var rs = barcodeReader.Decode(img);

                    //sw.Stop();

                    //Console.WriteLine("Decode Time: {0} ms", sw.ElapsedMilliseconds);

                    if (rs != null)
                    {
                        resultCallback(rs);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DECODE FAILED: " + ex);
                }
            });

            output.AlwaysDiscardsLateVideoFrames = true;
            output.SetSampleBufferDelegate(outputRecorder, queue);

            PerformanceCounter.Stop(perf4, "PERF: SetupCamera Finished.  Took {0} ms.");

            session.AddOutput(output);
            //session.StartRunning ();


            var perf5 = PerformanceCounter.Start();

            NSError err = null;
            if (captureDevice.LockForConfiguration(out err))
            {
                if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.ContinuousAutoFocus))
                {
                    captureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus;
                }
                else if (captureDevice.IsFocusModeSupported(AVCaptureFocusMode.AutoFocus))
                {
                    captureDevice.FocusMode = AVCaptureFocusMode.AutoFocus;
                }

                if (captureDevice.IsExposureModeSupported(AVCaptureExposureMode.ContinuousAutoExposure))
                {
                    captureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure;
                }
                else if (captureDevice.IsExposureModeSupported(AVCaptureExposureMode.AutoExpose))
                {
                    captureDevice.ExposureMode = AVCaptureExposureMode.AutoExpose;
                }

                if (captureDevice.IsWhiteBalanceModeSupported(AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance))
                {
                    captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance;
                }
                else if (captureDevice.IsWhiteBalanceModeSupported(AVCaptureWhiteBalanceMode.AutoWhiteBalance))
                {
                    captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.AutoWhiteBalance;
                }

                if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0) && captureDevice.AutoFocusRangeRestrictionSupported)
                {
                    captureDevice.AutoFocusRangeRestriction = AVCaptureAutoFocusRangeRestriction.Near;
                }

                if (captureDevice.FocusPointOfInterestSupported)
                {
                    captureDevice.FocusPointOfInterest = new PointF(0.5f, 0.5f);
                }

                if (captureDevice.ExposurePointOfInterestSupported)
                {
                    captureDevice.ExposurePointOfInterest = new PointF(0.5f, 0.5f);
                }

                captureDevice.UnlockForConfiguration();
            }
            else
            {
                Console.WriteLine("Failed to Lock for Config: " + err.Description);
            }

            PerformanceCounter.Stop(perf5, "PERF: Setup Focus in {0} ms.");

            return(true);
        }