[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