public static Media Convert(string filename, IFile file)
        {
            if (file == null)
            {
                return(null);
            }
            try
            {
                lock (_lock)
                {
                    Media  m = new Media();
                    Part   p = new Part();
                    Thread mediaInfoThread = new Thread(() =>
                    {
                        if (minstance == null)
                        {
                            minstance = new MediaInfoLib.MediaInfo();
                        }
                        if (minstance.Open(filename) == 0)
                        {
                            return;                                //it's a boolean response.
                        }
                        Stream VideoStream = null;

                        m.Duration = p.Duration = minstance.GetLong(StreamKind.General, 0, "Duration");
                        p.Size     = minstance.GetLong(StreamKind.General, 0, "FileSize");

                        int brate = minstance.GetInt(StreamKind.General, 0, "BitRate");
                        if (brate != 0)
                        {
                            m.Bitrate = (int)Math.Round(brate / 1000F);
                        }

                        int chaptercount = minstance.GetInt(StreamKind.General, 0, "MenuCount");
                        m.Chaptered      = chaptercount > 0;

                        int video_count = minstance.GetInt(StreamKind.General, 0, "VideoCount");
                        int audio_count = minstance.GetInt(StreamKind.General, 0, "AudioCount");
                        int text_count  = minstance.GetInt(StreamKind.General, 0, "TextCount");

                        m.Container  = p.Container = TranslateContainer(minstance.Get(StreamKind.General, 0, "Format"));
                        string codid = minstance.Get(StreamKind.General, 0, "CodecID");
                        if (!string.IsNullOrEmpty(codid) && (codid.Trim().ToLower() == "qt"))
                        {
                            m.Container = p.Container = "mov";
                        }

                        List <Stream> streams = new List <Stream>();
                        byte iidx             = 0;
                        if (video_count > 0)
                        {
                            for (int x = 0; x < video_count; x++)
                            {
                                Stream s = TranslateVideoStream(minstance, x);
                                if (x == 0)
                                {
                                    VideoStream = s;
                                    m.Width     = s.Width;
                                    m.Height    = s.Height;
                                    if (m.Height != 0)
                                    {
                                        if (m.Width != 0)
                                        {
                                            m.VideoResolution = GetResolution(m.Width, m.Height);
                                            m.AspectRatio     = GetAspectRatio(m.Width, m.Height, s.PA);
                                        }
                                    }
                                    if (s.FrameRate != 0)
                                    {
                                        float fr   = System.Convert.ToSingle(s.FrameRate);
                                        string frs = ((int)Math.Round(fr)).ToString(CultureInfo.InvariantCulture);
                                        if (!string.IsNullOrEmpty(s.ScanType))
                                        {
                                            if (s.ScanType.ToLower().Contains("int"))
                                            {
                                                frs += "i";
                                            }
                                            else
                                            {
                                                frs += "p";
                                            }
                                        }
                                        else
                                        {
                                            frs += "p";
                                        }
                                        if ((frs == "25p") || (frs == "25i"))
                                        {
                                            frs = "PAL";
                                        }
                                        else if ((frs == "30p") || (frs == "30i"))
                                        {
                                            frs = "NTSC";
                                        }
                                        m.VideoFrameRate = frs;
                                    }
                                    m.VideoCodec = string.IsNullOrEmpty(s.CodecID) ? s.Codec : s.CodecID;
                                    if (m.Duration != 0 && s.Duration != 0)
                                    {
                                        if (s.Duration > m.Duration)
                                        {
                                            m.Duration = p.Duration = s.Duration;
                                        }
                                    }
                                    if (video_count == 1)
                                    {
                                        s.Default = 0;
                                        s.Forced  = 0;
                                    }
                                }

                                if (m.Container != "mkv")
                                {
                                    s.Index = iidx;
                                    iidx++;
                                }
                                streams.Add(s);
                            }
                        }
                        int totalsoundrate = 0;
                        if (audio_count > 0)
                        {
                            for (int x = 0; x < audio_count; x++)
                            {
                                Stream s = TranslateAudioStream(minstance, x);
                                if ((s.Codec == "adpcm") && (p.Container == "flv"))
                                {
                                    s.Codec = "adpcm_swf";
                                }
                                if (x == 0)
                                {
                                    m.AudioCodec    = string.IsNullOrEmpty(s.CodecID) ? s.Codec : s.CodecID;
                                    m.AudioChannels = s.Channels;
                                    if (m.Duration != 0 && s.Duration != 0)
                                    {
                                        if (s.Duration > m.Duration)
                                        {
                                            m.Duration = p.Duration = s.Duration;
                                        }
                                    }
                                    if (audio_count == 1)
                                    {
                                        s.Default = 0;
                                        s.Forced  = 0;
                                    }
                                }
                                if (s.Bitrate != 0)
                                {
                                    totalsoundrate += s.Bitrate;
                                }
                                if (m.Container != "mkv")
                                {
                                    s.Index = iidx;
                                    iidx++;
                                }
                                streams.Add(s);
                            }
                        }
                        if ((VideoStream != null) && VideoStream.Bitrate == 0 && m.Bitrate != 0)
                        {
                            VideoStream.Bitrate = m.Bitrate - totalsoundrate;
                        }
                        if (text_count > 0)
                        {
                            for (int x = 0; x < audio_count; x++)
                            {
                                Stream s = TranslateTextStream(minstance, x);
                                streams.Add(s);
                                if (text_count == 1)
                                {
                                    s.Default = 0;
                                    s.Forced  = 0;
                                }
                                if (m.Container != "mkv")
                                {
                                    s.Index = iidx;
                                    iidx++;
                                }
                            }
                        }

                        m.Parts = new List <Part> {
                            p
                        };
                        bool over = false;
                        if (m.Container == "mkv")
                        {
                            byte val = byte.MaxValue;
                            foreach (Stream s in streams.OrderBy(a => a.Index).Skip(1))
                            {
                                if (s.Index <= 0)
                                {
                                    over = true;
                                    break;
                                }
                                s.idx = s.Index;
                                if (s.idx < val)
                                {
                                    val = s.idx;
                                }
                            }
                            if (val != 0 && !over)
                            {
                                foreach (Stream s in streams)
                                {
                                    s.idx   = (byte)(s.idx - val);
                                    s.Index = s.idx;
                                }
                            }
                            else if (over)
                            {
                                byte xx = 0;
                                foreach (Stream s in streams)
                                {
                                    s.idx   = xx++;
                                    s.Index = s.idx;
                                }
                            }
                            streams = streams.OrderBy(a => a.idx).ToList();
                        }
                        p.Streams = streams;
                    });
                    mediaInfoThread.Start();
                    bool finished = mediaInfoThread.Join(TimeSpan.FromMinutes(5)); //TODO Move Timeout to settings
                    if (!finished)
                    {
                        try
                        {
                            mediaInfoThread.Abort();
                        }
                        catch
                        {
                            /*ignored*/
                        }
                        try
                        {
                            CloseMediaInfo();
                        }
                        catch
                        {
                            /*ignored*/
                        }
                        return(null);
                    }
                    if ((p.Container == "mp4") || (p.Container == "mov"))
                    {
                        p.Has64bitOffsets       = 0;
                        p.OptimizedForStreaming = 0;
                        m.OptimizedForStreaming = 0;
                        byte[] buffer = new byte[8];
                        FileSystemResult <System.IO.Stream> fsr = file.OpenRead();
                        if (fsr == null || !fsr.IsOk)
                        {
                            return(null);
                        }
                        System.IO.Stream fs = fsr.Result;
                        fs.Read(buffer, 0, 4);
                        int siz = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
                        fs.Seek(siz, SeekOrigin.Begin);
                        fs.Read(buffer, 0, 8);
                        if ((buffer[4] == 'f') && (buffer[5] == 'r') && (buffer[6] == 'e') && (buffer[7] == 'e'))
                        {
                            siz = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3] - 8);
                            fs.Seek(siz, SeekOrigin.Current);
                            fs.Read(buffer, 0, 8);
                        }
                        if ((buffer[4] == 'm') && (buffer[5] == 'o') && (buffer[6] == 'o') && (buffer[7] == 'v'))
                        {
                            p.OptimizedForStreaming = 1;
                            m.OptimizedForStreaming = 1;
                            siz = ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]) - 8;

                            buffer = new byte[siz];
                            fs.Read(buffer, 0, siz);
                            if (!FindInBuffer("trak", 0, siz, buffer, out int opos, out int oposmax))
                            {
                                return(m);
                            }
                            if (!FindInBuffer("mdia", opos, oposmax, buffer, out opos, out oposmax))
                            {
                                return(m);
                            }
                            if (!FindInBuffer("minf", opos, oposmax, buffer, out opos, out oposmax))
                            {
                                return(m);
                            }
                            if (!FindInBuffer("stbl", opos, oposmax, buffer, out opos, out oposmax))
                            {
                                return(m);
                            }
                            if (!FindInBuffer("co64", opos, oposmax, buffer, out opos, out oposmax))
                            {
                                return(m);
                            }
                            p.Has64bitOffsets = 1;
                        }
                    }
                    return(m);
                }
            }
            finally
            {
                minstance?.Close();

                GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
                GC.Collect();
            }
        }