public IFOParse(string filename) { m_file = new FileInfo(filename); FileStream fs = File.OpenRead(filename); try { #region Header // verify valid video IFO header byte[] id = new byte[12]; if (fs.Read(id, 0, 12) != 12) { throw new IOException("Error reading IFO file"); } string idStr = Encoding.ASCII.GetString(id, 0, 12); if (idStr != "DVDVIDEO-VTS") { throw new Exception("Invalid IFO Header"); } #endregion #region Version // verify IFO version (1.0 or 1.1) if (fs.Seek(0x21, SeekOrigin.Begin) != 0x21) { throw new IOException("Error reading IFO file"); } byte[] version = new byte[1]; if (fs.Read(version, 0, 1) != 1) { throw new IOException("Error reading IFO file"); } if (version[0] != 0x10 && version[0] != 0x11) { throw new Exception("Invalid IFO Header Version"); } #endregion #region PGC Info // find offset to pgc tables if (fs.Seek(0xcc, SeekOrigin.Begin) != 0xcc) { throw new IOException("Error reading IFO file"); } byte[] pgcOffsetData = new byte[4]; if (fs.Read(pgcOffsetData, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } int pgcOffset = (pgcOffsetData[0] << 24) + (pgcOffsetData[1] << 16) + (pgcOffsetData[2] << 8) + pgcOffsetData[3]; // get count of pgcs if (fs.Seek(pgcOffset * 2048, SeekOrigin.Begin) != pgcOffset * 2048) { throw new IOException("Error reading IFO file"); } byte[] pgciData = new byte[2]; if (fs.Read(pgciData, 0, 2) != 2) { throw new IOException("Error reading IFO file"); } int pgcCount = (pgciData[0] << 8) + pgciData[1]; for (int i = 1; i <= pgcCount; i++) { ProgramChain pgc = new ProgramChain(this); // get pgc's info offset within pgc (length is 4 bytes into pgc info) if (fs.Seek((pgcOffset * 2048) + (i * 8) + 4, SeekOrigin.Begin) != (pgcOffset * 2048) + (i * 8) + 4) { throw new IOException("Error reading IFO file"); } byte[] pgcStartData = new byte[4]; if (fs.Read(pgcStartData, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } int pgcStart = (pgcStartData[0] << 24) + (pgcStartData[1] << 16) + (pgcStartData[2] << 8) + pgcStartData[3]; // get pgc's playback time if (fs.Seek((pgcOffset * 2048) + pgcStart + 4, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 4) { throw new IOException("Error reading IFO file"); } byte[] playbackTimeData = new byte[4]; if (fs.Read(playbackTimeData, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } // frame rate int frameRate = (playbackTimeData[3] & 0xC0) >> 6; if (frameRate == 3) { pgc.FrameRate = 30; } else if (frameRate == 1) { pgc.FrameRate = 25; } // duration int playbackTime = (playbackTimeData[0] << 24) + (playbackTimeData[1] << 16) + (playbackTimeData[2] << 8) + playbackTimeData[3]; int hour = ((playbackTime >> 28) & 0x0f) * 10 + ((playbackTime >> 24) & 0x0f); int min = ((playbackTime >> 20) & 0x0f) * 10 + ((playbackTime >> 16) & 0x0f); int sec = ((playbackTime >> 12) & 0x0f) * 10 + ((playbackTime >> 8) & 0x0f); int frame = (((playbackTime >> 4) & 0x0f) * 10 + (playbackTime & 0x0f)) - 120; pgc.Duration = hour * 3600 + min * 60 + sec; pgc.PartialFrames = frame; // get pgc's cell playback info table if (fs.Seek((pgcOffset * 2048) + pgcStart + 0xE8, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 0xE8) { throw new IOException("Error reading IFO file"); } byte[] C_PBKT_buf = new byte[2]; if (fs.Read(C_PBKT_buf, 0, 2) != 2) { throw new IOException("Error reading IFO file"); } int C_PBKT = (C_PBKT_buf[0] << 8) + C_PBKT_buf[1]; if (C_PBKT != 0) { C_PBKT += (pgcOffset * 2048) + pgcStart; } // get pgc's cell position info table if (fs.Seek((pgcOffset * 2048) + pgcStart + 0xEA, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 0xEA) { throw new IOException("Error reading IFO file"); } byte[] C_POST_buf = new byte[2]; if (fs.Read(C_POST_buf, 0, 2) != 2) { throw new IOException("Error reading IFO file"); } int C_POST = (C_POST_buf[0] << 8) + C_POST_buf[1]; if (C_POST != 0) { C_POST += (pgcOffset * 2048) + pgcStart; } // get pgc's number of cells if (fs.Seek((pgcOffset * 2048) + pgcStart + 3, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 3) { throw new IOException("Error reading IFO file"); } byte[] nCells_buf = new byte[1]; if (fs.Read(nCells_buf, 0, 1) != 1) { throw new IOException("Error reading IFO file"); } int nCells = nCells_buf[0]; int nAngles = 1; if (C_POST != 0 && C_PBKT != 0) { for (int nCell = 0; nCell < nCells; nCell++) { Cell c = new Cell(); // get info for cell /*if (fs.Seek(C_PBKT + 24 * nCell, SeekOrigin.Begin) != C_PBKT + 24 * nCell) * throw new IOException("Error reading IFO file"); * byte[] iCat_buf = new byte[1]; * if (fs.Read(iCat_buf, 0, 1) != 1) * throw new IOException("Error reading IFO file"); * * // ignore multi-angle * int iCat = iCat_buf[0] & 0xF10; * // 0101=First; 1001=Middle ; 1101=Last * if (iCat == 0x50) * nAngles = 1; * else if (iCat == 0x90) * nAngles++; * else if (iCat == 0xD0) * { * nAngles++; * break; * }*/ #region read duration if (fs.Seek(C_PBKT + 24 * nCell + 4, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 4) { throw new IOException("Error reading IFO file"); } playbackTimeData = new byte[4]; if (fs.Read(playbackTimeData, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } playbackTime = (playbackTimeData[0] << 24) + (playbackTimeData[1] << 16) + (playbackTimeData[2] << 8) + playbackTimeData[3]; hour = ((playbackTime >> 28) & 0x0f) * 10 + ((playbackTime >> 24) & 0x0f); min = ((playbackTime >> 20) & 0x0f) * 10 + ((playbackTime >> 16) & 0x0f); sec = ((playbackTime >> 12) & 0x0f) * 10 + ((playbackTime >> 8) & 0x0f); frame = (((playbackTime >> 4) & 0x0f) * 10 + (playbackTime & 0x0f)) - 120; c.Duration = hour * 3600 + min * 60 + sec; c.PartialFrames = frame; #endregion #region entry point if (fs.Seek(C_PBKT + 24 * nCell + 8, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 8) { throw new IOException("Error reading IFO file"); } byte[] entryPointBuf = new byte[4]; if (fs.Read(entryPointBuf, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } c.FirstSector = (entryPointBuf[0] << 24) + (entryPointBuf[1] << 16) + (entryPointBuf[2] << 8) + entryPointBuf[3]; #endregion #region last sector if (fs.Seek(C_PBKT + 24 * nCell + 20, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 20) { throw new IOException("Error reading IFO file"); } byte[] lastSectorBuf = new byte[4]; if (fs.Read(lastSectorBuf, 0, 4) != 4) { throw new IOException("Error reading IFO file"); } c.LastSector = (lastSectorBuf[0] << 24) + (lastSectorBuf[1] << 16) + (lastSectorBuf[2] << 8) + lastSectorBuf[3]; #endregion if (fs.Seek(C_POST + 4 * nCell, SeekOrigin.Begin) != C_POST + 4 * nCell) { throw new IOException("Error reading IFO file"); } byte[] vobIDBuf = new byte[2]; if (fs.Read(vobIDBuf, 0, 2) != 2) { throw new IOException("Error reading IFO file"); } c.VobID = (vobIDBuf[0] << 8) + vobIDBuf[1]; if (fs.Seek(C_POST + 4 * nCell + 3, SeekOrigin.Begin) != C_POST + 4 * nCell + 3) { throw new IOException("Error reading IFO file"); } byte[] cellIDBuf = new byte[1]; if (fs.Read(cellIDBuf, 0, 1) != 1) { throw new IOException("Error reading IFO file"); } c.CellID = cellIDBuf[0]; pgc.Cells.Add(c); } } pgc.Angles = nAngles; m_pgcs.Add(pgc); } #endregion #region Video if (fs.Seek(0x200, SeekOrigin.Begin) != 0x200) { throw new IOException("Error reading IFO file"); } byte[] videoAttributes = new byte[2]; if (fs.Read(videoAttributes, 0, 2) != 2) { throw new IOException("Error reading IFO file"); } byte va1 = videoAttributes[0]; byte va2 = videoAttributes[1]; // video mode if (((va1 & 0x30) >> 4) == 0) { m_videoMode = "NTSC"; } else if (((va1 & 0x30) >> 4) == 1) { m_videoMode = "PAL"; } // aspect if (((va1 & 0xC) >> 2) == 0) { m_aspectRatio = "4:3"; } else if (((va1 & 0xC) >> 2) == 3) { m_aspectRatio = "16:9"; } // resolution int resolution = ((va2 & 0x38) >> 3); switch (resolution) { case 0: m_resolution = "720x480"; break; case 1: m_resolution = "704x480"; break; case 2: m_resolution = "352x480"; break; case 3: m_resolution = "352x240"; break; } #endregion #region Audio // http://dvd.sourceforge.net/dvdinfo/ifo.html // find count of audio streams if (fs.Seek(0x203, SeekOrigin.Begin) != 0x203) { throw new IOException("Error reading IFO file"); } byte[] numAudio = new byte[1]; if (fs.Read(numAudio, 0, 1) != 1) { throw new IOException("Error reading IFO file"); } m_numAudio = numAudio[0]; for (int i = 0; i < m_numAudio; i++) { byte[] audioFormatData = new byte[8]; if (fs.Read(audioFormatData, 0, 8) != 8) { throw new IOException("Error reading IFO file"); } // check if the language is 'specified' string lang = ""; if (((audioFormatData[0] & 0xC) >> 2) > 0) { // extract the two character ASCII code for the language char langID1 = (char)audioFormatData[2]; char langID2 = (char)audioFormatData[3]; lang = String.Format("{0}{1}", (char)audioFormatData[2], (char)audioFormatData[3]); // translate some language codes //http://www.dvd-replica.com/DVD/vtslanguage.php if (lang == "en") { lang = "English"; } else if (lang == "es") { lang = "Spanish"; } else if (lang == "fr") { lang = "French"; } else if (lang == "ja") { lang = "Japanese"; } else if (lang == "ar") { lang = "Arabic"; } else if (lang == "no") { lang = "Norwegian"; } else if (lang == "pl") { lang = "Polish"; } else if (lang == "km") { lang = "Cambodian"; } else if (lang == "pt") { lang = "Portuguese"; } else if (lang == "zh") { lang = "Chinese"; } else if (lang == "ro") { lang = "Romanian"; } else if (lang == "ru") { lang = "Russian"; } else if (lang == "cs") { lang = "Czech"; } else if (lang == "da") { lang = "Danish"; } else if (lang == "nl") { lang = "Dutch"; } else if (lang == "sa") { lang = "Sanskrit"; } else if (lang == "eo") { lang = "Esperanto"; } else if (lang == "fi") { lang = "Finnish"; } else if (lang == "de") { lang = "German"; } else if (lang == "el") { lang = "Greek"; } else if (lang == "sw") { lang = "Swahili"; } else if (lang == "sv") { lang = "Swedish"; } else if (lang == "iw") { lang = "Hebrew"; } else if (lang == "hi") { lang = "Hindi"; } else if (lang == "th") { lang = "Thai"; } else if (lang == "ga") { lang = "Irish"; } else if (lang == "it") { lang = "Italian"; } else if (lang == "vi") { lang = "Vietnamese"; } else if (lang == "ko") { lang = "Korean"; } else if (lang == "ji") { lang = "Yiddish"; } else if (lang == "la") { lang = "Latin"; } else if (audioFormatData[2] == 0) { lang = ""; } int audioType = audioFormatData[5]; switch (audioType) { case 0: case 1: case 2: //for visually impaired break; case 3: //director's comments case 4: //alt. director's comments lang += "/c"; break; } } // display the number of channels in the audio stream int channels = (audioFormatData[1] & 0x7) + 1; if (lang != "") { lang += " "; } lang += String.Format("{0}ch", channels); // find the format for the stream and add it to the format list if it is supported int audioFormat = (audioFormatData[0] & 0xe0) >> 5; switch (audioFormat) { case 0: m_audioFormat.Add(new AudioFormatDetails("AC3", lang, 0x80 + i)); break; case 2: m_audioFormat.Add(new AudioFormatDetails("MPEG1", lang, 0xC0 + i)); break; case 4: m_audioFormat.Add(new AudioFormatDetails("LPCM", lang, 0xA0 + i)); break; case 6: // DTS case 3: // MPEG 2 default: // ignore other stream types (don't add to the list) //throw new IOException("This DVD contains an unsupported audio type"); //m_audioFormat.Add(new AudioFormatDetails("DTS", lang, 0x88 + i)); break; } } #endregion #region VOB File info // VTS_##_0.IFO -> VTS_##_1.VOB string vobFile = filename.Replace("0.IFO", "1.VOB"); int idx = vobFile.LastIndexOf("_"); if (idx == -1) { // got a straight vob file like "TRAILER.VOB" VOB v = new VOB(filename.ToUpper().Replace("IFO", "VOB")); m_vobs.Add(v); } else { string vobBase = ""; int vobNum = 0; long nextSectors = 0; // extract the VOB index # into vobNum // vobBase will contain the title's index vobBase = vobFile.Substring(0, idx); // up to last _ vobNum = Convert.ToInt32(vobFile.Substring(idx + 1, 1)); if (vobNum == 0) { vobNum++; } while (true) { vobFile = vobBase + "_" + vobNum.ToString("0") + ".VOB"; vobNum++; if (File.Exists(vobFile) == false) { break; } VOB v = new VOB(vobFile); v.FirstSector = nextSectors; nextSectors += v.Sectors; m_vobs.Add(v); } } #endregion } finally { fs.Close(); } }
public IFOParse(string filename) { m_file = new FileInfo(filename); FileStream fs = File.OpenRead(filename); try { #region Header // verify valid video IFO header byte[] id = new byte[12]; if(fs.Read(id, 0, 12) != 12) throw new IOException("Error reading IFO file"); string idStr = Encoding.ASCII.GetString(id, 0, 12); if(idStr != "DVDVIDEO-VTS") throw new Exception("Invalid IFO Header"); #endregion #region Version // verify IFO version (1.0 or 1.1) if(fs.Seek(0x21, SeekOrigin.Begin) != 0x21) throw new IOException("Error reading IFO file"); byte[] version = new byte[1]; if(fs.Read(version, 0, 1) != 1) throw new IOException("Error reading IFO file"); if(version[0] != 0x10 && version[0] != 0x11) throw new Exception("Invalid IFO Header Version"); #endregion #region PGC Info // find offset to pgc tables if(fs.Seek(0xcc, SeekOrigin.Begin) != 0xcc) throw new IOException("Error reading IFO file"); byte[] pgcOffsetData = new byte[4]; if(fs.Read(pgcOffsetData, 0, 4) != 4) throw new IOException("Error reading IFO file"); int pgcOffset = (pgcOffsetData[0] << 24) + (pgcOffsetData[1] << 16) + (pgcOffsetData[2] << 8) + pgcOffsetData[3]; // get count of pgcs if(fs.Seek(pgcOffset * 2048, SeekOrigin.Begin) != pgcOffset * 2048) throw new IOException("Error reading IFO file"); byte[] pgciData = new byte[2]; if(fs.Read(pgciData, 0, 2) != 2) throw new IOException("Error reading IFO file"); int pgcCount = (pgciData[0] << 8) + pgciData[1]; for (int i = 1; i <= pgcCount; i++) { ProgramChain pgc = new ProgramChain(this); // get pgc's info offset within pgc (length is 4 bytes into pgc info) if(fs.Seek((pgcOffset * 2048) + (i * 8) + 4, SeekOrigin.Begin) != (pgcOffset * 2048) + (i * 8) + 4) throw new IOException("Error reading IFO file"); byte[] pgcStartData = new byte[4]; if(fs.Read(pgcStartData, 0, 4) != 4) throw new IOException("Error reading IFO file"); int pgcStart = (pgcStartData[0] << 24) + (pgcStartData[1] << 16) + (pgcStartData[2] << 8) + pgcStartData[3]; // get pgc's playback time if(fs.Seek((pgcOffset * 2048) + pgcStart + 4, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 4) throw new IOException("Error reading IFO file"); byte[] playbackTimeData = new byte[4]; if(fs.Read(playbackTimeData, 0, 4) != 4) throw new IOException("Error reading IFO file"); // frame rate int frameRate = (playbackTimeData[3] & 0xC0) >> 6; if(frameRate == 3) pgc.FrameRate = 30; else if(frameRate == 1) pgc.FrameRate = 25; // duration int playbackTime = (playbackTimeData[0] << 24) + (playbackTimeData[1] << 16) + (playbackTimeData[2] << 8) + playbackTimeData[3]; int hour = ((playbackTime >> 28) & 0x0f) * 10 + ((playbackTime >> 24) & 0x0f); int min = ((playbackTime >> 20) & 0x0f) * 10 + ((playbackTime >> 16) & 0x0f); int sec = ((playbackTime >> 12) & 0x0f) * 10 + ((playbackTime >> 8) & 0x0f); int frame = (((playbackTime >> 4) & 0x0f) * 10 + (playbackTime & 0x0f)) - 120; pgc.Duration = hour * 3600 + min * 60 + sec; pgc.PartialFrames = frame; // get pgc's cell playback info table if (fs.Seek((pgcOffset * 2048) + pgcStart + 0xE8, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 0xE8) throw new IOException("Error reading IFO file"); byte[] C_PBKT_buf = new byte[2]; if (fs.Read(C_PBKT_buf, 0, 2) != 2) throw new IOException("Error reading IFO file"); int C_PBKT = (C_PBKT_buf[0] << 8) + C_PBKT_buf[1]; if (C_PBKT != 0) C_PBKT += (pgcOffset * 2048) + pgcStart; // get pgc's cell position info table if (fs.Seek((pgcOffset * 2048) + pgcStart + 0xEA, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 0xEA) throw new IOException("Error reading IFO file"); byte[] C_POST_buf = new byte[2]; if (fs.Read(C_POST_buf, 0, 2) != 2) throw new IOException("Error reading IFO file"); int C_POST = (C_POST_buf[0] << 8) + C_POST_buf[1]; if (C_POST != 0) C_POST += (pgcOffset * 2048) + pgcStart; // get pgc's number of cells if (fs.Seek((pgcOffset * 2048) + pgcStart + 3, SeekOrigin.Begin) != (pgcOffset * 2048) + pgcStart + 3) throw new IOException("Error reading IFO file"); byte[] nCells_buf = new byte[1]; if (fs.Read(nCells_buf, 0, 1) != 1) throw new IOException("Error reading IFO file"); int nCells = nCells_buf[0]; int nAngles = 1; if (C_POST != 0 && C_PBKT != 0) { for (int nCell = 0; nCell < nCells; nCell++) { Cell c = new Cell(); // get info for cell /*if (fs.Seek(C_PBKT + 24 * nCell, SeekOrigin.Begin) != C_PBKT + 24 * nCell) throw new IOException("Error reading IFO file"); byte[] iCat_buf = new byte[1]; if (fs.Read(iCat_buf, 0, 1) != 1) throw new IOException("Error reading IFO file"); // ignore multi-angle int iCat = iCat_buf[0] & 0xF10; // 0101=First; 1001=Middle ; 1101=Last if (iCat == 0x50) nAngles = 1; else if (iCat == 0x90) nAngles++; else if (iCat == 0xD0) { nAngles++; break; }*/ #region read duration if (fs.Seek(C_PBKT + 24 * nCell + 4, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 4) throw new IOException("Error reading IFO file"); playbackTimeData = new byte[4]; if (fs.Read(playbackTimeData, 0, 4) != 4) throw new IOException("Error reading IFO file"); playbackTime = (playbackTimeData[0] << 24) + (playbackTimeData[1] << 16) + (playbackTimeData[2] << 8) + playbackTimeData[3]; hour = ((playbackTime >> 28) & 0x0f) * 10 + ((playbackTime >> 24) & 0x0f); min = ((playbackTime >> 20) & 0x0f) * 10 + ((playbackTime >> 16) & 0x0f); sec = ((playbackTime >> 12) & 0x0f) * 10 + ((playbackTime >> 8) & 0x0f); frame = (((playbackTime >> 4) & 0x0f) * 10 + (playbackTime & 0x0f)) - 120; c.Duration = hour * 3600 + min * 60 + sec; c.PartialFrames = frame; #endregion #region entry point if (fs.Seek(C_PBKT + 24 * nCell + 8, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 8) throw new IOException("Error reading IFO file"); byte[] entryPointBuf = new byte[4]; if (fs.Read(entryPointBuf, 0, 4) != 4) throw new IOException("Error reading IFO file"); c.FirstSector = (entryPointBuf[0] << 24) + (entryPointBuf[1] << 16) + (entryPointBuf[2] << 8) + entryPointBuf[3]; #endregion #region last sector if (fs.Seek(C_PBKT + 24 * nCell + 20, SeekOrigin.Begin) != C_PBKT + 24 * nCell + 20) throw new IOException("Error reading IFO file"); byte[] lastSectorBuf = new byte[4]; if (fs.Read(lastSectorBuf, 0, 4) != 4) throw new IOException("Error reading IFO file"); c.LastSector = (lastSectorBuf[0] << 24) + (lastSectorBuf[1] << 16) + (lastSectorBuf[2] << 8) + lastSectorBuf[3]; #endregion if (fs.Seek(C_POST + 4 * nCell, SeekOrigin.Begin) != C_POST + 4 * nCell) throw new IOException("Error reading IFO file"); byte[] vobIDBuf = new byte[2]; if (fs.Read(vobIDBuf, 0, 2) != 2) throw new IOException("Error reading IFO file"); c.VobID = (vobIDBuf[0] << 8) + vobIDBuf[1]; if (fs.Seek(C_POST + 4 * nCell + 3, SeekOrigin.Begin) != C_POST + 4 * nCell + 3) throw new IOException("Error reading IFO file"); byte[] cellIDBuf = new byte[1]; if (fs.Read(cellIDBuf, 0, 1) != 1) throw new IOException("Error reading IFO file"); c.CellID = cellIDBuf[0]; pgc.Cells.Add(c); } } pgc.Angles = nAngles; m_pgcs.Add(pgc); } #endregion #region Video if(fs.Seek(0x200, SeekOrigin.Begin) != 0x200) throw new IOException("Error reading IFO file"); byte[] videoAttributes = new byte[2]; if(fs.Read(videoAttributes, 0, 2) != 2) throw new IOException("Error reading IFO file"); byte va1 = videoAttributes[0]; byte va2 = videoAttributes[1]; // video mode if(((va1 & 0x30) >> 4) == 0) m_videoMode = "NTSC"; else if(((va1 & 0x30) >> 4) == 1) m_videoMode = "PAL"; // aspect if(((va1 & 0xC) >> 2) == 0) m_aspectRatio = "4:3"; else if(((va1 & 0xC) >> 2) == 3) m_aspectRatio = "16:9"; // resolution int resolution = ((va2 & 0x38) >> 3); switch(resolution) { case 0: m_resolution = "720x480"; break; case 1: m_resolution = "704x480"; break; case 2: m_resolution = "352x480"; break; case 3: m_resolution = "352x240"; break; } #endregion #region Audio // find count of audio streams if(fs.Seek(0x203, SeekOrigin.Begin) != 0x203) throw new IOException("Error reading IFO file"); byte[] numAudio = new byte[1]; if(fs.Read(numAudio, 0, 1) != 1) throw new IOException("Error reading IFO file"); m_numAudio = numAudio[0]; byte[] audioFormatData = new byte[1]; if(fs.Read(audioFormatData, 0, 1) != 1) throw new IOException("Error reading IFO file"); int audioFormat = (audioFormatData[0] & 0xe0) >> 5; switch(audioFormat) { case 0: m_audioFormat = "AC3"; break; case 2: m_audioFormat = "MPEG1"; break; case 3: m_audioFormat = "MPEG2"; break; case 4: m_audioFormat = "LPCM"; break; case 6: m_audioFormat = "DTS"; break; } #endregion #region VOB File info // VTS_##_0.IFO -> VTS_##_1.VOB string vobFile = filename.Replace("0.IFO", "1.VOB"); int idx = vobFile.LastIndexOf("_"); if (idx == -1) { // got a straight vob file like "TRAILER.VOB" VOB v = new VOB(filename.ToUpper().Replace("IFO", "VOB")); m_vobs.Add(v); } else { string vobBase = ""; int vobNum = 0; long nextSectors = 0; // extract the VOB index # into vobNum // vobBase will contain the title's index vobBase = vobFile.Substring(0, idx); // up to last _ vobNum = Convert.ToInt32(vobFile.Substring(idx + 1, 1)); if (vobNum == 0) vobNum++; while (true) { vobFile = vobBase + "_" + vobNum.ToString("0") + ".VOB"; vobNum++; if (File.Exists(vobFile) == false) break; VOB v = new VOB(vobFile); v.FirstSector = nextSectors; nextSectors += v.Sectors; m_vobs.Add(v); } } #endregion } finally { fs.Close(); } }