|
MythTV
0.26-pre
|
00001 /* 00002 * This file is part of libbluray 00003 * Copyright (C) 2009-2010 Obliter0n 00004 * Copyright (C) 2009-2010 John Stebbins 00005 * Copyright (C) 2010 hpi1 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library. If not, see 00019 * <http://www.gnu.org/licenses/>. 00020 */ 00021 00022 #if HAVE_CONFIG_H 00023 #include "config.h" 00024 #endif 00025 00026 #include "bluray.h" 00027 #include "register.h" 00028 #include "util/macro.h" 00029 #include "util/logging.h" 00030 #include "util/strutl.h" 00031 #include "bdnav/navigation.h" 00032 #include "bdnav/index_parse.h" 00033 #include "bdnav/meta_parse.h" 00034 #include "bdnav/clpi_parse.h" 00035 #include "hdmv/hdmv_vm.h" 00036 #include "decoders/graphics_controller.h" 00037 #include "file/file.h" 00038 #ifdef DLOPEN_CRYPTO_LIBS 00039 #include "file/dl.h" 00040 #endif 00041 #ifdef USING_BDJAVA 00042 #include "bdj/bdj.h" 00043 #endif 00044 00045 #ifndef DLOPEN_CRYPTO_LIBS 00046 #include <libaacs/aacs.h> 00047 #include <libbdplus/bdplus.h> 00048 #endif 00049 #include <stdlib.h> 00050 #include <inttypes.h> 00051 #include <string.h> 00052 #include <sys/types.h> 00053 00054 #include "mythiowrapper.h" 00055 00056 typedef int (*fptr_int)(); 00057 typedef int32_t (*fptr_int32)(); 00058 typedef void* (*fptr_p_void)(); 00059 00060 #define MAX_EVENTS 31 /* 2^n - 1 */ 00061 typedef struct bd_event_queue_s { 00062 unsigned in; /* next free slot */ 00063 unsigned out; /* next event */ 00064 BD_EVENT ev[MAX_EVENTS+1]; 00065 } BD_EVENT_QUEUE; 00066 00067 typedef enum { 00068 title_undef = 0, 00069 title_hdmv, 00070 title_bdj, 00071 } BD_TITLE_TYPE; 00072 00073 typedef struct { 00074 /* current clip */ 00075 NAV_CLIP *clip; 00076 BD_FILE_H *fp; 00077 uint64_t clip_size; 00078 uint64_t clip_block_pos; 00079 uint64_t clip_pos; 00080 00081 /* current aligned unit */ 00082 uint16_t int_buf_off; 00083 00084 BD_UO_MASK uo_mask; 00085 00086 } BD_STREAM; 00087 00088 typedef struct { 00089 NAV_CLIP *clip; 00090 uint64_t clip_size; 00091 uint8_t *buf; 00092 } BD_PRELOAD; 00093 00094 struct bluray { 00095 00096 /* current disc */ 00097 char *device_path; 00098 BLURAY_DISC_INFO disc_info; 00099 INDX_ROOT *index; 00100 META_ROOT *meta; 00101 NAV_TITLE_LIST *title_list; 00102 00103 /* current playlist */ 00104 NAV_TITLE *title; 00105 uint32_t title_idx; 00106 uint64_t s_pos; 00107 00108 /* streams */ 00109 BD_STREAM st0; /* main path */ 00110 BD_PRELOAD st_ig; /* preloaded IG stream sub path */ 00111 00112 /* buffer for bd_read(): current aligned unit of main stream (st0) */ 00113 uint8_t int_buf[6144]; 00114 00115 /* seamless angle change request */ 00116 int seamless_angle_change; 00117 uint32_t angle_change_pkt; 00118 uint32_t angle_change_time; 00119 unsigned request_angle; 00120 00121 /* chapter tracking */ 00122 uint64_t next_chapter_start; 00123 00124 /* aacs */ 00125 #ifdef DLOPEN_CRYPTO_LIBS 00126 void *h_libaacs; // library handle 00127 #endif 00128 void *aacs; 00129 fptr_p_void libaacs_open; 00130 fptr_int libaacs_decrypt_unit; 00131 00132 /* BD+ */ 00133 #ifdef DLOPEN_CRYPTO_LIBS 00134 void *h_libbdplus; // library handle 00135 #endif 00136 void *bdplus; 00137 fptr_p_void bdplus_init; 00138 fptr_int32 bdplus_seek; 00139 fptr_int32 bdplus_fixup; 00140 00141 /* player state */ 00142 BD_REGISTERS *regs; // player registers 00143 BD_EVENT_QUEUE *event_queue; // navigation mode event queue 00144 BD_TITLE_TYPE title_type; // type of current title (in navigation mode) 00145 00146 HDMV_VM *hdmv_vm; 00147 uint8_t hdmv_suspended; 00148 00149 void *bdjava; 00150 00151 /* graphics */ 00152 GRAPHICS_CONTROLLER *graphics_controller; 00153 }; 00154 00155 #ifdef DLOPEN_CRYPTO_LIBS 00156 # define DL_CALL(lib,func,param,...) \ 00157 do { \ 00158 fptr_p_void fptr = (fptr_p_void)dl_dlsym(lib, #func); \ 00159 if (fptr) { \ 00160 fptr(param, ##__VA_ARGS__); \ 00161 } \ 00162 } while (0) 00163 #else 00164 # define DL_CALL(lib,func,param,...) \ 00165 func (param, ##__VA_ARGS__) 00166 #endif 00167 00168 /* 00169 * Navigation mode event queue 00170 */ 00171 00172 static void _init_event_queue(BLURAY *bd) 00173 { 00174 if (!bd->event_queue) { 00175 bd->event_queue = calloc(1, sizeof(struct bd_event_queue_s)); 00176 } else { 00177 memset(bd->event_queue, 0, sizeof(struct bd_event_queue_s)); 00178 } 00179 } 00180 00181 static int _get_event(BLURAY *bd, BD_EVENT *ev) 00182 { 00183 struct bd_event_queue_s *eq = bd->event_queue; 00184 00185 if (eq) { 00186 if (eq->in != eq->out) { 00187 *ev = eq->ev[eq->out]; 00188 eq->out = (eq->out + 1) & MAX_EVENTS; 00189 return 1; 00190 } 00191 } 00192 00193 ev->event = BD_EVENT_NONE; 00194 00195 return 0; 00196 } 00197 00198 static int _queue_event(BLURAY *bd, BD_EVENT ev) 00199 { 00200 struct bd_event_queue_s *eq = bd->event_queue; 00201 00202 if (eq) { 00203 unsigned new_in = (eq->in + 1) & MAX_EVENTS; 00204 00205 if (new_in != eq->out) { 00206 eq->ev[eq->in] = ev; 00207 eq->in = new_in; 00208 return 1; 00209 } 00210 00211 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "_queue_event(%d, %d): queue overflow !\n", ev.event, ev.param); 00212 } 00213 00214 return 0; 00215 } 00216 00217 /* 00218 + * PSR utils 00219 + */ 00220 00221 static void _update_stream_psr_by_lang(BD_REGISTERS *regs, 00222 uint32_t psr_lang, uint32_t psr_stream, 00223 uint32_t enable_flag, uint32_t undefined_val, 00224 MPLS_STREAM *streams, unsigned num_streams) 00225 { 00226 uint32_t psr_val; 00227 int stream_idx = -1; 00228 unsigned ii; 00229 00230 /* get preferred language */ 00231 psr_val = bd_psr_read(regs, psr_lang); 00232 if (psr_val == 0xffffff) { 00233 /* language setting not initialized */ 00234 return; 00235 } 00236 00237 /* find stream */ 00238 00239 for (ii = 0; ii < num_streams; ii++) { 00240 if (psr_val == str_to_uint32((const char *)streams[ii].lang, 3)) { 00241 stream_idx = ii; 00242 break; 00243 } 00244 } 00245 00246 if (stream_idx < 0) { 00247 /* requested language not found */ 00248 stream_idx = undefined_val - 1; 00249 enable_flag = 0; 00250 } 00251 /* update PSR */ 00252 00253 BD_DEBUG(DBG_BLURAY, "Selected stream %d (language %s)\n", ii, streams[ii].lang); 00254 00255 bd_psr_lock(regs); 00256 00257 psr_val = bd_psr_read(regs, psr_stream) & 0xffff0000; 00258 psr_val |= (stream_idx + 1) | enable_flag; 00259 bd_psr_write(regs, psr_stream, psr_val); 00260 00261 bd_psr_unlock(regs); 00262 } 00263 00264 static void _update_clip_psrs(BLURAY *bd, NAV_CLIP *clip) 00265 { 00266 bd_psr_write(bd->regs, PSR_PLAYITEM, clip->ref); 00267 bd_psr_write(bd->regs, PSR_TIME, clip->in_time); 00268 00269 /* Update selected audio and subtitle stream PSRs when not using menus. 00270 * Selection is based on language setting PSRs and clip STN. 00271 */ 00272 if (bd->title_type == title_undef) { 00273 MPLS_STN *stn = &clip->title->pl->play_item[clip->ref].stn; 00274 00275 _update_stream_psr_by_lang(bd->regs, 00276 PSR_AUDIO_LANG, PSR_PRIMARY_AUDIO_ID, 0, 0xff, 00277 stn->audio, stn->num_audio); 00278 _update_stream_psr_by_lang(bd->regs, 00279 PSR_PG_AND_SUB_LANG, PSR_PG_STREAM, 0x80000000, 0xfff, 00280 stn->pg, stn->num_pg); 00281 } 00282 } 00283 00284 00285 static void _update_chapter_psr(BLURAY *bd) 00286 { 00287 uint32_t current_chapter = bd_get_current_chapter(bd); 00288 bd->next_chapter_start = bd_chapter_pos(bd, current_chapter + 1); 00289 bd_psr_write(bd->regs, PSR_CHAPTER, current_chapter + 1); 00290 } 00291 00292 /* 00293 * clip access (BD_STREAM) 00294 */ 00295 00296 static void _close_m2ts(BD_STREAM *st) 00297 { 00298 if (st->fp != NULL) { 00299 file_close(st->fp); 00300 st->fp = NULL; 00301 } 00302 00303 /* reset UO mask */ 00304 memset(&st->uo_mask, 0, sizeof(st->uo_mask)); 00305 } 00306 00307 static int _open_m2ts(BLURAY *bd, BD_STREAM *st) 00308 { 00309 char *f_name; 00310 struct stat buf; 00311 00312 _close_m2ts(st); 00313 00314 f_name = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "STREAM" DIR_SEP "%s", 00315 bd->device_path, st->clip->name); 00316 00317 st->clip_pos = (uint64_t)st->clip->start_pkt * 192; 00318 st->clip_block_pos = (st->clip_pos / 6144) * 6144; 00319 00320 if ((st->fp = file_open(f_name, "rb"))) { 00321 // Original libbluray code 00322 // file_seek(st->fp, 0, SEEK_END); 00323 // if ((st->clip_size = file_tell(st->fp))) { 00324 // New 'stat' and modified 'if' to minimize RingBuffer seeking 00325 // Optimize here for now until we can optimize in the RingBuffer itself 00326 if (mythfile_stat(f_name, &buf) == 0) 00327 st->clip_size = buf.st_size; 00328 else 00329 st->clip_size = 0; 00330 00331 if (st->clip_size) { 00332 file_seek(st->fp, st->clip_block_pos, SEEK_SET); 00333 st->int_buf_off = 6144; 00334 X_FREE(f_name); 00335 00336 if (bd->bdplus) { 00337 DL_CALL(bd->h_libbdplus, bdplus_set_title, 00338 bd->bdplus, st->clip->clip_id); 00339 } 00340 00341 if (bd->aacs) { 00342 uint32_t title = bd_psr_read(bd->regs, PSR_TITLE_NUMBER); 00343 DL_CALL(bd->h_libaacs, aacs_select_title, 00344 bd->aacs, title); 00345 } 00346 00347 if (st == &bd->st0) { 00348 MPLS_PL *pl = st->clip->title->pl; 00349 st->uo_mask = bd_uo_mask_combine(pl->app_info.uo_mask, 00350 pl->play_item[st->clip->ref].uo_mask); 00351 00352 _update_clip_psrs(bd, st->clip); 00353 } 00354 00355 return 1; 00356 } 00357 00358 BD_DEBUG(DBG_BLURAY, "Clip %s empty! (%p)\n", f_name, bd); 00359 } 00360 00361 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Unable to open clip %s! (%p)\n", 00362 f_name, bd); 00363 00364 X_FREE(f_name); 00365 return 0; 00366 } 00367 00368 static int _read_block(BLURAY *bd, BD_STREAM *st, uint8_t *buf) 00369 { 00370 const int len = 6144; 00371 00372 if (st->fp) { 00373 BD_DEBUG(DBG_STREAM, "Reading unit [%d bytes] at %"PRIu64"... (%p)\n", 00374 len, st->clip_block_pos, bd); 00375 00376 if (len + st->clip_block_pos <= st->clip_size) { 00377 int read_len; 00378 00379 if ((read_len = file_read(st->fp, buf, len))) { 00380 if (read_len != len) 00381 BD_DEBUG(DBG_STREAM | DBG_CRIT, "Read %d bytes at %"PRIu64" ; requested %d ! (%p)\n", read_len, st->clip_block_pos, len, bd); 00382 00383 if (bd->aacs && bd->libaacs_decrypt_unit) { 00384 if (!bd->libaacs_decrypt_unit(bd->aacs, buf)) { 00385 BD_DEBUG(DBG_AACS | DBG_CRIT, "Unable decrypt unit (AACS)! (%p)\n", bd); 00386 00387 return 0; 00388 } // decrypt 00389 } // aacs 00390 00391 st->clip_block_pos += len; 00392 00393 // bdplus fixup, if required. 00394 if (bd->bdplus_fixup && bd->bdplus) { 00395 int32_t numFixes; 00396 numFixes = bd->bdplus_fixup(bd->bdplus, len, buf); 00397 #if 1 00398 if (numFixes) { 00399 BD_DEBUG(DBG_BDPLUS, 00400 "BDPLUS did %u fixups\n", numFixes); 00401 } 00402 #endif 00403 00404 } 00405 00406 /* Check TP_extra_header Copy_permission_indicator. If != 0, unit is still encrypted. */ 00407 if (buf[0] & 0xc0) { 00408 BD_DEBUG(DBG_BLURAY | DBG_CRIT, 00409 "TP header copy permission indicator != 0, unit is still encrypted? (%p)\n", bd); 00410 _queue_event(bd, (BD_EVENT){BD_EVENT_ENCRYPTED, 0}); 00411 return 0; 00412 } 00413 00414 BD_DEBUG(DBG_STREAM, "Read unit OK! (%p)\n", bd); 00415 00416 return 1; 00417 } 00418 00419 BD_DEBUG(DBG_STREAM | DBG_CRIT, "Read %d bytes at %"PRIu64" failed ! (%p)\n", len, st->clip_block_pos, bd); 00420 00421 return 0; 00422 } 00423 00424 BD_DEBUG(DBG_STREAM | DBG_CRIT, "Read past EOF ! (%p)\n", bd); 00425 00426 return 0; 00427 } 00428 00429 BD_DEBUG(DBG_BLURAY, "No valid title selected! (%p)\n", bd); 00430 00431 return 0; 00432 } 00433 00434 /* 00435 * clip preload (BD_PRELOAD) 00436 */ 00437 00438 static void _close_preload(BD_PRELOAD *p) 00439 { 00440 X_FREE(p->buf); 00441 memset(p, 0, sizeof(*p)); 00442 } 00443 00444 static int _preload_m2ts(BLURAY *bd, BD_PRELOAD *p) 00445 { 00446 /* setup and open BD_STREAM */ 00447 00448 BD_STREAM st; 00449 00450 memset(&st, 0, sizeof(st)); 00451 st.clip = p->clip; 00452 00453 if (!_open_m2ts(bd, &st)) { 00454 return 0; 00455 } 00456 00457 /* allocate buffer */ 00458 p->clip_size = st.clip_size; 00459 p->buf = realloc(p->buf, p->clip_size); 00460 00461 /* read clip to buffer */ 00462 00463 uint8_t *buf = p->buf; 00464 uint8_t *end = p->buf + p->clip_size; 00465 00466 for (; buf < end; buf += 6144) { 00467 if (!_read_block(bd, &st, buf)) { 00468 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "_preload_m2ts(): error loading %s at %"PRIu64"\n", 00469 st.clip->name, (uint64_t)(buf - p->buf)); 00470 _close_m2ts(&st); 00471 _close_preload(p); 00472 return 0; 00473 } 00474 } 00475 00476 /* */ 00477 00478 BD_DEBUG(DBG_BLURAY, "_preload_m2ts(): loaded %"PRIu64" bytes from %s\n", 00479 st.clip_size, st.clip->name); 00480 00481 _close_m2ts(&st); 00482 00483 return 1; 00484 } 00485 00486 static int64_t _seek_stream(BLURAY *bd, BD_STREAM *st, 00487 NAV_CLIP *clip, uint32_t clip_pkt) 00488 { 00489 if (!clip) 00490 return -1; 00491 00492 if (!st->fp || !st->clip || clip->ref != st->clip->ref) { 00493 // The position is in a new clip 00494 st->clip = clip; 00495 if (!_open_m2ts(bd, st)) { 00496 return -1; 00497 } 00498 } 00499 00500 st->clip_pos = (uint64_t)clip_pkt * 192; 00501 st->clip_block_pos = (st->clip_pos / 6144) * 6144; 00502 00503 file_seek(st->fp, st->clip_block_pos, SEEK_SET); 00504 00505 st->int_buf_off = 6144; 00506 00507 return st->clip_pos; 00508 } 00509 00510 /* 00511 * libaacs and libbdplus open / close 00512 */ 00513 00514 static void _libaacs_close(BLURAY *bd) 00515 { 00516 if (bd->aacs) { 00517 DL_CALL(bd->h_libaacs, aacs_close, bd->aacs); 00518 bd->aacs = NULL; 00519 } 00520 } 00521 00522 static void _libaacs_unload(BLURAY *bd) 00523 { 00524 _libaacs_close(bd); 00525 00526 #ifdef DLOPEN_CRYPTO_LIBS 00527 if (bd->h_libaacs) { 00528 dl_dlclose(bd->h_libaacs); 00529 bd->h_libaacs = NULL; 00530 } 00531 #endif 00532 00533 bd->libaacs_open = NULL; 00534 bd->libaacs_decrypt_unit = NULL; 00535 } 00536 00537 static int _libaacs_required(BLURAY *bd) 00538 { 00539 BD_FILE_H *fd; 00540 char *tmp; 00541 00542 tmp = str_printf("%s/AACS/Unit_Key_RO.inf", bd->device_path); 00543 fd = file_open(tmp, "rb"); 00544 X_FREE(tmp); 00545 00546 if (fd) { 00547 file_close(fd); 00548 00549 BD_DEBUG(DBG_BLURAY, "AACS/Unit_Key_RO.inf found. Disc seems to be AACS protected (%p)\n", bd); 00550 bd->disc_info.aacs_detected = 1; 00551 return 1; 00552 } 00553 00554 BD_DEBUG(DBG_BLURAY, "AACS/Unit_Key_RO.inf not found. No AACS protection (%p)\n", bd); 00555 bd->disc_info.aacs_detected = 0; 00556 return 0; 00557 } 00558 00559 static int _libaacs_load(BLURAY *bd) 00560 { 00561 #ifdef DLOPEN_CRYPTO_LIBS 00562 if (bd->h_libaacs) { 00563 return 1; 00564 } 00565 00566 bd->disc_info.libaacs_detected = 0; 00567 if ((bd->h_libaacs = dl_dlopen("libaacs", "0"))) { 00568 00569 BD_DEBUG(DBG_BLURAY, "Loading libaacs (%p)\n", bd->h_libaacs); 00570 00571 bd->libaacs_open = (fptr_p_void)dl_dlsym(bd->h_libaacs, "aacs_open"); 00572 bd->libaacs_decrypt_unit = (fptr_int)dl_dlsym(bd->h_libaacs, "aacs_decrypt_unit"); 00573 00574 if (bd->libaacs_open && bd->libaacs_decrypt_unit) { 00575 BD_DEBUG(DBG_BLURAY, "Loaded libaacs (%p)\n", bd->h_libaacs); 00576 bd->disc_info.libaacs_detected = 1; 00577 return 1; 00578 00579 } else { 00580 BD_DEBUG(DBG_BLURAY, "libaacs dlsym failed! (%p)\n", bd->h_libaacs); 00581 } 00582 00583 } else { 00584 BD_DEBUG(DBG_BLURAY, "libaacs not found! (%p)\n", bd); 00585 } 00586 00587 _libaacs_unload(bd); 00588 00589 return 0; 00590 00591 #else 00592 BD_DEBUG(DBG_BLURAY, "Using libaacs via normal linking\n"); 00593 00594 bd->libaacs_open = &aacs_open; 00595 bd->libaacs_decrypt_unit = &aacs_decrypt_unit; 00596 bd->disc_info.libaacs_detected = 1; 00597 00598 return 1; 00599 #endif 00600 } 00601 00602 static int _libaacs_open(BLURAY *bd, const char *keyfile_path) 00603 { 00604 _libaacs_close(bd); 00605 00606 if (!_libaacs_required(bd)) { 00607 /* no AACS */ 00608 return 1; /* no error if libaacs is not needed */ 00609 } 00610 00611 if (!_libaacs_load(bd)) { 00612 /* no libaacs */ 00613 return 0; 00614 } 00615 00616 bd->aacs = bd->libaacs_open(bd->device_path, keyfile_path); 00617 00618 if (bd->aacs) { 00619 BD_DEBUG(DBG_BLURAY, "Opened libaacs (%p)\n", bd->aacs); 00620 bd->disc_info.aacs_handled = 1; 00621 return 1; 00622 } 00623 00624 BD_DEBUG(DBG_BLURAY, "aacs_open() failed!\n"); 00625 bd->disc_info.aacs_handled = 0; 00626 00627 _libaacs_unload(bd); 00628 return 0; 00629 } 00630 00631 static uint8_t *_libaacs_get_vid(BLURAY *bd) 00632 { 00633 if (bd->aacs) { 00634 #ifdef DLOPEN_CRYPTO_LIBS 00635 fptr_p_void fptr = (fptr_p_void)dl_dlsym(bd->h_libaacs, "aacs_get_vid"); 00636 if (fptr) { 00637 return (uint8_t*)fptr(bd->aacs); 00638 } 00639 BD_DEBUG(DBG_BLURAY, "aacs_get_vid() dlsym failed! (%p)", bd); 00640 return NULL; 00641 #else 00642 return aacs_get_vid(bd->aacs); 00643 #endif 00644 } 00645 00646 BD_DEBUG(DBG_BLURAY, "_libaacs_get_vid(): libaacs not initialized! (%p)", bd); 00647 return NULL; 00648 } 00649 00650 static void _libbdplus_close(BLURAY *bd) 00651 { 00652 if (bd->bdplus) { 00653 DL_CALL(bd->h_libbdplus, bdplus_free, bd->bdplus); 00654 bd->bdplus = NULL; 00655 } 00656 } 00657 00658 static void _libbdplus_unload(BLURAY *bd) 00659 { 00660 _libbdplus_close(bd); 00661 00662 #ifdef DLOPEN_CRYPTO_LIBS 00663 if (bd->h_libbdplus) { 00664 dl_dlclose(bd->h_libbdplus); 00665 bd->h_libbdplus = NULL; 00666 } 00667 #endif 00668 00669 bd->bdplus_init = NULL; 00670 bd->bdplus_seek = NULL; 00671 bd->bdplus_fixup = NULL; 00672 } 00673 00674 static int _libbdplus_required(BLURAY *bd) 00675 { 00676 BD_FILE_H *fd; 00677 char *tmp; 00678 00679 tmp = str_printf("%s/BDSVM/00000.svm", bd->device_path); 00680 fd = file_open(tmp, "rb"); 00681 X_FREE(tmp); 00682 00683 if (fd) { 00684 file_close(fd); 00685 00686 BD_DEBUG(DBG_BLURAY, "BDSVM/00000.svm found. Disc seems to be BD+ protected (%p)\n", bd); 00687 bd->disc_info.bdplus_detected = 1; 00688 return 1; 00689 } 00690 00691 BD_DEBUG(DBG_BLURAY, "BDSVM/00000.svm not found. No BD+ protection (%p)\n", bd); 00692 bd->disc_info.bdplus_detected = 0; 00693 return 0; 00694 } 00695 00696 static int _libbdplus_load(BLURAY *bd) 00697 { 00698 BD_DEBUG(DBG_BDPLUS, "attempting to load libbdplus\n"); 00699 00700 #ifdef DLOPEN_CRYPTO_LIBS 00701 if (bd->h_libbdplus) { 00702 return 1; 00703 } 00704 00705 bd->disc_info.libbdplus_detected = 0; 00706 if ((bd->h_libbdplus = dl_dlopen("libbdplus", "0"))) { 00707 00708 BD_DEBUG(DBG_BLURAY, "Loading libbdplus (%p)\n", bd->h_libbdplus); 00709 00710 bd->bdplus_init = (fptr_p_void)dl_dlsym(bd->h_libbdplus, "bdplus_init"); 00711 bd->bdplus_seek = (fptr_int32)dl_dlsym(bd->h_libbdplus, "bdplus_seek"); 00712 bd->bdplus_fixup = (fptr_int32)dl_dlsym(bd->h_libbdplus, "bdplus_fixup"); 00713 00714 if (bd->bdplus_init && bd->bdplus_seek && bd->bdplus_fixup) { 00715 BD_DEBUG(DBG_BLURAY, "Loaded libbdplus (%p)\n", bd->h_libbdplus); 00716 bd->disc_info.libbdplus_detected = 1; 00717 return 1; 00718 } 00719 00720 BD_DEBUG(DBG_BLURAY, "libbdplus dlsym failed! (%p)\n", bd->h_libbdplus); 00721 00722 } else { 00723 BD_DEBUG(DBG_BLURAY, "libbdplus not found! (%p)\n", bd); 00724 } 00725 00726 _libbdplus_unload(bd); 00727 00728 return 0; 00729 00730 #else 00731 BD_DEBUG(DBG_BLURAY,"Using libbdplus via normal linking\n"); 00732 00733 bd->bdplus_init = &bdplus_init; 00734 bd->bdplus_seek = &bdplus_seek; 00735 bd->bdplus_fixup = &bdplus_fixup; 00736 bd->disc_info.libbdplus_detected = 1; 00737 00738 return 1; 00739 #endif 00740 } 00741 00742 static int _libbdplus_open(BLURAY *bd, const char *keyfile_path) 00743 { 00744 // Take a quick stab to see if we want/need bdplus 00745 // we should fix this, and add various string functions. 00746 uint8_t vid[16] = { 00747 0xC5,0x43,0xEF,0x2A,0x15,0x0E,0x50,0xC4,0xE2,0xCA, 00748 0x71,0x65,0xB1,0x7C,0xA7,0xCB}; // FIXME 00749 00750 _libbdplus_close(bd); 00751 00752 if (!_libbdplus_required(bd)) { 00753 /* no BD+ */ 00754 return 1; /* no error if libbdplus is not needed */ 00755 } 00756 00757 if (!_libbdplus_load(bd)) { 00758 /* no libbdplus */ 00759 return 0; 00760 } 00761 00762 const uint8_t *aacs_vid = (const uint8_t *)_libaacs_get_vid(bd); 00763 bd->bdplus = bd->bdplus_init(bd->device_path, keyfile_path, aacs_vid ? aacs_vid : vid); 00764 00765 if (bd->bdplus) { 00766 BD_DEBUG(DBG_BLURAY,"libbdplus initialized\n"); 00767 bd->disc_info.bdplus_handled = 1; 00768 return 1; 00769 } 00770 00771 BD_DEBUG(DBG_BLURAY,"bdplus_init() failed\n"); 00772 bd->disc_info.bdplus_handled = 0; 00773 00774 _libbdplus_unload(bd); 00775 return 0; 00776 } 00777 00778 /* 00779 * index open 00780 */ 00781 00782 static int _index_open(BLURAY *bd) 00783 { 00784 if (!bd->index) { 00785 char *file; 00786 00787 file = str_printf("%s/BDMV/index.bdmv", bd->device_path); 00788 bd->index = indx_parse(file); 00789 X_FREE(file); 00790 } 00791 00792 return !!bd->index; 00793 } 00794 00795 /* 00796 * meta open 00797 */ 00798 00799 static int _meta_open(BLURAY *bd) 00800 { 00801 if (!bd->meta){ 00802 bd->meta = meta_parse(bd->device_path); 00803 } 00804 00805 return !!bd->meta; 00806 } 00807 /* 00808 * disc info 00809 */ 00810 00811 const BLURAY_DISC_INFO *bd_get_disc_info(BLURAY *bd) 00812 { 00813 return &bd->disc_info; 00814 } 00815 00816 static void _fill_disc_info(BLURAY *bd) 00817 { 00818 bd->disc_info.bluray_detected = 0; 00819 bd->disc_info.top_menu_supported = 0; 00820 bd->disc_info.first_play_supported = 0; 00821 bd->disc_info.num_hdmv_titles = 0; 00822 bd->disc_info.num_bdj_titles = 0; 00823 bd->disc_info.num_unsupported_titles = 0; 00824 00825 if (bd->index) { 00826 INDX_PLAY_ITEM *pi; 00827 unsigned ii; 00828 00829 bd->disc_info.bluray_detected = 1; 00830 00831 pi = &bd->index->first_play; 00832 if (pi->object_type == indx_object_type_hdmv && pi->hdmv.id_ref != 0xffff) { 00833 bd->disc_info.first_play_supported = 1; 00834 } 00835 00836 pi = &bd->index->top_menu; 00837 if (pi->object_type == indx_object_type_hdmv && pi->hdmv.id_ref != 0xffff) { 00838 bd->disc_info.top_menu_supported = 1; 00839 } 00840 00841 for (ii = 0; ii < bd->index->num_titles; ii++) { 00842 if (bd->index->titles[ii].object_type == indx_object_type_hdmv) { 00843 bd->disc_info.num_hdmv_titles++; 00844 } 00845 if (bd->index->titles[ii].object_type == indx_object_type_bdj) { 00846 bd->disc_info.num_bdj_titles++; 00847 bd->disc_info.num_unsupported_titles++; 00848 } 00849 } 00850 } 00851 } 00852 00853 /* 00854 * open / close 00855 */ 00856 00857 BLURAY *bd_open(const char* device_path, const char* keyfile_path) 00858 { 00859 BLURAY *bd = calloc(1, sizeof(BLURAY)); 00860 00861 if (device_path) { 00862 00863 bd->device_path = (char*)malloc(strlen(device_path) + 1); 00864 strcpy(bd->device_path, device_path); 00865 00866 _libaacs_open(bd, keyfile_path); 00867 00868 _libbdplus_open(bd, keyfile_path); 00869 00870 _index_open(bd); 00871 00872 bd->meta = NULL; 00873 00874 bd->regs = bd_registers_init(); 00875 00876 _fill_disc_info(bd); 00877 00878 BD_DEBUG(DBG_BLURAY, "BLURAY initialized! (%p)\n", bd); 00879 } else { 00880 X_FREE(bd); 00881 00882 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "No device path provided!\n"); 00883 } 00884 00885 return bd; 00886 } 00887 00888 void bd_close(BLURAY *bd) 00889 { 00890 bd_stop_bdj(bd); 00891 00892 _libaacs_unload(bd); 00893 00894 _libbdplus_unload(bd); 00895 00896 _close_m2ts(&bd->st0); 00897 _close_preload(&bd->st_ig); 00898 00899 if (bd->title_list != NULL) { 00900 nav_free_title_list(bd->title_list); 00901 } 00902 if (bd->title != NULL) { 00903 nav_title_close(bd->title); 00904 } 00905 00906 hdmv_vm_free(&bd->hdmv_vm); 00907 00908 gc_free(&bd->graphics_controller); 00909 indx_free(&bd->index); 00910 bd_registers_free(bd->regs); 00911 00912 X_FREE(bd->event_queue); 00913 X_FREE(bd->device_path); 00914 00915 BD_DEBUG(DBG_BLURAY, "BLURAY destroyed! (%p)\n", bd); 00916 00917 X_FREE(bd); 00918 } 00919 00920 /* 00921 * seeking and current position 00922 */ 00923 00924 static int64_t _seek_internal(BLURAY *bd, 00925 NAV_CLIP *clip, uint32_t title_pkt, uint32_t clip_pkt) 00926 { 00927 if (_seek_stream(bd, &bd->st0, clip, clip_pkt) >= 0) { 00928 00929 /* update title position */ 00930 bd->s_pos = (uint64_t)title_pkt * 192; 00931 00932 /* chapter tracking */ 00933 _update_chapter_psr(bd); 00934 00935 BD_DEBUG(DBG_BLURAY, "Seek to %"PRIu64" (%p)\n", 00936 bd->s_pos, bd); 00937 00938 if (bd->bdplus_seek && bd->bdplus) { 00939 bd->bdplus_seek(bd->bdplus, bd->st0.clip_block_pos); 00940 } 00941 } 00942 00943 return bd->s_pos; 00944 } 00945 00946 /* _change_angle() should be used only before call to _seek_internal() ! */ 00947 static void _change_angle(BLURAY *bd) 00948 { 00949 if (bd->seamless_angle_change) { 00950 bd->st0.clip = nav_set_angle(bd->title, bd->st0.clip, bd->request_angle); 00951 bd->seamless_angle_change = 0; 00952 bd_psr_write(bd->regs, PSR_ANGLE_NUMBER, bd->title->angle + 1); 00953 00954 /* force re-opening .m2ts file in _seek_internal() */ 00955 _close_m2ts(&bd->st0); 00956 } 00957 } 00958 00959 int64_t bd_seek_time(BLURAY *bd, uint64_t tick) 00960 { 00961 uint32_t clip_pkt, out_pkt; 00962 NAV_CLIP *clip; 00963 00964 tick /= 2; 00965 00966 if (bd->title && 00967 tick < bd->title->duration) { 00968 00969 _change_angle(bd); 00970 00971 // Find the closest access unit to the requested position 00972 clip = nav_time_search(bd->title, tick, &clip_pkt, &out_pkt); 00973 00974 return _seek_internal(bd, clip, out_pkt, clip_pkt); 00975 } 00976 00977 return bd->s_pos; 00978 } 00979 00980 uint64_t bd_tell_time(BLURAY *bd) 00981 { 00982 uint32_t clip_pkt = 0, out_pkt = 0, out_time = 0; 00983 00984 if (bd && bd->title) { 00985 nav_packet_search(bd->title, bd->s_pos / 192, &clip_pkt, &out_pkt, &out_time); 00986 } 00987 00988 return ((uint64_t)out_time) * 2; 00989 } 00990 00991 int64_t bd_seek_chapter(BLURAY *bd, unsigned chapter) 00992 { 00993 uint32_t clip_pkt, out_pkt; 00994 NAV_CLIP *clip; 00995 00996 if (bd->title && 00997 chapter < bd->title->chap_list.count) { 00998 00999 _change_angle(bd); 01000 01001 // Find the closest access unit to the requested position 01002 clip = nav_chapter_search(bd->title, chapter, &clip_pkt, &out_pkt); 01003 01004 return _seek_internal(bd, clip, out_pkt, clip_pkt); 01005 } 01006 01007 return bd->s_pos; 01008 } 01009 01010 int64_t bd_chapter_pos(BLURAY *bd, unsigned chapter) 01011 { 01012 uint32_t clip_pkt, out_pkt; 01013 01014 if (bd->title && 01015 chapter < bd->title->chap_list.count) { 01016 01017 // Find the closest access unit to the requested position 01018 nav_chapter_search(bd->title, chapter, &clip_pkt, &out_pkt); 01019 return (int64_t)out_pkt * 192; 01020 } 01021 01022 return -1; 01023 } 01024 01025 uint32_t bd_get_current_chapter(BLURAY *bd) 01026 { 01027 if (bd->title) { 01028 return nav_chapter_get_current(bd->st0.clip, bd->st0.clip_pos / 192); 01029 } 01030 01031 return 0; 01032 } 01033 01034 int64_t bd_seek_playitem(BLURAY *bd, unsigned clip_ref) 01035 { 01036 uint32_t clip_pkt, out_pkt; 01037 NAV_CLIP *clip; 01038 01039 if (bd->title && 01040 clip_ref < bd->title->clip_list.count) { 01041 01042 _change_angle(bd); 01043 01044 clip = &bd->title->clip_list.clip[clip_ref]; 01045 clip_pkt = clip->start_pkt; 01046 out_pkt = clip->pos; 01047 01048 return _seek_internal(bd, clip, out_pkt, clip_pkt); 01049 } 01050 01051 return bd->s_pos; 01052 } 01053 01054 int64_t bd_seek_mark(BLURAY *bd, unsigned mark) 01055 { 01056 uint32_t clip_pkt, out_pkt; 01057 NAV_CLIP *clip; 01058 01059 if (bd->title && 01060 mark < bd->title->mark_list.count) { 01061 01062 _change_angle(bd); 01063 01064 // Find the closest access unit to the requested position 01065 clip = nav_mark_search(bd->title, mark, &clip_pkt, &out_pkt); 01066 01067 return _seek_internal(bd, clip, out_pkt, clip_pkt); 01068 } 01069 01070 return bd->s_pos; 01071 } 01072 01073 int64_t bd_seek(BLURAY *bd, uint64_t pos) 01074 { 01075 uint32_t pkt, clip_pkt, out_pkt, out_time; 01076 NAV_CLIP *clip; 01077 01078 if (bd->title && 01079 pos < (uint64_t)bd->title->packets * 192) { 01080 01081 pkt = pos / 192; 01082 01083 _change_angle(bd); 01084 01085 // Find the closest access unit to the requested position 01086 clip = nav_packet_search(bd->title, pkt, &clip_pkt, &out_pkt, &out_time); 01087 01088 return _seek_internal(bd, clip, out_pkt, clip_pkt); 01089 } 01090 01091 return bd->s_pos; 01092 } 01093 01094 uint64_t bd_get_title_size(BLURAY *bd) 01095 { 01096 if (bd && bd->title) { 01097 return (uint64_t)bd->title->packets * 192; 01098 } 01099 return UINT64_C(0); 01100 } 01101 01102 uint64_t bd_tell(BLURAY *bd) 01103 { 01104 return bd ? bd->s_pos : INT64_C(0); 01105 } 01106 01107 /* 01108 * read 01109 */ 01110 01111 static int64_t _clip_seek_time(BLURAY *bd, uint64_t tick) 01112 { 01113 uint32_t clip_pkt, out_pkt; 01114 01115 if (tick < bd->st0.clip->out_time) { 01116 01117 // Find the closest access unit to the requested position 01118 nav_clip_time_search(bd->st0.clip, tick, &clip_pkt, &out_pkt); 01119 01120 return _seek_internal(bd, bd->st0.clip, out_pkt, clip_pkt); 01121 } 01122 01123 return bd->s_pos; 01124 } 01125 01126 int bd_read(BLURAY *bd, unsigned char *buf, int len) 01127 { 01128 BD_STREAM *st = &bd->st0; 01129 int out_len; 01130 01131 if (st->fp) { 01132 out_len = 0; 01133 BD_DEBUG(DBG_STREAM, "Reading [%d bytes] at %"PRIu64"... (%p)\n", len, bd->s_pos, bd); 01134 01135 while (len > 0) { 01136 uint32_t clip_pkt; 01137 01138 unsigned int size = len; 01139 // Do we need to read more data? 01140 clip_pkt = st->clip_pos / 192; 01141 if (bd->seamless_angle_change) { 01142 if (clip_pkt >= bd->angle_change_pkt) { 01143 if (clip_pkt >= st->clip->end_pkt) { 01144 st->clip = nav_next_clip(bd->title, st->clip); 01145 if (!_open_m2ts(bd, st)) { 01146 return -1; 01147 } 01148 bd->s_pos = st->clip->pos; 01149 } else { 01150 _change_angle(bd); 01151 _clip_seek_time(bd, bd->angle_change_time); 01152 } 01153 bd->seamless_angle_change = 0; 01154 } else { 01155 uint64_t angle_pos; 01156 01157 angle_pos = bd->angle_change_pkt * 192; 01158 if (angle_pos - st->clip_pos < size) 01159 { 01160 size = angle_pos - st->clip_pos; 01161 } 01162 } 01163 } 01164 if (st->int_buf_off == 6144 || clip_pkt >= st->clip->end_pkt) { 01165 01166 // Do we need to get the next clip? 01167 if (st->clip == NULL) { 01168 // We previously reached the last clip. Nothing 01169 // else to read. 01170 _queue_event(bd, (BD_EVENT){BD_EVENT_END_OF_TITLE, 0}); 01171 return 0; 01172 } 01173 if (clip_pkt >= st->clip->end_pkt) { 01174 01175 // split read()'s at clip boundary 01176 if (out_len) { 01177 return out_len; 01178 } 01179 01180 MPLS_PI *pi = &st->clip->title->pl->play_item[st->clip->ref]; 01181 01182 // handle still mode clips 01183 if (pi->still_mode == BLURAY_STILL_INFINITE) { 01184 _queue_event(bd, (BD_EVENT){BD_EVENT_STILL_TIME, 0}); 01185 return 0; 01186 } 01187 if (pi->still_mode == BLURAY_STILL_TIME) { 01188 if (bd->event_queue) { 01189 _queue_event(bd, (BD_EVENT){BD_EVENT_STILL_TIME, pi->still_time}); 01190 return 0; 01191 } 01192 } 01193 01194 // find next clip 01195 st->clip = nav_next_clip(bd->title, st->clip); 01196 if (st->clip == NULL) { 01197 BD_DEBUG(DBG_BLURAY|DBG_STREAM, "End of title (%p)\n", bd); 01198 _queue_event(bd, (BD_EVENT){BD_EVENT_END_OF_TITLE, 0}); 01199 return 0; 01200 } 01201 if (!_open_m2ts(bd, st)) { 01202 return -1; 01203 } 01204 } 01205 01206 if (_read_block(bd, st, bd->int_buf)) { 01207 01208 st->int_buf_off = st->clip_pos % 6144; 01209 01210 } else { 01211 return out_len; 01212 } 01213 } 01214 if (size > (unsigned int)6144 - st->int_buf_off) { 01215 size = 6144 - st->int_buf_off; 01216 } 01217 memcpy(buf, bd->int_buf + st->int_buf_off, size); 01218 buf += size; 01219 len -= size; 01220 out_len += size; 01221 st->clip_pos += size; 01222 st->int_buf_off += size; 01223 bd->s_pos += size; 01224 } 01225 01226 /* chapter tracking */ 01227 if (bd->s_pos > bd->next_chapter_start) { 01228 _update_chapter_psr(bd); 01229 } 01230 01231 BD_DEBUG(DBG_STREAM, "%d bytes read OK! (%p)\n", out_len, bd); 01232 01233 return out_len; 01234 } 01235 01236 BD_DEBUG(DBG_STREAM | DBG_CRIT, "bd_read(): no valid title selected! (%p)\n", bd); 01237 01238 return -1; 01239 } 01240 01241 int bd_read_skip_still(BLURAY *bd) 01242 { 01243 BD_STREAM *st = &bd->st0; 01244 01245 if (st->clip) { 01246 MPLS_PI *pi = &st->clip->title->pl->play_item[st->clip->ref]; 01247 01248 if (pi->still_mode == BLURAY_STILL_TIME) { 01249 st->clip = nav_next_clip(bd->title, st->clip); 01250 if (st->clip) { 01251 return _open_m2ts(bd, st); 01252 } 01253 } 01254 } 01255 01256 return 0; 01257 } 01258 01259 /* 01260 * preloader for asynchronous sub paths 01261 */ 01262 01263 static int _find_ig_stream(BLURAY *bd, uint16_t *pid, int *sub_path_idx) 01264 { 01265 MPLS_PI *pi = &bd->title->pl->play_item[0]; 01266 unsigned ig_stream = bd_psr_read(bd->regs, PSR_IG_STREAM_ID); 01267 01268 if (ig_stream > 0 && ig_stream <= pi->stn.num_ig) { 01269 ig_stream--; 01270 if (pi->stn.ig[ig_stream].stream_type == 2) { 01271 *sub_path_idx = pi->stn.ig[ig_stream].subpath_id; 01272 } 01273 *pid = pi->stn.ig[ig_stream].pid; 01274 01275 BD_DEBUG(DBG_BLURAY, "_find_ig_stream(): current IG stream pid 0x%04x sub-path %d\n", 01276 *pid, *sub_path_idx); 01277 return 1; 01278 } 01279 01280 return 0; 01281 } 01282 01283 static int _preload_ig_subpath(BLURAY *bd) 01284 { 01285 int ig_subpath = -1; 01286 uint16_t ig_pid = 0; 01287 01288 _find_ig_stream(bd, &ig_pid, &ig_subpath); 01289 01290 if (!bd->graphics_controller) { 01291 return 0; 01292 } 01293 01294 if (ig_subpath < 0) { 01295 return 0; 01296 } 01297 01298 bd->st_ig.clip = &bd->title->sub_path[ig_subpath].clip_list.clip[0]; 01299 01300 if (!_preload_m2ts(bd, &bd->st_ig)) { 01301 return 0; 01302 } 01303 01304 gc_decode_ts(bd->graphics_controller, ig_pid, bd->st_ig.buf, bd->st_ig.clip_size / 6144, -1); 01305 01306 return 1; 01307 } 01308 01309 static int _preload_subpaths(BLURAY *bd) 01310 { 01311 if (bd->title->pl->sub_count <= 0) { 01312 return 0; 01313 } 01314 01315 return _preload_ig_subpath(bd); 01316 } 01317 01318 /* 01319 * select title / angle 01320 */ 01321 01322 static void _close_playlist(BLURAY *bd) 01323 { 01324 if (bd->graphics_controller) { 01325 gc_run(bd->graphics_controller, GC_CTRL_RESET, 0, NULL); 01326 } 01327 01328 _close_m2ts(&bd->st0); 01329 _close_preload(&bd->st_ig); 01330 01331 if (bd->title) { 01332 nav_title_close(bd->title); 01333 bd->title = NULL; 01334 } 01335 } 01336 01337 static int _open_playlist(BLURAY *bd, const char *f_name, unsigned angle) 01338 { 01339 _close_playlist(bd); 01340 01341 bd->title = nav_title_open(bd->device_path, f_name, angle); 01342 if (bd->title == NULL) { 01343 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Unable to open title %s! (%p)\n", 01344 f_name, bd); 01345 return 0; 01346 } 01347 01348 bd->seamless_angle_change = 0; 01349 bd->s_pos = 0; 01350 01351 bd->next_chapter_start = bd_chapter_pos(bd, 1); 01352 01353 bd_psr_write(bd->regs, PSR_PLAYLIST, atoi(bd->title->name)); 01354 bd_psr_write(bd->regs, PSR_ANGLE_NUMBER, bd->title->angle + 1); 01355 bd_psr_write(bd->regs, PSR_CHAPTER, 1); 01356 01357 // Get the initial clip of the playlist 01358 bd->st0.clip = nav_next_clip(bd->title, NULL); 01359 if (_open_m2ts(bd, &bd->st0)) { 01360 BD_DEBUG(DBG_BLURAY, "Title %s selected! (%p)\n", f_name, bd); 01361 01362 _preload_subpaths(bd); 01363 01364 return 1; 01365 } 01366 return 0; 01367 } 01368 01369 int bd_select_playlist(BLURAY *bd, uint32_t playlist) 01370 { 01371 char *f_name = str_printf("%05d.mpls", playlist); 01372 int result; 01373 01374 if (bd->title_list) { 01375 /* update current title */ 01376 unsigned i; 01377 for (i = 0; i < bd->title_list->count; i++) { 01378 if (playlist == bd->title_list->title_info[i].mpls_id) { 01379 bd->title_idx = i; 01380 break; 01381 } 01382 } 01383 } 01384 01385 result = _open_playlist(bd, f_name, 0); 01386 01387 X_FREE(f_name); 01388 return result; 01389 } 01390 01391 // Select a title for playback 01392 // The title index is an index into the list 01393 // established by bd_get_titles() 01394 int bd_select_title(BLURAY *bd, uint32_t title_idx) 01395 { 01396 const char *f_name; 01397 01398 // Open the playlist 01399 if (bd->title_list == NULL) { 01400 BD_DEBUG(DBG_BLURAY, "Title list not yet read! (%p)\n", bd); 01401 return 0; 01402 } 01403 if (bd->title_list->count <= title_idx) { 01404 BD_DEBUG(DBG_BLURAY, "Invalid title index %d! (%p)\n", title_idx, bd); 01405 return 0; 01406 } 01407 01408 bd->title_idx = title_idx; 01409 f_name = bd->title_list->title_info[title_idx].name; 01410 01411 return _open_playlist(bd, f_name, 0); 01412 } 01413 01414 uint32_t bd_get_current_title(BLURAY *bd) 01415 { 01416 return bd->title_idx; 01417 } 01418 01419 int bd_select_angle(BLURAY *bd, unsigned angle) 01420 { 01421 unsigned orig_angle; 01422 01423 if (bd->title == NULL) { 01424 BD_DEBUG(DBG_BLURAY, "Title not yet selected! (%p)\n", bd); 01425 return 0; 01426 } 01427 01428 orig_angle = bd->title->angle; 01429 01430 bd->st0.clip = nav_set_angle(bd->title, bd->st0.clip, angle); 01431 01432 if (orig_angle == bd->title->angle) { 01433 return 1; 01434 } 01435 01436 bd_psr_write(bd->regs, PSR_ANGLE_NUMBER, bd->title->angle + 1); 01437 01438 if (!_open_m2ts(bd, &bd->st0)) { 01439 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "Error selecting angle %d ! (%p)\n", angle, bd); 01440 return 0; 01441 } 01442 01443 return 1; 01444 } 01445 01446 unsigned bd_get_current_angle(BLURAY *bd) 01447 { 01448 if (bd->title) { 01449 return bd->title->angle; 01450 } 01451 return 0; 01452 } 01453 01454 01455 void bd_seamless_angle_change(BLURAY *bd, unsigned angle) 01456 { 01457 uint32_t clip_pkt; 01458 01459 clip_pkt = (bd->st0.clip_pos + 191) / 192; 01460 bd->angle_change_pkt = nav_angle_change_search(bd->st0.clip, clip_pkt, 01461 &bd->angle_change_time); 01462 bd->request_angle = angle; 01463 bd->seamless_angle_change = 1; 01464 } 01465 01466 /* 01467 * title lists 01468 */ 01469 01470 uint32_t bd_get_titles(BLURAY *bd, uint8_t flags, uint32_t min_title_length) 01471 { 01472 if (!bd) { 01473 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_get_titles(NULL) failed (%p)\n", bd); 01474 return 0; 01475 } 01476 01477 if (bd->title_list != NULL) { 01478 nav_free_title_list(bd->title_list); 01479 } 01480 bd->title_list = nav_get_title_list(bd->device_path, flags, min_title_length); 01481 01482 if (!bd->title_list) { 01483 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "nav_get_title_list(%s) failed (%p)\n", bd->device_path, bd); 01484 return 0; 01485 } 01486 01487 return bd->title_list->count; 01488 } 01489 01490 static void _copy_streams(NAV_CLIP *clip, BLURAY_STREAM_INFO *streams, MPLS_STREAM *si, int count) 01491 { 01492 int ii; 01493 01494 for (ii = 0; ii < count; ii++) { 01495 streams[ii].coding_type = si[ii].coding_type; 01496 streams[ii].format = si[ii].format; 01497 streams[ii].rate = si[ii].rate; 01498 streams[ii].char_code = si[ii].char_code; 01499 memcpy(streams[ii].lang, si[ii].lang, 4); 01500 streams[ii].pid = si[ii].pid; 01501 streams[ii].aspect = nav_lookup_aspect(clip, si[ii].pid); 01502 } 01503 } 01504 01505 static BLURAY_TITLE_INFO* _fill_title_info(NAV_TITLE* title, uint32_t title_idx, uint32_t playlist) 01506 { 01507 BLURAY_TITLE_INFO *title_info; 01508 unsigned int ii; 01509 01510 title_info = calloc(1, sizeof(BLURAY_TITLE_INFO)); 01511 title_info->idx = title_idx; 01512 title_info->playlist = playlist; 01513 title_info->duration = (uint64_t)title->duration * 2; 01514 title_info->angle_count = title->angle_count; 01515 title_info->chapter_count = title->chap_list.count; 01516 title_info->chapters = calloc(title_info->chapter_count, sizeof(BLURAY_TITLE_CHAPTER)); 01517 for (ii = 0; ii < title_info->chapter_count; ii++) { 01518 title_info->chapters[ii].idx = ii; 01519 title_info->chapters[ii].start = (uint64_t)title->chap_list.mark[ii].title_time * 2; 01520 title_info->chapters[ii].duration = (uint64_t)title->chap_list.mark[ii].duration * 2; 01521 title_info->chapters[ii].offset = (uint64_t)title->chap_list.mark[ii].title_pkt * 192L; 01522 } 01523 title_info->clip_count = title->clip_list.count; 01524 title_info->clips = calloc(title_info->clip_count, sizeof(BLURAY_CLIP_INFO)); 01525 for (ii = 0; ii < title_info->clip_count; ii++) { 01526 MPLS_PI *pi = &title->pl->play_item[ii]; 01527 BLURAY_CLIP_INFO *ci = &title_info->clips[ii]; 01528 NAV_CLIP *nc = &title->clip_list.clip[ii]; 01529 01530 ci->pkt_count = nc->end_pkt - nc->start_pkt; 01531 ci->still_mode = pi->still_mode; 01532 ci->still_time = pi->still_time; 01533 ci->video_stream_count = pi->stn.num_video; 01534 ci->audio_stream_count = pi->stn.num_audio; 01535 ci->pg_stream_count = pi->stn.num_pg + pi->stn.num_pip_pg; 01536 ci->ig_stream_count = pi->stn.num_ig; 01537 ci->sec_video_stream_count = pi->stn.num_secondary_video; 01538 ci->sec_audio_stream_count = pi->stn.num_secondary_audio; 01539 ci->video_streams = calloc(ci->video_stream_count, sizeof(BLURAY_STREAM_INFO)); 01540 ci->audio_streams = calloc(ci->audio_stream_count, sizeof(BLURAY_STREAM_INFO)); 01541 ci->pg_streams = calloc(ci->pg_stream_count, sizeof(BLURAY_STREAM_INFO)); 01542 ci->ig_streams = calloc(ci->ig_stream_count, sizeof(BLURAY_STREAM_INFO)); 01543 ci->sec_video_streams = calloc(ci->sec_video_stream_count, sizeof(BLURAY_STREAM_INFO)); 01544 ci->sec_audio_streams = calloc(ci->sec_audio_stream_count, sizeof(BLURAY_STREAM_INFO)); 01545 _copy_streams(nc, ci->video_streams, pi->stn.video, ci->video_stream_count); 01546 _copy_streams(nc, ci->audio_streams, pi->stn.audio, ci->audio_stream_count); 01547 _copy_streams(nc, ci->pg_streams, pi->stn.pg, ci->pg_stream_count); 01548 _copy_streams(nc, ci->ig_streams, pi->stn.ig, ci->ig_stream_count); 01549 _copy_streams(nc, ci->sec_video_streams, pi->stn.secondary_video, ci->sec_video_stream_count); 01550 _copy_streams(nc, ci->sec_audio_streams, pi->stn.secondary_audio, ci->sec_audio_stream_count); 01551 } 01552 01553 return title_info; 01554 } 01555 01556 static BLURAY_TITLE_INFO *_get_title_info(BLURAY *bd, uint32_t title_idx, uint32_t playlist, const char *mpls_name, 01557 unsigned angle) 01558 { 01559 NAV_TITLE *title; 01560 BLURAY_TITLE_INFO *title_info; 01561 01562 title = nav_title_open(bd->device_path, mpls_name, angle); 01563 if (title == NULL) { 01564 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Unable to open title %s! (%p)\n", 01565 mpls_name, bd); 01566 return NULL; 01567 } 01568 01569 title_info = _fill_title_info(title, title_idx, playlist); 01570 01571 nav_title_close(title); 01572 return title_info; 01573 } 01574 01575 BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx, unsigned angle) 01576 { 01577 if (bd->title_list == NULL) { 01578 BD_DEBUG(DBG_BLURAY, "Title list not yet read! (%p)\n", bd); 01579 return NULL; 01580 } 01581 if (bd->title_list->count <= title_idx) { 01582 BD_DEBUG(DBG_BLURAY, "Invalid title index %d! (%p)\n", title_idx, bd); 01583 return NULL; 01584 } 01585 01586 return _get_title_info(bd, 01587 title_idx, bd->title_list->title_info[title_idx].mpls_id, 01588 bd->title_list->title_info[title_idx].name, 01589 angle); 01590 } 01591 01592 BLURAY_TITLE_INFO* bd_get_playlist_info(BLURAY *bd, uint32_t playlist, unsigned angle) 01593 { 01594 char *f_name = str_printf("%05d.mpls", playlist); 01595 BLURAY_TITLE_INFO *title_info; 01596 01597 title_info = _get_title_info(bd, 0, playlist, f_name, angle); 01598 01599 X_FREE(f_name); 01600 01601 return title_info; 01602 } 01603 01604 void bd_free_title_info(BLURAY_TITLE_INFO *title_info) 01605 { 01606 unsigned int ii; 01607 01608 X_FREE(title_info->chapters); 01609 for (ii = 0; ii < title_info->clip_count; ii++) { 01610 X_FREE(title_info->clips[ii].video_streams); 01611 X_FREE(title_info->clips[ii].audio_streams); 01612 X_FREE(title_info->clips[ii].pg_streams); 01613 X_FREE(title_info->clips[ii].ig_streams); 01614 X_FREE(title_info->clips[ii].sec_video_streams); 01615 X_FREE(title_info->clips[ii].sec_audio_streams); 01616 } 01617 X_FREE(title_info->clips); 01618 X_FREE(title_info); 01619 } 01620 01621 /* 01622 * player settings 01623 */ 01624 01625 int bd_set_player_setting(BLURAY *bd, uint32_t idx, uint32_t value) 01626 { 01627 static const struct { uint32_t idx; uint32_t psr; } map[] = { 01628 { BLURAY_PLAYER_SETTING_PARENTAL, PSR_PARENTAL }, 01629 { BLURAY_PLAYER_SETTING_AUDIO_CAP, PSR_AUDIO_CAP }, 01630 { BLURAY_PLAYER_SETTING_AUDIO_LANG, PSR_AUDIO_LANG }, 01631 { BLURAY_PLAYER_SETTING_PG_LANG, PSR_PG_AND_SUB_LANG }, 01632 { BLURAY_PLAYER_SETTING_MENU_LANG, PSR_MENU_LANG }, 01633 { BLURAY_PLAYER_SETTING_COUNTRY_CODE, PSR_COUNTRY }, 01634 { BLURAY_PLAYER_SETTING_REGION_CODE, PSR_REGION }, 01635 { BLURAY_PLAYER_SETTING_VIDEO_CAP, PSR_VIDEO_CAP }, 01636 { BLURAY_PLAYER_SETTING_TEXT_CAP, PSR_TEXT_CAP }, 01637 { BLURAY_PLAYER_SETTING_PLAYER_PROFILE, PSR_PROFILE_VERSION }, 01638 }; 01639 01640 unsigned i; 01641 01642 if (idx == BLURAY_PLAYER_SETTING_PLAYER_PROFILE) { 01643 value = ((value & 0xf) << 16) | 0x0200; /* version fixed to BD-RO Part 3, version 2.0 */ 01644 } 01645 01646 for (i = 0; i < sizeof(map) / sizeof(map[0]); i++) { 01647 if (idx == map[i].idx) { 01648 return !bd_psr_setting_write(bd->regs, idx, value); 01649 } 01650 } 01651 01652 return 0; 01653 } 01654 01655 int bd_set_player_setting_str(BLURAY *bd, uint32_t idx, const char *s) 01656 { 01657 switch (idx) { 01658 case BLURAY_PLAYER_SETTING_AUDIO_LANG: 01659 case BLURAY_PLAYER_SETTING_PG_LANG: 01660 case BLURAY_PLAYER_SETTING_MENU_LANG: 01661 return bd_set_player_setting(bd, idx, str_to_uint32(s, 3)); 01662 01663 case BLURAY_PLAYER_SETTING_COUNTRY_CODE: 01664 return bd_set_player_setting(bd, idx, str_to_uint32(s, 2)); 01665 01666 default: 01667 return 0; 01668 } 01669 } 01670 01671 /* 01672 * bdj 01673 */ 01674 01675 int bd_start_bdj(BLURAY *bd, const char *start_object) 01676 { 01677 #ifdef USING_BDJAVA 01678 if (bd->bdjava == NULL) { 01679 bd->bdjava = bdj_open(bd->device_path, start_object, bd, bd->regs); 01680 return !!bd->bdjava; 01681 } else { 01682 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "BD-J is already running (%p)\n", bd); 01683 return 1; 01684 } 01685 #else 01686 BD_DEBUG(DBG_BLURAY | DBG_CRIT, "%s.bdjo: BD-J not compiled in (%p)\n", start_object, bd); 01687 #endif 01688 return 0; 01689 } 01690 01691 void bd_stop_bdj(BLURAY *bd) 01692 { 01693 if (bd->bdjava != NULL) { 01694 #ifdef USING_BDJAVA 01695 bdj_close((BDJAVA*)bd->bdjava); 01696 #else 01697 BD_DEBUG(DBG_BLURAY, "BD-J not compiled in (%p)\n", bd); 01698 #endif 01699 bd->bdjava = NULL; 01700 } 01701 } 01702 01703 /* 01704 * Navigation mode interface 01705 */ 01706 01707 static void _process_psr_restore_event(BLURAY *bd, BD_PSR_EVENT *ev) 01708 { 01709 /* PSR restore events are handled internally. 01710 * Restore stored playback position. 01711 */ 01712 01713 BD_DEBUG(DBG_BLURAY, "PSR restore: psr%u = %u (%p)\n", ev->psr_idx, ev->new_val, bd); 01714 01715 switch (ev->psr_idx) { 01716 case PSR_ANGLE_NUMBER: 01717 /* can't set angle before playlist is opened */ 01718 return; 01719 case PSR_TITLE_NUMBER: 01720 /* pass to the application */ 01721 _queue_event(bd, (BD_EVENT){BD_EVENT_TITLE, ev->new_val}); 01722 return; 01723 case PSR_CHAPTER: 01724 /* will be selected automatically */ 01725 return; 01726 case PSR_PLAYLIST: 01727 bd_select_playlist(bd, ev->new_val); 01728 nav_set_angle(bd->title, bd->st0.clip, bd_psr_read(bd->regs, PSR_ANGLE_NUMBER) - 1); 01729 return; 01730 case PSR_PLAYITEM: 01731 bd_seek_playitem(bd, ev->new_val); 01732 return; 01733 case PSR_TIME: 01734 bd_seek_time(bd, ((int64_t)ev->new_val) << 1); 01735 return; 01736 01737 case PSR_SELECTED_BUTTON_ID: 01738 case PSR_MENU_PAGE_ID: 01739 /* handled by graphics controller */ 01740 return; 01741 01742 default: 01743 /* others: ignore */ 01744 return; 01745 } 01746 } 01747 01748 /* 01749 * notification events to APP 01750 */ 01751 01752 static void _process_psr_write_event(BLURAY *bd, BD_PSR_EVENT *ev) 01753 { 01754 if (ev->ev_type == BD_PSR_WRITE) { 01755 BD_DEBUG(DBG_BLURAY, "PSR write: psr%u = %u (%p)\n", ev->psr_idx, ev->new_val, bd); 01756 } 01757 01758 switch (ev->psr_idx) { 01759 01760 /* current playback position */ 01761 01762 case PSR_ANGLE_NUMBER: _queue_event(bd, (BD_EVENT){BD_EVENT_ANGLE, ev->new_val}); break; 01763 case PSR_TITLE_NUMBER: _queue_event(bd, (BD_EVENT){BD_EVENT_TITLE, ev->new_val}); break; 01764 case PSR_PLAYLIST: _queue_event(bd, (BD_EVENT){BD_EVENT_PLAYLIST, ev->new_val}); break; 01765 case PSR_PLAYITEM: _queue_event(bd, (BD_EVENT){BD_EVENT_PLAYITEM, ev->new_val}); break; 01766 case PSR_CHAPTER: _queue_event(bd, (BD_EVENT){BD_EVENT_CHAPTER, ev->new_val}); break; 01767 01768 default:; 01769 } 01770 } 01771 01772 static void _process_psr_change_event(BLURAY *bd, BD_PSR_EVENT *ev) 01773 { 01774 BD_DEBUG(DBG_BLURAY, "PSR change: psr%u = %u (%p)\n", ev->psr_idx, ev->new_val, bd); 01775 01776 _process_psr_write_event(bd, ev); 01777 01778 switch (ev->psr_idx) { 01779 01780 /* stream selection */ 01781 01782 case PSR_IG_STREAM_ID: 01783 _queue_event(bd, (BD_EVENT){BD_EVENT_IG_STREAM, ev->new_val}); 01784 break; 01785 01786 case PSR_PRIMARY_AUDIO_ID: 01787 _queue_event(bd, (BD_EVENT){BD_EVENT_AUDIO_STREAM, ev->new_val}); 01788 break; 01789 01790 case PSR_PG_STREAM: 01791 if ((ev->new_val & 0x80000fff) != (ev->old_val & 0x80000fff)) { 01792 _queue_event(bd, (BD_EVENT){BD_EVENT_PG_TEXTST, !!(ev->new_val & 0x80000000)}); 01793 _queue_event(bd, (BD_EVENT){BD_EVENT_PG_TEXTST_STREAM, ev->new_val & 0xfff}); 01794 } 01795 break; 01796 01797 case PSR_SECONDARY_AUDIO_VIDEO: 01798 /* secondary video */ 01799 if ((ev->new_val & 0x8f00ff00) != (ev->old_val & 0x8f00ff00)) { 01800 _queue_event(bd, (BD_EVENT){BD_EVENT_SECONDARY_VIDEO, !!(ev->new_val & 0x80000000)}); 01801 _queue_event(bd, (BD_EVENT){BD_EVENT_SECONDARY_VIDEO_SIZE, (ev->new_val >> 24) & 0xf}); 01802 _queue_event(bd, (BD_EVENT){BD_EVENT_SECONDARY_VIDEO_STREAM, (ev->new_val & 0xff00) >> 8}); 01803 } 01804 /* secondary audio */ 01805 if ((ev->new_val & 0x400000ff) != (ev->old_val & 0x400000ff)) { 01806 _queue_event(bd, (BD_EVENT){BD_EVENT_SECONDARY_AUDIO, !!(ev->new_val & 0x40000000)}); 01807 _queue_event(bd, (BD_EVENT){BD_EVENT_SECONDARY_AUDIO_STREAM, ev->new_val & 0xff}); 01808 } 01809 break; 01810 01811 default:; 01812 } 01813 } 01814 01815 static void _process_psr_event(void *handle, BD_PSR_EVENT *ev) 01816 { 01817 BLURAY *bd = (BLURAY*)handle; 01818 01819 switch(ev->ev_type) { 01820 case BD_PSR_WRITE: 01821 _process_psr_write_event(bd, ev); 01822 break; 01823 case BD_PSR_CHANGE: 01824 _process_psr_change_event(bd, ev); 01825 break; 01826 case BD_PSR_RESTORE: 01827 _process_psr_restore_event(bd, ev); 01828 break; 01829 01830 case BD_PSR_SAVE: 01831 BD_DEBUG(DBG_BLURAY, "PSR save event (%p)\n", bd); 01832 break; 01833 default: 01834 BD_DEBUG(DBG_BLURAY, "PSR event %d: psr%u = %u (%p)\n", ev->ev_type, ev->psr_idx, ev->new_val, bd); 01835 break; 01836 } 01837 } 01838 01839 static void _queue_initial_psr_events(BLURAY *bd) 01840 { 01841 const uint32_t psrs[] = { 01842 PSR_ANGLE_NUMBER, 01843 PSR_TITLE_NUMBER, 01844 PSR_CHAPTER, 01845 PSR_PLAYLIST, 01846 PSR_PLAYITEM, 01847 PSR_IG_STREAM_ID, 01848 PSR_PRIMARY_AUDIO_ID, 01849 PSR_PG_STREAM, 01850 PSR_SECONDARY_AUDIO_VIDEO, 01851 }; 01852 unsigned ii; 01853 01854 for (ii = 0; ii < sizeof(psrs) / sizeof(psrs[0]); ii++) { 01855 BD_PSR_EVENT ev = { 01856 .ev_type = BD_PSR_CHANGE, 01857 .psr_idx = psrs[ii], 01858 .old_val = 0, 01859 .new_val = bd_psr_read(bd->regs, psrs[ii]), 01860 }; 01861 01862 _process_psr_change_event(bd, &ev); 01863 } 01864 } 01865 01866 static int _play_bdj(BLURAY *bd, const char *name) 01867 { 01868 bd->title_type = title_bdj; 01869 01870 #ifdef USING_BDJAVA 01871 bd_stop_bdj(bd); 01872 return bd_start_bdj(bd, name); 01873 #else 01874 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "_bdj_play(BDMV/BDJ/%s.jar) not implemented (%p)\n", name, bd); 01875 return 0; 01876 #endif 01877 } 01878 01879 static int _play_hdmv(BLURAY *bd, unsigned id_ref) 01880 { 01881 int result = 1; 01882 01883 bd->title_type = title_hdmv; 01884 01885 #ifdef USING_BDJAVA 01886 bd_stop_bdj(bd); 01887 #endif 01888 01889 if (!bd->hdmv_vm) { 01890 bd->hdmv_vm = hdmv_vm_init(bd->device_path, bd->regs, bd->index); 01891 } 01892 01893 if (hdmv_vm_select_object(bd->hdmv_vm, id_ref)) { 01894 result = 0; 01895 } 01896 01897 bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm); 01898 01899 return result; 01900 } 01901 01902 static int _play_title(BLURAY *bd, unsigned title) 01903 { 01904 /* first play object ? */ 01905 if (title == BLURAY_TITLE_FIRST_PLAY) { 01906 INDX_PLAY_ITEM *p = &bd->index->first_play; 01907 01908 bd_psr_write(bd->regs, PSR_TITLE_NUMBER, 0xffff); /* 5.2.3.3 */ 01909 01910 if (p->object_type == indx_object_type_hdmv) { 01911 if (p->hdmv.id_ref == 0xffff) { 01912 /* no first play title (5.2.3.3) */ 01913 bd->title_type = title_hdmv; 01914 return 1; 01915 } 01916 return _play_hdmv(bd, p->hdmv.id_ref); 01917 } 01918 01919 if (p->object_type == indx_object_type_bdj) { 01920 return _play_bdj(bd, p->bdj.name); 01921 } 01922 01923 return 0; 01924 } 01925 01926 /* bd_play not called ? */ 01927 if (bd->title_type == title_undef) { 01928 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_call_title(): bd_play() not called !\n"); 01929 return 0; 01930 } 01931 01932 /* top menu ? */ 01933 if (title == BLURAY_TITLE_TOP_MENU) { 01934 INDX_PLAY_ITEM *p = &bd->index->top_menu; 01935 01936 bd_psr_write(bd->regs, PSR_TITLE_NUMBER, 0); /* 5.2.3.3 */ 01937 01938 if (p->object_type == indx_object_type_hdmv) { 01939 if (p->hdmv.id_ref == 0xffff) { 01940 /* no top menu (5.2.3.3) */ 01941 bd->title_type = title_hdmv; 01942 return 0; 01943 } 01944 return _play_hdmv(bd, p->hdmv.id_ref); 01945 } 01946 01947 if (p->object_type == indx_object_type_bdj) { 01948 return _play_bdj(bd, p->bdj.name); 01949 } 01950 01951 return 0; 01952 } 01953 01954 /* valid title from disc index ? */ 01955 if (title > 0 && title <= bd->index->num_titles) { 01956 INDX_TITLE *t = &bd->index->titles[title-1]; 01957 01958 bd_psr_write(bd->regs, PSR_TITLE_NUMBER, title); /* 5.2.3.3 */ 01959 01960 if (t->object_type == indx_object_type_hdmv) { 01961 return _play_hdmv(bd, t->hdmv.id_ref); 01962 } else { 01963 return _play_bdj(bd, t->bdj.name); 01964 } 01965 } 01966 01967 return 0; 01968 } 01969 01970 int bd_play(BLURAY *bd) 01971 { 01972 /* reset player state */ 01973 01974 bd->title_type = title_undef; 01975 01976 if (bd->hdmv_vm) { 01977 hdmv_vm_free(&bd->hdmv_vm); 01978 } 01979 01980 _init_event_queue(bd); 01981 01982 bd_psr_lock(bd->regs); 01983 bd_psr_register_cb(bd->regs, _process_psr_event, bd); 01984 _queue_initial_psr_events(bd); 01985 bd_psr_unlock(bd->regs); 01986 01987 return _play_title(bd, BLURAY_TITLE_FIRST_PLAY); 01988 } 01989 01990 int bd_play_title(BLURAY *bd, unsigned title) 01991 { 01992 if (bd->title_type == title_undef && title != BLURAY_TITLE_FIRST_PLAY) { 01993 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_play_title(): bd_play() not called\n"); 01994 return 0; 01995 } 01996 01997 if (bd->st0.uo_mask.title_search) { 01998 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "title search masked by stream\n"); 01999 return 0; 02000 } 02001 02002 if (bd->title_type == title_hdmv) { 02003 if (hdmv_vm_get_uo_mask(bd->hdmv_vm) & HDMV_TITLE_SEARCH_MASK) { 02004 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "title search masked by movie object\n"); 02005 return 0; 02006 } 02007 } 02008 02009 return _play_title(bd, title); 02010 } 02011 02012 int bd_menu_call(BLURAY *bd, int64_t pts) 02013 { 02014 if (pts >= 0) { 02015 bd_psr_write(bd->regs, PSR_TIME, (uint32_t)(((uint64_t)pts) >> 1)); 02016 } 02017 02018 if (bd->title_type == title_undef) { 02019 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_menu_call(): bd_play() not called\n"); 02020 return 0; 02021 } 02022 02023 if (bd->st0.uo_mask.menu_call) { 02024 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "menu call masked by stream\n"); 02025 return 0; 02026 } 02027 02028 if (bd->title_type == title_hdmv) { 02029 if (hdmv_vm_get_uo_mask(bd->hdmv_vm) & HDMV_MENU_CALL_MASK) { 02030 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "menu call masked by movie object\n"); 02031 return 0; 02032 } 02033 02034 if (hdmv_vm_suspend_pl(bd->hdmv_vm) < 0) { 02035 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_menu_call(): error storing playback location\n"); 02036 } 02037 } 02038 02039 return _play_title(bd, BLURAY_TITLE_TOP_MENU); 02040 } 02041 02042 static int _run_gc(BLURAY *bd, gc_ctrl_e msg, uint32_t param) 02043 { 02044 int result = -1; 02045 02046 if (bd && bd->graphics_controller && bd->hdmv_vm) { 02047 GC_NAV_CMDS cmds = {-1, NULL, -1}; 02048 02049 result = gc_run(bd->graphics_controller, msg, param, &cmds); 02050 02051 if (cmds.num_nav_cmds > 0) { 02052 hdmv_vm_set_object(bd->hdmv_vm, cmds.num_nav_cmds, cmds.nav_cmds); 02053 bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm); 02054 } 02055 } 02056 02057 return result; 02058 } 02059 02060 static void _process_hdmv_vm_event(BLURAY *bd, HDMV_EVENT *hev) 02061 { 02062 BD_DEBUG(DBG_BLURAY, "HDMV event: %d %d\n", hev->event, hev->param); 02063 02064 switch (hev->event) { 02065 case HDMV_EVENT_TITLE: 02066 _close_playlist(bd); 02067 _play_title(bd, hev->param); 02068 break; 02069 02070 case HDMV_EVENT_PLAY_PL: 02071 bd_select_playlist(bd, hev->param); 02072 /* initialize menus */ 02073 _run_gc(bd, GC_CTRL_NOP, 0); 02074 break; 02075 02076 case HDMV_EVENT_PLAY_PI: 02077 _queue_event(bd, (BD_EVENT){BD_EVENT_SEEK, 0}); 02078 bd_seek_playitem(bd, hev->param); 02079 break; 02080 02081 case HDMV_EVENT_PLAY_PM: 02082 _queue_event(bd, (BD_EVENT){BD_EVENT_SEEK, 0}); 02083 bd_seek_mark(bd, hev->param); 02084 break; 02085 02086 case HDMV_EVENT_PLAY_STOP: 02087 // stop current playlist 02088 _close_playlist(bd); 02089 break; 02090 02091 case HDMV_EVENT_STILL: 02092 _queue_event(bd, (BD_EVENT){BD_EVENT_STILL, hev->param}); 02093 break; 02094 02095 case HDMV_EVENT_ENABLE_BUTTON: 02096 _run_gc(bd, GC_CTRL_ENABLE_BUTTON, hev->param); 02097 break; 02098 02099 case HDMV_EVENT_DISABLE_BUTTON: 02100 _run_gc(bd, GC_CTRL_DISABLE_BUTTON, hev->param); 02101 break; 02102 02103 case HDMV_EVENT_SET_BUTTON_PAGE: 02104 _run_gc(bd, GC_CTRL_SET_BUTTON_PAGE, hev->param); 02105 break; 02106 02107 case HDMV_EVENT_POPUP_OFF: 02108 _run_gc(bd, GC_CTRL_POPUP, 0); 02109 break; 02110 02111 case HDMV_EVENT_IG_END: 02112 _run_gc(bd, GC_CTRL_IG_END, 0); 02113 break; 02114 02115 case HDMV_EVENT_END: 02116 case HDMV_EVENT_NONE: 02117 default: 02118 break; 02119 } 02120 } 02121 02122 static int _run_hdmv(BLURAY *bd) 02123 { 02124 HDMV_EVENT hdmv_ev; 02125 02126 /* run VM */ 02127 if (hdmv_vm_run(bd->hdmv_vm, &hdmv_ev) < 0) { 02128 _queue_event(bd, (BD_EVENT){BD_EVENT_ERROR, 0}); 02129 bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm); 02130 return -1; 02131 } 02132 02133 /* process all events */ 02134 do { 02135 _process_hdmv_vm_event(bd, &hdmv_ev); 02136 02137 } while (!hdmv_vm_get_event(bd->hdmv_vm, &hdmv_ev)); 02138 02139 /* update VM state */ 02140 bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm); 02141 02142 return 0; 02143 } 02144 02145 int bd_read_ext(BLURAY *bd, unsigned char *buf, int len, BD_EVENT *event) 02146 { 02147 if (_get_event(bd, event)) { 02148 return 0; 02149 } 02150 02151 /* run HDMV VM ? */ 02152 if (!bd->hdmv_suspended && bd->title_type == title_hdmv) { 02153 02154 while (!bd->hdmv_suspended) { 02155 02156 if (_run_hdmv(bd) < 0) { 02157 BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_read_ext(): HDMV VM error\n"); 02158 bd->title_type = title_undef; 02159 return -1; 02160 } 02161 if (_get_event(bd, event)) { 02162 return 0; 02163 } 02164 } 02165 } 02166 02167 if (len < 1) { 02168 /* just polled events ? */ 02169 return 0; 02170 } 02171 02172 int bytes = bd_read(bd, buf, len); 02173 02174 if (bytes == 0) { 02175 02176 // if no next clip (=end of title), resume HDMV VM 02177 if (!bd->st0.clip && bd->title_type == title_hdmv) { 02178 hdmv_vm_resume(bd->hdmv_vm); 02179 bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm); 02180 BD_DEBUG(DBG_BLURAY, "bd_read_ext(): reached end of playlist. hdmv_suspended=%d\n", bd->hdmv_suspended); 02181 } 02182 } 02183 02184 _get_event(bd, event); 02185 02186 return bytes; 02187 } 02188 02189 int bd_get_event(BLURAY *bd, BD_EVENT *event) 02190 { 02191 if (!bd->event_queue) { 02192 _init_event_queue(bd); 02193 02194 bd_psr_register_cb(bd->regs, _process_psr_event, bd); 02195 _queue_initial_psr_events(bd); 02196 } 02197 02198 if (event) { 02199 return _get_event(bd, event); 02200 } 02201 02202 return 0; 02203 } 02204 02205 /* 02206 * user interaction 02207 */ 02208 02209 void bd_set_scr(BLURAY *bd, int64_t pts) 02210 { 02211 if (pts >= 0) { 02212 bd_psr_write(bd->regs, PSR_TIME, (uint32_t)(((uint64_t)pts) >> 1)); 02213 } 02214 } 02215 02216 int bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x, uint16_t y) 02217 { 02218 bd_set_scr(bd, pts); 02219 02220 return _run_gc(bd, GC_CTRL_MOUSE_MOVE, (x << 16) | y); 02221 } 02222 02223 int bd_user_input(BLURAY *bd, int64_t pts, uint32_t key) 02224 { 02225 bd_set_scr(bd, pts); 02226 02227 return _run_gc(bd, GC_CTRL_VK_KEY, key); 02228 } 02229 02230 void bd_register_overlay_proc(BLURAY *bd, void *handle, bd_overlay_proc_f func) 02231 { 02232 if (!bd) { 02233 return; 02234 } 02235 02236 gc_free(&bd->graphics_controller); 02237 02238 if (func) { 02239 bd->graphics_controller = gc_init(bd->regs, handle, func); 02240 } 02241 } 02242 02243 /* 02244 * 02245 */ 02246 02247 struct meta_dl *bd_get_meta(BLURAY *bd) 02248 { 02249 if (!bd) { 02250 return NULL; 02251 } 02252 02253 if (!bd->meta) { 02254 _meta_open(bd); 02255 } 02256 02257 uint32_t psr_menu_lang = bd_psr_read(bd->regs, PSR_MENU_LANG); 02258 02259 if (psr_menu_lang != 0 && psr_menu_lang != 0xffffff) { 02260 const char language_code[] = {(psr_menu_lang >> 16) & 0xff, (psr_menu_lang >> 8) & 0xff, psr_menu_lang & 0xff, 0 }; 02261 return meta_get(bd->meta, language_code); 02262 } 02263 else { 02264 return meta_get(bd->meta, NULL); 02265 } 02266 } 02267 02268 struct clpi_cl *bd_get_clpi(BLURAY *bd, unsigned clip_ref) 02269 { 02270 NAV_CLIP *clip; 02271 02272 if (bd->title && clip_ref < bd->title->clip_list.count) { 02273 clip = &bd->title->clip_list.clip[clip_ref]; 02274 CLPI_CL *cl = (CLPI_CL*) calloc(1, sizeof(CLPI_CL)); 02275 return clpi_copy(cl, clip->cl); 02276 } 02277 return NULL; 02278 } 02279 02280 void bd_free_clpi(struct clpi_cl *cl) 02281 { 02282 clpi_free(cl); 02283 }
1.7.6.1