[libdvdnav-devel] [Git][videolan/libdvdread][master] 7 commits: make the menu reader reusable

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Wed Jul 29 06:42:42 UTC 2026



Jean-Baptiste Kempf pushed to branch master at VideoLAN / libdvdread


Commits:
4edd91ae by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
make the menu reader reusable

- - - - -
37b57f2f by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
read the audio manager menu

- - - - -
422b3573 by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
make the highlight reader reusable

- - - - -
c648e17d by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
read still video highlights

- - - - -
03fc2c92 by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
identify the text data manager start address

- - - - -
867cd6c7 by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
read the text data language units

- - - - -
8aab6551 by Saifelden Mohamed Ismail at 2026-07-29T08:40:31+02:00
read the audio manager text data

- - - - -


4 changed files:

- src/dvdread/ifo_types.h
- src/dvdread/nav_read.h
- src/ifo_read.c
- src/nav_read.c


Changes:

=====================================
src/dvdread/ifo_types.h
=====================================
@@ -596,9 +596,11 @@ typedef struct {
   uint32_t att_srpt_sa;     /* start sector of the audio title SRPT */
   uint32_t aott_srpt_sa;    /* start sector of the audio only title SRPT */
   uint32_t amgm_pgci_ut_sa; /* start sector of the menu PGCI unit table */
-  uint8_t  zero_9[48];
+  uint8_t  zero_9[4];
+  uint32_t txtdt_mgi_sa;    /* start sector of the text data manager */
+  uint8_t  zero_10[40];
   uint8_t  last_sector_audio_sys_space;
-  uint8_t  zero_10[79];
+  uint8_t  zero_11[79];
   uint8_t  menu_prescence_3; /* will be set to 0x01*/
     /* XXX lots of padding after this to complete the sector*/
 } ATTRIBUTE_PACKED amgi_mat_t;
@@ -1391,6 +1393,9 @@ typedef struct {
 
       /* ASVS */
       asvs_mat_t             *asvs_mat;
+
+      pgci_ut_t              *amgm_pgci_ut;
+      txtdt_mgi_t            *amg_txtdt_mgi;
     };
 
     struct{


=====================================
src/dvdread/nav_read.h
=====================================
@@ -39,6 +39,7 @@ extern "C" {
  * @param buffer Pointer to the buffer of the on disc PCI data.
  */
 DVDREAD_API void navRead_PCI(pci_t *, unsigned char *);
+DVDREAD_API void navRead_ASV_PCI(pci_t *, unsigned char *);
 
 /**
  * Reads the DSI packet data pointed to into dsi struct.


=====================================
src/ifo_read.c
=====================================
@@ -92,6 +92,8 @@ static const uint8_t my_friendly_zeros[2048];
 /* Prototypes for internal functions */
 static int ifoRead_VMG(ifo_handle_t *ifofile);
 static int ifoRead_AMG(ifo_handle_t *ifofile);
+static int ifoRead_AMGM_PGCI_UT(ifo_handle_t *ifofile);
+static int ifoRead_AMG_TXTDT_MGI(ifo_handle_t *ifofile);
 /* Can be used to make simple dvd-a playback, no menus*/
 static int ifoRead_SAMG(ifo_handle_t *ifofile);
 /* for the still video set */
@@ -125,10 +127,14 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
                                        unsigned int sector);
 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
                                   unsigned int offset);
+static int ifoRead_TXTDT_MGI_at(ifo_handle_t *ifofile, txtdt_mgi_t **dest,
+                                unsigned int sector);
 
 static void ifoFree_PGC(pgc_t *pgc);
 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
 static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
+static void ifoFree_PGCI_UT_internal(pgci_ut_t *pgci_ut);
+static void ifoFree_TXTDT_MGI_internal(txtdt_mgi_t *txtdt_mgi);
 
 static inline int DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) {
   return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset);
@@ -474,6 +480,12 @@ static ifo_handle_t *ifoOpenFileOrBackup(dvd_reader_t *ctx, int title,
     if(!ifoRead_TIF(ifofile,2))
       goto ifoOpen_fail;
 
+    /* must be read before the file is closed below */
+    if(!ifoRead_AMGM_PGCI_UT(ifofile))
+      Log1(ctx, "Failed to read the audio manager menu (AMGM_PGCI_UT)");
+    if(!ifoRead_AMG_TXTDT_MGI(ifofile))
+      Log1(ctx, "Failed to read the audio manager text data (TXTDT_MGI)");
+
     /* Should read SAMG as it contains location to AOB pointers */
     DVDCloseFile(ifop->file);
     ifop->file = DVDOpenFile(ctx, 2, DVD_READ_SAMG_INFO);
@@ -807,6 +819,9 @@ void ifoClose(ifo_handle_t *ifofile) {
         free(ifofile->vtsi_mat);
       break;
     case IFO_AUDIO:
+      ifoFree_PGCI_UT_internal(ifofile->amgm_pgci_ut);
+      ifoFree_TXTDT_MGI_internal(ifofile->amg_txtdt_mgi);
+
       if(ifofile->amgi_mat)
         free(ifofile->amgi_mat);
 
@@ -1413,6 +1428,7 @@ static int ifoRead_AMG(ifo_handle_t *ifofile) {
   B2N_32(amgi_mat->att_srpt_sa);
   B2N_32(amgi_mat->aott_srpt_sa);
   B2N_32(amgi_mat->amgm_pgci_ut_sa);
+  B2N_32(amgi_mat->txtdt_mgi_sa);
   CHECK_ZERO(amgi_mat->zero_1);
   CHECK_ZERO(amgi_mat->zero_2);
   CHECK_ZERO(amgi_mat->zero_3);
@@ -1421,6 +1437,7 @@ static int ifoRead_AMG(ifo_handle_t *ifofile) {
   CHECK_ZERO(amgi_mat->zero_6);
   CHECK_ZERO(amgi_mat->zero_9);
   CHECK_ZERO(amgi_mat->zero_10);
+  CHECK_ZERO(amgi_mat->zero_11);
   CHECK_VALUE(amgi_mat->specification_version == 0x0012);
 
   return 1;
@@ -3281,47 +3298,28 @@ static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) {
   return -1;
 }
 
-int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
+static int ifoRead_PGCI_UT_at(ifo_handle_t *ifofile, pgci_ut_t **dest,
+                              unsigned int sector) {
   struct ifo_handle_private_s *ifop = PRIV(ifofile);
   pgci_ut_t *pgci_ut;
-  unsigned int sector;
   unsigned int i;
   int info_length;
   uint8_t *data, *ptr;
 
-  if(!ifofile)
-    return 0;
-
-  if(ifofile->vmgi_mat) {
-    if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
-      return 1;
-    sector = ifofile->vmgi_mat->vmgm_pgci_ut;
-  } else if(ifofile->vtsi_mat) {
-    if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
-      return 1;
-    sector = ifofile->vtsi_mat->vtsm_pgci_ut;
-  } else {
-    return 0;
-  }
-
-  ifofile->pgci_ut = calloc(1, sizeof(pgci_ut_t));
-  if(!ifofile->pgci_ut)
+  pgci_ut = calloc(1, sizeof(pgci_ut_t));
+  if(!pgci_ut)
     return 0;
 
   if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) {
-    free(ifofile->pgci_ut);
-    ifofile->pgci_ut = NULL;
+    free(pgci_ut);
     return 0;
   }
 
-  if(!(DVDReadBytes(ifop->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
-    free(ifofile->pgci_ut);
-    ifofile->pgci_ut = NULL;
+  if(!(DVDReadBytes(ifop->file, pgci_ut, PGCI_UT_SIZE))) {
+    free(pgci_ut);
     return 0;
   }
 
-  pgci_ut = ifofile->pgci_ut;
-
   B2N_16(pgci_ut->nr_of_lus);
   B2N_32(pgci_ut->last_byte);
 
@@ -3334,13 +3332,11 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
   data = calloc(1, info_length);
   if(!data) {
     free(pgci_ut);
-    ifofile->pgci_ut = NULL;
     return 0;
   }
   if(!(DVDReadBytes(ifop->file, data, info_length))) {
     free(data);
     free(pgci_ut);
-    ifofile->pgci_ut = NULL;
     return 0;
   }
 
@@ -3348,7 +3344,6 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
   if(!pgci_ut->lu) {
     free(data);
     free(pgci_ut);
-    ifofile->pgci_ut = NULL;
     return 0;
   }
   ptr = data;
@@ -3389,7 +3384,6 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
       }
       free(pgci_ut->lu);
       free(pgci_ut);
-      ifofile->pgci_ut = NULL;
       return 0;
     }
     pgci_ut->lu[i].pgcit->ref_count = 1;
@@ -3403,34 +3397,81 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
       }
       free(pgci_ut->lu);
       free(pgci_ut);
-      ifofile->pgci_ut = NULL;
       return 0;
     }
     /* FIXME: Iterate and verify that all menus that should exists accordingly
      * to pgci_ut->lu[i].exists really do? */
   }
 
+  *dest = pgci_ut;
   return 1;
 }
 
+int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
+  unsigned int sector;
 
-void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
   if(!ifofile)
-    return;
+    return 0;
+
+  if(ifofile->vmgi_mat) {
+    if(ifofile->vmgi_mat->vmgm_pgci_ut == 0)
+      return 1;
+    sector = ifofile->vmgi_mat->vmgm_pgci_ut;
+  } else if(ifofile->vtsi_mat) {
+    if(ifofile->vtsi_mat->vtsm_pgci_ut == 0)
+      return 1;
+    sector = ifofile->vtsi_mat->vtsm_pgci_ut;
+  } else {
+    return 0;
+  }
+
+  return ifoRead_PGCI_UT_at(ifofile, &ifofile->pgci_ut, sector);
+}
+
+static int ifoRead_AMGM_PGCI_UT(ifo_handle_t *ifofile) {
+  if(!ifofile || !ifofile->amgi_mat)
+    return 0;
+
+  if(ifofile->amgi_mat->amgm_pgci_ut_sa == 0)
+    return 1;
+
+  return ifoRead_PGCI_UT_at(ifofile, &ifofile->amgm_pgci_ut,
+                            ifofile->amgi_mat->amgm_pgci_ut_sa);
+}
+
+static int ifoRead_AMG_TXTDT_MGI(ifo_handle_t *ifofile) {
+  if(!ifofile || !ifofile->amgi_mat)
+    return 0;
 
-  if(ifofile->pgci_ut) {
+  if(ifofile->amgi_mat->txtdt_mgi_sa == 0)
+    return 1;
+
+  return ifoRead_TXTDT_MGI_at(ifofile, &ifofile->amg_txtdt_mgi,
+                              ifofile->amgi_mat->txtdt_mgi_sa);
+}
+
+
+static void ifoFree_PGCI_UT_internal(pgci_ut_t *pgci_ut) {
+  if(pgci_ut) {
     unsigned int i;
 
-    for(i = 0; i < ifofile->pgci_ut->nr_of_lus; i++) {
-      ifoFree_PGCIT_internal(ifofile->pgci_ut->lu[i].pgcit);
-      ifofile->pgci_ut->lu[i].pgcit = NULL;
+    for(i = 0; i < pgci_ut->nr_of_lus; i++) {
+      ifoFree_PGCIT_internal(pgci_ut->lu[i].pgcit);
+      pgci_ut->lu[i].pgcit = NULL;
     }
-    free(ifofile->pgci_ut->lu);
-    free(ifofile->pgci_ut);
-    ifofile->pgci_ut = NULL;
+    free(pgci_ut->lu);
+    free(pgci_ut);
   }
 }
 
+void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
+  if(!ifofile)
+    return;
+
+  ifoFree_PGCI_UT_internal(ifofile->pgci_ut);
+  ifofile->pgci_ut = NULL;
+}
+
 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
                                   vts_attributes_t *vts_attributes,
                                   unsigned int offset) {
@@ -3587,47 +3628,91 @@ void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
 }
 
 
-int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
+static int ifoRead_TXTDT_MGI_at(ifo_handle_t *ifofile, txtdt_mgi_t **dest,
+                                unsigned int sector) {
   struct ifo_handle_private_s *ifop = PRIV(ifofile);
   txtdt_mgi_t *txtdt_mgi;
+  unsigned int i;
+  int info_length;
+  uint8_t *data, *ptr;
 
-  if(!ifofile)
+  txtdt_mgi = calloc(1, sizeof(txtdt_mgi_t));
+  if(!txtdt_mgi)
     return 0;
 
-  if(!ifofile->vmgi_mat)
+  if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) {
+    free(txtdt_mgi);
     return 0;
+  }
 
-  /* Return successfully if there is nothing to read. */
-  if(ifofile->vmgi_mat->txtdt_mgi == 0)
-    return 1;
-
-  if(!DVDFileSeek_(ifop->file,
-                   ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
+  if(!(DVDReadBytes(ifop->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
+    Log0(ifop->ctx, "Unable to read TXTDT_MGI.");
+    free(txtdt_mgi);
     return 0;
+  }
 
-  txtdt_mgi = calloc(1, sizeof(txtdt_mgi_t));
-  if(!txtdt_mgi) {
+  B2N_16(txtdt_mgi->nr_of_language_units);
+  B2N_32(txtdt_mgi->last_byte);
+
+  CHECK_VALUE(TXTDT_MGI_SIZE
+              + (uint32_t)txtdt_mgi->nr_of_language_units * TXTDT_LU_SIZE
+              <= txtdt_mgi->last_byte + 1);
+
+  info_length = txtdt_mgi->nr_of_language_units * TXTDT_LU_SIZE;
+  data = calloc(1, info_length);
+  if(!data) {
+    free(txtdt_mgi);
+    return 0;
+  }
+  if(!(DVDReadBytes(ifop->file, data, info_length))) {
+    free(data);
+    free(txtdt_mgi);
     return 0;
   }
-  ifofile->txtdt_mgi = txtdt_mgi;
 
-  if(!(DVDReadBytes(ifop->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
-    Log0(ifop->ctx, "Unable to read TXTDT_MGI.");
+  txtdt_mgi->lu = calloc(txtdt_mgi->nr_of_language_units, sizeof(txtdt_lu_t));
+  if(!txtdt_mgi->lu) {
+    free(data);
     free(txtdt_mgi);
-    ifofile->txtdt_mgi = NULL;
     return 0;
   }
+  ptr = data;
+  for(i = 0; i < txtdt_mgi->nr_of_language_units; i++) {
+    memcpy(&txtdt_mgi->lu[i], ptr, TXTDT_LU_SIZE);
+    ptr += TXTDT_LU_SIZE;
+    B2N_16(txtdt_mgi->lu[i].lang_code);
+    B2N_32(txtdt_mgi->lu[i].txtdt_start_byte);
+    CHECK_VALUE(txtdt_mgi->lu[i].txtdt_start_byte <= txtdt_mgi->last_byte);
+  }
+  free(data);
 
-  /* Log1(ifop->ctx, "-- Not done yet --\n"); */
+  *dest = txtdt_mgi;
   return 1;
 }
 
+int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
+  if(!ifofile || !ifofile->vmgi_mat)
+    return 0;
+
+  /* Return successfully if there is nothing to read. */
+  if(ifofile->vmgi_mat->txtdt_mgi == 0)
+    return 1;
+
+  return ifoRead_TXTDT_MGI_at(ifofile, &ifofile->txtdt_mgi,
+                              ifofile->vmgi_mat->txtdt_mgi);
+}
+
+static void ifoFree_TXTDT_MGI_internal(txtdt_mgi_t *txtdt_mgi) {
+  if(txtdt_mgi) {
+    free(txtdt_mgi->lu);
+    free(txtdt_mgi);
+  }
+}
+
 void ifoFree_TXTDT_MGI(ifo_handle_t *ifofile) {
   if(!ifofile)
     return;
 
-  if(ifofile->txtdt_mgi) {
-    free(ifofile->txtdt_mgi);
-    ifofile->txtdt_mgi = NULL;
-  }
+  ifoFree_TXTDT_MGI_internal(ifofile->txtdt_mgi);
+  ifofile->txtdt_mgi = NULL;
 }


=====================================
src/nav_read.c
=====================================
@@ -41,8 +41,10 @@
                 __FILE__, __LINE__, # arg );\
   }
 
+static void read_hli(pci_t *pci, unsigned char *buffer);
+
 void navRead_PCI(pci_t *pci, unsigned char *buffer) {
-  int32_t i, j;
+  int32_t i;
   getbits_state_t state;
   if (!getbits_init(&state, buffer)) abort(); /* Passed NULL pointers */
 
@@ -93,6 +95,24 @@ void navRead_PCI(pci_t *pci, unsigned char *buffer) {
   for(i = 0; i < 9; i++)
     pci->nsml_agli.nsml_agl_dsta[i] = getbits(&state, 32 );
 
+  read_hli(pci, buffer + 96);
+
+#ifndef NDEBUG
+  CHECK_VALUE(pci->pci_gi.zero1 == 0);
+#endif /* !NDEBUG */
+}
+
+/* the still picture NAV packet, substream 0x02, has no PCI general information */
+void navRead_ASV_PCI(pci_t *pci, unsigned char *buffer) {
+  memset(pci, 0, sizeof(*pci));
+  read_hli(pci, buffer);
+}
+
+static void read_hli(pci_t *pci, unsigned char *buffer) {
+  int32_t i, j;
+  getbits_state_t state;
+  if (!getbits_init(&state, buffer)) abort();
+
   /* pci hli hli_gi */
   pci->hli.hl_gi.hli_ss = getbits(&state, 16 );
   pci->hli.hl_gi.hli_s_ptm = getbits(&state, 32 );
@@ -150,9 +170,6 @@ void navRead_PCI(pci_t *pci, unsigned char *buffer) {
 #ifndef NDEBUG
   /* Asserts */
 
-  /* pci pci gi */
-  CHECK_VALUE(pci->pci_gi.zero1 == 0);
-
   /* pci hli hli_gi */
   CHECK_VALUE(pci->hli.hl_gi.zero1 == 0);
   CHECK_VALUE(pci->hli.hl_gi.zero2 == 0);



View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/f6b2ca10dc96ece32896b5cc7969b4eb94d18ee0...8aab6551a3a5de40649a74d98cdfad003d5e4ba7

-- 
View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/f6b2ca10dc96ece32896b5cc7969b4eb94d18ee0...8aab6551a3a5de40649a74d98cdfad003d5e4ba7
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the libdvdnav-devel mailing list