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(); } }