public static CMBufferQueue FromCallbacks(int count, CMBufferGetTime getDecodeTimeStamp, CMBufferGetTime getPresentationTimeStamp, CMBufferGetTime getDuration,
                                                  CMBufferGetBool isDataReady, CMBufferCompare compare, NSString dataBecameReadyNotification, CMBufferGetSize getTotalSize)
        {
            var bq     = new CMBufferQueue(count);
            var cbacks = new CMBufferCallbacks()
            {
                version                   = (uint)(getTotalSize == null ? 0 : 1),
                refcon                    = GCHandle.ToIntPtr(bq.gch),
                XgetDecodeTimeStamp       = getDecodeTimeStamp == null ? (BufferGetTimeCallback)null : GetDecodeTimeStamp,
                XgetPresentationTimeStamp = getPresentationTimeStamp == null ? (BufferGetTimeCallback)null : GetPresentationTimeStamp,
                XgetDuration              = getDuration == null ? (BufferGetTimeCallback)null : GetDuration,
                XisDataReady              = isDataReady == null ? (BufferGetBooleanCallback)null : GetDataReady,
                Xcompare                  = compare == null ? (BufferCompareCallback)null : Compare,
                cfStringPtr_dataBecameReadyNotification = dataBecameReadyNotification == null ? IntPtr.Zero : dataBecameReadyNotification.Handle,
                XgetSize = getTotalSize == null ? (BufferGetSizeCallback)null : GetTotalSize
            };

            bq.getDecodeTimeStamp       = getDecodeTimeStamp;
            bq.getPresentationTimeStamp = getPresentationTimeStamp;
            bq.getDuration  = getDuration;
            bq.isDataReady  = isDataReady;
            bq.compare      = compare;
            bq.getTotalSize = getTotalSize;

            if (CMBufferQueueCreate(IntPtr.Zero, count, cbacks, out bq.handle) == 0)
            {
                return(bq);
            }

            bq.Dispose();
            return(null);
        }
        public static CMBufferQueue CreateUnsorted(int count)
        {
            var bq = new CMBufferQueue(count);
            // note: different version of iOS can return a different (size) structure, e.g. iOS 7.1,
            // that structure might not map to our `CMBufferCallbacks2` managed representation
            // and can cause a crash, e.g. bug #17330
            // since we don't need the managed bcallbacks (it's the native callback that will be used for this queue)
            // then we can simply use an IntPtr to represent them (no GCHandle)
            var callbacks = CMBufferQueueGetCallbacksForUnsortedSampleBuffers();

            if (CMBufferQueueCreate(IntPtr.Zero, count, callbacks, out bq.handle) == 0)
            {
                return(bq);
            }

            return(null);
        }