public static IEnumerable <ChapterInfo> GetStreams(string ifoFile) { var pgcCount = IfoParser.GetPGCnb(ifoFile); for (var i = 1; i <= pgcCount; i++) { yield return(GetChapterInfo(ifoFile, i)); } }
private static List <Chapter> GetChapters(string ifoFile, int programChain, out IfoTimeSpan duration, out decimal fps) { var chapters = new List <Chapter>(); duration = IfoTimeSpan.Zero; fps = 0; var stream = new FileStream(ifoFile, FileMode.Open, FileAccess.Read, FileShare.Read); var pcgItPosition = stream.GetPCGIP_Position(); var programChainPrograms = -1; var programTime = TimeSpan.Zero; decimal fpsLocal; if (programChain >= 0) { var chainOffset = stream.GetChainOffset(pcgItPosition, programChain); programTime = stream.ReadTimeSpan(pcgItPosition, chainOffset, out fpsLocal) ?? TimeSpan.Zero; programChainPrograms = stream.GetNumberOfPrograms(pcgItPosition, chainOffset); } else { var programChains = stream.GetProgramChains(pcgItPosition); for (var curChain = 1; curChain <= programChains; curChain++) { var chainOffset = stream.GetChainOffset(pcgItPosition, curChain); var time = stream.ReadTimeSpan(pcgItPosition, chainOffset, out fpsLocal); if (time == null) { break; } if (time.Value <= programTime) { continue; } programChain = curChain; programChainPrograms = stream.GetNumberOfPrograms(pcgItPosition, chainOffset); programTime = time.Value; } } if (programChain < 0) { return(null); } chapters.Add(new Chapter { Name = "Chapter 01", Time = TimeSpan.Zero }); var longestChainOffset = stream.GetChainOffset(pcgItPosition, programChain); int programMapOffset = IfoParser.ToInt16(stream.GetFileBlock((pcgItPosition + longestChainOffset) + 230, 2)); int cellTableOffset = IfoParser.ToInt16(stream.GetFileBlock((pcgItPosition + longestChainOffset) + 0xE8, 2)); for (var currentProgram = 0; currentProgram < programChainPrograms; ++currentProgram) { int entryCell = stream.GetFileBlock(((pcgItPosition + longestChainOffset) + programMapOffset) + currentProgram, 1)[0]; var exitCell = entryCell; if (currentProgram < (programChainPrograms - 1)) { exitCell = stream.GetFileBlock(((pcgItPosition + longestChainOffset) + programMapOffset) + (currentProgram + 1), 1)[0] - 1; } var totalTime = IfoTimeSpan.Zero; for (var currentCell = entryCell; currentCell <= exitCell; currentCell++) { var cellStart = cellTableOffset + ((currentCell - 1) * 0x18); var bytes = stream.GetFileBlock((pcgItPosition + longestChainOffset) + cellStart, 4); var cellType = bytes[0] >> 6; if (cellType == 0x00 || cellType == 0x01) { bytes = stream.GetFileBlock(((pcgItPosition + longestChainOffset) + cellStart) + 4, 4); var ret = IfoParser.ReadTimeSpan(bytes, out fps) ?? IfoTimeSpan.Zero; totalTime.IsNTSC = ret.IsNTSC; totalTime += ret; } } duration.IsNTSC = totalTime.IsNTSC; duration += totalTime; if (currentProgram + 1 < programChainPrograms) { chapters.Add(new Chapter { Name = $"Chapter {currentProgram + 2:D2}", Time = duration }); } } stream.Dispose(); return(chapters); }