public int GetFreeFrameIndex()
        {
            int i = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_GetFreeFrameIndex(h);

            if (i < 0)
            {
                QuickSyncStatic.ThrowOnBadStatus((mfxStatus)i, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_GetFreeFrameIndex));
            }
            return(i);
        }
        public unsafe void EncodeFrame(int frameIndex, ref BitStreamChunk bitstreamChunk)
        {
            bitstreamChunk.bytesAvailable = 0;
            var a   = frameIntPtrs[frameIndex];
            var sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_EncodeFrame(h, (mfxFrameSurface1 *)a);

            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_EncodeFrame));

            CopyOutBitstream(ref bitstreamChunk);
        }
        bool Flush2(ref BitStreamChunk bitstreamChunk)
        {
            bitstreamChunk.bytesAvailable = 0;
            var sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Flush2(h);

            if (sts == mfxStatus.MFX_ERR_MORE_DATA)
            {
                return(false);
            }
            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Flush2));

            CopyOutBitstream(ref bitstreamChunk);
            return(true);
        }
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: dispose managed state (managed objects).
                }

                NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Delete(h);
                h = IntPtr.Zero;
                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.

                disposedValue = true;
            }
        }
        unsafe public LowLevelEncoderNative(mfxVideoParam mfxEncParams, mfxIMPL impl)
        {
            mfxStatus sts;

            this._session = new mfxSession();
            var ver = new mfxVersion()
            {
                Major = 1, Minor = 3
            };

            fixed(mfxSession *s = &_session)
            sts = UnsafeNativeMethods.MFXInit(impl, &ver, s);

            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(UnsafeNativeMethods.MFXInit));



            h = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_New();
            Trace.Assert(h != IntPtr.Zero);
            shared               = (EncoderShared *)h;
            shared->session      = _session;
            shared->mfxEncParams = mfxEncParams;
            Trace.Assert(shared->safety == sizeof(EncoderShared));



            sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Init(h);


            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_Init));

            frameIntPtrs = new IntPtr[shared->nEncSurfNum];
            for (int i = 0; i < frameIntPtrs.Length; i++)
            {
                frameIntPtrs[i] = (IntPtr)shared->pmfxSurfaces[i];
            }

            GetAndPrintWarnings();
        }
        public void UnlockFrame(IntPtr frame)
        {
            var sts = NativeLLEncoderUnsafeNativeMethods.NativeEncoder_UnlockFrame(h, frame);

            QuickSyncStatic.ThrowOnBadStatus(sts, nameof(NativeLLEncoderUnsafeNativeMethods.NativeEncoder_UnlockFrame));
        }