private void InitializeConverters(bool shouldResize)
        {
            var videoStreamIndex = Array.FindIndex(_StreamsContextArr, x => x.DecoderContext->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO);

            if (videoStreamIndex < 0)
            {
                throw new Exception("No video stream found");
            }

            if (shouldResize)
            {
                var decoderContext = _StreamsContextArr[videoStreamIndex].DecoderContext;

                _videoConverter = new VideoFrameConverter(new Size(decoderContext->width, decoderContext->height),
                                                          decoderContext->pix_fmt,
                                                          _size,
                                                          TARGET_PIX_FORMAT);
            }

            var audioStreamIndex = Array.FindIndex(_StreamsContextArr, x => x.DecoderContext->codec_type == AVMediaType.AVMEDIA_TYPE_AUDIO);

            if (audioStreamIndex > -1)
            {
                _audioConverter = new AudioFrameConverter(_StreamsContextArr[audioStreamIndex].EncoderContext,
                                                          _StreamsContextArr[audioStreamIndex].DecoderContext);
            }
        }
        public void Start(string url, bool tcp = false)
        {
            _pFormatContext = ffmpeg.avformat_alloc_context();

            _pFormatContext->interrupt_callback = new AVIOInterruptCB()
            {
                callback = new AVIOInterruptCB_callback_func()
                {
                    Pointer = Marshal.GetFunctionPointerForDelegate(_interruptCallbackDelegate)
                }
            };

            var pFormatContext = _pFormatContext;

            _initDate  = DateTime.Now;
            _connected = false;
            _cancel    = false;

            AVDictionary *pOptions = null;

            if (tcp)
            {
                ffmpeg.av_dict_set(&pOptions, "rtsp_transport", "tcp", 0);
            }

            ffmpeg.avformat_open_input(&pFormatContext, url, null, &pOptions).ThrowExceptionIfError();
            _connected = true;

            ffmpeg.avformat_find_stream_info(_pFormatContext, null).ThrowExceptionIfError();

            AVStream *pStream = null;

            for (var i = 0; i < _pFormatContext->nb_streams; i++)
            {
                if (_pFormatContext->streams[i]->codec->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO)
                {
                    pStream = _pFormatContext->streams[i];
                    break;
                }
            }

            if (pStream == null)
            {
                throw new InvalidOperationException("Could not found video stream.");
            }

            _streamIndex   = pStream->index;
            _pCodecContext = pStream->codec;

            var codecId = _pCodecContext->codec_id;
            var pCodec  = ffmpeg.avcodec_find_decoder(codecId);

            if (pCodec == null)
            {
                throw new InvalidOperationException("Unsupported codec.");
            }

            ffmpeg.avcodec_open2(_pCodecContext, pCodec, null).ThrowExceptionIfError();

            var frameSize   = new Size(_pCodecContext->width, _pCodecContext->height);
            var pixelFormat = _pCodecContext->pix_fmt;

            _videoFrameConverter = new VideoFrameConverter(frameSize, pixelFormat, frameSize, AVPixelFormat.AV_PIX_FMT_BGR24);

            _pPacket = ffmpeg.av_packet_alloc();
            _pFrame  = ffmpeg.av_frame_alloc();
        }
        public void Dispose()
        {
            if (_videoConverter != null)
            {
                _videoConverter.Dispose();
                _videoConverter = null;
            }

            if (_audioConverter != null)
            {
                _audioConverter.Dispose();
                _audioConverter = null;
            }

            _outputName         = null;
            _inputName          = null;
            _validStreamIndexes = null;

            for (int i = 0; i < _StreamsContextArr.Length; i++)
            {
                fixed(AVCodecContext **ptr = &_StreamsContextArr[i].DecoderContext)
                {
                    ffmpeg.avcodec_free_context(ptr);
                }

                if (_pOutputFmCtx != null && _StreamsContextArr.Length > i && _pOutputFmCtx->streams[i] != null && _StreamsContextArr[i].EncoderContext != null)
                {
                    fixed(AVCodecContext **ptr = &_StreamsContextArr[i].EncoderContext)
                    {
                        ffmpeg.avcodec_free_context(ptr);
                    }
                }
            }

            fixed(AVFormatContext **ptr = &_pInputFmtCtx)
            {
                ffmpeg.avformat_close_input(ptr);
            }

            if (_pOutputFmCtx != null && (_pOutputFmCtx->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0)
            {
                ffmpeg.avio_closep(&_pOutputFmCtx->pb);
            }

            ffmpeg.avformat_free_context(_pOutputFmCtx);
            _pOutputFmCtx = null;

            ffmpeg.avformat_free_context(_pInputFmtCtx);
            _pInputFmtCtx = null;

            if (_pReusablePacket != null)
            {
                FreePacket(realloc: false);
            }

            if (_pReusableFrame != null)
            {
                FreeFrame(realloc: false);
            }

            _StreamsContextArr = null;
        }