void ReleaseRenderTexture(object encoderLock)
        {
            if (_cameraOutputTexture != null)
            {
                _cameraOutputTexture.Release();
            }
            _cameraOutputTexture = null;

            if (_vidEnc != IntPtr.Zero && _vCfgEnc != IntPtr.Zero && _vTxfEnc != IntPtr.Zero &&
                _aCfgEnc != IntPtr.Zero && _audEnc != IntPtr.Zero)
            {
                IntPtr _vidEncCopy  = _vidEnc;
                IntPtr _vCfgEncCopy = _vCfgEnc;
                IntPtr _vTxfEncCopy = _vTxfEnc;
                IntPtr _aCfgEncCopy = _aCfgEnc;
                IntPtr _audEncCopy  = _audEnc;


                int msTimeout = 1000 / MixCastAV.chunksPerSec;

                new Thread(() =>
                {
                    lock (encoderLock)
                    {
                        Thread.Sleep(msTimeout);
                        //Debug.Log("Asynchronously cleaning up encoder: " + _encCopy.ToString());
                        MixCastAV.writeTrailerCloseStreams(_vidEncCopy);
                        MixCastAV.freeVideoCfg(_vCfgEncCopy);
                        MixCastAV.freeAudioEncodeContext(_audEncCopy);
                        MixCastAV.freeVideoTransform(_vTxfEncCopy);
                        MixCastAV.freeAudioCfg(_aCfgEncCopy);
                    }
                }).Start();
            }

            _vidEnc  = IntPtr.Zero;
            _vCfgEnc = IntPtr.Zero;
            _vTxfEnc = IntPtr.Zero;
            _aCfgEnc = IntPtr.Zero;
            _audEnc  = IntPtr.Zero;
        }
        private void _killDecoder()
        {
            bool resFreeDec = false;
            bool resFreeCfg = false;
            bool resFreeTxf = false;

            MixCastAV.ReleaseDecodeInterface(decoderInterface);
            System.Threading.Thread.Sleep(2);             //untested amount of sleep time in ms needed to avoid race condition


            //free the decoder
            if (vidDec != IntPtr.Zero)
            {
                resFreeDec = MixCastAV.freeDecodeContext(vidDec) == 0 ? true : false;
            }
            vidDec = IntPtr.Zero;

            //free the data config
            if (cfgVidDec != IntPtr.Zero)
            {
                resFreeCfg = MixCastAV.freeVideoCfg(cfgVidDec) == 0 ? true : false;
            }
            cfgVidDec = IntPtr.Zero;

            //free the transformer
            if (vidTxfDec != IntPtr.Zero)
            {
                resFreeTxf = MixCastAV.freeVideoTransform(vidTxfDec) == 0 ? true : false;
            }
            vidTxfDec = IntPtr.Zero;


            if (resFreeDec == false || resFreeCfg == false || resFreeTxf == false)
            {
                Debug.LogError("Error Freeing Device Feed. " + vidDec);
            }
        }
        protected bool BuildEncoder(string outputPath)
        {
            if (_vCfgEnc != IntPtr.Zero || _vidEnc != IntPtr.Zero || _vTxfEnc != IntPtr.Zero ||
                _audEnc != IntPtr.Zero || _aCfgEnc != IntPtr.Zero)
            {
                Debug.LogError("Could not setup the encoder, previous session is still running");
                return(false);
            }

            encodeInterface = -1;

            //build our encoder here
            _vCfgEnc = MixCastAV.getVideoEncodeCfg(outputPath, _width, _height,
                                                   Framerate, SRC_PIX_FMT, _width, _height, Framerate, DST_PIX_FMT,
                                                   GopSize, BitRate, CODEC_TYPE, CODEC_NAME, FLIP_VERTICAL);

            //Debug.LogWarningFormat( "vCfgEnc: w({0}), h({1}), src_pix({2}), dst_pix({3}), GopSize({4}), bitrate({5}), codec_type({6}), codec_name({7})",
            //    _width, _height, SRC_PIX_FMT, DST_PIX_FMT, GopSize, BitRate, CODEC_TYPE, CODEC_NAME );

            //_aCfgEnc = LibAvStuff.getAudioEncodeCfg(new StringBuilder(dummyName), DEFCHANNELS, DEFSAMPLERATE, DEFBITDEPTH,
            //    DEFCHANNELS, DEFSAMPLERATE, DEFBITDEPTH, AudioBitrate, new StringBuilder(MP2_CODECNAME), new StringBuilder(MP2_CODECNAME));

            //for AAC, we should be using 32 bit depth
            _aCfgEnc = MixCastAV.getAudioEncodeCfg(dummyName, DEFCHANNELS, DEFSAMPLERATE, DEFBITDEPTH,
                                                   DEFCHANNELS, DEFSAMPLERATE, AAC_BITDEPTH, AudioBitrate, AAC_CODECNAME, AAC_CODECNAME);

            int ret = MixCastAV.getAudioAndVideoEncodeContextMux(ref _audEnc, ref _vidEnc, _aCfgEnc, _vCfgEnc);

            if (_vidEnc == IntPtr.Zero || _audEnc == IntPtr.Zero || ret < 0)
            {
                Debug.LogError("Could not setup the encoder, please check configuration");
                EventCenter.HandleEvent(Category, EventCenter.Result.Error, "Warning_Video_Encoder_Error", true);
                MixCastAV.freeVideoCfg(_vCfgEnc);
                MixCastAV.freeAudioCfg(_aCfgEnc);
                _vCfgEnc = IntPtr.Zero;
                _aCfgEnc = IntPtr.Zero;
                return(false);
            }

            _vTxfEnc = MixCastAV.getVideoTransformContext(_vCfgEnc);
            if (_vTxfEnc == IntPtr.Zero)
            {
                Debug.LogError("Could not setup the video transformer for encoding, please check configuration");
                EventCenter.HandleEvent(Category, EventCenter.Result.Error, "Warning_Video_Encoder_Error", true);
                MixCastAV.freeVideoCfg(_vCfgEnc);
                _vCfgEnc = IntPtr.Zero;
                _vidEnc  = IntPtr.Zero;
                return(false);
            }

            if (_bitrateKbps <= 0)
            {
                _bitrateKbps = (ulong)(_width * _height / BITS_IN_KILOBIT);
            }

            if (_vidEnc != IntPtr.Zero && _vCfgEnc != IntPtr.Zero && _vTxfEnc != IntPtr.Zero)
            {
                encodeInterface = MixCastAV.CreateEncodeInterface(_vidEnc, _vCfgEnc, _vTxfEnc);
            }

            return(encodeInterface != -1);
        }