[libbluray-devel] [Git][videolan/libbluray][master] Parse chapter name metadata present on some discs
Petri Hintukainen
gitlab at videolan.org
Thu Jul 23 18:44:14 CEST 2020
Petri Hintukainen pushed to branch master at VideoLAN / libbluray
Commits:
bbe8341e by hpi1 at 2020-07-23T19:36:05+03:00
Parse chapter name metadata present on some discs
- - - - -
2 changed files:
- src/libbluray/bdnav/meta_parse.c
- src/libbluray/bdnav/meta_parse.h
Changes:
=====================================
src/libbluray/bdnav/meta_parse.c
=====================================
@@ -57,6 +57,9 @@
struct meta_root {
uint8_t dl_count;
META_DL * dl_entries;
+
+ unsigned tn_count;
+ META_TN *tn_entries;
};
#ifdef HAVE_LIBXML2
@@ -122,16 +125,39 @@ static void _parseManifestNode(xmlNode * a_node, META_DL *disclib)
}
}
+static void _parseTnManifestNode(xmlNode * a_node, META_TN *disclib)
+{
+ xmlNode *cur_node = NULL;
+
+ for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+ if (cur_node->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur_node->parent->name, BAD_CAST_CONST "chapters")) {
+ if (xmlStrEqual(cur_node->name, BAD_CAST_CONST "name")) {
+ char **new_entries = realloc(disclib->chapter_name, ((disclib->num_chapter + 1)*sizeof(char *)));
+ if (new_entries) {
+ int i = disclib->num_chapter;
+ disclib->num_chapter++;
+ disclib->chapter_name = new_entries;
+ disclib->chapter_name[i] = (char*)xmlNodeGetContent(cur_node);
+ }
+ }
+ }
+ }
+ _parseTnManifestNode(cur_node->children, disclib);
+ }
+}
+
static void _findMetaXMLfiles(META_ROOT *meta, BD_DISC *disc)
{
BD_DIR_H *dir;
BD_DIRENT ent;
+ int res;
+
dir = disc_open_dir(disc, "BDMV" DIR_SEP "META" DIR_SEP "DL");
if (dir == NULL) {
BD_DEBUG(DBG_DIR, "Failed to open meta dir BDMV/META/DL/\n");
- return;
- }
- int res;
+ } else {
+
for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
if (ent.d_name[0] == '.')
continue;
@@ -151,6 +177,31 @@ static void _findMetaXMLfiles(META_ROOT *meta, BD_DISC *disc)
}
}
dir_close(dir);
+ }
+
+ dir = disc_open_dir(disc, "BDMV" DIR_SEP "META" DIR_SEP "TN");
+ if (dir == NULL) {
+ BD_DEBUG(DBG_DIR, "Failed to open meta dir BDMV/META/TN/\n");
+ } else {
+ for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
+ if (strncasecmp(ent.d_name, "tnmt_", 5) == 0 && strlen(ent.d_name) == 18 ) {
+ META_TN *new_tn_entries = realloc(meta->tn_entries, ((meta->tn_count + 1)*sizeof(META_TN)));
+ if (new_tn_entries) {
+ uint8_t i = meta->tn_count;
+ meta->tn_count++;
+ meta->tn_entries = new_tn_entries;
+ memset(&meta->tn_entries[i], 0, sizeof(meta->tn_entries[i]));
+
+ meta->tn_entries[i].filename = str_dup(ent.d_name);
+ strncpy(meta->tn_entries[i].language_code, ent.d_name + 5, 3);
+ meta->tn_entries[i].playlist = atoi(ent.d_name + 9);
+ meta->tn_entries[i].language_code[3] = '\0';
+ str_tolower(meta->tn_entries[i].language_code);
+ }
+ }
+ }
+ dir_close(dir);
+ }
}
#endif
@@ -195,6 +246,30 @@ META_ROOT *meta_parse(BD_DISC *disc)
X_FREE(data);
}
}
+
+ for (i = 0; i < root->tn_count; i++) {
+ uint8_t *data = NULL;
+ size_t size;
+ size = disc_read_file(disc, "BDMV" DIR_SEP "META" DIR_SEP "TN",
+ root->tn_entries[i].filename,
+ &data);
+ if (!data || size == 0) {
+ BD_DEBUG(DBG_DIR, "Failed to read BDMV/META/TN/%s\n", root->tn_entries[i].filename);
+ } else {
+ xmlDocPtr doc;
+ doc = xmlReadMemory((char*)data, (int)size, NULL, NULL, 0);
+ if (doc == NULL) {
+ BD_DEBUG(DBG_DIR, "Failed to parse BDMV/META/TN/%s\n", root->tn_entries[i].filename);
+ } else {
+ xmlNode *root_element = NULL;
+ root_element = xmlDocGetRootElement(doc);
+ _parseTnManifestNode(root_element, &root->tn_entries[i]);
+ xmlFreeDoc(doc);
+ }
+ X_FREE(data);
+ }
+ }
+
xmlCleanupParser();
return root;
#else
@@ -239,6 +314,48 @@ const META_DL *meta_get(const META_ROOT *meta_root, const char *language_code)
#endif
}
+const META_TN *meta_get_tn(const META_ROOT *meta_root, const char *language_code, unsigned playlist)
+{
+#ifdef HAVE_LIBXML2
+ unsigned i;
+ META_TN *tn_default = NULL, *tn_first = NULL;
+
+ if (meta_root == NULL || meta_root->tn_count == 0) {
+ return NULL;
+ }
+
+ for (i = 0; i < meta_root->tn_count; i++) {
+ if (meta_root->tn_entries[i].playlist == playlist) {
+ if (language_code && strcmp(language_code, meta_root->tn_entries[i].language_code) == 0) {
+ return &meta_root->tn_entries[i];
+ }
+ if (strcmp(DEFAULT_LANGUAGE, meta_root->tn_entries[i].language_code) == 0) {
+ tn_default = &meta_root->tn_entries[i];
+ }
+ if (!tn_first) {
+ tn_first = &meta_root->tn_entries[i];
+ }
+ }
+ }
+
+ if (tn_default) {
+ BD_DEBUG(DBG_DIR, "Requested disclib language '%s' not found, using default language '" DEFAULT_LANGUAGE "'\n", language_code);
+ return tn_default;
+ }
+ if (tn_first) {
+ BD_DEBUG(DBG_DIR, "Requested disclib language '%s' or default '" DEFAULT_LANGUAGE "' not found, using '%s' instead\n",
+ language_code, tn_first->language_code);
+ return tn_first;
+ }
+ return NULL;
+#else
+ (void)meta_root;
+ (void)language_code;
+ (void)playlist;
+ return NULL;
+#endif
+}
+
void meta_free(META_ROOT **p)
{
(void)p;
@@ -261,6 +378,17 @@ void meta_free(META_ROOT **p)
XML_FREE((*p)->dl_entries[i].di_alternative);
}
X_FREE((*p)->dl_entries);
+
+ for (i = 0; i < (*p)->tn_count; i++) {
+ uint32_t c;
+ for (c = 0; c < (*p)->tn_entries[i].num_chapter; c++) {
+ XML_FREE((*p)->tn_entries[i].chapter_name[c]);
+ }
+ X_FREE((*p)->tn_entries[i].chapter_name);
+ X_FREE((*p)->tn_entries[i].filename);
+ }
+ X_FREE((*p)->tn_entries);
+
X_FREE(*p);
}
#endif
=====================================
src/libbluray/bdnav/meta_parse.h
=====================================
@@ -24,13 +24,24 @@
struct bd_disc;
struct meta_dl;
+struct meta_tn;
struct meta_root;
typedef struct meta_root META_ROOT;
+typedef struct meta_tn {
+ char language_code[4];
+ char * filename;
+
+ unsigned playlist;
+ unsigned num_chapter;
+ char **chapter_name;
+} META_TN;
+
BD_PRIVATE struct meta_root * meta_parse(struct bd_disc *disc) BD_ATTR_MALLOC;
BD_PRIVATE void meta_free (struct meta_root **index);
BD_PRIVATE const struct meta_dl * meta_get (const struct meta_root *meta_root, const char *language_code);
+BD_PRIVATE const struct meta_tn * meta_get_tn(const struct meta_root *meta_root, const char *language_code, unsigned playlist);
#endif // _META_PARSE_H_
View it on GitLab: https://code.videolan.org/videolan/libbluray/-/commit/bbe8341e03b1ca538120f3ba36e8927c98172b66
--
View it on GitLab: https://code.videolan.org/videolan/libbluray/-/commit/bbe8341e03b1ca538120f3ba36e8927c98172b66
You're receiving this email because of your account on code.videolan.org.
More information about the libbluray-devel
mailing list