1 /*****************************************************************************
2 * bluray.c: Blu-ray disc support plugin
3 *****************************************************************************
4 * Copyright © 2010-2012 VideoLAN, VLC authors and libbluray AUTHORS
6 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
7 * Hugo Beauzée-Luyssen <hugo@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
29 #include <stdatomic.h>
31 #if defined (HAVE_MNTENT_H) && defined(HAVE_SYS_STAT_H)
34 #include <fcntl.h> /* O_* */
35 #include <unistd.h> /* close() */
39 # include <sys/param.h>
40 # include <sys/ucred.h>
41 # include <sys/mount.h>
44 #include <vlc_common.h>
45 #include <vlc_mouse.h>
46 #include <vlc_plugin.h>
47 #include <vlc_demux.h> /* demux_t */
48 #include <vlc_input.h> /* Seekpoints, chapters */
49 #include <vlc_dialog.h> /* BD+/AACS warnings */
50 #include <vlc_url.h> /* vlc_path2uri */
51 #include <vlc_iso_lang.h>
54 #include "../demux/mpeg/timestamps.h"
55 #include "../demux/timestamps_filter.h"
57 /* FIXME we should find a better way than including that */
58 #include "../../src/text/iso-639_def.h"
61 #include <libbluray/bluray.h>
62 #include <libbluray/bluray-version.h>
63 #include <libbluray/keys.h>
64 #include <libbluray/meta_data.h>
65 #include <libbluray/overlay.h>
67 //#define DEBUG_BLURAY
69 # include <libbluray/log_control.h>
70 # define BLURAY_DEBUG_MASK (0xFFFFF & ~DBG_STREAM)
71 static vlc_object_t
*p_bluray_DebugObject
;
72 static void bluray_DebugHandler(const char *psz
)
74 size_t len
= strlen(psz
);
77 if(psz
[len
- 1] == '\n')
78 psz_log
= strndup(psz
, len
- 1);
79 msg_Dbg(p_bluray_DebugObject
, "%s", psz_log
? psz_log
: psz
);
84 /*****************************************************************************
86 *****************************************************************************/
88 #define BD_MENU_TEXT N_("Blu-ray menus")
89 #define BD_MENU_LONGTEXT N_("Use Blu-ray menus. If disabled, "\
90 "the movie will start directly")
91 #define BD_REGION_TEXT N_("Region code")
92 #define BD_REGION_LONGTEXT N_("Blu-Ray player region code. "\
93 "Some discs can be played only with a correct region code.")
95 static const char *const ppsz_region_code
[] = {
97 static const char *const ppsz_region_code_text
[] = {
98 "Region A", "Region B", "Region C" };
100 #define REGION_DEFAULT 1 /* Index to region list. Actual region code is (1<<REGION_DEFAULT) */
101 #define LANGUAGE_DEFAULT ("eng")
103 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,0)
104 # define BLURAY_DEMUX
107 #ifndef BD_STREAM_TYPE_VIDEO_HEVC
108 # define BD_STREAM_TYPE_VIDEO_HEVC 0x24
112 static int blurayOpen (vlc_object_t
*);
113 static void blurayClose(vlc_object_t
*);
116 set_shortname(N_("Blu-ray"))
117 set_description(N_("Blu-ray Disc support (libbluray)"))
119 set_category(CAT_INPUT
)
120 set_subcategory(SUBCAT_INPUT_ACCESS
)
121 set_capability("access", 500)
122 add_bool("bluray-menu", true, BD_MENU_TEXT
, BD_MENU_LONGTEXT
, false)
123 add_string("bluray-region", ppsz_region_code
[REGION_DEFAULT
], BD_REGION_TEXT
, BD_REGION_LONGTEXT
, false)
124 change_string_list(ppsz_region_code
, ppsz_region_code_text
)
126 add_shortcut("bluray", "file")
128 set_callbacks(blurayOpen
, blurayClose
)
133 set_description( "BluRay demuxer" )
134 set_category( CAT_INPUT
)
135 set_subcategory( SUBCAT_INPUT_DEMUX
)
136 set_capability( "demux", 5 )
137 set_callbacks( blurayOpen
, blurayClose
)
142 /* libbluray's overlay.h defines 2 types of overlay (bd_overlay_plane_e). */
143 #define MAX_OVERLAY 2
145 typedef enum OverlayStatus
{
147 ToDisplay
, //Used to mark the overlay to be displayed the first time.
149 Outdated
//used to update the overlay after it has been sent to the vout
152 typedef struct bluray_spu_updater_sys_t bluray_spu_updater_sys_t
;
154 typedef struct bluray_overlay_t
158 OverlayStatus status
;
159 subpicture_region_t
*p_regions
;
162 /* pointer to last subpicture updater.
163 * used to disconnect this overlay from vout when:
164 * - the overlay is closed
165 * - vout is changed and this overlay is sent to the new vout
167 bluray_spu_updater_sys_t
*p_updater
;
175 unsigned int i_title
;
176 unsigned int i_longest_title
;
177 input_title_t
**pp_title
;
179 unsigned cur_seekpoint
;
182 vlc_mutex_t pl_info_lock
;
183 BLURAY_TITLE_INFO
*p_pl_info
;
184 const BLURAY_CLIP_INFO
*p_clip_info
;
188 input_attachment_t
**attachments
;
191 /* Meta information */
192 const META_DL
*p_meta
;
195 bluray_overlay_t
*p_overlays
[MAX_OVERLAY
];
199 bool b_popup_available
;
200 vlc_tick_t i_still_end_time
;
202 vlc_mutex_t bdj_overlay_lock
; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
205 vlc_mouse_t oldmouse
;
207 es_out_id_t
*p_dummy_video
;
208 es_out_id_t
*p_video_es
;
213 bool b_spu_enable
; /* enabled / disabled */
214 vlc_demux_chained_t
*p_parser
;
216 bool b_pl_playing
; /* true when playing playlist */
219 vlc_mutex_t read_block_lock
;
221 /* Used to store bluray disc path */
226 * Local ES index storage
232 int i_next_block_flags
;
236 static bool es_pair_Add(vlc_array_t
*p_array
, const es_format_t
*p_fmt
,
239 es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
240 if (likely(p_pair
!= NULL
))
243 p_pair
->i_next_block_flags
= 0;
244 p_pair
->b_recyling
= false;
245 if(vlc_array_append(p_array
, p_pair
) != VLC_SUCCESS
)
252 es_format_Init(&p_pair
->fmt
, p_fmt
->i_cat
, p_fmt
->i_codec
);
253 es_format_Copy(&p_pair
->fmt
, p_fmt
);
256 return p_pair
!= NULL
;
259 static void es_pair_Remove(vlc_array_t
*p_array
, es_pair_t
*p_pair
)
261 vlc_array_remove(p_array
, vlc_array_index_of_item(p_array
, p_pair
));
262 es_format_Clean(&p_pair
->fmt
);
266 static es_pair_t
*getEsPair(vlc_array_t
*p_array
,
267 bool (*match
)(const es_pair_t
*, const void *),
270 for (size_t i
= 0; i
< vlc_array_count(p_array
); ++i
)
272 es_pair_t
*p_pair
= vlc_array_item_at_index(p_array
, i
);
273 if(match(p_pair
, param
))
279 static bool es_pair_compare_PID(const es_pair_t
*p_pair
, const void *p_pid
)
281 return p_pair
->fmt
.i_id
== *((const int *)p_pid
);
284 static bool es_pair_compare_ES(const es_pair_t
*p_pair
, const void *p_es
)
286 return p_pair
->p_es
== (const es_out_id_t
*)p_es
;
289 static bool es_pair_compare_Unused(const es_pair_t
*p_pair
, const void *priv
)
292 return p_pair
->b_recyling
;
295 static es_pair_t
*getEsPairByPID(vlc_array_t
*p_array
, int i_pid
)
297 return getEsPair(p_array
, es_pair_compare_PID
, &i_pid
);
300 static es_pair_t
*getEsPairByES(vlc_array_t
*p_array
, const es_out_id_t
*p_es
)
302 return getEsPair(p_array
, es_pair_compare_ES
, p_es
);
305 static es_pair_t
*getUnusedEsPair(vlc_array_t
*p_array
)
307 return getEsPair(p_array
, es_pair_compare_Unused
, 0);
313 struct bluray_spu_updater_sys_t
315 vlc_mutex_t lock
; // protect p_overlay pointer and ref_cnt
316 bluray_overlay_t
*p_overlay
; // NULL if overlay has been closed
317 int ref_cnt
; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
321 * cut the connection between vout and overlay.
322 * - called when vout is closed or overlay is closed.
323 * - frees bluray_spu_updater_sys_t when both sides have been closed.
325 static void unref_subpicture_updater(bluray_spu_updater_sys_t
*p_sys
)
327 vlc_mutex_lock(&p_sys
->lock
);
328 int refs
= --p_sys
->ref_cnt
;
329 p_sys
->p_overlay
= NULL
;
330 vlc_mutex_unlock(&p_sys
->lock
);
333 vlc_mutex_destroy(&p_sys
->lock
);
339 * FIXME: partiallyy duplicated from src/input/es_out.c
341 static const char *DemuxGetLanguageCode( demux_t
*p_demux
, const char *psz_var
)
343 const iso639_lang_t
*pl
;
347 psz_lang
= var_CreateGetString( p_demux
, psz_var
);
349 return LANGUAGE_DEFAULT
;
351 /* XXX: we will use only the first value
352 * (and ignore other ones in case of a list) */
353 if( ( p
= strchr( psz_lang
, ',' ) ) )
356 for( pl
= p_languages
; pl
->psz_eng_name
!= NULL
; pl
++ )
358 if( *psz_lang
== '\0' )
360 if( !strcasecmp( pl
->psz_eng_name
, psz_lang
) ||
361 !strcasecmp( pl
->psz_iso639_1
, psz_lang
) ||
362 !strcasecmp( pl
->psz_iso639_2T
, psz_lang
) ||
363 !strcasecmp( pl
->psz_iso639_2B
, psz_lang
) )
369 if( pl
->psz_eng_name
!= NULL
)
370 return pl
->psz_iso639_2T
;
372 return LANGUAGE_DEFAULT
;
375 /*****************************************************************************
377 *****************************************************************************/
378 static es_out_t
*esOutNew(vlc_object_t
*, es_out_t
*, void *);
380 static int blurayControl(demux_t
*, int, va_list);
381 static int blurayDemux(demux_t
*);
383 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
);
384 static int bluraySetTitle(demux_t
*p_demux
, int i_title
);
386 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
* const overlay
);
387 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
* const overlay
);
389 static void onMouseEvent(const vlc_mouse_t
*mouse
, void *user_data
);
390 static void blurayRestartParser(demux_t
*p_demux
, bool);
391 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
);
393 #define STILL_IMAGE_NOT_SET 0
394 #define STILL_IMAGE_INFINITE -1
396 #define CURRENT_TITLE p_sys->pp_title[p_sys->cur_title]
397 #define CUR_LENGTH CURRENT_TITLE->i_length
400 static void FindMountPoint(char **file
)
402 char *device
= *file
;
403 #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H)
404 /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
405 * we look up the real device */
406 char *bd_device
= realpath(device
, NULL
);
407 if (bd_device
== NULL
)
411 if (lstat (bd_device
, &st
) == 0 && S_ISBLK (st
.st_mode
)) {
412 FILE *mtab
= setmntent ("/proc/self/mounts", "r");
414 struct mntent
*m
, mbuf
;
417 while ((m
= getmntent_r (mtab
, &mbuf
, buf
, sizeof(buf
))) != NULL
) {
418 if (!strcmp (m
->mnt_fsname
, bd_device
)) {
420 *file
= strdup(m
->mnt_dir
);
429 #elif defined(__APPLE__)
431 if (!stat (device
, &st
) && S_ISBLK (st
.st_mode
)) {
432 int fs_count
= getfsstat (NULL
, 0, MNT_NOWAIT
);
434 struct statfs mbuf
[128];
435 getfsstat (mbuf
, fs_count
* sizeof(mbuf
[0]), MNT_NOWAIT
);
436 for (int i
= 0; i
< fs_count
; ++i
)
437 if (!strcmp (mbuf
[i
].f_mntfromname
, device
)) {
439 *file
= strdup(mbuf
[i
].f_mntonname
);
445 # warning Disc device to mount point not implemented
446 VLC_UNUSED( device
);
450 static void blurayReleaseVideoES(demux_t
*p_demux
)
452 demux_sys_t
*p_sys
= p_demux
->p_sys
;
454 if (p_sys
->p_video_es
!= NULL
) {
455 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
456 bluray_overlay_t
*p_ov
= p_sys
->p_overlays
[i
];
458 vlc_mutex_lock(&p_ov
->lock
);
459 if (p_ov
->i_channel
!= -1) {
460 msg_Err(p_demux
, "blurayReleaseVout: subpicture channel exists\n");
461 es_out_Control( p_demux
->out
, ES_OUT_VOUT_FLUSH_OVERLAY
,
462 p_sys
->p_video_es
, p_ov
->i_channel
);
464 p_ov
->i_channel
= -1;
465 p_ov
->status
= Closed
;
466 vlc_mutex_unlock(&p_ov
->lock
);
468 if (p_ov
->p_updater
) {
469 unref_subpicture_updater(p_ov
->p_updater
);
470 p_ov
->p_updater
= NULL
;
474 p_sys
->p_video_es
= NULL
;
478 /*****************************************************************************
479 * BD-J background video
480 *****************************************************************************/
482 static es_out_id_t
* blurayCreateBackgroundUnlocked(demux_t
*p_demux
)
484 demux_sys_t
*p_sys
= p_demux
->p_sys
;
486 if (p_sys
->p_dummy_video
)
487 return p_sys
->p_dummy_video
;
489 msg_Info(p_demux
, "Start background");
493 es_format_Init( &fmt
, VIDEO_ES
, VLC_CODEC_I420
);
494 video_format_Setup( &fmt
.video
, VLC_CODEC_I420
,
495 1920, 1080, 1920, 1080, 1, 1);
496 fmt
.i_priority
= ES_PRIORITY_SELECTABLE_MIN
;
497 fmt
.i_id
= 4115; /* 4113 = main video. 4114 = MVC. 4115 = unused. */
499 fmt
.psz_description
= strdup("Background video");
501 p_sys
->p_dummy_video
= es_out_Add(p_demux
->out
, &fmt
);
503 if (!p_sys
->p_dummy_video
) {
504 msg_Err(p_demux
, "Error adding background ES");
508 block_t
*p_block
= block_Alloc(fmt
.video
.i_width
* fmt
.video
.i_height
*
509 fmt
.video
.i_bits_per_pixel
/ 8);
511 msg_Err(p_demux
, "Error allocating block for background video");
515 // XXX TODO: what would be correct timestamp ???
516 p_block
->i_dts
= p_block
->i_pts
= vlc_tick_now() + VLC_TICK_FROM_MS(40);
518 uint8_t *p
= p_block
->p_buffer
;
519 memset(p
, 0, fmt
.video
.i_width
* fmt
.video
.i_height
);
520 p
+= fmt
.video
.i_width
* fmt
.video
.i_height
;
521 memset(p
, 0x80, fmt
.video
.i_width
* fmt
.video
.i_height
/ 2);
523 es_out_Send(p_demux
->out
, p_sys
->p_dummy_video
, p_block
);
525 es_out_Control( p_demux
->out
, ES_OUT_VOUT_SET_MOUSE_EVENT
,
526 p_sys
->p_dummy_video
, onMouseEvent
, p_demux
);
529 es_format_Clean(&fmt
);
530 return p_sys
->p_dummy_video
;
533 static void stopBackground(demux_t
*p_demux
)
535 demux_sys_t
*p_sys
= p_demux
->p_sys
;
537 if (!p_sys
->p_dummy_video
) {
541 msg_Info(p_demux
, "Stop background");
543 es_out_Del(p_demux
->out
, p_sys
->p_dummy_video
);
545 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
546 if (p_sys
->p_video_es
== p_sys
->p_dummy_video
)
547 blurayReleaseVideoES(p_demux
);
548 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
550 p_sys
->p_dummy_video
= NULL
;
553 /*****************************************************************************
554 * cache current playlist (title) information
555 *****************************************************************************/
557 static void setTitleInfo(demux_sys_t
*p_sys
, BLURAY_TITLE_INFO
*info
)
559 vlc_mutex_lock(&p_sys
->pl_info_lock
);
561 if (p_sys
->p_pl_info
) {
562 bd_free_title_info(p_sys
->p_pl_info
);
564 p_sys
->p_pl_info
= info
;
565 p_sys
->p_clip_info
= NULL
;
567 if (p_sys
->p_pl_info
&& p_sys
->p_pl_info
->clip_count
) {
568 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[0];
571 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
574 /*****************************************************************************
575 * create input attachment for thumbnail
576 *****************************************************************************/
578 static void attachThumbnail(demux_t
*p_demux
)
580 demux_sys_t
*p_sys
= p_demux
->p_sys
;
585 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,9,0)
586 if (p_sys
->p_meta
->thumb_count
> 0 && p_sys
->p_meta
->thumbnails
) {
589 if (bd_get_meta_file(p_sys
->bluray
, p_sys
->p_meta
->thumbnails
[0].path
, &data
, &size
) > 0) {
591 input_attachment_t
*p_attachment
;
593 snprintf(psz_name
, sizeof(psz_name
), "picture%d_%s", p_sys
->i_attachments
, p_sys
->p_meta
->thumbnails
[0].path
);
595 p_attachment
= vlc_input_attachment_New(psz_name
, NULL
, "Album art", data
, size
);
597 p_sys
->i_cover_idx
= p_sys
->i_attachments
;
598 TAB_APPEND(p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
606 /*****************************************************************************
608 *****************************************************************************/
610 static int probeStream(demux_t
*p_demux
)
612 /* input must be seekable */
613 bool b_canseek
= false;
614 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_canseek
);
619 /* first sector(s) should be filled with zeros */
621 const uint8_t *p_peek
;
622 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 2048 );
623 if( i_peek
!= 2048 ) {
627 if (p_peek
[ --i_peek
]) {
636 static int blurayReadBlock(void *object
, void *buf
, int lba
, int num_blocks
)
638 demux_t
*p_demux
= (demux_t
*)object
;
639 demux_sys_t
*p_sys
= p_demux
->p_sys
;
642 assert(p_demux
->s
!= NULL
);
644 vlc_mutex_lock(&p_sys
->read_block_lock
);
646 if (vlc_stream_Seek( p_demux
->s
, lba
* INT64_C(2048) ) == VLC_SUCCESS
) {
647 size_t req
= (size_t)2048 * num_blocks
;
650 got
= vlc_stream_Read( p_demux
->s
, buf
, req
);
652 msg_Err(p_demux
, "read from lba %d failed", lba
);
657 msg_Err(p_demux
, "seek to lba %d failed", lba
);
660 vlc_mutex_unlock(&p_sys
->read_block_lock
);
666 /*****************************************************************************
667 * probing of local files
668 *****************************************************************************/
670 /* Descriptor Tag (ECMA 167, 3/7.2) */
671 static int decode_descriptor_tag(const uint8_t *buf
)
674 uint8_t checksum
= 0;
677 id
= buf
[0] | (buf
[1] << 8);
679 /* calculate tag checksum */
680 for (i
= 0; i
< 4; i
++) {
681 checksum
= (uint8_t)(checksum
+ buf
[i
]);
683 for (i
= 5; i
< 16; i
++) {
684 checksum
= (uint8_t)(checksum
+ buf
[i
]);
687 if (checksum
!= buf
[4]) {
694 static int probeFile(const char *psz_name
)
696 struct stat stat_info
;
699 int ret
= VLC_EGENERIC
;
702 fd
= vlc_open(psz_name
, O_RDONLY
| O_NONBLOCK
);
707 if (fstat(fd
, &stat_info
) == -1) {
710 if (!S_ISREG(stat_info
.st_mode
) && !S_ISBLK(stat_info
.st_mode
)) {
714 /* first sector should be filled with zeros */
715 if (read(fd
, peek
, sizeof(peek
)) != sizeof(peek
)) {
718 for (i
= 0; i
< sizeof(peek
); i
++) {
724 /* Check AVDP tag checksum */
725 if (lseek(fd
, 256 * 2048, SEEK_SET
) == -1 ||
726 read(fd
, peek
, 16) != 16 ||
727 decode_descriptor_tag(peek
) != 2) {
738 /*****************************************************************************
739 * blurayOpen: module init function
740 *****************************************************************************/
741 static int blurayOpen(vlc_object_t
*object
)
743 demux_t
*p_demux
= (demux_t
*)object
;
746 uint64_t i_init_pos
= 0;
748 const char *error_msg
= NULL
;
749 #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
751 if (p_demux
->out
== NULL
)
754 forced
= !strncasecmp(p_demux
->psz_url
, "bluray:", 7);
757 if (!strncasecmp(p_demux
->psz_url
, "file:", 5)) {
758 /* use access_demux for local files */
762 if (probeStream(p_demux
) != VLC_SUCCESS
) {
766 } else if (!forced
) {
767 if (!p_demux
->psz_filepath
) {
771 if (probeFile(p_demux
->psz_filepath
) != VLC_SUCCESS
) {
777 p_demux
->p_sys
= p_sys
= vlc_obj_calloc(object
, 1, sizeof(*p_sys
));
778 if (unlikely(!p_sys
))
781 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
783 /* init demux info fields */
786 TAB_INIT(p_sys
->i_title
, p_sys
->pp_title
);
787 TAB_INIT(p_sys
->i_attachments
, p_sys
->attachments
);
789 vlc_mouse_Init(&p_sys
->oldmouse
);
791 vlc_mutex_init(&p_sys
->pl_info_lock
);
792 vlc_mutex_init(&p_sys
->bdj_overlay_lock
);
793 vlc_mutex_init(&p_sys
->read_block_lock
); /* used during bd_open_stream() */
795 /* request sub demuxers to skip continuity check as some split
796 file concatenation are just resetting counters... */
797 var_Create( p_demux
, "ts-cc-check", VLC_VAR_BOOL
);
798 var_SetBool( p_demux
, "ts-cc-check", false );
801 p_bluray_DebugObject
= VLC_OBJECT(p_demux
);
802 bd_set_debug_mask(BLURAY_DEBUG_MASK
);
803 bd_set_debug_handler(bluray_DebugHandler
);
809 i_init_pos
= vlc_stream_Tell(p_demux
->s
);
811 p_sys
->bluray
= bd_init();
812 if (!bd_open_stream(p_sys
->bluray
, p_demux
, blurayReadBlock
)) {
813 bd_close(p_sys
->bluray
);
814 p_sys
->bluray
= NULL
;
819 if (!p_demux
->psz_filepath
) {
820 /* no path provided (bluray://). use default DVD device. */
821 p_sys
->psz_bd_path
= var_InheritString(object
, "dvd");
823 /* store current bd path */
824 p_sys
->psz_bd_path
= strdup(p_demux
->psz_filepath
);
827 /* If we're passed a block device, try to convert it to the mount point. */
828 FindMountPoint(&p_sys
->psz_bd_path
);
830 p_sys
->bluray
= bd_open(p_sys
->psz_bd_path
, NULL
);
832 if (!p_sys
->bluray
) {
836 /* Warning the user about AACS/BD+ */
837 const BLURAY_DISC_INFO
*disc_info
= bd_get_disc_info(p_sys
->bluray
);
839 /* Is it a bluray? */
840 if (!disc_info
->bluray_detected
) {
842 BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
847 msg_Info(p_demux
, "First play: %i, Top menu: %i\n"
848 "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
849 disc_info
->first_play_supported
, disc_info
->top_menu_supported
,
850 disc_info
->num_hdmv_titles
, disc_info
->num_bdj_titles
,
851 disc_info
->num_unsupported_titles
);
854 if (disc_info
->aacs_detected
) {
855 msg_Dbg(p_demux
, "Disc is using AACS");
856 if (!disc_info
->libaacs_detected
)
857 BLURAY_ERROR(_("This Blu-ray Disc needs a library for AACS decoding"
858 ", and your system does not have it."));
859 if (!disc_info
->aacs_handled
) {
860 if (disc_info
->aacs_error_code
) {
861 switch (disc_info
->aacs_error_code
) {
862 case BD_AACS_CORRUPTED_DISC
:
863 BLURAY_ERROR(_("Blu-ray Disc is corrupted."));
864 case BD_AACS_NO_CONFIG
:
865 BLURAY_ERROR(_("Missing AACS configuration file!"));
867 BLURAY_ERROR(_("No valid processing key found in AACS config file."));
868 case BD_AACS_NO_CERT
:
869 BLURAY_ERROR(_("No valid host certificate found in AACS config file."));
870 case BD_AACS_CERT_REVOKED
:
871 BLURAY_ERROR(_("AACS Host certificate revoked."));
872 case BD_AACS_MMC_FAILED
:
873 BLURAY_ERROR(_("AACS MMC failed."));
880 if (disc_info
->bdplus_detected
) {
881 msg_Dbg(p_demux
, "Disc is using BD+");
882 if (!disc_info
->libbdplus_detected
)
883 BLURAY_ERROR(_("This Blu-ray Disc needs a library for BD+ decoding"
884 ", and your system does not have it."));
885 if (!disc_info
->bdplus_handled
)
886 BLURAY_ERROR(_("Your system BD+ decoding library does not work. "
887 "Missing configuration?"));
890 /* set player region code */
891 char *psz_region
= var_InheritString(p_demux
, "bluray-region");
892 unsigned int region
= psz_region
? (psz_region
[0] - 'A') : REGION_DEFAULT
;
894 bd_set_player_setting(p_sys
->bluray
, BLURAY_PLAYER_SETTING_REGION_CODE
, 1<<region
);
896 /* set preferred languages */
897 const char *psz_code
= DemuxGetLanguageCode( p_demux
, "audio-language" );
898 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
, psz_code
);
899 psz_code
= DemuxGetLanguageCode( p_demux
, "sub-language" );
900 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
, psz_code
);
901 psz_code
= DemuxGetLanguageCode( p_demux
, "menu-language" );
902 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_MENU_LANG
, psz_code
);
904 /* Get disc metadata */
905 p_sys
->p_meta
= bd_get_meta(p_sys
->bluray
);
907 msg_Warn(p_demux
, "Failed to get meta info.");
909 p_sys
->i_cover_idx
= -1;
910 attachThumbnail(p_demux
);
912 p_sys
->b_menu
= var_InheritBool(p_demux
, "bluray-menu");
914 /* Check BD-J capability */
915 if (p_sys
->b_menu
&& disc_info
->bdj_detected
&& !disc_info
->bdj_handled
) {
916 msg_Err(p_demux
, "BD-J menus not supported. Playing without menus. "
917 "BD-J support: %d, JVM found: %d, JVM usable: %d",
918 disc_info
->bdj_supported
, disc_info
->libjvm_detected
, disc_info
->bdj_handled
);
919 vlc_dialog_display_error(p_demux
, _("Java required"),
920 _("This Blu-ray disc requires Java for menus support.%s\nThe disc will be played without menus."),
921 !disc_info
->libjvm_detected
? _("Java was not found on your system.") : "");
922 p_sys
->b_menu
= false;
925 /* Get titles and chapters */
926 blurayInitTitles(p_demux
, disc_info
->num_hdmv_titles
+ disc_info
->num_bdj_titles
+ 1/*Top Menu*/ + 1/*First Play*/);
929 * Initialize the event queue, so we can receive events in blurayDemux(Menu).
931 bd_get_event(p_sys
->bluray
, NULL
);
933 /* Registering overlay event handler */
934 bd_register_overlay_proc(p_sys
->bluray
, p_demux
, blurayOverlayProc
);
938 /* Register ARGB overlay handler for BD-J */
939 if (disc_info
->num_bdj_titles
)
940 bd_register_argb_overlay_proc(p_sys
->bluray
, p_demux
, blurayArgbOverlayProc
, NULL
);
942 /* libbluray will start playback from "First-Title" title */
943 if (bd_play(p_sys
->bluray
) == 0)
944 BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support."));
947 /* set start title number */
948 if (bluraySetTitle(p_demux
, p_sys
->i_longest_title
) != VLC_SUCCESS
) {
949 msg_Err(p_demux
, "Could not set the title %d", p_sys
->i_longest_title
);
954 p_sys
->p_tf_out
= timestamps_filter_es_out_New(p_demux
->out
);
955 if(unlikely(!p_sys
->p_tf_out
))
958 p_sys
->p_out
= esOutNew(VLC_OBJECT(p_demux
), p_sys
->p_tf_out
, p_demux
);
959 if (unlikely(p_sys
->p_out
== NULL
))
962 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
963 if (!p_sys
->p_parser
) {
964 msg_Err(p_demux
, "Failed to create TS demuxer");
968 p_demux
->pf_control
= blurayControl
;
969 p_demux
->pf_demux
= blurayDemux
;
975 vlc_dialog_display_error(p_demux
, _("Blu-ray error"), "%s", error_msg
);
978 if (p_demux
->s
!= NULL
) {
979 /* restore stream position */
980 if (vlc_stream_Seek(p_demux
->s
, i_init_pos
) != VLC_SUCCESS
) {
981 msg_Err(p_demux
, "Failed to seek back to stream start");
991 /*****************************************************************************
992 * blurayClose: module destroy function
993 *****************************************************************************/
994 static void blurayClose(vlc_object_t
*object
)
996 demux_t
*p_demux
= (demux_t
*)object
;
997 demux_sys_t
*p_sys
= p_demux
->p_sys
;
999 setTitleInfo(p_sys
, NULL
);
1002 * Close libbluray first.
1003 * This will close all the overlays before we release p_vout
1004 * bd_close(NULL) can crash
1006 if (p_sys
->bluray
) {
1007 bd_close(p_sys
->bluray
);
1010 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1011 blurayReleaseVideoES(p_demux
);
1012 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1014 if (p_sys
->p_parser
)
1015 vlc_demux_chained_Delete(p_sys
->p_parser
);
1017 if (p_sys
->p_out
!= NULL
)
1018 es_out_Delete(p_sys
->p_out
);
1020 timestamps_filter_es_out_Delete(p_sys
->p_tf_out
);
1023 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1024 vlc_input_title_Delete(p_sys
->pp_title
[i
]);
1025 TAB_CLEAN(p_sys
->i_title
, p_sys
->pp_title
);
1027 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1028 vlc_input_attachment_Delete(p_sys
->attachments
[i
]);
1029 TAB_CLEAN(p_sys
->i_attachments
, p_sys
->attachments
);
1031 vlc_mutex_destroy(&p_sys
->pl_info_lock
);
1032 vlc_mutex_destroy(&p_sys
->bdj_overlay_lock
);
1033 vlc_mutex_destroy(&p_sys
->read_block_lock
);
1035 free(p_sys
->psz_bd_path
);
1038 /*****************************************************************************
1039 * Elementary streams handling
1040 *****************************************************************************/
1041 static uint8_t blurayGetStreamsUnlocked(demux_sys_t
*p_sys
,
1043 BLURAY_STREAM_INFO
**pp_streams
)
1045 if(!p_sys
->p_clip_info
)
1048 switch(i_stream_type
)
1050 case BD_EVENT_AUDIO_STREAM
:
1051 *pp_streams
= p_sys
->p_clip_info
->audio_streams
;
1052 return p_sys
->p_clip_info
->audio_stream_count
;
1053 case BD_EVENT_PG_TEXTST_STREAM
:
1054 *pp_streams
= p_sys
->p_clip_info
->pg_streams
;
1055 return p_sys
->p_clip_info
->pg_stream_count
;
1061 static BLURAY_STREAM_INFO
* blurayGetStreamInfoUnlocked(demux_sys_t
*p_sys
,
1063 uint8_t i_stream_idx
)
1065 BLURAY_STREAM_INFO
*p_streams
= NULL
;
1066 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_stream_type
, &p_streams
);
1067 if(i_stream_idx
< i_streams_count
)
1068 return &p_streams
[i_stream_idx
];
1073 static BLURAY_STREAM_INFO
* blurayGetStreamInfoByPIDUnlocked(demux_sys_t
*p_sys
,
1076 for(int i_type
=BD_EVENT_AUDIO_STREAM
; i_type
<=BD_EVENT_SECONDARY_VIDEO_STREAM
; i_type
++)
1078 BLURAY_STREAM_INFO
*p_streams
;
1079 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_type
, &p_streams
);
1080 for(uint8_t i
=0; i
<i_streams_count
; i
++)
1082 if(p_streams
[i
].pid
== i_pid
)
1083 return &p_streams
[i
];
1089 static void setStreamLang(demux_sys_t
*p_sys
, es_format_t
*p_fmt
)
1091 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1093 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoByPIDUnlocked(p_sys
, p_fmt
->i_id
);
1096 free(p_fmt
->psz_language
);
1097 p_fmt
->psz_language
= strndup((const char *)p_stream
->lang
, 3);
1100 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1103 static int blurayGetStreamPID(demux_sys_t
*p_sys
, int i_stream_type
, uint8_t i_stream_idx
)
1105 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1107 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoUnlocked(p_sys
,
1110 int i_pid
= p_stream
? p_stream
->pid
: -1;
1112 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1117 /*****************************************************************************
1118 * bluray fake es_out
1119 *****************************************************************************/
1122 es_out_t
*p_dst_out
;
1123 vlc_object_t
*p_obj
;
1124 vlc_array_t es
; /* es_pair_t */
1125 bool b_entered_recycling
;
1127 bool b_discontinuity
;
1128 bool b_disable_output
;
1132 int i_audio_pid
; /* Selected audio stream. -1 if default */
1134 int i_spu_pid
; /* Selected spu stream. -1 if default */
1137 } bluray_esout_priv_t
;
1141 BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
= ES_OUT_PRIVATE_START
,
1142 BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
,
1143 BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
,
1144 BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
,
1145 BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
,
1148 static es_out_id_t
*bluray_esOutAdd(es_out_t
*p_out
, const es_format_t
*p_fmt
)
1150 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1151 demux_t
*p_demux
= esout_priv
->priv
;
1152 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1154 bool b_select
= false;
1156 es_format_Copy(&fmt
, p_fmt
);
1158 vlc_mutex_lock(&esout_priv
->lock
);
1160 switch (fmt
.i_cat
) {
1162 if (esout_priv
->selected
.i_video_pid
!= -1 && esout_priv
->selected
.i_video_pid
!= p_fmt
->i_id
)
1163 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1164 b_select
= (p_fmt
->i_id
== 0x1011);
1167 if (esout_priv
->selected
.i_audio_pid
!= -1) {
1168 if (esout_priv
->selected
.i_audio_pid
== p_fmt
->i_id
)
1170 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1172 setStreamLang(p_sys
, &fmt
);
1175 if (esout_priv
->selected
.i_spu_pid
!= -1) {
1176 if (esout_priv
->selected
.i_spu_pid
== p_fmt
->i_id
)
1177 b_select
= p_sys
->b_spu_enable
;
1178 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1180 setStreamLang(p_sys
, &fmt
);
1186 es_out_id_t
*p_es
= NULL
;
1187 if (p_fmt
->i_id
>= 0) {
1188 /* Ensure we are not overriding anything */
1189 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, p_fmt
->i_id
);
1192 msg_Info(p_demux
, "Adding ES %d select %d", p_fmt
->i_id
, b_select
);
1193 p_es
= es_out_Add(esout_priv
->p_dst_out
, &fmt
);
1194 es_pair_Add(&esout_priv
->es
, &fmt
, p_es
);
1198 msg_Info(p_demux
, "Reusing ES %d", p_fmt
->i_id
);
1199 p_pair
->b_recyling
= false;
1200 p_es
= p_pair
->p_es
;
1201 if(!es_format_IsSimilar(&fmt
, &p_pair
->fmt
))
1203 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_SET_ES_FMT
, p_pair
->p_es
, &fmt
);
1204 es_format_Clean(&p_pair
->fmt
);
1205 es_format_Copy(&p_pair
->fmt
, &fmt
);
1209 es_out_Control(p_demux
->out
, ES_OUT_SET_ES
, p_es
);
1211 if (p_es
&& fmt
.i_cat
== VIDEO_ES
)
1213 es_out_Control( p_demux
->out
, ES_OUT_VOUT_SET_MOUSE_EVENT
, p_es
,
1214 onMouseEvent
, p_demux
);
1215 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1216 p_sys
->p_video_es
= p_es
;
1217 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1219 es_format_Clean(&fmt
);
1221 vlc_mutex_unlock(&esout_priv
->lock
);
1226 static void bluray_esOutDeleteNonReusedESUnlocked(es_out_t
*p_out
)
1228 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1229 if(!esout_priv
->b_entered_recycling
)
1231 esout_priv
->b_entered_recycling
= false;
1234 while((p_pair
= getUnusedEsPair(&esout_priv
->es
)))
1236 msg_Info(esout_priv
->p_obj
, "Trashing unused ES %d", p_pair
->fmt
.i_id
);
1237 es_out_Del(esout_priv
->p_dst_out
, p_pair
->p_es
);
1238 es_pair_Remove(&esout_priv
->es
, p_pair
);
1242 static int bluray_esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1244 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1245 vlc_mutex_lock(&esout_priv
->lock
);
1247 bluray_esOutDeleteNonReusedESUnlocked(p_out
);
1249 if(esout_priv
->b_discontinuity
)
1250 esout_priv
->b_discontinuity
= false;
1252 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1253 if(p_pair
&& p_pair
->i_next_block_flags
)
1255 p_block
->i_flags
|= p_pair
->i_next_block_flags
;
1256 p_pair
->i_next_block_flags
= 0;
1258 if(esout_priv
->b_disable_output
)
1260 block_Release(p_block
);
1263 vlc_mutex_unlock(&esout_priv
->lock
);
1264 return (p_block
) ? es_out_Send(esout_priv
->p_dst_out
, p_es
, p_block
) : VLC_SUCCESS
;
1267 static void bluray_esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1269 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1270 demux_t
*p_demux
= esout_priv
->priv
;
1271 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1273 vlc_mutex_lock(&esout_priv
->lock
);
1275 if(esout_priv
->b_discontinuity
)
1276 esout_priv
->b_discontinuity
= false;
1278 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1281 p_pair
->b_recyling
= true;
1282 esout_priv
->b_entered_recycling
= true;
1285 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1286 if (p_es
== p_sys
->p_video_es
)
1287 p_sys
->p_video_es
= NULL
;
1288 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1290 vlc_mutex_unlock(&esout_priv
->lock
);
1293 static int bluray_esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1295 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1297 vlc_mutex_lock(&esout_priv
->lock
);
1299 if(esout_priv
->b_disable_output
&&
1300 i_query
< ES_OUT_PRIVATE_START
)
1302 vlc_mutex_unlock(&esout_priv
->lock
);
1303 return VLC_EGENERIC
;
1306 if(esout_priv
->b_discontinuity
)
1307 esout_priv
->b_discontinuity
= false;
1311 case BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
:
1312 case BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
:
1314 bool b_select
= (i_query
== BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
);
1315 const int i_bluray_stream_type
= va_arg(args
, int);
1316 const int i_pid
= va_arg(args
, int);
1317 switch(i_bluray_stream_type
)
1319 case BD_EVENT_AUDIO_STREAM
:
1320 esout_priv
->selected
.i_audio_pid
= i_pid
;
1322 case BD_EVENT_PG_TEXTST_STREAM
:
1323 esout_priv
->selected
.i_spu_pid
= i_pid
;
1329 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, i_pid
);
1330 if(unlikely(!p_pair
))
1332 vlc_mutex_unlock(&esout_priv
->lock
);
1333 return VLC_EGENERIC
;
1336 i_ret
= es_out_Control(esout_priv
->p_dst_out
,
1337 b_select
? ES_OUT_SET_ES
: ES_OUT_UNSET_ES
,
1341 case BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
:
1343 esout_priv
->b_discontinuity
= true;
1344 i_ret
= VLC_SUCCESS
;
1347 case BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
:
1348 case BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
:
1350 esout_priv
->b_disable_output
= (i_query
== BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
1351 i_ret
= VLC_SUCCESS
;
1354 case ES_OUT_SET_ES_DEFAULT
:
1356 case ES_OUT_UNSET_ES
:
1357 case ES_OUT_SET_ES_STATE
:
1358 i_ret
= VLC_EGENERIC
;
1361 case ES_OUT_GET_ES_STATE
:
1362 va_arg(args
, es_out_id_t
*);
1363 *va_arg(args
, bool *) = true;
1364 i_ret
= VLC_SUCCESS
;
1368 i_ret
= es_out_vaControl(esout_priv
->p_dst_out
, i_query
, args
);
1371 vlc_mutex_unlock(&esout_priv
->lock
);
1375 static void bluray_esOutDestroy(es_out_t
*p_out
)
1377 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1379 for (size_t i
= 0; i
< vlc_array_count(&esout_priv
->es
); ++i
)
1380 free(vlc_array_item_at_index(&esout_priv
->es
, i
));
1381 vlc_array_clear(&esout_priv
->es
);
1382 vlc_mutex_destroy(&esout_priv
->lock
);
1386 static const struct es_out_callbacks bluray_esOutCallbacks
= {
1387 .add
= bluray_esOutAdd
,
1388 .send
= bluray_esOutSend
,
1389 .del
= bluray_esOutDel
,
1390 .control
= bluray_esOutControl
,
1391 .destroy
= bluray_esOutDestroy
,
1394 static es_out_t
*esOutNew(vlc_object_t
*p_obj
, es_out_t
*p_dst_out
, void *priv
)
1396 bluray_esout_priv_t
*esout_priv
= malloc(sizeof(*esout_priv
));
1397 if (unlikely(esout_priv
== NULL
))
1400 vlc_array_init(&esout_priv
->es
);
1401 esout_priv
->p_dst_out
= p_dst_out
;
1402 esout_priv
->p_obj
= p_obj
;
1403 esout_priv
->priv
= priv
;
1404 esout_priv
->es_out
.cbs
= &bluray_esOutCallbacks
;
1405 esout_priv
->b_discontinuity
= false;
1406 esout_priv
->b_disable_output
= false;
1407 esout_priv
->b_entered_recycling
= false;
1408 esout_priv
->selected
.i_audio_pid
= -1;
1409 esout_priv
->selected
.i_video_pid
= -1;
1410 esout_priv
->selected
.i_spu_pid
= -1;
1411 vlc_mutex_init(&esout_priv
->lock
);
1412 return &esout_priv
->es_out
;
1415 /*****************************************************************************
1416 * subpicture_updater_t functions:
1417 *****************************************************************************/
1419 static bluray_overlay_t
*updater_lock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1421 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1422 vlc_mutex_lock(&p_upd_sys
->lock
);
1424 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1426 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1427 vlc_mutex_lock(&ov
->lock
);
1431 /* overlay has been closed */
1432 vlc_mutex_unlock(&p_upd_sys
->lock
);
1436 static void updater_unlock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1438 assert (p_upd_sys
->p_overlay
);
1440 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1441 vlc_mutex_unlock(&p_upd_sys
->lock
);
1444 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1445 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1446 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1449 VLC_UNUSED(b_fmt_src
);
1450 VLC_UNUSED(b_fmt_dst
);
1451 VLC_UNUSED(p_fmt_src
);
1452 VLC_UNUSED(p_fmt_dst
);
1455 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1456 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1462 int res
= p_overlay
->status
== Outdated
;
1464 updater_unlock_overlay(p_upd_sys
);
1469 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1470 const video_format_t
*p_fmt_src
,
1471 const video_format_t
*p_fmt_dst
,
1474 VLC_UNUSED(p_fmt_src
);
1475 VLC_UNUSED(p_fmt_dst
);
1477 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1478 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1485 * When this function is called, all p_subpic regions are gone.
1486 * We need to duplicate our regions (stored internaly) to this subpic.
1488 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1490 updater_unlock_overlay(p_upd_sys
);
1494 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1495 while (p_src
!= NULL
) {
1496 *p_dst
= subpicture_region_Copy(p_src
);
1499 p_dst
= &(*p_dst
)->p_next
;
1500 p_src
= p_src
->p_next
;
1503 (*p_dst
)->p_next
= NULL
;
1504 p_overlay
->status
= Displayed
;
1506 updater_unlock_overlay(p_upd_sys
);
1509 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1511 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1512 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1515 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1516 p_overlay
->status
= ToDisplay
;
1517 p_overlay
->i_channel
= -1;
1518 updater_unlock_overlay(p_upd_sys
);
1521 unref_subpicture_updater(p_upd_sys
);
1524 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1526 bluray_spu_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1527 if (unlikely(p_upd_sys
== NULL
)) {
1531 p_upd_sys
->p_overlay
= p_ov
;
1533 subpicture_updater_t updater
= {
1534 .pf_validate
= subpictureUpdaterValidate
,
1535 .pf_update
= subpictureUpdaterUpdate
,
1536 .pf_destroy
= subpictureUpdaterDestroy
,
1540 subpicture_t
*p_pic
= subpicture_New(&updater
);
1541 if (p_pic
== NULL
) {
1546 p_pic
->i_original_picture_width
= p_ov
->width
;
1547 p_pic
->i_original_picture_height
= p_ov
->height
;
1548 p_pic
->b_absolute
= true;
1550 vlc_mutex_init(&p_upd_sys
->lock
);
1551 p_upd_sys
->ref_cnt
= 2;
1553 p_ov
->p_updater
= p_upd_sys
;
1558 /*****************************************************************************
1559 * User input events:
1560 *****************************************************************************/
1561 static void onMouseEvent(const vlc_mouse_t
*newmouse
, void *user_data
)
1563 demux_t
*p_demux
= user_data
;
1564 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1567 vlc_mouse_Init(&p_sys
->oldmouse
);
1571 if (vlc_mouse_HasMoved(&p_sys
->oldmouse
, newmouse
))
1572 bd_mouse_select(p_sys
->bluray
, -1, newmouse
->i_x
, newmouse
->i_y
);
1574 if (vlc_mouse_HasPressed( &p_sys
->oldmouse
, newmouse
, MOUSE_BUTTON_LEFT
))
1575 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1576 p_sys
->oldmouse
= *newmouse
;
1579 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1581 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1582 return VLC_EGENERIC
;
1587 /*****************************************************************************
1588 * libbluray overlay handling:
1589 *****************************************************************************/
1591 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1593 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1594 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1598 /* drop overlay from vout */
1599 if (ov
->p_updater
) {
1600 unref_subpicture_updater(ov
->p_updater
);
1602 /* no references to this overlay exist in vo anymore */
1603 if (p_sys
->p_video_es
&& ov
->i_channel
!= -1) {
1604 es_out_Control( p_demux
->out
, ES_OUT_VOUT_FLUSH_OVERLAY
,
1605 p_sys
->p_video_es
, ov
->i_channel
);
1608 vlc_mutex_destroy(&ov
->lock
);
1609 subpicture_region_ChainDelete(ov
->p_regions
);
1612 p_sys
->p_overlays
[plane
] = NULL
;
1615 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1616 if (p_sys
->p_overlays
[i
])
1619 /* All overlays have been closed */
1620 blurayReleaseVideoES(p_demux
);
1624 * Mark the overlay as "ToDisplay" status.
1625 * This will not send the overlay to the vout instantly, as the vout
1626 * may not be acquired (not acquirable) yet.
1627 * If is has already been acquired, the overlay has already been sent to it,
1628 * therefore, we only flag the overlay as "Outdated"
1630 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1632 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1633 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1636 * If the overlay is already displayed, mark the picture as outdated.
1637 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1639 vlc_mutex_lock(&ov
->lock
);
1640 if (ov
->status
>= Displayed
&& p_sys
->p_video_es
) {
1641 ov
->status
= Outdated
;
1642 vlc_mutex_unlock(&ov
->lock
);
1647 * Mark the overlay as available, but don't display it right now.
1648 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1649 * the overlay is computed
1651 ov
->status
= ToDisplay
;
1652 vlc_mutex_unlock(&ov
->lock
);
1655 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1657 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1659 assert(p_sys
->p_overlays
[plane
] == NULL
);
1661 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1662 if (unlikely(ov
== NULL
))
1666 ov
->height
= height
;
1669 vlc_mutex_init(&ov
->lock
);
1671 p_sys
->p_overlays
[plane
] = ov
;
1675 * Destroy every regions in the subpicture.
1676 * This is done in two steps:
1677 * - Wiping our private regions list
1678 * - Flagging the overlay as outdated, so the changes are replicated from
1679 * the subpicture_updater_t::pf_update
1680 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1682 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1684 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1685 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1687 vlc_mutex_lock(&ov
->lock
);
1689 subpicture_region_ChainDelete(ov
->p_regions
);
1690 ov
->p_regions
= NULL
;
1691 ov
->status
= Outdated
;
1693 vlc_mutex_unlock(&ov
->lock
);
1697 * This will draw to the overlay by adding a region to our region list
1698 * This will have to be copied to the subpicture used to render the overlay.
1700 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1702 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1705 * Compute a subpicture_region_t.
1706 * It will be copied and sent to the vout later.
1708 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1710 /* Find a region to update */
1711 subpicture_region_t
**pp_reg
= &p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1712 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1713 subpicture_region_t
*p_last
= NULL
;
1714 while (p_reg
!= NULL
) {
1716 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1717 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1719 pp_reg
= &p_reg
->p_next
;
1720 p_reg
= p_reg
->p_next
;
1726 *pp_reg
= p_reg
->p_next
;
1727 subpicture_region_Delete(p_reg
);
1729 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1733 /* If there is no region to update, create a new one. */
1736 video_format_Init(&fmt
, 0);
1737 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1739 p_reg
= subpicture_region_New(&fmt
);
1742 /* Append it to our list. */
1744 p_last
->p_next
= p_reg
;
1745 else /* If we don't have a last region, then our list empty */
1746 p_sys
->p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1749 /* Now we can update the region, regardless it's an update or an insert */
1750 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1751 for (int y
= 0; y
< ov
->h
; y
++)
1752 for (int x
= 0; x
< ov
->w
;) {
1753 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1754 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1760 p_reg
->fmt
.p_palette
->i_entries
= 256;
1761 for (int i
= 0; i
< 256; ++i
) {
1762 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1763 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1764 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1765 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1769 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1771 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1775 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1777 demux_t
*p_demux
= (demux_t
*)ptr
;
1778 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1781 msg_Info(p_demux
, "Closing overlays.");
1782 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1783 if (p_sys
->p_video_es
)
1784 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1785 blurayCloseOverlay(p_demux
, i
);
1786 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1790 switch (overlay
->cmd
) {
1791 case BD_OVERLAY_INIT
:
1792 msg_Info(p_demux
, "Initializing overlay");
1793 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1794 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1795 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1797 case BD_OVERLAY_CLOSE
:
1798 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1799 blurayClearOverlay(p_demux
, overlay
->plane
);
1800 blurayCloseOverlay(p_demux
, overlay
->plane
);
1801 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1803 case BD_OVERLAY_CLEAR
:
1804 blurayClearOverlay(p_demux
, overlay
->plane
);
1806 case BD_OVERLAY_FLUSH
:
1807 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1808 blurayActivateOverlay(p_demux
, overlay
->plane
);
1809 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1811 case BD_OVERLAY_DRAW
:
1812 case BD_OVERLAY_WIPE
:
1813 blurayDrawOverlay(p_demux
, overlay
);
1816 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
1822 * ARGB overlay (BD-J)
1824 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1826 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1828 blurayInitOverlay(p_demux
, plane
, width
, height
);
1830 if (!p_sys
->p_overlays
[plane
]->p_regions
) {
1832 video_format_Init(&fmt
, 0);
1833 video_format_Setup(&fmt
, VLC_CODEC_RGBA
, width
, height
, width
, height
, 1, 1);
1835 p_sys
->p_overlays
[plane
]->p_regions
= subpicture_region_New(&fmt
);
1839 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
1841 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1843 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1845 /* Find a region to update */
1846 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1848 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1852 /* Now we can update the region */
1853 const uint32_t *src0
= ov
->argb
;
1854 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
1855 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
1858 for (int y
= 0; y
< ov
->h
; y
++) {
1859 // XXX: add support for this format ? Should be possible with OPENGL/VDPAU/...
1860 // - or add libbluray option to select the format ?
1861 for (int x
= 0; x
< ov
->w
; x
++) {
1862 dst0
[x
*4 ] = src0
[x
]>>16; /* R */
1863 dst0
[x
*4+1] = src0
[x
]>>8; /* G */
1864 dst0
[x
*4+2] = src0
[x
]; /* B */
1865 dst0
[x
*4+3] = src0
[x
]>>24; /* A */
1869 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
1872 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1874 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1878 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
1880 demux_t
*p_demux
= (demux_t
*)ptr
;
1881 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1883 switch (overlay
->cmd
) {
1884 case BD_ARGB_OVERLAY_INIT
:
1885 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1886 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1887 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1889 case BD_ARGB_OVERLAY_CLOSE
:
1890 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1891 blurayClearOverlay(p_demux
, overlay
->plane
);
1892 blurayCloseOverlay(p_demux
, overlay
->plane
);
1893 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1895 case BD_ARGB_OVERLAY_FLUSH
:
1896 blurayActivateOverlay(p_demux
, overlay
->plane
);
1898 case BD_ARGB_OVERLAY_DRAW
:
1899 blurayDrawArgbOverlay(p_demux
, overlay
);
1902 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
1907 static void bluraySendOverlayToVout(demux_t
*p_demux
, bluray_overlay_t
*p_ov
)
1909 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1911 assert(p_ov
!= NULL
);
1912 assert(p_ov
->i_channel
== -1);
1914 if (p_ov
->p_updater
) {
1915 unref_subpicture_updater(p_ov
->p_updater
);
1916 p_ov
->p_updater
= NULL
;
1919 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
1921 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
1926 * After this point, the picture should not be accessed from the demux thread,
1927 * as it is held by the vout thread.
1928 * This must be done only once per subpicture, ie. only once between each
1929 * blurayInitOverlay & blurayCloseOverlay call.
1931 int ret
= es_out_Control( p_demux
->out
, ES_OUT_VOUT_ADD_OVERLAY
,
1932 p_sys
->p_video_es
, p_pic
, &p_ov
->i_channel
);
1933 if (ret
!= VLC_SUCCESS
)
1935 unref_subpicture_updater(p_ov
->p_updater
);
1936 p_ov
->p_updater
= NULL
;
1937 subpicture_Delete(p_pic
);
1942 * Mark the picture as Outdated, as it contains no region for now.
1943 * This will make the subpicture_updater_t call pf_update
1945 p_ov
->status
= Outdated
;
1948 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
1950 t
->i_length
= FROM_SCALE_NZ(title_info
->duration
);
1952 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
1953 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
1954 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
1956 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
1957 seekpoint_t
*s
= vlc_seekpoint_New();
1961 s
->i_time_offset
= FROM_SCALE_NZ(title_info
->chapters
[j
].start
);
1963 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
1967 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
)
1969 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1970 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
1972 /* get and set the titles */
1973 uint32_t i_title
= menu_titles
;
1975 if (!p_sys
->b_menu
) {
1976 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
1977 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
1980 for (uint32_t i
= 0; i
< i_title
; i
++) {
1981 input_title_t
*t
= vlc_input_title_New();
1985 if (!p_sys
->b_menu
) {
1986 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
1987 blurayUpdateTitleInfo(t
, title_info
);
1988 bd_free_title_info(title_info
);
1990 } else if (i
== 0) {
1991 t
->psz_name
= strdup(_("Top Menu"));
1992 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
1993 } else if (i
== i_title
- 1) {
1994 t
->psz_name
= strdup(_("First Play"));
1995 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
1996 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1999 /* add possible title name from disc metadata */
2000 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
2001 if (di
->titles
[i
]->name
) {
2002 t
->psz_name
= strdup(di
->titles
[i
]->name
);
2004 if (di
->titles
[i
]->interactive
) {
2005 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
2010 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
2014 static void blurayRestartParser(demux_t
*p_demux
, bool b_flush
)
2017 * This is a hack and will have to be removed.
2018 * The parser should be flushed, and not destroy/created each time
2019 * we are changing title.
2021 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2024 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
2026 if (p_sys
->p_parser
)
2027 vlc_demux_chained_Delete(p_sys
->p_parser
);
2030 es_out_Control(p_sys
->p_tf_out
, ES_OUT_TF_FILTER_RESET
);
2032 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
2033 if (!p_sys
->p_parser
)
2034 msg_Err(p_demux
, "Failed to create TS demuxer");
2036 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
);
2039 /*****************************************************************************
2040 * bluraySetTitle: select new BD title
2041 *****************************************************************************/
2042 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
2044 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2046 if (p_sys
->b_menu
) {
2049 msg_Dbg(p_demux
, "Playing TopMenu Title");
2050 result
= bd_menu_call(p_sys
->bluray
, -1);
2051 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
2052 msg_Dbg(p_demux
, "Playing FirstPlay Title");
2053 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
2055 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
2056 result
= bd_play_title(p_sys
->bluray
, i_title
);
2060 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
2061 return VLC_EGENERIC
;
2067 /* Looking for the main title, ie the longest duration */
2069 i_title
= p_sys
->i_longest_title
;
2070 else if ((unsigned)i_title
> p_sys
->i_title
)
2071 return VLC_EGENERIC
;
2073 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
2075 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
2076 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
2077 return VLC_EGENERIC
;
2083 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
2084 # define BLURAY_AUDIO_STREAM 0
2087 static void blurayOnUserStreamSelection(demux_sys_t
*p_sys
, int i_pid
)
2089 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2091 if (p_sys
->p_clip_info
) {
2093 if ((i_pid
& 0xff00) == 0x1100) {
2095 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
2096 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
2097 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
2099 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
,
2100 (const char *) p_sys
->p_clip_info
->audio_streams
[i_id
].lang
);
2104 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
2106 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
2107 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
2108 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
2110 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
,
2111 (const char *) p_sys
->p_clip_info
->pg_streams
[i_id
].lang
);
2118 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2121 /*****************************************************************************
2122 * blurayControl: handle the controls
2123 *****************************************************************************/
2124 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
2126 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2130 case DEMUX_CAN_SEEK
:
2131 case DEMUX_CAN_PAUSE
:
2132 case DEMUX_CAN_CONTROL_PACE
:
2133 pb_bool
= va_arg(args
, bool *);
2137 case DEMUX_GET_PTS_DELAY
:
2138 *va_arg(args
, vlc_tick_t
*) =
2139 VLC_TICK_FROM_MS(var_InheritInteger(p_demux
, "disc-caching"));
2142 case DEMUX_SET_PAUSE_STATE
:
2144 #ifdef BLURAY_RATE_NORMAL
2145 bool b_paused
= (bool)va_arg(args
, int);
2146 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
2147 return VLC_EGENERIC
;
2154 int i_id
= va_arg(args
, int);
2155 blurayOnUserStreamSelection(p_sys
, i_id
);
2158 case DEMUX_SET_TITLE
:
2160 int i_title
= va_arg(args
, int);
2161 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
2162 /* make sure GUI restores the old setting in title menu ... */
2163 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2164 return VLC_EGENERIC
;
2166 blurayRestartParser(p_demux
, true);
2167 notifyDiscontinuityToParser(p_sys
);
2168 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2171 case DEMUX_SET_SEEKPOINT
:
2173 int i_chapter
= va_arg(args
, int);
2174 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
2175 blurayRestartParser(p_demux
, true);
2176 notifyDiscontinuityToParser(p_sys
);
2177 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2180 case DEMUX_TEST_AND_CLEAR_FLAGS
:
2182 unsigned *restrict flags
= va_arg(args
, unsigned *);
2183 *flags
&= p_sys
->updates
;
2184 p_sys
->updates
&= ~*flags
;
2187 case DEMUX_GET_TITLE
:
2188 *va_arg(args
, int *) = p_sys
->cur_title
;
2191 case DEMUX_GET_SEEKPOINT
:
2192 *va_arg(args
, int *) = p_sys
->cur_seekpoint
;
2195 case DEMUX_GET_TITLE_INFO
:
2197 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
2198 int *pi_int
= va_arg(args
, int *);
2199 int *pi_title_offset
= va_arg(args
, int *);
2200 int *pi_chapter_offset
= va_arg(args
, int *);
2203 *pi_title_offset
= 0;
2204 *pi_chapter_offset
= 0;
2206 /* Duplicate local title infos */
2208 *ppp_title
= vlc_alloc(p_sys
->i_title
, sizeof(input_title_t
*));
2210 return VLC_EGENERIC
;
2211 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
2213 input_title_t
*p_dup
= vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
2215 (*ppp_title
)[(*pi_int
)++] = p_dup
;
2221 case DEMUX_GET_LENGTH
:
2223 if(p_sys
->cur_title
< p_sys
->i_title
&&
2224 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2225 return VLC_EGENERIC
;
2226 *va_arg(args
, vlc_tick_t
*) = p_sys
->cur_title
< p_sys
->i_title
? CUR_LENGTH
: 0;
2229 case DEMUX_SET_TIME
:
2231 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(va_arg(args
, vlc_tick_t
)));
2232 blurayRestartParser(p_demux
, true);
2233 notifyDiscontinuityToParser(p_sys
);
2234 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2237 case DEMUX_GET_TIME
:
2239 vlc_tick_t
*pi_time
= va_arg(args
, vlc_tick_t
*);
2240 if(p_sys
->cur_title
< p_sys
->i_title
&&
2241 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2242 return VLC_EGENERIC
;
2243 *pi_time
= FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
));
2247 case DEMUX_GET_POSITION
:
2249 double *pf_position
= va_arg(args
, double *);
2250 if(p_sys
->cur_title
< p_sys
->i_title
&&
2251 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2252 return VLC_EGENERIC
;
2253 *pf_position
= p_sys
->cur_title
< p_sys
->i_title
&& CUR_LENGTH
> 0 ?
2254 (double)FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
2257 case DEMUX_SET_POSITION
:
2259 double f_position
= va_arg(args
, double);
2260 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(f_position
*CUR_LENGTH
));
2261 blurayRestartParser(p_demux
, true);
2262 notifyDiscontinuityToParser(p_sys
);
2263 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2267 case DEMUX_GET_META
:
2269 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
2270 const META_DL
*meta
= p_sys
->p_meta
;
2272 return VLC_EGENERIC
;
2274 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
2276 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
2277 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
2278 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
2280 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
2281 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
2283 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
2285 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
2286 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
2287 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
2289 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
2290 char *psz_thumbpath
;
2291 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
2292 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > -1) {
2293 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
2294 free(psz_thumbpath
);
2295 if (unlikely(psz_thumburl
== NULL
))
2298 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
2306 case DEMUX_GET_ATTACHMENTS
:
2308 input_attachment_t
***ppp_attach
=
2309 va_arg(args
, input_attachment_t
***);
2310 int *pi_int
= va_arg(args
, int *);
2312 if (p_sys
->i_attachments
<= 0)
2313 return VLC_EGENERIC
;
2316 *ppp_attach
= vlc_alloc(p_sys
->i_attachments
, sizeof(input_attachment_t
*));
2318 return VLC_EGENERIC
;
2319 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
2321 input_attachment_t
*p_dup
= vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
2323 (*ppp_attach
)[(*pi_int
)++] = p_dup
;
2328 case DEMUX_NAV_ACTIVATE
:
2329 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
2330 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2332 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
2334 return sendKeyEvent(p_sys
, BD_VK_UP
);
2335 case DEMUX_NAV_DOWN
:
2336 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
2337 case DEMUX_NAV_LEFT
:
2338 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
2339 case DEMUX_NAV_RIGHT
:
2340 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
2341 case DEMUX_NAV_POPUP
:
2342 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2343 case DEMUX_NAV_MENU
:
2344 if (p_sys
->b_menu
) {
2345 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
2346 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2349 msg_Err(p_demux
, "Can't select Top Menu title");
2350 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2352 return VLC_EGENERIC
;
2354 case DEMUX_CAN_RECORD
:
2356 case DEMUX_SET_GROUP_DEFAULT
:
2357 case DEMUX_SET_GROUP_ALL
:
2358 case DEMUX_SET_GROUP_LIST
:
2359 case DEMUX_HAS_UNSUPPORTED_META
:
2361 return VLC_EGENERIC
;
2366 /*****************************************************************************
2367 * libbluray event handling
2368 *****************************************************************************/
2369 static void writeTsPacketWDiscontinuity( uint8_t *p_buf
, uint16_t i_pid
,
2370 const uint8_t *p_payload
, uint8_t i_payload
)
2372 uint8_t ts_header
[] = {
2373 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2375 0x40 | ((i_pid
& 0x1f00) >> 8), i_pid
& 0xFF, /* PUSI + PID */
2376 i_payload
? 0x30 : 0x20, /* adaptation field, payload / no payload */
2377 192 - (4 + 5) - i_payload
, /* adaptation field length */
2378 0x82, /* af: discontinuity indicator + priv data */
2379 0x0E, /* priv data size */
2381 'D', 'I', 'S', 'C', 'O', 'N', 'T', 'I', 'N', 'U',
2384 memcpy( p_buf
, ts_header
, sizeof(ts_header
) );
2385 memset( &p_buf
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
) - i_payload
);
2387 memcpy( &p_buf
[192 - i_payload
], p_payload
, i_payload
);
2390 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
2391 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
2393 for( size_t i
=0; i
< i_sinfo
; i
++ )
2395 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2397 block_t
*p_block
= block_Alloc(192);
2401 writeTsPacketWDiscontinuity( p_block
->p_buffer
, i_pid
, NULL
, 0 );
2403 vlc_demux_chained_Send(p_parser
, p_block
);
2407 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2408 p_clip->memb##_stream_count )
2410 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
)
2412 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2419 DONOTIFY(sec_audio
);
2420 DONOTIFY(sec_video
);
2426 static void streamFlush( demux_sys_t
*p_sys
)
2429 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2430 * Packet is flushed only when TS packet with PUSI flag set is received.
2432 * Fix this by emitting (video) ts packet with PUSI flag set.
2433 * Add video sequence end code to payload so that also video decoder is flushed.
2434 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2437 if (p_sys
->b_flushed
)
2440 block_t
*p_block
= block_Alloc(192);
2444 bd_stream_type_e i_coding_type
;
2446 /* set correct sequence end code */
2447 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2448 if (p_sys
->p_clip_info
!= NULL
)
2449 i_coding_type
= p_sys
->p_clip_info
->video_streams
[0].coding_type
;
2452 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2455 switch( i_coding_type
)
2457 case BLURAY_STREAM_TYPE_VIDEO_MPEG1
:
2458 case BLURAY_STREAM_TYPE_VIDEO_MPEG2
:
2460 i_eos
= 0xB7; /* MPEG2 sequence end */
2462 case BLURAY_STREAM_TYPE_VIDEO_VC1
:
2463 case BLURAY_STREAM_TYPE_VIDEO_H264
:
2464 i_eos
= 0x0A; /* VC1 / H.264 sequence end */
2466 case BD_STREAM_TYPE_VIDEO_HEVC
:
2467 i_eos
= 0x48; /* HEVC sequence end NALU */
2471 uint8_t seq_end_pes
[] = {
2472 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2473 0x00, 0x00, 0x01, i_eos
, /* PES payload: sequence end */
2474 0x00, /* 2nd byte for HEVC NAL, pads others */
2477 writeTsPacketWDiscontinuity( p_block
->p_buffer
, 0x1011, seq_end_pes
, sizeof(seq_end_pes
) );
2479 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2480 p_sys
->b_flushed
= true;
2483 static void blurayResetStillImage( demux_t
*p_demux
)
2485 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2487 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
) {
2488 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
2490 blurayRestartParser(p_demux
, false);
2491 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2495 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2497 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2499 /* time period elapsed ? */
2500 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
&&
2501 p_sys
->i_still_end_time
!= STILL_IMAGE_INFINITE
&&
2502 p_sys
->i_still_end_time
<= vlc_tick_now()) {
2503 msg_Dbg(p_demux
, "Still image end");
2504 bd_read_skip_still(p_sys
->bluray
);
2506 blurayResetStillImage(p_demux
);
2510 /* show last frame as still image */
2511 if (p_sys
->i_still_end_time
== STILL_IMAGE_NOT_SET
) {
2513 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2514 p_sys
->i_still_end_time
= vlc_tick_now() + vlc_tick_from_sec( i_timeout
);
2516 msg_Dbg(p_demux
, "Still image (infinite)");
2517 p_sys
->i_still_end_time
= STILL_IMAGE_INFINITE
;
2520 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2523 /* stop buffering */
2525 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2528 /* avoid busy loops (read returns no data) */
2529 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2532 static void blurayOnStreamSelectedEvent(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2534 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2537 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2540 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2541 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2542 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2543 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2548 if (i_type
== BD_EVENT_PG_TEXTST_STREAM
&& !p_sys
->b_spu_enable
)
2549 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
, (int)i_type
, i_pid
);
2551 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
, (int)i_type
, i_pid
);
2555 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2557 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2559 blurayRestartParser(p_demux
, true);
2561 /* read title info and init some values */
2563 p_sys
->cur_title
= bd_get_current_title(p_sys
->bluray
);
2564 p_sys
->cur_seekpoint
= 0;
2565 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2567 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2569 blurayUpdateTitleInfo(p_sys
->pp_title
[p_sys
->cur_title
], p_title_info
);
2571 p_sys
->updates
|= INPUT_UPDATE_TITLE_LIST
;
2573 setTitleInfo(p_sys
, p_title_info
);
2575 blurayResetStillImage(p_demux
);
2578 static void blurayUpdateCurrentClip(demux_t
*p_demux
, uint32_t clip
)
2580 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2582 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2584 p_sys
->p_clip_info
= NULL
;
2586 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2588 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2590 /* Let's assume a single video track for now.
2591 * This may brake later, but it's enough for now.
2593 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2596 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2598 blurayResetStillImage(p_demux
);
2601 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
)
2603 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2606 case BD_EVENT_TITLE
:
2607 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2608 p_sys
->cur_title
= p_sys
->i_title
- 1;
2610 p_sys
->cur_title
= e
->param
;
2611 /* this is feature title, we don't know yet which playlist it will play (if any) */
2612 setTitleInfo(p_sys
, NULL
);
2613 /* reset title infos here ? */
2614 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2615 /* might be BD-J title with no video */
2617 case BD_EVENT_PLAYLIST
:
2618 /* Start of playlist playback (?????.mpls) */
2619 blurayUpdatePlaylist(p_demux
, e
->param
);
2620 if (p_sys
->b_pl_playing
) {
2621 /* previous playlist was stopped in middle. flush to avoid delay */
2622 msg_Info(p_demux
, "Stopping playlist playback");
2623 blurayRestartParser(p_demux
, false);
2624 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2626 p_sys
->b_pl_playing
= true;
2628 case BD_EVENT_PLAYITEM
:
2629 notifyDiscontinuityToParser(p_sys
);
2630 blurayUpdateCurrentClip(p_demux
, e
->param
);
2632 case BD_EVENT_CHAPTER
:
2633 if (e
->param
&& e
->param
< 0xffff)
2634 p_sys
->cur_seekpoint
= e
->param
- 1;
2636 p_sys
->cur_seekpoint
= 0;
2637 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2639 case BD_EVENT_PLAYMARK
:
2640 case BD_EVENT_ANGLE
:
2642 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2643 case BD_EVENT_UO_MASK_CHANGED
:
2644 /* This event could be used to grey out unselectable items in title menu */
2648 p_sys
->b_menu_open
= e
->param
;
2650 case BD_EVENT_POPUP
:
2651 p_sys
->b_popup_available
= e
->param
;
2652 /* TODO: show / hide pop-up menu button in gui ? */
2658 case BD_EVENT_ERROR
:
2659 /* fatal error (with menus) */
2660 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2661 "Playback with BluRay menus failed");
2662 p_sys
->b_fatal_error
= true;
2664 case BD_EVENT_ENCRYPTED
:
2665 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2666 "This disc seems to be encrypted");
2667 p_sys
->b_fatal_error
= true;
2669 case BD_EVENT_READ_ERROR
:
2670 msg_Err(p_demux
, "bluray: read error\n");
2674 * stream selection events
2676 case BD_EVENT_PG_TEXTST
:
2677 p_sys
->b_spu_enable
= e
->param
;
2679 case BD_EVENT_AUDIO_STREAM
:
2680 case BD_EVENT_PG_TEXTST_STREAM
:
2681 blurayOnStreamSelectedEvent(p_demux
, e
->event
, e
->param
);
2683 case BD_EVENT_IG_STREAM
:
2684 case BD_EVENT_SECONDARY_AUDIO
:
2685 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2686 case BD_EVENT_SECONDARY_VIDEO
:
2687 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2688 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2692 * playback control events
2694 case BD_EVENT_STILL_TIME
:
2695 blurayStillImage(p_demux
, e
->param
);
2697 case BD_EVENT_DISCONTINUITY
:
2698 /* reset demuxer (partially decoded PES packets must be dropped) */
2699 blurayRestartParser(p_demux
, false);
2700 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2702 case BD_EVENT_END_OF_TITLE
:
2703 p_sys
->b_pl_playing
= false;
2706 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2707 /* avoid busy loop (bd_read() returns no data) */
2708 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2712 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2717 static bool blurayIsBdjTitle(demux_t
*p_demux
)
2719 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2720 unsigned int i_title
= p_sys
->cur_title
;
2721 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2723 if (di
&& di
->titles
) {
2724 if ((i_title
<= di
->num_titles
&& di
->titles
[i_title
] && di
->titles
[i_title
]->bdj
) ||
2725 (i_title
== p_sys
->i_title
- 1 && di
->first_play
&& di
->first_play
->bdj
)) {
2733 static void blurayHandleOverlays(demux_t
*p_demux
, int nread
)
2735 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2737 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2739 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
2740 bluray_overlay_t
*ov
= p_sys
->p_overlays
[i
];
2744 vlc_mutex_lock(&ov
->lock
);
2745 bool display
= ov
->status
== ToDisplay
;
2746 vlc_mutex_unlock(&ov
->lock
);
2748 /* NOTE: we might want to enable background video always when there's no video stream playing.
2749 Now, with some discs, there are perioids (even seconds) during which the video window
2750 disappears and just playlist is shown.
2751 (sometimes BD-J runs slowly ...)
2753 if (!p_sys
->p_video_es
&& p_sys
->b_menu
&&
2754 !p_sys
->p_pl_info
&& nread
== 0 &&
2755 blurayIsBdjTitle(p_demux
)) {
2757 /* Looks like there's no video stream playing.
2758 Emit blank frame so that BD-J overlay can be drawn. */
2759 p_sys
->p_video_es
= blurayCreateBackgroundUnlocked(p_demux
);
2762 if (p_sys
->p_video_es
!= NULL
) {
2763 bluraySendOverlayToVout(p_demux
, ov
);
2768 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2771 #define BD_TS_PACKET_SIZE (192)
2772 #define NB_TS_PACKETS (200)
2773 #define BD_READ_SIZE (NB_TS_PACKETS * BD_TS_PACKET_SIZE)
2775 static int blurayDemux(demux_t
*p_demux
)
2777 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2780 block_t
*p_block
= block_Alloc(BD_READ_SIZE
);
2782 return VLC_DEMUXER_EGENERIC
;
2786 if (p_sys
->b_menu
== false) {
2787 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
);
2788 while (bd_get_event(p_sys
->bluray
, &e
))
2789 blurayHandleEvent(p_demux
, &e
);
2791 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
, &e
);
2792 while (e
.event
!= BD_EVENT_NONE
) {
2793 blurayHandleEvent(p_demux
, &e
);
2794 bd_get_event(p_sys
->bluray
, &e
);
2798 blurayHandleOverlays(p_demux
, nread
);
2801 block_Release(p_block
);
2802 if (p_sys
->b_fatal_error
|| nread
< 0) {
2803 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
2804 return VLC_DEMUXER_EGENERIC
;
2806 if (!p_sys
->b_menu
) {
2807 return VLC_DEMUXER_EOF
;
2809 return VLC_DEMUXER_SUCCESS
;
2812 p_block
->i_buffer
= nread
;
2814 stopBackground(p_demux
);
2816 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2818 p_sys
->b_flushed
= false;
2820 return VLC_DEMUXER_SUCCESS
;