diff options
Diffstat (limited to 'xine/BluRay/input_bluray.c')
-rw-r--r-- | xine/BluRay/input_bluray.c | 667 |
1 files changed, 0 insertions, 667 deletions
diff --git a/xine/BluRay/input_bluray.c b/xine/BluRay/input_bluray.c deleted file mode 100644 index aa04122c..00000000 --- a/xine/BluRay/input_bluray.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Copyright (C) 2000-2005 the xine project - * - * Copyright (C) 2009 Petri Hintukainen <phintuka@users.sourceforge.net> - * - * This file is part of xine, a free video player. - * - * xine is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * xine 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * Input plugin for BluRay discs / images - * - * Requires libbluray from http://www.assembla.com/spaces/libbluray/ - * Tested with SVN revision 103 - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* asprintf: */ -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <dlfcn.h> - -#include <bluray.h> -#include <libbdnav/navigation.h> - -#define LOG_MODULE "input_bluray" -#define LOG_VERBOSE - -#define LOG - -#define LOGMSG(x...) xine_log (this->stream->xine, XINE_LOG_MSG, "input_bluray: " x); - - -#ifdef HAVE_CONFIG_H -# include "xine_internal.h" -# include "input_plugin.h" -#else -# include <xine/xine_internal.h> -# include <xine/input_plugin.h> -#endif - -#ifndef EXPORTED -# define EXPORTED __attribute__((visibility("default"))) -#endif - -#ifndef MIN -# define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#ifndef MAX -# define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#define ALIGNED_UNIT_SIZE 6144 -#define PKT_SIZE 192 -#define TICKS_IN_MS 45 - -typedef struct { - - input_class_t input_class; - - xine_t *xine; - - /* config */ - char *mountpoint; - char *keyfile; - char *device; - -} bluray_input_class_t; - -typedef struct { - input_plugin_t input_plugin; - - xine_stream_t *stream; - bluray_input_class_t *class; - char *mrl; - char *disc_root; - - BLURAY *bdh; - NAV_TITLE *nav_title; - -} bluray_input_plugin_t; - -static int open_clip (bluray_input_plugin_t *this, NAV_CLIP *clip) -{ - /* NOTE: bluray.h bd_select_title() actually opens CLIP, not TITLE ! */ - - int clip_id; - if (sscanf(clip->name, "%d.m2ts", &clip_id) != 1) - clip_id = 0; - - lprintf("Selecting clip %d: bd_select_title(%d - %s) for title %s\n", - clip_id, clip_id, clip->name, this->nav_title->name); - - if (!bd_select_title(this->bdh, clip_id)) { - LOGMSG("bd_select_title(%d) failed: %s\n", clip_id, strerror(errno)); - _x_message(this->stream, XINE_MSG_FILE_NOT_FOUND, this->mrl, NULL); - - return -1; - } - - lprintf("Clip length: %"PRIu64" bytes\n", (uint64_t)this->bdh->s_size); - - return 1; -} - -static int next_clip (bluray_input_plugin_t *this) -{ - /* select clip */ - - NAV_CLIP *clip = nav_next_clip(this->nav_title, NULL); - if (!clip) { - LOGMSG("nav_next_clip() FAILED\n"); - return -1; - } - lprintf("clip change: title %s clip %s (%d clips, %d chapters)\n", - this->nav_title->name, clip->name, - this->nav_title->clip_list.count, this->nav_title->chap_list.count); - - /* open clip */ - - return open_clip(this, clip); -} - -static int open_title (bluray_input_plugin_t *this, int title) -{ - if (this->nav_title) - nav_title_close(this->nav_title); - - /* open title */ - - char mpls[11] = {0}; - snprintf(mpls, sizeof(mpls), "%05d.mpls", MIN(99999, MAX(0, title))); - - this->nav_title = nav_title_open(this->disc_root, mpls); - - if (!this->nav_title) { - LOGMSG("nav_title_open(%s, %s) FAILED\n", this->disc_root, mpls); - return -1; - } - -#ifdef LOG - int ms = this->nav_title->duration / TICKS_IN_MS; - lprintf("Opened title %s. Length %"PRId64" bytes / %02d:%02d:%02d.%03d\n", - this->nav_title->name, (int64_t)this->nav_title->packets * PKT_SIZE, - ms / 3600000, (ms % 3600000 / 60000), (ms % 60000) / 1000, ms % 1000); -#endif - - /* set stream metainfo */ - - /* title */ - if (strcmp(this->disc_root, this->class->mountpoint)) { - char *t = strrchr(this->disc_root, '/'); - if (!t[1]) - while (t > this->disc_root && t[-1] != '/') t--; - t = strdup(t); - if (t[strlen(t)-1] == '/') - t[strlen(t)-1] = 0; - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, t); - free(t); - } - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_TITLE_NUMBER, title); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER, this->nav_title->angle); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, 1); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT, this->nav_title->chap_list.count); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_CHAPTERS, this->nav_title->chap_list.count>0); - - return next_clip(this); -} - -/* - * xine plugin interface - */ - -static uint32_t bluray_plugin_get_capabilities (input_plugin_t *this_gen) -{ - return INPUT_CAP_SEEKABLE | - INPUT_CAP_BLOCK | - INPUT_CAP_AUDIOLANG | - INPUT_CAP_SPULANG; -} - -static off_t bluray_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - if (!this || !this->bdh || len < 0) - return -1; - - if (this->bdh->aacs) { - - /* - * Split large reads to aligned units - */ - - off_t todo = len; - off_t block = MIN(todo, ALIGNED_UNIT_SIZE - (this->bdh->s_pos % ALIGNED_UNIT_SIZE)); - - while (block > 0) { - off_t result = bd_read(this->bdh, (unsigned char *)buf, block); - if (result != block) { - if (result < 0) { - LOGMSG("ERROR: bd_read(aacs, %"PRId64") : got %"PRId64" !\n", block, result); - return result; - } - return len - todo + MAX(0, result); - } - todo -= result; - buf += result; - - block = MIN(todo, ALIGNED_UNIT_SIZE); - } - - return len; - } - - off_t result = bd_read (this->bdh, (unsigned char *)buf, len); - - if (result < 0) - LOGMSG("bd_read() failed: %s (%d of %d)\n", strerror(errno), (int)result, (int)len); - -#if 0 - if (buf[4] != 0x47) { - LOGMSG("bd_read(): invalid data ? [%02x %02x %02x %02x %02x ...]\n", - buf[0], buf[1], buf[2], buf[3], buf[4]); - return 0; - } -#endif - - return result; -} - -static buf_element_t *bluray_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) -{ - buf_element_t *buf = fifo->buffer_pool_alloc (fifo); - - if (todo > (off_t)buf->max_size) - todo = buf->max_size; - - if (todo > ALIGNED_UNIT_SIZE) - todo = ALIGNED_UNIT_SIZE; - - if (todo > 0) { - - buf->size = bluray_plugin_read(this_gen, (char*)buf->mem, todo); - buf->type = BUF_DEMUX_BLOCK; - - if (buf->size > 0) - return buf; - } - - buf->free_buffer (buf); - return NULL; -} - -static off_t bluray_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - if (!this || !this->bdh || !this->nav_title) - return -1; - - /* convert relative seeks to absolute */ - - if (origin == SEEK_CUR) { - offset = this->bdh->s_pos + offset; - } - else if (origin == SEEK_END) { - if (offset < this->bdh->s_size) - offset = this->bdh->s_size - offset; - else - offset = 0; - } - - /* clip seek point to nearest random access point */ - - uint32_t in_pkt = offset / PKT_SIZE; - uint32_t out_pkt = in_pkt; - uint32_t out_time = 0; - nav_packet_search(this->nav_title, in_pkt, &out_pkt, &out_time); - lprintf("bluray_plugin_seek() seeking to %"PRId64" (packet %d)\n", offset, in_pkt); - offset = (off_t)PKT_SIZE * (off_t)out_pkt; - lprintf("Nearest random access point at %"PRId64" (packet %d)\n", offset, out_pkt); - - /* clip to aligned unit start */ - - offset -= (offset % ALIGNED_UNIT_SIZE); - - /* seek */ - - lprintf("bluray_plugin_seek() seeking to %lld (aligned unit)\n", (long long)offset); - - return bd_seek (this->bdh, offset); -} - -static off_t bluray_plugin_get_current_pos (input_plugin_t *this_gen) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - return this->bdh ? this->bdh->s_pos : 0; -} - -static off_t bluray_plugin_get_length (input_plugin_t *this_gen) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - return this->bdh ? this->bdh->s_size : -1; -} - -static uint32_t bluray_plugin_get_blocksize (input_plugin_t *this_gen) -{ - return ALIGNED_UNIT_SIZE; -} - -static const char* bluray_plugin_get_mrl (input_plugin_t *this_gen) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - return this->mrl; -} - -static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - if (!this || !this->stream || !data) - return INPUT_OPTIONAL_UNSUPPORTED; - - switch (data_type) { - - case INPUT_OPTIONAL_DATA_DEMUXER: -#ifdef HAVE_CONFIG_H - *(const char **)data = "mpeg-ts"; -#else - *(const char **)data = "mpeg-ts-hdmv"; -#endif - return INPUT_OPTIONAL_SUCCESS; - - /* - * audio track language: - * - channel number can be mpeg-ts PID (0x1100 ... 0x11ff) - */ - case INPUT_OPTIONAL_DATA_AUDIOLANG: - if (this->nav_title) { - int channel = *((int *)data); - CLPI_PROG *prog = &this->nav_title->clip_list.clip->cl->program.progs[0]; - int i, n = 0; - for (i=0 ; i < prog->num_streams; i++) - if (prog->streams[i].pid >= 0x1100 && prog->streams[i].pid < 0x1200) { - /* audio stream #n */ - if (channel == n || channel == prog->streams[i].pid) { - memcpy(data, prog->streams[i].lang, 4); - - lprintf("INPUT_OPTIONAL_DATA_AUDIOLANG: ch %d pid %x: %s\n", - channel, prog->streams[i].pid, prog->streams[i].lang); - - return INPUT_OPTIONAL_SUCCESS; - } - n++; - } - } - return INPUT_OPTIONAL_UNSUPPORTED; - - /* - * SPU track language: - * - channel number can be mpeg-ts PID (0x1200 ... 0x12ff) - */ - case INPUT_OPTIONAL_DATA_SPULANG: - if (this->nav_title) { - int channel = *((int *)data); - CLPI_PROG *prog = &this->nav_title->clip_list.clip->cl->program.progs[0]; - int i, n = 0; - for (i=0 ; i < prog->num_streams; i++) - if (prog->streams[i].pid >= 0x1200 && prog->streams[i].pid < 0x1300 && - prog->streams[i].coding_type >= 0x90 && prog->streams[i].coding_type <= 0x92) { - /* subtitle stream #n */ - if (channel == n || channel == prog->streams[i].pid) { - - memcpy(data, prog->streams[i].lang, 4); - - lprintf("INPUT_OPTIONAL_DATA_SPULANG: ch %d pid %x: %s\n", - channel, prog->streams[i].pid, prog->streams[i].lang); - - return INPUT_OPTIONAL_SUCCESS; - } - n++; - } - } - return INPUT_OPTIONAL_UNSUPPORTED; - - default: - return DEMUX_OPTIONAL_UNSUPPORTED; - } - - return INPUT_OPTIONAL_UNSUPPORTED; -} - -static void bluray_plugin_dispose (input_plugin_t *this_gen) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - - if (this->bdh) - bd_close(this->bdh); - - if (this->nav_title) - nav_title_close(this->nav_title); - - free (this->mrl); - free (this->disc_root); - - free (this); -} - -static int bluray_plugin_open (input_plugin_t *this_gen) -{ - bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen; - int title = -1, chapter = 0; - - lprintf("bluray_plugin_open\n"); - - /* validate mrl */ - - if (strncasecmp (this->mrl, "bluray:", 7)) - return -1; - - if (!strcasecmp (this->mrl, "bluray:") || - !strcasecmp (this->mrl, "bluray:/") || - !strcasecmp (this->mrl, "bluray://") || - !strcasecmp (this->mrl, "bluray:///")) { - - this->disc_root = strdup(this->class->mountpoint); - - } else if (!strncasecmp (this->mrl, "bluray:/", 8)) { - - if (!strncasecmp (this->mrl, "bluray:///", 10)) - this->disc_root = strdup(this->mrl + 9); - else if (!strncasecmp (this->mrl, "bluray://", 9)) - this->disc_root = strdup(this->mrl + 8); - else - this->disc_root = strdup(this->mrl + 7); - - _x_mrl_unescape(this->disc_root); - - if (this->disc_root[strlen(this->disc_root)-1] != '/') { - char *end = strrchr(this->disc_root, '/'); - if (end && end[1]) - if (sscanf(end, "/%d.%d", &title, &chapter) < 1) - title = 0; - *end = 0; - } - - } else { - return -1; - } - - /* if title was not in mrl, find the main title */ - - if (title < 0) { - char *main_title = nav_find_main_title(this->disc_root); - title = 0; - if (main_title) { - if (sscanf(main_title, "%d.mpls", &title) != 1) - title = 0; - lprintf("main title: %s (%d) \n", main_title, title); - } else { - LOGMSG("nav_find_main_title(%s) failed\n", this->disc_root); - } - } - - /* open libbluray */ - - /* replace ~/ in keyfile path */ - char *keyfile = NULL; - if (this->class->keyfile && !strncmp(this->class->keyfile, "~/", 2)) - if (asprintf(&keyfile, "%s/%s", xine_get_homedir(), this->class->keyfile + 2) < 0) - keyfile = NULL; - /* open */ - if (! (this->bdh = bd_open (this->disc_root, keyfile ?: this->class->keyfile))) { - LOGMSG("bd_open(\'%s\') failed: %s\n", this->disc_root, strerror(errno)); - free(keyfile); - return -1; - } - free(keyfile); - lprintf("bd_open(\'%s\') OK\n", this->disc_root); - - /* select title */ - - if (open_title(this, title) < 0) - return -1; - - /* jump to chapter */ - - if (chapter > 0) { - uint32_t out_pkt = 0; - NAV_CLIP *clip = nav_chapter_search(this->nav_title, chapter, &out_pkt); - bluray_plugin_seek(&this->input_plugin, (off_t)(clip->title_pkt + out_pkt) * PKT_SIZE, SEEK_SET); - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, chapter); - } - - return 1; -} - -static input_plugin_t *bluray_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, - const char *mrl) -{ - bluray_input_plugin_t *this; - - lprintf("bluray_class_get_instance\n"); - - if (strncasecmp (mrl, "bluray:", 7)) - return NULL; - - this = (bluray_input_plugin_t *) calloc(1, sizeof (bluray_input_plugin_t)); - - this->stream = stream; - this->class = (bluray_input_class_t*)cls_gen; - this->mrl = strdup(mrl); - - this->input_plugin.open = bluray_plugin_open; - this->input_plugin.get_capabilities = bluray_plugin_get_capabilities; - this->input_plugin.read = bluray_plugin_read; - this->input_plugin.read_block = bluray_plugin_read_block; - this->input_plugin.seek = bluray_plugin_seek; - this->input_plugin.get_current_pos = bluray_plugin_get_current_pos; - this->input_plugin.get_length = bluray_plugin_get_length; - this->input_plugin.get_blocksize = bluray_plugin_get_blocksize; - this->input_plugin.get_mrl = bluray_plugin_get_mrl; - this->input_plugin.get_optional_data = bluray_plugin_get_optional_data; - this->input_plugin.dispose = bluray_plugin_dispose; - this->input_plugin.input_class = cls_gen; - - return &this->input_plugin; -} - -/* - * plugin class - */ - -static void mountpoint_change_cb(void *data, xine_cfg_entry_t *cfg) -{ - bluray_input_class_t *this = (bluray_input_class_t *) data; - - this->mountpoint = cfg->str_value; -} - -static void device_change_cb(void *data, xine_cfg_entry_t *cfg) -{ - bluray_input_class_t *this = (bluray_input_class_t *) data; - - this->device = cfg->str_value; -} - -static void keyfile_change_cb(void *data, xine_cfg_entry_t *cfg) -{ - bluray_input_class_t *this = (bluray_input_class_t *) data; - - this->keyfile = cfg->str_value; -} - -static const char *bluray_class_get_description (input_class_t *this_gen) -{ - return _("BluRay input plugin"); -} - -static const char *bluray_class_get_identifier (input_class_t *this_gen) -{ - return "bluray"; -} - -static char **bluray_class_get_autoplay_list (input_class_t *this_gen, int *num_files) -{ - static char *autoplay_list[] = { "bluray:/", NULL }; - - *num_files = 1; - - return autoplay_list; -} - -static int bluray_class_eject_media (input_class_t *this_gen) -{ -#if 0 - bluray_input_class_t *this = (bluray_input_class_t*) this_gen; - - return media_eject_media (this->xine, this->device); -#endif - return 1; -} - -static void bluray_class_dispose (input_class_t *this_gen) -{ - bluray_input_class_t *this = (bluray_input_class_t *) this_gen; - config_values_t *config = this->xine->config; - - config->unregister_callback(config, "media.bluray.mountpoint"); - config->unregister_callback(config, "media.bluray.device"); - config->unregister_callback(config, "media.bluray.keyfile"); - - free (this); -} - -static void *bluray_init_plugin (xine_t *xine, void *data) -{ - config_values_t *config = xine->config; - bluray_input_class_t *this = (bluray_input_class_t *) calloc(1, sizeof (bluray_input_class_t)); - - this->xine = xine; - - this->input_class.get_instance = bluray_class_get_instance; - this->input_class.get_identifier = bluray_class_get_identifier; - this->input_class.get_description = bluray_class_get_description; - this->input_class.get_dir = NULL; - this->input_class.get_autoplay_list = bluray_class_get_autoplay_list; - this->input_class.dispose = bluray_class_dispose; - this->input_class.eject_media = bluray_class_eject_media; - - this->mountpoint = config->register_filename(config, "media.bluray.mountpoint", - "/mnt/bluray", XINE_CONFIG_STRING_IS_DIRECTORY_NAME, - _("BluRay mount point"), - _("Default mount location for BluRay discs."), - 0, mountpoint_change_cb, (void *) this); - this->device = config->register_filename(config, "media.bluray.device", - "/dev/dvd", XINE_CONFIG_STRING_IS_DIRECTORY_NAME, - _("device used for BluRay playback"), - _("The path to the device " - "which you intend to use for playing BluRy discs."), - 0, device_change_cb, (void *) this); - this->keyfile = config->register_filename(config, "media.bluray.keyfile", - "~/.xine/aacskeys.bin", XINE_CONFIG_STRING_IS_DIRECTORY_NAME, - _("AACS key file"), - _("Location of libaacs key file."), - 0, keyfile_change_cb, (void *) this); - - return this; -} - -/* - * exported plugin catalog entry - */ - -const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "BLURAY", XINE_VERSION_CODE, NULL, bluray_init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; |