public virtual void DidOutputSampleBuffer(AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
        {
            // HACK: Change CMSampleBuffer.GetFormatDescription() to CMSampleBuffer.GetVideoFormatDescription()
            // HACK Change CMFormatDescription to CMVideoFormatDescription
            // CMFormatDescription formatDescription = sampleBuffer.GetFormatDescription ();
            CMVideoFormatDescription formatDescription = sampleBuffer.GetVideoFormatDescription();

            if (connection == videoConnection)
            {
                // Get framerate
                CMTime timestamp = sampleBuffer.PresentationTimeStamp;
                CalculateFramerateAtTimestamp(timestamp);

                // Get frame dimensions (for onscreen display)
                if (VideoDimensions.IsEmpty)
                {
                    // HACK: Change GetVideoPresentationDimensions() to GetPresentationDimensions()
                    // VideoDimensions = formatDescription.GetVideoPresentationDimensions (true, false);
                    VideoDimensions = formatDescription.GetPresentationDimensions(true, false);
                }

                // Get the buffer type
                if (VideoType == 0)
                {
                    VideoType = formatDescription.MediaSubType;
                }

                // Synchronously process the pixel buffer to de-green it.
                using (var pixelBuffer = sampleBuffer.GetImageBuffer())
                    ProcessPixelBuffer(pixelBuffer);

                previewBufferQueue.Enqueue(sampleBuffer);

                //var writeBuffer = sampleBuffer.Duplicate ();
                InvokeOnMainThread(() => {
                    INativeObject j = previewBufferQueue.Dequeue();

                    var sbuf = j as CMSampleBuffer;
                    if (sbuf == null)
                    {
#if DEBUG
                        // Record the current sampleBuffer.ClassHandle
                        // Then run another iteration and on the next one, print the ClassHandle
                        Console.WriteLine("The type is {0}", j.ToString());
#endif
                        return;
                    }

                    using (CVImageBuffer pixBuf = sbuf.GetImageBuffer()) {
                        if (PixelBufferReadyForDisplay != null)
                        {
                            PixelBufferReadyForDisplay(pixBuf);
                        }
                    }
                });
            }
            // keep a reference to 'sampleBuffer', movieWritingQueue will remove it
            CompleteBufferUse(sampleBuffer);

            movieWritingQueue.DispatchAsync(() => {
                if (assetWriter != null)
                {
                    bool wasReadyToRecord = (readyToRecordAudio && readyToRecordVideo);

                    if (connection == videoConnection)
                    {
                        // Initialize the video input if this is not done yet
                        if (!readyToRecordVideo)
                        {
                            readyToRecordVideo = SetupAssetWriterVideoInput(formatDescription);
                        }

                        // Write the video data to file
                        if (readyToRecordVideo && readyToRecordAudio)
                        {
                            WriteSampleBuffer(sampleBuffer, AVMediaType.Video);
                        }
                    }
                    else if (connection == audioConnection)
                    {
                        if (!readyToRecordAudio)
                        {
                            readyToRecordAudio = SetupAssetWriterAudioInput(formatDescription);
                        }

                        if (readyToRecordAudio && readyToRecordVideo)
                        {
                            WriteSampleBuffer(sampleBuffer, AVMediaType.Audio);
                        }
                    }
                    bool isReadyToRecord = (readyToRecordAudio && readyToRecordVideo);

                    if (!wasReadyToRecord && isReadyToRecord)
                    {
                        recordingWillBeStarted = false;
                        IsRecording            = true;

                        if (RecordingDidStart != null)
                        {
                            RecordingDidStart();
                        }
                    }
                }
                CompleteBufferUse(sampleBuffer);
            });
        }