# How-to mplayer and Blue-Ray # 09/Nov/29 You have to patch mplayer first. You can find more info there: - https://help.ubuntu.com/community/RestrictedFormats/BluRayAndHDDVD - http://www.phoronix.com/forums/showthread.php?t=20181 - http://forum.doom9.org/showpost.php?p=1327197&postcount=8 [down atm] - http://archives.free.net.ph/message/20090914.085053.e59fb42a.pt.html -- SNIP -- Autor: Jonathan Nell Data: 2009-09-14 10:50 +200 Para: mplayer-dev-eng Assunto: [MPlayer-dev-eng] [PATCH] Bluray stream support Refactored as per (most) suggestions. Still no real error checking or Doxy. Stream seeking should work a bit better now. Index: stream/stream_bd.c =================================================================== --- stream/stream_bd.c (revision 0) +++ stream/stream_bd.c (revision 0) @@ -0,0 +1,254 @@ +/* + * Bluray stream playback + * by cRTrn13 2009 + * + * 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. + */ + +#include +#include + +#include "libavutil/aes.h" +#include "libmpdemux/demuxer.h" +#include "libavutil/intreadwrite.h" + +#include "m_struct.h" +#include "m_option.h" + +#include "stream.h" + +#define BD_UNIT_SIZE 6144 +#define BD_CBC_IV "\x0B\xA0\xF8\xDD\xFE\xA6\x1F\xB3\xD8\xDF\x9F\x56\x6A\x05\x0F\x78" +#define BD_UKF_PATH "/%s/AACS/Unit_Key_RO.inf" +#define BD_MKB_PATH "/%s/AACS/MKB_RO.inf" +#define BD_M2TS_PATH "/%s/BDMV/STREAM/%05ld.m2ts" + +static struct stream_priv_s { + int title; + char* device; + unsigned char* vuk; +} stream_priv_dflts = { + 1, + NULL +}; + +// Format: BD://@VUK/<mnt/location> +// --> e.g.: BD://117@AABBCCDDEEFF11223344556677889900/media/THE_MUMMY/ +#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) +static const m_option_t stream_opts_fields[] = { + { "username", ST_OFF(title), CONF_TYPE_INT, M_OPT_RANGE, 0, 99999, NULL}, + { "hostname", ST_OFF(vuk), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + { "filename", ST_OFF(device), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; + +static const struct m_struct_st stream_opts = { + "bd", + sizeof(struct stream_priv_s), + &stream_priv_dflts, + stream_opts_fields +}; + +struct uk { + unsigned char key[16]; +}; + +struct uks { + struct uk *keys; + int count; +}; + +struct bd_priv { + unsigned long title; + char *device; + unsigned char vuk[16]; + FILE* title_file; + struct uks uks; + unsigned char iv[16]; + struct AVAES *aescbc; + off_t pos; +}; + +static void bd_get_uks(struct bd_priv *bd) +{ + unsigned char *buf; + size_t file_size; + int pos; + int i; + struct AVAES *a; + FILE *file; + char filename[200]; + + snprintf(filename, sizeof(filename), BD_UKF_PATH, bd->device); + file_size = 0; + file = fopen(filename, "rb"); + fseek(file, 0, SEEK_END); + file_size = ftell(file); + rewind(file); + buf = malloc(file_size); + fread(buf, 1, file_size, file); + fclose(file); + + pos = AV_RB32(buf); + if (pos < file_size) { + bd->uks.count = AV_RB16(&buf[pos]); + bd->uks.keys = calloc(bd->uks.count,sizeof(struct uk)); + + a = av_malloc(av_aes_size); + av_aes_init(a, bd->vuk ,128 ,1); + + for (i = 0; i < bd->uks.count; i++) { + int key_pos = pos + i * 48 + 48; + if (key_pos + 16 <= file_size) + av_aes_crypt(a, bd->uks.keys[i].key, &buf[key_pos], 1, NULL, 1); // decrypt unit key + } + + free(a); + } + + free(buf); +} + +static off_t bd_read(struct bd_priv *bd, unsigned char *buf, int len) +{ + int read_len; + + fseek(bd->title_file, bd->pos, SEEK_SET); + + if ( (read_len = fread(buf, 1, len, bd->title_file)) == len) { + if (bd->pos % BD_UNIT_SIZE) { + // decrypt in place + av_aes_crypt(bd->aescbc, buf, buf, len / 16, bd->iv, 1); + } else { + // reset aes context as at start of unit + unsigned char enc_seed[16]; + struct AVAES *a; + memcpy(bd->iv, BD_CBC_IV, 16); + + // set up AES key from uk and seed + a = av_malloc(av_aes_size); + av_aes_init(a, bd->uks.keys[0].key, 128, 0); + + // perform encryption of first 16 bytes of unit (seed) + av_aes_crypt(a, enc_seed, buf, 1, NULL, 0); + av_free(a); + + // perform xor + int i; + for(i = 0; i < 16; i++) + enc_seed[i] ^= buf[i]; + + // set uk AES-CBC key from enc_seed and BD_CBC_IV + av_aes_init(bd->aescbc, enc_seed, 128, 1); + + // decrypt + av_aes_crypt(bd->aescbc, &buf[16], &buf[16], (len - 16) / 16, bd->iv, 1); + } + + bd->pos += len; + } + + return read_len; +} + +static void bd_stream_close(stream_t *s) +{ + struct bd_priv *bd = s->priv; + fclose(bd->title_file); + av_free(bd->aescbc); + free(bd->uks.keys); + free(bd); +} + +static int bd_stream_seek(stream_t *s, off_t pos) +{ + struct bd_priv *bd = s->priv; + + // must seek to start of unit + pos -= pos % BD_UNIT_SIZE; + bd->pos = pos; + s->pos = pos; + + return 1; +} + +static int bd_stream_fill_buffer(stream_t *s, char *buf, int len) +{ + int read_len; + struct bd_priv *bd = s->priv; + + read_len = bd_read(bd, buf, len); + + s->pos = bd->pos; + + return read_len; +} + +static int bd_stream_open(stream_t *s, int mode, void* opts, int* file_format) +{ + unsigned int byte; + int i; + char filename[200]; + + struct stream_priv_s* p = opts; + struct bd_priv *bd = calloc(1, sizeof(*bd)); + + s->sector_size = BD_UNIT_SIZE; + s->flags = STREAM_READ | STREAM_SEEK; + s->fill_buffer = bd_stream_fill_buffer; + s->seek = bd_stream_seek; + s->close = bd_stream_close; + s->start_pos = 0; + s->priv = bd; + s->type = STREAMTYPE_BD; + s->url = strdup("bd://"); + + // change vuk ascii hex into byte array + for (i = 0; i < 16; ++i) { + if(sscanf(p->vuk, "%2x", &byte) != 1) break; + bd->vuk[i] = byte; + p->vuk += 2; + } + + bd->pos = 0; + bd->title = p->title; + bd->device = p->device; + + // get and decrypt unit keys + bd_get_uks(bd); + + bd->aescbc=av_malloc(av_aes_size); + + snprintf(filename, sizeof(filename), BD_M2TS_PATH, bd->device,bd->title); + bd->title_file = fopen(filename, "rb"); + fseek(bd->title_file, 0, SEEK_END); + s->end_pos = ftell(bd->title_file); + rewind(bd->title_file); + + return STREAM_OK; +} + +const stream_info_t stream_info_bd = { + "Bluray", + "bd", + "cRTrn13", + "", + bd_stream_open, + { "bd", NULL }, + &stream_opts, + 1 +}; Index: stream/stream.c =================================================================== --- stream/stream.c (revision 29676) +++ stream/stream.c (working copy) @@ -34,6 +34,7 @@ static int (*stream_check_interrupt_cb)(int time) = NULL; +extern const stream_info_t stream_info_bd; extern const stream_info_t stream_info_vcd; extern const stream_info_t stream_info_cdda; extern const stream_info_t stream_info_netstream; @@ -63,6 +64,7 @@ extern const stream_info_t stream_info_dvd; static const stream_info_t* const auto_open_streams[] = { + &stream_info_bd, #ifdef CONFIG_VCD &stream_info_vcd, #endif Index: stream/stream.h =================================================================== --- stream/stream.h (revision 29676) +++ stream/stream.h (working copy) @@ -25,6 +25,7 @@ #define STREAMTYPE_TV 17 #define STREAMTYPE_MF 18 #define STREAMTYPE_RADIO 19 +#define STREAMTYPE_BD 20 #define STREAM_BUFFER_SIZE 2048 Index: Makefile =================================================================== --- Makefile (revision 29676) +++ Makefile (working copy) @@ -514,6 +514,7 @@ osdep/$(TIMER) \ stream/open.c \ stream/stream.c \ + stream/stream_bd.c \ stream/stream_cue.c \ stream/stream_file.c \ stream/stream_mf.c \ _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@??? https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng ---------