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 */