/** * Reads the given VMG file. * * @param dvdDir Mount directory of the DVD * @param vmgName Path and name of the VMG file */ private void readVmgFile(File dvdDir, String vmgName) throws IOException { LOG.info("Reading VMG file %s", vmgName); try (IfoRandomAccessFile vmg = new IfoRandomAccessFile(dvdDir, vmgName)) { if (!"DVDVIDEO-VMG".equals(vmg.readFixedString(12))) { throw new IfoException("No VMG file"); } long tt_srpt = vmg.at(0xC4).readOffset(); LOG.debug("tt_srpt: 0x%08X", tt_srpt); vmg.at(tt_srpt); int titlesCount = vmg.readu16(); LOG.debug("titlesCount: %d", titlesCount); long endAddress = vmg.skip(2).readu32(); long computedTitles = endAddress / 12; LOG.debug("computedTitles: %d", computedTitles); if (computedTitles != titlesCount) { LOG.warn( "Different number of titles: %d != %d, using the latter one", titlesCount, computedTitles); titlesCount = (int) computedTitles; } int lastVtsn = -1; List<DvdTitle> vtsnTitles = new ArrayList<>(); for (int ix = 0; ix < titlesCount; ix++) { DvdTitle title = new DvdTitle(); title.setTitle(ix + 1); title.setAngles(vmg.skip(1).readu8()); title.setChapters(vmg.readu16()); title.setVtsn(vmg.skip(2).readu8()); title.setVts(vmg.readu8()); vmg.skip(4); titles.add(title); LOG.debug("Title %2d: vtsn=%d, vts=%d", title.getTitle(), title.getVtsn(), title.getVts()); if (title.getVtsn() != lastVtsn) { if (!vtsnTitles.isEmpty()) { completeTitles(dvdDir, lastVtsn, vtsnTitles); } vtsnTitles.clear(); lastVtsn = title.getVtsn(); } vtsnTitles.add(title); } if (!vtsnTitles.isEmpty()) { completeTitles(dvdDir, lastVtsn, vtsnTitles); } } }