Mercurial > mplayer.hg
changeset 31877:e30fe0cb79cd
Add incomplete clipinf reading support to display audio
and subtitle languages and make -alang and -slang work.
author | reimar |
---|---|
date | Wed, 11 Aug 2010 20:59:03 +0000 |
parents | c52e80f24086 |
children | e9458f705c3f |
files | command.c mencoder.c mplayer.c stream/stream_bd.c stream/stream_bd.h |
diffstat | 5 files changed, 189 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/command.c Wed Aug 11 20:44:29 2010 +0000 +++ b/command.c Wed Aug 11 20:59:03 2010 +0000 @@ -53,6 +53,7 @@ #ifdef CONFIG_DVBIN #include "stream/dvbin.h" #endif +#include "stream/stream_bd.h" #ifdef CONFIG_DVDREAD #include "stream/stream_dvd.h" #endif @@ -899,6 +900,12 @@ sh_audio_t* sh = mpctx->sh_audio; if (sh && sh->lang) av_strlcpy(lang, sh->lang, 40); + // TODO: use a proper STREAM_CTRL instead of this mess + else if (sh && mpctx->stream->type == STREAMTYPE_BD) { + const char *l = bd_lang_from_id(mpctx->stream, sh->aid); + if (l) + av_strlcpy(lang, l, sizeof(lang)); + } #ifdef CONFIG_DVDREAD else if (mpctx->stream->type == STREAMTYPE_DVD) { int code = dvd_lang_from_aid(mpctx->stream, current_id); @@ -1440,6 +1447,14 @@ } #endif + if (mpctx->stream->type == STREAMTYPE_BD + && d_sub && d_sub->sh && dvdsub_id >= 0) { + const char *lang = bd_lang_from_id(mpctx->stream, ((sh_sub_t*)d_sub->sh)->sid); + if (!lang) lang = MSGTR_Unknown; + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, lang); + return M_PROPERTY_OK; + } + if ((mpctx->demuxer->type == DEMUXER_TYPE_MATROSKA || mpctx->demuxer->type == DEMUXER_TYPE_LAVF || mpctx->demuxer->type == DEMUXER_TYPE_LAVF_PREFERRED
--- a/mencoder.c Wed Aug 11 20:44:29 2010 +0000 +++ b/mencoder.c Wed Aug 11 20:59:03 2010 +0000 @@ -79,6 +79,7 @@ #include "osdep/priority.h" #include "osdep/timer.h" #include "stream/stream.h" +#include "stream/stream_bd.h" #ifdef CONFIG_DVDREAD #include "stream/stream_dvd.h" #endif @@ -708,6 +709,11 @@ mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_OpenedStream, file_format, (int)(stream->start_pos), (int)(stream->end_pos)); +if(stream->type==STREAMTYPE_BD){ + if(audio_id==-1) audio_id=bd_aid_from_lang(stream,audio_lang); + if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=bd_sid_from_lang(stream,dvdsub_lang); +} + #ifdef CONFIG_DVDREAD if(stream->type==STREAMTYPE_DVD){ if(audio_lang && audio_id==-1) audio_id=dvd_aid_from_lang(stream,audio_lang);
--- a/mplayer.c Wed Aug 11 20:44:29 2010 +0000 +++ b/mplayer.c Wed Aug 11 20:59:03 2010 +0000 @@ -92,6 +92,7 @@ #include "libvo/video_out.h" #include "stream/cache2.h" #include "stream/stream.h" +#include "stream/stream_bd.h" #include "stream/stream_dvdnav.h" #include "stream/stream_radio.h" #include "stream/tv.h" @@ -3343,6 +3344,11 @@ exit_player_with_rc(EXIT_EOF, 0); } +if(mpctx->stream->type==STREAMTYPE_BD){ + if(audio_id==-1) audio_id=bd_aid_from_lang(mpctx->stream,audio_lang); + if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=bd_sid_from_lang(mpctx->stream,dvdsub_lang); +} + #ifdef CONFIG_DVDREAD if(mpctx->stream->type==STREAMTYPE_DVD){ current_module="dvd lang->id";
--- a/stream/stream_bd.c Wed Aug 11 20:44:29 2010 +0000 +++ b/stream/stream_bd.c Wed Aug 11 20:59:03 2010 +0000 @@ -29,10 +29,12 @@ #include "m_struct.h" #include "m_option.h" #include "stream.h" +#include "stream_bd.h" static const int BD_UNIT_SIZE = 6144; static const char BD_UKF_PATH[] = "%s/AACS/Unit_Key_RO.inf"; static const char BD_M2TS_PATH[] = "%s/BDMV/STREAM/%05d.m2ts"; +static const char BD_CLIPINF_PATH[] = "%s/BDMV/CLIPINF/%05d.clpi"; static const char DEFAULT_BD_DEVICE[] = "/mnt/bd"; @@ -79,6 +81,15 @@ key *keys; }; +// This is just a guess +#define LANG_NAME_LEN 20 + +struct lang_map { + int id; + int type; + char lang_name[LANG_NAME_LEN + 1]; +}; + struct bd_priv { key vuk; key iv; @@ -89,6 +100,8 @@ struct AVAES *aeseed; off_t pos; struct uks uks; + int nr_lang_maps; + struct lang_map *lang_maps; }; static void bd_stream_close(stream_t *s) @@ -304,6 +317,125 @@ return read_len; } +static int is_video_type(int type) +{ + switch (type) { + case 1: + case 2: + case 0x10: + case 0x1b: + case 0xD1: + case 0xEA: + return 1; + } + return 0; +} + +static int is_audio_type(int type) +{ + switch (type) { + case 3: + case 4: + case 0x0f: + case 0x11: + case 0x81: + case 0x8A: + case 0x82: + case 0x85: + case 0x86: + return 1; + } + return 0; +} + +static int is_sub_type(int type) +{ + switch (type) { + case 0x90: + return 1; + } + return 0; +} + +const char *bd_lang_from_id(stream_t *s, int id) +{ + struct bd_priv *bd = s->priv; + int i; + for (i = 0; i < bd->nr_lang_maps; i++) { + if (bd->lang_maps[i].id == id) + return bd->lang_maps[i].lang_name; + } + return NULL; +} + +int bd_aid_from_lang(stream_t *s, const char *lang) +{ + struct bd_priv *bd = s->priv; + int i; + for (i = 0; i < bd->nr_lang_maps; i++) { + if (is_audio_type(bd->lang_maps[i].type) && + strstr(bd->lang_maps[i].lang_name, lang)) + return bd->lang_maps[i].id; + } + return -1; +} + +int bd_sid_from_lang(stream_t *s, const char *lang) +{ + struct bd_priv *bd = s->priv; + int i; + for (i = 0; i < bd->nr_lang_maps; i++) { + if (is_sub_type(bd->lang_maps[i].type) && + strstr(bd->lang_maps[i].lang_name, lang)) + return bd->lang_maps[i].id; + } + return -1; +} + +static void get_clipinf(struct bd_priv *bd) +{ + int i; + int langmap_offset, index_offset, end_offset; + char filename[PATH_MAX]; + stream_t *file; + + snprintf(filename, sizeof(filename), BD_CLIPINF_PATH, bd->device, bd->title); + file = open_stream(filename, NULL, NULL); + if (!file) { + mp_msg(MSGT_OPEN, MSGL_ERR, "Cannot open clipinf %s\n", filename); + return; + } + if (stream_read_qword(file) != AV_RB64("HDMV0200")) { + mp_msg(MSGT_OPEN, MSGL_ERR, "Unknown clipinf format\n"); + return; + } + stream_read_dword(file); // unknown offset + langmap_offset = stream_read_dword(file); + index_offset = stream_read_dword(file); + end_offset = stream_read_dword(file); + + // read language <-> stream id mappings + stream_seek(file, langmap_offset); + stream_read_dword(file); // size + stream_skip(file, 8); // unknown + bd->nr_lang_maps = stream_read_char(file); // number of entries + stream_read_char(file); // unknown + + bd->lang_maps = calloc(bd->nr_lang_maps, sizeof(*bd->lang_maps)); + for (i = 0; i < bd->nr_lang_maps; i++) { + int type; + bd->lang_maps[i].id = stream_read_word(file); + stream_read_char(file); // unknown + type = stream_read_char(file); + if (!is_video_type(type) && !is_audio_type(type) && !is_sub_type(type)) + mp_msg(MSGT_OPEN, MSGL_WARN, "Unknown type %x in clipinf\n", type); + bd->lang_maps[i].type = type; + stream_read(file, bd->lang_maps[i].lang_name, LANG_NAME_LEN); + } + + free_stream(file); +} + static int bd_stream_open(stream_t *s, int mode, void* opts, int* file_format) { char filename[PATH_MAX]; @@ -348,6 +480,8 @@ return STREAM_ERROR; s->end_pos = bd->title_file->end_pos; + get_clipinf(bd); + return STREAM_OK; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stream/stream_bd.h Wed Aug 11 20:59:03 2010 +0000 @@ -0,0 +1,28 @@ +/* + * This file is part of MPlayer. + * + * MPlayer 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. + * + * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPLAYER_STREAM_BD_H +#define MPLAYER_STREAM_BD_H + +#include "stream.h" + +const char *bd_lang_from_id(stream_t *s, int id); +int bd_aid_from_lang(stream_t *s, const char *lang); +int bd_sid_from_lang(stream_t *s, const char *lang); + +#endif /* MPLAYER_STREAM_BD_H */