Example #1
0
        public override List<ChapterInfo> GetStreams(string location, int titlenum)
        {
            int titleSetNum = titlenum;

              if (location.StartsWith("VTS_"))
              {
            titleSetNum = int.Parse(Path.GetFileNameWithoutExtension(location)
             .ToUpper()
             .Replace("VTS_", string.Empty)
             .Replace("_0.IFO", string.Empty));
              }

              ChapterInfo pgc = new ChapterInfo();
              pgc.SourceType = "DVD";
              pgc.SourceName = location;
              pgc.SourceHash = ChapterExtractor.ComputeMD5Sum(location);
              pgc.Extractor = Application.ProductName + " " + Application.ProductVersion;
              pgc.Title = Path.GetFileNameWithoutExtension(location);
              OnStreamDetected(pgc);

              TimeSpan duration;
              double fps;
              pgc.Chapters = GetChapters(location, titleSetNum, out duration, out fps);
              pgc.Duration = duration;
              pgc.FramesPerSecond = fps;
              OnChaptersLoaded(pgc);

              OnExtractionComplete();
              return Enumerable.Repeat(pgc, 1).ToList();
        }
Example #2
0
 protected void OnChaptersLoaded(ChapterInfo pgc)
 {
     if (ChaptersLoaded != null)
     {
         ChaptersLoaded(this, new ProgramChainArg()
         {
             ProgramChain = pgc
         });
     }
 }
Example #3
0
 protected void OnStreamDetected(ChapterInfo pgc)
 {
     if (StreamDetected != null)
     {
         StreamDetected(this, new ProgramChainArg()
         {
             ProgramChain = pgc
         });
     }
 }
Example #4
0
        public override List <ChapterInfo> GetStreams(string location, int numtitle)
        {
            ChapterInfo pgc = new ChapterInfo();

            pgc.Chapters   = new List <ChapterEntry>();
            pgc.SourceHash = ChapterExtractor.ComputeMD5Sum(location);
            pgc.SourceName = location;
            pgc.Title      = Path.GetFileNameWithoutExtension(location);
            pgc.SourceType = "Blu-Ray";
            pgc.Extractor  = Application.ProductName + " " + Application.ProductVersion;

            FileInfo fileInfo = new FileInfo(location);

            OnStreamDetected(pgc);
            TSPlaylistFile mpls = new TSPlaylistFile(fileInfo);

            //Dictionary<string, TSStreamClipFile> clips = new Dictionary<string,TSStreamClipFile>();
            mpls.Scan();
            foreach (double d in mpls.Chapters)
            {
                pgc.Chapters.Add(new ChapterEntry()
                {
                    Name = string.Empty,
                    Time = new TimeSpan((long)(d * (double)TimeSpan.TicksPerSecond))
                });
            }

            pgc.Duration = new TimeSpan((long)(mpls.TotalLength * (double)TimeSpan.TicksPerSecond));

            foreach (TSStreamClip clip in mpls.StreamClips)
            {
                clip.StreamClipFile.Scan();
                foreach (TSStream stream in clip.StreamClipFile.Streams.Values)
                {
                    if (stream.IsVideoStream)
                    {
                        pgc.FramesPerSecond = (double)((TSVideoStream)stream).FrameRateEnumerator /
                                              (double)((TSVideoStream)stream).FrameRateDenominator;
                        break;
                    }
                }
                if (pgc.FramesPerSecond != 0)
                {
                    break;
                }
            }

            OnChaptersLoaded(pgc);
            OnExtractionComplete();
            return(new List <ChapterInfo>()
            {
                pgc
            });
        }
Example #5
0
        public float Similarity(ChapterInfo other)
        {
            float count   = 0F;
            float matches = 0F;

            count++;
            if (Title != null && Title.Equals(other.Title, StringComparison.InvariantCultureIgnoreCase))
            {
                matches++;
            }

            count++;
            if (SourceHash != null && SourceHash.Equals(other.SourceHash))
            {
                matches++;
            }

            count++;
            if (LangCode != null && LangCode.Equals(other.LangCode))
            {
                matches++;
            }

            count++;
            if (Math.Abs(Duration.TotalSeconds - other.Duration.TotalSeconds) < 1)
            {
                matches++;
            }

            count++;
            if (Math.Round(FramesPerSecond * 1000) - Math.Round(other.FramesPerSecond * 1000) == 0)
            {
                matches++;
            }

            for (int i = 0; i < Chapters.Count; i++)
            {
                count = count + 2F;
                if (i < other.Chapters.Count)
                {
                    if (Chapters[i].Name != null && Chapters[i].Name.Equals(other.Chapters[i].Name, StringComparison.InvariantCultureIgnoreCase))
                    {
                        matches++;
                    }
                    if (Math.Abs(Chapters[i].Time.TotalSeconds - other.Chapters[i].Time.TotalSeconds) < 1)
                    {
                        matches++;
                    }
                }
            }
            return(matches / count);
        }
Example #6
0
        public override List <ChapterInfo> GetStreams(string location, int numtitle)
        {
            List <ChapterInfo> pgcs = new List <ChapterInfo>();
            XDocument          doc  = XDocument.Load(location);
            XNamespace         ns   = "http://www.dvdforum.org/2005/HDDVDVideo/Playlist";

            foreach (XElement ts in doc.Element(ns + "Playlist").Elements(ns + "TitleSet"))
            {
                float timeBase = GetFps((string)ts.Attribute("timeBase"));
                float tickBase = GetFps((string)ts.Attribute("tickBase"));
                foreach (XElement title in ts.Elements(ns + "Title").Where(t => t.Element(ns + "ChapterList") != null))
                {
                    ChapterInfo         pgc      = new ChapterInfo();
                    List <ChapterEntry> chapters = new List <ChapterEntry>();
                    pgc.SourceName      = location;
                    pgc.SourceHash      = ChapterExtractor.ComputeMD5Sum(location);
                    pgc.SourceType      = "HD-DVD";
                    pgc.FramesPerSecond = 24D;
                    pgc.Extractor       = Application.ProductName + " " + Application.ProductVersion;
                    OnStreamDetected(pgc);

                    int tickBaseDivisor = (int?)title.Attribute("tickBaseDivisor") ?? 1;
                    pgc.Duration = GetTimeSpan((string)title.Attribute("titleDuration"), timeBase, tickBase, tickBaseDivisor);
                    string titleName = Path.GetFileNameWithoutExtension(location);
                    if (title.Attribute("id") != null)
                    {
                        titleName = (string)title.Attribute("id");
                    }
                    if (title.Attribute("displayName") != null)
                    {
                        titleName = (string)title.Attribute("displayName");
                    }
                    pgc.Title = titleName;
                    foreach (XElement chapter in title.Element(ns + "ChapterList").Elements(ns + "Chapter"))
                    {
                        chapters.Add(new ChapterEntry()
                        {
                            Name = (string)chapter.Attribute("displayName"),
                            Time = GetTimeSpan((string)chapter.Attribute("titleTimeBegin"), timeBase, tickBase, tickBaseDivisor)
                        });
                    }
                    pgc.Chapters = chapters;
                    OnChaptersLoaded(pgc);
                    //pgc.ChangeFps(24D / 1.001D);
                    pgcs.Add(pgc);
                }
            }
            pgcs = pgcs.OrderByDescending(p => p.Duration).ToList();
            OnExtractionComplete();
            return(pgcs);
        }
Example #7
0
        public override List<ChapterInfo> GetStreams(string location, int numtitle)
        {
            List<ChapterInfo> pgcs = new List<ChapterInfo>();
              XDocument doc = XDocument.Load(location);
              XNamespace ns = "http://www.dvdforum.org/2005/HDDVDVideo/Playlist";
              foreach (XElement ts in doc.Element(ns + "Playlist").Elements(ns + "TitleSet"))
              {
            float timeBase = GetFps((string)ts.Attribute("timeBase"));
            float tickBase = GetFps((string)ts.Attribute("tickBase"));
            foreach (XElement title in ts.Elements(ns + "Title").Where(t => t.Element(ns + "ChapterList") != null))
            {
              ChapterInfo pgc = new ChapterInfo();
              List<ChapterEntry> chapters = new List<ChapterEntry>();
              pgc.SourceName = location;
              pgc.SourceHash = ChapterExtractor.ComputeMD5Sum(location);
              pgc.SourceType = "HD-DVD";
              pgc.FramesPerSecond = 24D;
              pgc.Extractor = Application.ProductName + " " + Application.ProductVersion;
              OnStreamDetected(pgc);

              int tickBaseDivisor = (int?)title.Attribute("tickBaseDivisor") ?? 1;
              pgc.Duration = GetTimeSpan((string)title.Attribute("titleDuration"), timeBase, tickBase, tickBaseDivisor);
              string titleName = Path.GetFileNameWithoutExtension(location);
              if (title.Attribute("id") != null) titleName = (string)title.Attribute("id");
              if (title.Attribute("displayName") != null) titleName = (string)title.Attribute("displayName");
              pgc.Title = titleName;
              foreach (XElement chapter in title.Element(ns + "ChapterList").Elements(ns + "Chapter"))
              {
            chapters.Add(new ChapterEntry()
            {
              Name = (string)chapter.Attribute("displayName"),
              Time = GetTimeSpan((string)chapter.Attribute("titleTimeBegin"), timeBase, tickBase, tickBaseDivisor)
            });
              }
              pgc.Chapters = chapters;
              OnChaptersLoaded(pgc);
              //pgc.ChangeFps(24D / 1.001D);
              pgcs.Add(pgc);
            }
              }
              pgcs = pgcs.OrderByDescending(p => p.Duration).ToList();
              OnExtractionComplete();
              return pgcs;
        }
Example #8
0
        public static ChapterInfo Load(XElement root)
        {
            ChapterInfo ci = new ChapterInfo();

            ci.LangCode  = (string)root.Attribute(XNamespace.Xml + "lang");
            ci.Extractor = (string)root.Attribute("extractor");

            if (root.Element(CgNs + "title") != null)
            {
                ci.Title = (string)root.Element(CgNs + "title");
            }

            XElement @ref = root.Element(CgNs + "ref");

            if (@ref != null)
            {
                ci.ChapterSetId = (int?)@ref.Element(CgNs + "chapterSetId");
                ci.ImdbId       = (string)@ref.Element(CgNs + "imdbId");
                ci.MovieDbId    = (int?)@ref.Element(CgNs + "movieDbId");
            }

            XElement src = root.Element(CgNs + "source");

            if (src != null)
            {
                ci.SourceName = (string)src.Element(CgNs + "name");
                if (src.Element(CgNs + "type") != null)
                {
                    ci.SourceType = (string)src.Element(CgNs + "type");
                }
                ci.SourceHash      = (string)src.Element(CgNs + "hash");
                ci.FramesPerSecond = Convert.ToDouble(src.Element(CgNs + "fps").Value, new System.Globalization.NumberFormatInfo());
                ci.Duration        = TimeSpan.Parse(src.Element(CgNs + "duration").Value);
            }

            ci.Chapters = root.Element(CgNs + "chapters").Elements(CgNs + "chapter")
                          .Select(e => new ChapterEntry()
            {
                Name = (string)e.Attribute("name"), Time = TimeSpan.Parse((string)e.Attribute("time"))
            }).ToList();
            return(ci);
        }
Example #9
0
        public override List <ChapterInfo> GetStreams(string location, int numtitle)
        {
            List <ChapterInfo> pgcs = new List <ChapterInfo>();

            ProcessStartInfo psi = new ProcessStartInfo(@"d:\programs\eac3to\eac3to.exe", location);

            psi.CreateNoWindow  = true;
            psi.UseShellExecute = false;
            //psi.RedirectStandardError = true;
            psi.RedirectStandardOutput = true;
            psi.WorkingDirectory       = Application.StartupPath;
            Process p      = Process.Start(psi);
            string  output = p.StandardOutput.ReadToEnd();

            p.WaitForExit();

            foreach (Match m in Regex.Matches(output, @"\d\).+:\d\d"))
            {
                string[] data = m.Value.Split(',');

                string sourceFile = Path.Combine(Path.Combine(Path.Combine(
                                                                  location, "BDMV"), "PLAYLIST"), data[0].Split(')')[1].Trim());

                ChapterInfo pgc = new ChapterInfo()
                {
                    Duration   = TimeSpan.Parse(data[data.Length - 1].Trim()),
                    SourceName = data[0].Split(')')[0],
                    SourceHash = ChapterExtractor.ComputeMD5Sum(sourceFile)
                };
                OnStreamDetected(pgc);
                pgcs.Add(pgc);
            }

            /*
             * 1) 00001.mpls, 00002.m2ts, 1:34:15
             * - h264/AVC, 1080p24 /1.001 (16:9)
             * - AC3, Spanish, multi-channel, 48khz
             * - DTS Master Audio, English, multi-channel, 48khz
             *
             * 2) 00027.mpls, 00036.m2ts, 0:24:19
             * - h264/AVC, 1080p24 /1.001 (16:9)
             * - AC3, English, stereo, 48khz
             */

            foreach (ChapterInfo pgc in pgcs)
            {
                psi.Arguments = location + " " + pgc.SourceName + ")";
                p             = Process.Start(psi);
                output        = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
                if (output.Contains("Chapters"))
                {
                    if (File.Exists("chapters.txt"))
                    {
                        File.Delete("chapters.txt");
                    }
                    psi.Arguments = location + " " + pgc.SourceName + ") chapters.txt";
                    p             = Process.Start(psi);
                    output        = p.StandardOutput.ReadToEnd();
                    p.WaitForExit();
                    if (!output.Contains("Creating file \"chapters.txt\"...") && !output.Contains("Done!"))
                    {
                        throw new Exception("Error creating chapters file.");
                    }
                    TextExtractor extractor = new TextExtractor();
                    pgc.Chapters = extractor.GetStreams("chapters.txt", numtitle)[0].Chapters;
                    OnChaptersLoaded(pgc);
                }
            }

            /*
             * M2TS, 1 video track, 2 audio tracks, 6 subtitle tracks, 1:34:15
             * 1: Chapters, 25 chapters
             * 2: h264/AVC, 1080p24 /1.001 (16:9)
             * 3: AC3, Spanish, 5.1 channels, 448kbps, 48khz, dialnorm: -27dB
             * 4: DTS Master Audio, English, 5.1 channels, 24 bits, 48khz
             * (core: DTS, 5.1 channels, 24 bits, 1509kbps, 48khz)
             * 5: Subtitle (PGS), English
             * 6: Subtitle (PGS), Spanish
             * 7: Subtitle (PGS), Spanish
             * 8: Subtitle (PGS), French
             * 9: Subtitle (PGS), Chinese
             * 10: Subtitle (PGS), Korean
             */

            OnExtractionComplete();
            return(pgcs);
        }
Example #10
0
        public override List<ChapterInfo> GetStreams(string location, int numtitle)
        {
            ChapterInfo pgc = new ChapterInfo();
              List<ChapterEntry> chapters = new List<ChapterEntry>();
              pgc.SourceName = location;
              pgc.SourceHash = ChapterExtractor.ComputeMD5Sum(location);
              pgc.SourceType = "Blu-Ray";
              pgc.Extractor = Application.ProductName + " " + Application.ProductVersion;
              pgc.Title = Path.GetFileNameWithoutExtension(location);

              FileInfo fileInfo = new FileInfo(location);
              byte[] data = File.ReadAllBytes(location);

              string fileType = ASCIIEncoding.ASCII.GetString(data, 0, 8);

              if ((fileType != "MPLS0100" && fileType != "MPLS0200")
            /*|| data[45] != 1*/)
              {
            throw new Exception(string.Format(
            "Playlist {0} has an unknown file type {1}.",
            fileInfo.Name, fileType));
              }

              Debug.WriteLine(string.Format("\tFileType: {0}", fileType));

              List<Clip> chapterClips = GetClips(data);
              pgc.Duration = new TimeSpan((long)(chapterClips.Sum(c => c.Length) * (double)TimeSpan.TicksPerSecond));
              OnStreamDetected(pgc);

              int chaptersIndex =
              ((int)data[12] << 24) +
              ((int)data[13] << 16) +
              ((int)data[14] << 8) +
              ((int)data[15]);

              int chaptersLength =
              ((int)data[chaptersIndex] << 24) +
              ((int)data[chaptersIndex + 1] << 16) +
              ((int)data[chaptersIndex + 2] << 8) +
              ((int)data[chaptersIndex + 3]);

              byte[] chapterData = new byte[chaptersLength];
              Array.Copy(data, chaptersIndex + 4, chapterData, 0, chaptersLength);

              int chapterCount = ((int)chapterData[0] << 8) + chapterData[1];
              int chapterOffset = 2;
              for (int chapterIndex = 0; chapterIndex < chapterCount; chapterIndex++)
              {
            if (chapterData[chapterOffset + 1] == 1)
            {
              int streamFileIndex =
              ((int)chapterData[chapterOffset + 2] << 8) +
              chapterData[chapterOffset + 3];

              Clip streamClip = chapterClips[streamFileIndex];

              long chapterTime =
              ((long)chapterData[chapterOffset + 4] << 24) +
              ((long)chapterData[chapterOffset + 5] << 16) +
              ((long)chapterData[chapterOffset + 6] << 8) +
              ((long)chapterData[chapterOffset + 7]);

              double chapterSeconds = (double)chapterTime / 45000D;
              double relativeSeconds = chapterSeconds - streamClip.TimeIn + streamClip.RelativeTimeIn;
              chapters.Add(new ChapterEntry()
              {
            Name = string.Empty,
            Time = new TimeSpan((long)(relativeSeconds * (double)TimeSpan.TicksPerSecond))
              });
            }
            chapterOffset += 14;
              }
              pgc.Chapters = chapters;

              //TODO: get real FPS
              pgc.FramesPerSecond = mvCentralCore.Settings.DefaultFPS;

              OnChaptersLoaded(pgc);
              OnExtractionComplete();
              return new List<ChapterInfo>() { pgc };
        }
Example #11
0
        public float Similarity(ChapterInfo other)
        {
            float count = 0F;
            float matches = 0F;

            count++;
            if (Title != null && Title.Equals(other.Title, StringComparison.InvariantCultureIgnoreCase)) matches++;

            count++;
            if (SourceHash != null && SourceHash.Equals(other.SourceHash)) matches++;

            count++;
            if (LangCode != null && LangCode.Equals(other.LangCode)) matches++;

            count++;
            if (Math.Abs(Duration.TotalSeconds - other.Duration.TotalSeconds) < 1) matches++;

            count++;
            if (Math.Round(FramesPerSecond * 1000) - Math.Round(other.FramesPerSecond * 1000) == 0) matches++;

            for (int i = 0; i < Chapters.Count; i++)
            {
                count = count + 2F;
                if (i < other.Chapters.Count)
                {
                    if (Chapters[i].Name != null && Chapters[i].Name.Equals(other.Chapters[i].Name, StringComparison.InvariantCultureIgnoreCase)) matches++;
                    if (Math.Abs(Chapters[i].Time.TotalSeconds - other.Chapters[i].Time.TotalSeconds) < 1) matches++;
                }
            }
            return matches / count;
        }
Example #12
0
        public static ChapterInfo Load(XElement root)
        {
            ChapterInfo ci = new ChapterInfo();
            ci.LangCode = (string)root.Attribute(XNamespace.Xml + "lang");
            ci.Extractor = (string)root.Attribute("extractor");

            if (root.Element(CgNs + "title") != null)
                ci.Title = (string)root.Element(CgNs + "title");

            XElement @ref = root.Element(CgNs + "ref");
            if (@ref != null)
            {
                ci.ChapterSetId = (int?)@ref.Element(CgNs + "chapterSetId");
                ci.ImdbId = (string)@ref.Element(CgNs + "imdbId");
                ci.MovieDbId = (int?)@ref.Element(CgNs + "movieDbId");
            }

            XElement src = root.Element(CgNs + "source");
            if (src != null)
            {
                ci.SourceName = (string)src.Element(CgNs + "name");
                if (src.Element(CgNs + "type") != null)
                    ci.SourceType = (string)src.Element(CgNs + "type");
                ci.SourceHash = (string)src.Element(CgNs + "hash");
                ci.FramesPerSecond = Convert.ToDouble(src.Element(CgNs + "fps").Value, new System.Globalization.NumberFormatInfo());
                ci.Duration = TimeSpan.Parse(src.Element(CgNs + "duration").Value);
            }

            ci.Chapters = root.Element(CgNs + "chapters").Elements(CgNs + "chapter")
              .Select(e => new ChapterEntry() { Name = (string)e.Attribute("name"), Time = TimeSpan.Parse((string)e.Attribute("time")) }).ToList();
            return ci;
        }
Example #13
0
        public static ChapterInfo Load(string filename)
        {
            XDocument doc = XDocument.Load(filename);

            return(ChapterInfo.Load(doc.Root));
        }
Example #14
0
        public static ChapterInfo Load(XmlReader r)
        {
            XDocument doc = XDocument.Load(r);

            return(ChapterInfo.Load(doc.Root));
        }
Example #15
0
 protected void OnStreamDetected(ChapterInfo pgc)
 {
     if (StreamDetected != null) StreamDetected(this, new ProgramChainArg() { ProgramChain = pgc });
 }
Example #16
0
 protected void OnChaptersLoaded(ChapterInfo pgc)
 {
     if (ChaptersLoaded != null) ChaptersLoaded(this, new ProgramChainArg() { ProgramChain = pgc });
 }
Example #17
0
        public override List <ChapterInfo> GetStreams(string location, int numtitle)
        {
            ChapterInfo         pgc      = new ChapterInfo();
            List <ChapterEntry> chapters = new List <ChapterEntry>();

            pgc.SourceName = location;
            pgc.SourceHash = ChapterExtractor.ComputeMD5Sum(location);
            pgc.SourceType = "Blu-Ray";
            pgc.Extractor  = Application.ProductName + " " + Application.ProductVersion;
            pgc.Title      = Path.GetFileNameWithoutExtension(location);

            FileInfo fileInfo = new FileInfo(location);

            byte[] data = File.ReadAllBytes(location);

            string fileType = ASCIIEncoding.ASCII.GetString(data, 0, 8);

            if ((fileType != "MPLS0100" && fileType != "MPLS0200")
                /*|| data[45] != 1*/)
            {
                throw new Exception(string.Format(
                                        "Playlist {0} has an unknown file type {1}.",
                                        fileInfo.Name, fileType));
            }

            Debug.WriteLine(string.Format("\tFileType: {0}", fileType));

            List <Clip> chapterClips = GetClips(data);

            pgc.Duration = new TimeSpan((long)(chapterClips.Sum(c => c.Length) * (double)TimeSpan.TicksPerSecond));
            OnStreamDetected(pgc);

            int chaptersIndex =
                ((int)data[12] << 24) +
                ((int)data[13] << 16) +
                ((int)data[14] << 8) +
                ((int)data[15]);

            int chaptersLength =
                ((int)data[chaptersIndex] << 24) +
                ((int)data[chaptersIndex + 1] << 16) +
                ((int)data[chaptersIndex + 2] << 8) +
                ((int)data[chaptersIndex + 3]);

            byte[] chapterData = new byte[chaptersLength];
            Array.Copy(data, chaptersIndex + 4, chapterData, 0, chaptersLength);

            int chapterCount  = ((int)chapterData[0] << 8) + chapterData[1];
            int chapterOffset = 2;

            for (int chapterIndex = 0; chapterIndex < chapterCount; chapterIndex++)
            {
                if (chapterData[chapterOffset + 1] == 1)
                {
                    int streamFileIndex =
                        ((int)chapterData[chapterOffset + 2] << 8) +
                        chapterData[chapterOffset + 3];

                    Clip streamClip = chapterClips[streamFileIndex];

                    long chapterTime =
                        ((long)chapterData[chapterOffset + 4] << 24) +
                        ((long)chapterData[chapterOffset + 5] << 16) +
                        ((long)chapterData[chapterOffset + 6] << 8) +
                        ((long)chapterData[chapterOffset + 7]);

                    double chapterSeconds  = (double)chapterTime / 45000D;
                    double relativeSeconds = chapterSeconds - streamClip.TimeIn + streamClip.RelativeTimeIn;
                    chapters.Add(new ChapterEntry()
                    {
                        Name = string.Empty,
                        Time = new TimeSpan((long)(relativeSeconds * (double)TimeSpan.TicksPerSecond))
                    });
                }
                chapterOffset += 14;
            }
            pgc.Chapters = chapters;

            //TODO: get real FPS
            pgc.FramesPerSecond = mvCentralCore.Settings.DefaultFPS;

            OnChaptersLoaded(pgc);
            OnExtractionComplete();
            return(new List <ChapterInfo>()
            {
                pgc
            });
        }
Example #18
0
        public override List<ChapterInfo> GetStreams(string location, int numtitle)
        {
            List<ChapterInfo> pgcs = new List<ChapterInfo>();

              ProcessStartInfo psi = new ProcessStartInfo(@"d:\programs\eac3to\eac3to.exe", location);
              psi.CreateNoWindow = true;
              psi.UseShellExecute = false;
              //psi.RedirectStandardError = true;
              psi.RedirectStandardOutput = true;
              psi.WorkingDirectory = Application.StartupPath;
              Process p = Process.Start(psi);
              string output = p.StandardOutput.ReadToEnd();
              p.WaitForExit();

              foreach (Match m in Regex.Matches(output, @"\d\).+:\d\d"))
              {
            string[] data = m.Value.Split(',');

            string sourceFile = Path.Combine(Path.Combine(Path.Combine(
              location, "BDMV"), "PLAYLIST"), data[0].Split(')')[1].Trim());

            ChapterInfo pgc = new ChapterInfo()
            {
              Duration = TimeSpan.Parse(data[data.Length - 1].Trim()),
              SourceName = data[0].Split(')')[0],
              SourceHash = ChapterExtractor.ComputeMD5Sum(sourceFile)
            };
            OnStreamDetected(pgc);
            pgcs.Add(pgc);
              }
              /*
            1) 00001.mpls, 00002.m2ts, 1:34:15
               - h264/AVC, 1080p24 /1.001 (16:9)
               - AC3, Spanish, multi-channel, 48khz
               - DTS Master Audio, English, multi-channel, 48khz

            2) 00027.mpls, 00036.m2ts, 0:24:19
               - h264/AVC, 1080p24 /1.001 (16:9)
               - AC3, English, stereo, 48khz
               */

              foreach (ChapterInfo pgc in pgcs)
              {
            psi.Arguments = location + " " + pgc.SourceName + ")";
            p = Process.Start(psi);
            output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            if (output.Contains("Chapters"))
            {
              if (File.Exists("chapters.txt")) File.Delete("chapters.txt");
              psi.Arguments = location + " " + pgc.SourceName + ") chapters.txt";
              p = Process.Start(psi);
              output = p.StandardOutput.ReadToEnd();
              p.WaitForExit();
              if (!output.Contains("Creating file \"chapters.txt\"...") && !output.Contains("Done!"))
              {
            throw new Exception("Error creating chapters file.");
              }
              TextExtractor extractor = new TextExtractor();
              pgc.Chapters = extractor.GetStreams("chapters.txt", numtitle)[0].Chapters;
              OnChaptersLoaded(pgc);
            }
              }

              /*
            M2TS, 1 video track, 2 audio tracks, 6 subtitle tracks, 1:34:15
            1: Chapters, 25 chapters
            2: h264/AVC, 1080p24 /1.001 (16:9)
            3: AC3, Spanish, 5.1 channels, 448kbps, 48khz, dialnorm: -27dB
            4: DTS Master Audio, English, 5.1 channels, 24 bits, 48khz
               (core: DTS, 5.1 channels, 24 bits, 1509kbps, 48khz)
            5: Subtitle (PGS), English
            6: Subtitle (PGS), Spanish
            7: Subtitle (PGS), Spanish
            8: Subtitle (PGS), French
            9: Subtitle (PGS), Chinese
            10: Subtitle (PGS), Korean
               */

              OnExtractionComplete();
              return pgcs;
        }