Commit cc45b823 authored by Fraxinas's avatar Fraxinas

add metadata parser to extract detail info from disclib xml files on bluray

parent e5c6cbdf
......@@ -31,6 +31,7 @@ library_not_found="Could not find required library!"
function_not_found="Could not find required function!"
using_dlopen_crypto_libs="Using libaacs and libbdplus via dlopen."
using_normal_linking="Using libaacs and libbdplus via normal linking."
libxml2_missing="Could not find libxml2 - disclib meta parser disabled."
# configure options
AC_ARG_ENABLE([dlopen-crypto-libs],
......@@ -141,6 +142,9 @@ fi
AM_CONDITIONAL([DLOPEN_CRYPTO_LIBS],
[test $use_dlopen_crypto_libs = "auto" || test $use_dlopen_crypto_libs = "yes"])
# libxml2 for metadata parser
PKG_CHECK_MODULES(LIBXML2, libxml-2.0 >= 2.6, AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if libxml2 is to be used for metadata parsing]), AC_MSG_NOTICE($libxml2_missing))
# function testing for supported compiler options
check_cc_options()
{
......
......@@ -14,7 +14,7 @@ SET_DEBUG_OPTS = @SET_DEBUG_OPTS@
SET_INCLUDES = -I$(top_srcdir) -Ifile -Ilibbluray/bdnav
AM_CFLAGS = -std=c99 $(SET_FEATURES) $(SET_WARNINGS) $(SET_OPTIMIZATIONS) \
$(SET_DEBUG_OPTS) $(SET_INCLUDES)
$(SET_DEBUG_OPTS) $(SET_INCLUDES) $(LIBXML2_CFLAGS)
CFLAGS=$(shell test -z "$$CFLAGS" || echo "$$CFLAGS")
SOURCES_bdj = libbluray/bdj/bdj.h \
......@@ -48,6 +48,9 @@ libbluray_la_SOURCES=libbluray/bluray.h \
libbluray/bdnav/mpls_parse.c \
libbluray/bdnav/index_parse.h \
libbluray/bdnav/clpi_parse.h \
libbluray/bdnav/meta_data.h \
libbluray/bdnav/meta_parse.c \
libbluray/bdnav/meta_parse.h \
libbluray/decoders \
libbluray/decoders/pes_buffer.h \
libbluray/decoders/pes_buffer.c \
......@@ -86,8 +89,8 @@ libbluray_la_SOURCES=libbluray/bluray.h \
util/log_control.h \
util/bits.h \
util/logging.h
libbluray_la_HEADERS= libbluray/bluray.h file/filesystem.h util/log_control.h libbluray/keys.h libbluray/decoders/overlay.h
libbluray_la_LDFLAGS= -version-info $(LIB_VERSION_INFO) $(DLOPEN_LDFLAGS)
libbluray_la_HEADERS= libbluray/bluray.h file/filesystem.h util/log_control.h libbluray/keys.h libbluray/decoders/overlay.h libbluray/bdnav/meta_data.h
libbluray_la_LDFLAGS= -version-info $(LIB_VERSION_INFO) $(DLOPEN_LDFLAGS) $(LIBXML2_LIBS)
if USING_BDJAVA
libbluray_la_SOURCES+=$(SOURCES_bdj)
......
/*
* This file is part of libbluray
* Copyright (C) 2010 fraxinas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#if !defined(_META_DATA_H_)
#define _META_DATA_H_
#include <stdint.h>
typedef struct meta_thumbnail {
char * path;
uint32_t xres;
uint32_t yres;
} META_THUMBNAIL;
typedef struct meta_title {
uint32_t title_number;
char * title_name;
} META_TITLE;
typedef struct meta_dl {
char language_code[4];
char * filename;
char * di_name;
char * di_alternative;
uint8_t di_num_sets;
uint8_t di_set_number;
uint32_t toc_count;
META_TITLE * toc_entries;
uint8_t thumb_count;
META_THUMBNAIL * thumbnails;
} META_DL;
typedef struct meta_root {
uint8_t dl_count;
META_DL * dl_entries;
} META_ROOT;
#endif // _META_DATA_H_
/*
* This file is part of libbluray
* Copyright (C) 2010 fraxinas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "file/file.h"
#include "util/bits.h"
#include "util/logging.h"
#include "util/macro.h"
#include "util/strutl.h"
#include "meta_parse.h"
#include "libbluray/register.h"
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#ifdef HAVE_LIBXML2
#include <libxml/parser.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#endif
#ifdef HAVE_LIBXML2
static void _parseManifestNode(xmlNode * a_node, META_DL *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, xmlCharStrdup("title"))) {
if (xmlStrEqual(cur_node->name, xmlCharStrdup("name"))) {
disclib->di_name = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
}
if (xmlStrEqual(cur_node->name, xmlCharStrdup("alternative"))) {
disclib->di_alternative = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
}
if (xmlStrEqual(cur_node->name, xmlCharStrdup("numSets"))) {
disclib->di_num_sets = atoi((char*)xmlNodeGetContent(cur_node));
}
if (xmlStrEqual(cur_node->name, xmlCharStrdup("setNumber"))) {
disclib->di_set_number = atoi((char*)xmlNodeGetContent(cur_node));
}
}
else if (xmlStrEqual(cur_node->parent->name, xmlCharStrdup("tableOfContents"))) {
if (xmlStrEqual(cur_node->name, xmlCharStrdup("titleName")) && xmlGetProp(cur_node, xmlCharStrdup("titleNumber"))) {
int i = disclib->toc_count;
disclib->toc_count++;
disclib->toc_entries = realloc(disclib->toc_entries, (disclib->toc_count*sizeof(META_TITLE)));
disclib->toc_entries[i].title_number = atoi((const char*)xmlGetProp(cur_node, xmlCharStrdup("titleNumber")));
disclib->toc_entries[i].title_name = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
}
}
else if (xmlStrEqual(cur_node->parent->name, xmlCharStrdup("description"))) {
if (xmlStrEqual(cur_node->name, xmlCharStrdup("thumbnail")) && xmlGetProp(cur_node, xmlCharStrdup("href"))) {
uint8_t i = disclib->thumb_count;
disclib->thumb_count++;
disclib->thumbnails = realloc(disclib->thumbnails, (disclib->thumb_count*sizeof(META_THUMBNAIL)));
int len = xmlStrlen(xmlGetProp(cur_node, xmlCharStrdup("href")));
disclib->thumbnails[i].path = (char*) malloc(len+1);
strcpy(disclib->thumbnails[i].path, (char*) xmlGetProp(cur_node, xmlCharStrdup("href")));
if (xmlGetProp(cur_node, xmlCharStrdup("size"))) {
sscanf((const char*)xmlGetProp(cur_node, xmlCharStrdup("size")), "%ix%i", &disclib->thumbnails[i].xres, &disclib->thumbnails[i].yres);
}
else {
disclib->thumbnails[i].xres = disclib->thumbnails[i].yres = -1;
}
}
}
}
_parseManifestNode(cur_node->children, disclib);
}
}
static void _findMetaXMLfiles(META_ROOT *meta, const char *device_path)
{
BD_DIR_H *dir;
BD_DIRENT ent;
char *path = NULL;
path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "META" DIR_SEP "DL", device_path);
dir = dir_open(path);
if (dir == NULL) {
DEBUG(DBG_DIR, "Failed to open meta dir %s\n", path);
X_FREE(path);
return;
}
int res;
for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
if (ent.d_name[0] == '.')
continue;
else if (ent.d_name != NULL && strncasecmp(ent.d_name, "bdmt_", 5) == 0) {
uint8_t i = meta->dl_count;
meta->dl_count++;
meta->dl_entries = realloc(meta->dl_entries, (meta->dl_count*sizeof(META_DL)));
meta->dl_entries[i].filename = str_printf("%s", ent.d_name);
strncpy(meta->dl_entries[i].language_code, ent.d_name+5,3);
meta->dl_entries[i].language_code[3] = '\0';
}
}
dir_close(dir);
X_FREE(path);
}
#endif
META_ROOT *meta_parse(const char *device_path)
{
#ifdef HAVE_LIBXML2
META_ROOT *root = calloc(1, sizeof(META_ROOT));
root->dl_count = 0;
xmlDocPtr doc;
_findMetaXMLfiles(root, device_path);
uint8_t i;
for (i = 0; i < root->dl_count; i++) {
char *base = NULL;
base = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "META" DIR_SEP "DL" , device_path);
char *path = NULL;
path = str_printf("%s" DIR_SEP "%s", base, root->dl_entries[i].filename);
BD_FILE_H *handle = file_open(path, "rb");
if (handle == NULL) {
DEBUG(DBG_DIR, "Failed to open meta file (%s)\n", path);
continue;
}
file_seek(handle, 0, SEEK_END);
int64_t length = file_tell(handle);
if (length > 0) {
file_seek(handle, 0, SEEK_SET);
uint8_t *data = malloc(length);
int64_t size_read = file_read(handle, data, length);
doc = xmlReadMemory((char*)data, size_read, base, NULL, 0);
if (doc == NULL) {
DEBUG(DBG_DIR, "Failed to parse %s\n", path);
continue;
}
xmlNode *root_element = NULL;
root_element = xmlDocGetRootElement(doc);
root->dl_entries[i].di_name = root->dl_entries[i].di_alternative = NULL;
root->dl_entries[i].di_num_sets = root->dl_entries[i].di_set_number = -1;
root->dl_entries[i].toc_count = root->dl_entries[i].thumb_count = 0;
root->dl_entries[i].toc_entries = NULL;
root->dl_entries[i].thumbnails = NULL;
_parseManifestNode(root_element, &root->dl_entries[i]);
xmlFreeDoc(doc);
X_FREE(data);
}
file_close(handle);
}
xmlCleanupParser();
return root;
#else
DEBUG(DBG_DIR, "configured without libxml2 - can't parse meta info\n");
return NULL;
#endif
}
META_DL *meta_get(META_ROOT *meta_root, const char *language_code)
{
if (meta_root == NULL || meta_root->dl_count == 0) {
DEBUG(DBG_DIR, "meta_get not possible, no info available!\n");
return NULL;
}
if (language_code) {
uint8_t i;
for (i = 0; i < meta_root->dl_count; i++) {
if (strcasecmp(language_code, meta_root->dl_entries[i].language_code) == 0) {
return &meta_root->dl_entries[i];
}
}
for (i = 0; i < meta_root->dl_count; i++) {
if (strcasecmp(DEFAULT_LANGUAGE, meta_root->dl_entries[i].language_code) == 0) {
DEBUG(DBG_DIR, "requested disclib language '%s' not found, using default '"DEFAULT_LANGUAGE"'\n", language_code);
return &meta_root->dl_entries[i];
}
}
}
DEBUG(DBG_DIR, "requested disclib language '%s' or default '"DEFAULT_LANGUAGE"' not found, using '%s' instead\n", language_code, meta_root->dl_entries[0].language_code);
return &meta_root->dl_entries[0];
}
void meta_free(META_ROOT **p)
{
if (p && *p)
{
uint8_t i;
for (i = 0; i < (*p)->dl_count; i++) {
uint32_t t;
for (t=0; i < (*p)->dl_entries[i].toc_count; t++) {
X_FREE((*p)->dl_entries[i].toc_entries[t].title_name);
X_FREE((*p)->dl_entries[i].toc_entries);
}
for (t = 0; i < (*p)->dl_entries[i].thumb_count; t++) {
X_FREE((*p)->dl_entries[i].thumbnails[t].path);
X_FREE((*p)->dl_entries[i].thumbnails);
}
X_FREE((*p)->dl_entries[i].filename);
X_FREE((*p)->dl_entries[i].di_name);
X_FREE((*p)->dl_entries[i].di_alternative);
}
X_FREE(*p);
}
}
/*
* This file is part of libbluray
* Copyright (C) 2010 fraxinas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include "meta_data.h"
#if !defined(_META_PARSE_H_)
#define _META_PARSE_H_
BD_PRIVATE META_ROOT* meta_parse(const char *device_path);
BD_PRIVATE void meta_free(META_ROOT **index);
BD_PRIVATE META_DL* meta_get(META_ROOT *meta_root, const char *language_code);
#endif // _META_PARSE_H_
......@@ -30,6 +30,7 @@
#include "util/strutl.h"
#include "bdnav/navigation.h"
#include "bdnav/index_parse.h"
#include "bdnav/meta_parse.h"
#include "hdmv/hdmv_vm.h"
#include "decoders/graphics_controller.h"
#include "file/file.h"
......@@ -90,6 +91,7 @@ struct bluray {
char *device_path;
BLURAY_DISC_INFO disc_info;
INDX_ROOT *index;
META_ROOT *meta;
NAV_TITLE_LIST *title_list;
/* current playlist */
......@@ -673,6 +675,18 @@ static int _index_open(BLURAY *bd)
return !!bd->index;
}
/*
* meta open
*/
static int _meta_open(BLURAY *bd)
{
if (!bd->meta){
bd->meta = meta_parse(bd->device_path);
}
return !!bd->meta;
}
/*
* disc info
*/
......@@ -738,6 +752,8 @@ BLURAY *bd_open(const char* device_path, const char* keyfile_path)
_index_open(bd);
bd->meta = NULL;
bd->regs = bd_registers_init();
_fill_disc_info(bd);
......@@ -1989,3 +2005,24 @@ void bd_register_overlay_proc(BLURAY *bd, void *handle, bd_overlay_proc_f func)
bd->graphics_controller = gc_init(bd->regs, handle, func);
}
}
struct meta_dl *bd_get_meta(BLURAY *bd)
{
if (!bd) {
return NULL;
}
if (!bd->meta) {
_meta_open(bd);
}
uint32_t psr_menu_lang = bd_psr_read(bd->regs, PSR_MENU_LANG);
if (psr_menu_lang != 0 && psr_menu_lang != 0xffffff) {
const char language_code[] = {(psr_menu_lang >> 16) & 0xff, (psr_menu_lang >> 8) & 0xff, psr_menu_lang & 0xff, 0 };
return meta_get(bd->meta, language_code);
}
else {
return meta_get(bd->meta, NULL);
}
}
......@@ -597,4 +597,14 @@ void bd_user_input(BLURAY *bd, int64_t pts, uint32_t key);
*/
void bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x, uint16_t y);
struct meta_dl;
/**
*
* Get meta information about the bluray disc.
*
* @param bd BLURAY object
* @return allocated META_DL (disclib) object, NULL on error
*/
struct meta_dl *bd_get_meta(BLURAY *bd);
#endif /* BLURAY_H_ */
......@@ -64,6 +64,8 @@ typedef enum {
/* 48-61: caps for characteristic text subtitle */
} bd_psr_idx;
#define DEFAULT_LANGUAGE "eng"
/*
*
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment