[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