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 *****************************************************************************/
30 #if defined (HAVE_MNTENT_H) && defined(HAVE_SYS_STAT_H)
33 #include <fcntl.h> /* O_* */
34 #include <unistd.h> /* close() */
38 # include <sys/param.h>
39 # include <sys/ucred.h>
40 # include <sys/mount.h>
43 #include <vlc_common.h>
44 #include <vlc_plugin.h>
45 #include <vlc_demux.h> /* demux_t */
46 #include <vlc_input.h> /* Seekpoints, chapters */
47 #include <vlc_atomic.h>
48 #include <vlc_dialog.h> /* BD+/AACS warnings */
49 #include <vlc_vout.h> /* vout_PutSubpicture / subpicture_t */
50 #include <vlc_url.h> /* vlc_path2uri */
51 #include <vlc_iso_lang.h>
54 /* FIXME we should find a better way than including that */
55 #include "../../src/text/iso-639_def.h"
58 #include <libbluray/bluray.h>
59 #include <libbluray/bluray-version.h>
60 #include <libbluray/keys.h>
61 #include <libbluray/meta_data.h>
62 #include <libbluray/overlay.h>
64 /*****************************************************************************
66 *****************************************************************************/
68 #define BD_MENU_TEXT N_("Blu-ray menus")
69 #define BD_MENU_LONGTEXT N_("Use Blu-ray menus. If disabled, "\
70 "the movie will start directly")
71 #define BD_REGION_TEXT N_("Region code")
72 #define BD_REGION_LONGTEXT N_("Blu-Ray player region code. "\
73 "Some discs can be played only with a correct region code.")
75 static const char *const ppsz_region_code
[] = {
77 static const char *const ppsz_region_code_text
[] = {
78 "Region A", "Region B", "Region C" };
80 #define REGION_DEFAULT 1 /* Index to region list. Actual region code is (1<<REGION_DEFAULT) */
81 #define LANGUAGE_DEFAULT ("eng")
83 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,0)
88 static int blurayOpen (vlc_object_t
*);
89 static void blurayClose(vlc_object_t
*);
92 set_shortname(N_("Blu-ray"))
93 set_description(N_("Blu-ray Disc support (libbluray)"))
95 set_category(CAT_INPUT
)
96 set_subcategory(SUBCAT_INPUT_ACCESS
)
97 set_capability("access_demux", 200)
98 add_bool("bluray-menu", true, BD_MENU_TEXT
, BD_MENU_LONGTEXT
, false)
99 add_string("bluray-region", ppsz_region_code
[REGION_DEFAULT
], BD_REGION_TEXT
, BD_REGION_LONGTEXT
, false)
100 change_string_list(ppsz_region_code
, ppsz_region_code_text
)
102 add_shortcut("bluray", "file")
104 set_callbacks(blurayOpen
, blurayClose
)
109 set_description( "BluRay demuxer" )
110 set_category( CAT_INPUT
)
111 set_subcategory( SUBCAT_INPUT_DEMUX
)
112 set_capability( "demux", 5 )
113 set_callbacks( blurayOpen
, blurayClose
)
118 /* libbluray's overlay.h defines 2 types of overlay (bd_overlay_plane_e). */
119 #define MAX_OVERLAY 2
121 typedef enum OverlayStatus
{
123 ToDisplay
, //Used to mark the overlay to be displayed the first time.
125 Outdated
//used to update the overlay after it has been sent to the vout
128 typedef struct bluray_overlay_t
132 OverlayStatus status
;
133 subpicture_region_t
*p_regions
;
136 /* pointer to last subpicture updater.
137 * used to disconnect this overlay from vout when:
138 * - the overlay is closed
139 * - vout is changed and this overlay is sent to the new vout
141 struct subpicture_updater_sys_t
*p_updater
;
149 unsigned int i_title
;
150 unsigned int i_longest_title
;
151 input_title_t
**pp_title
;
153 vlc_mutex_t pl_info_lock
;
154 BLURAY_TITLE_INFO
*p_pl_info
;
155 const BLURAY_CLIP_INFO
*p_clip_info
;
159 input_attachment_t
**attachments
;
162 /* Meta information */
163 const META_DL
*p_meta
;
166 bluray_overlay_t
*p_overlays
[MAX_OVERLAY
];
170 bool b_popup_available
;
171 mtime_t i_still_end_time
;
173 vlc_mutex_t bdj_overlay_lock
; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
176 vout_thread_t
*p_vout
;
178 es_out_id_t
*p_dummy_video
;
183 int i_audio_stream_idx
; /* Selected audio stream. -1 if default */
184 int i_spu_stream_idx
; /* Selected subtitle stream. -1 if default */
185 bool b_spu_enable
; /* enabled / disabled */
187 vlc_demux_chained_t
*p_parser
;
189 bool b_pl_playing
; /* true when playing playlist */
192 vlc_mutex_t read_block_lock
;
194 /* Used to store bluray disc path */
198 struct subpicture_updater_sys_t
200 vlc_mutex_t lock
; // protect p_overlay pointer and ref_cnt
201 bluray_overlay_t
*p_overlay
; // NULL if overlay has been closed
202 int ref_cnt
; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
206 * cut the connection between vout and overlay.
207 * - called when vout is closed or overlay is closed.
208 * - frees subpicture_updater_sys_t when both sides have been closed.
210 static void unref_subpicture_updater(subpicture_updater_sys_t
*p_sys
)
212 vlc_mutex_lock(&p_sys
->lock
);
213 int refs
= --p_sys
->ref_cnt
;
214 p_sys
->p_overlay
= NULL
;
215 vlc_mutex_unlock(&p_sys
->lock
);
218 vlc_mutex_destroy(&p_sys
->lock
);
224 * FIXME: partiallyy duplicated from src/input/es_out.c
226 static const char *DemuxGetLanguageCode( demux_t
*p_demux
, const char *psz_var
)
228 const iso639_lang_t
*pl
;
232 psz_lang
= var_CreateGetString( p_demux
, psz_var
);
234 return LANGUAGE_DEFAULT
;
236 /* XXX: we will use only the first value
237 * (and ignore other ones in case of a list) */
238 if( ( p
= strchr( psz_lang
, ',' ) ) )
241 for( pl
= p_languages
; pl
->psz_eng_name
!= NULL
; pl
++ )
243 if( *psz_lang
== '\0' )
245 if( !strcasecmp( pl
->psz_eng_name
, psz_lang
) ||
246 !strcasecmp( pl
->psz_iso639_1
, psz_lang
) ||
247 !strcasecmp( pl
->psz_iso639_2T
, psz_lang
) ||
248 !strcasecmp( pl
->psz_iso639_2B
, psz_lang
) )
254 if( pl
->psz_eng_name
!= NULL
)
255 return pl
->psz_iso639_2T
;
257 return LANGUAGE_DEFAULT
;
260 /*****************************************************************************
262 *****************************************************************************/
263 static es_out_t
*esOutNew(demux_t
*p_demux
);
265 static int blurayControl(demux_t
*, int, va_list);
266 static int blurayDemux(demux_t
*);
268 static void blurayInitTitles(demux_t
*p_demux
, int menu_titles
);
269 static int bluraySetTitle(demux_t
*p_demux
, int i_title
);
271 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
* const overlay
);
272 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
* const overlay
);
274 static int onMouseEvent(vlc_object_t
*p_vout
, const char *psz_var
,
275 vlc_value_t old
, vlc_value_t val
, void *p_data
);
276 static int onIntfEvent(vlc_object_t
*, char const *,
277 vlc_value_t
, vlc_value_t
, void *);
279 static void blurayResetParser(demux_t
*p_demux
);
280 static void notifyDiscontinuity( demux_sys_t
*p_sys
);
282 #define FROM_TICKS(a) ((a)*CLOCK_FREQ / INT64_C(90000))
283 #define TO_TICKS(a) ((a)*INT64_C(90000)/CLOCK_FREQ)
284 #define CUR_LENGTH p_sys->pp_title[p_demux->info.i_title]->i_length
287 static void FindMountPoint(char **file
)
289 char *device
= *file
;
290 #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H)
291 /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
292 * we look up the real device */
293 char *bd_device
= realpath(device
, NULL
);
294 if (bd_device
== NULL
)
298 if (lstat (bd_device
, &st
) == 0 && S_ISBLK (st
.st_mode
)) {
299 FILE *mtab
= setmntent ("/proc/self/mounts", "r");
300 struct mntent
*m
, mbuf
;
303 while ((m
= getmntent_r (mtab
, &mbuf
, buf
, sizeof(buf
))) != NULL
) {
304 if (!strcmp (m
->mnt_fsname
, bd_device
)) {
306 *file
= strdup(m
->mnt_dir
);
314 #elif defined(__APPLE__)
316 if (!stat (device
, &st
) && S_ISBLK (st
.st_mode
)) {
317 int fs_count
= getfsstat (NULL
, 0, MNT_NOWAIT
);
319 struct statfs mbuf
[128];
320 getfsstat (mbuf
, fs_count
* sizeof(mbuf
[0]), MNT_NOWAIT
);
321 for (int i
= 0; i
< fs_count
; ++i
)
322 if (!strcmp (mbuf
[i
].f_mntfromname
, device
)) {
324 *file
= strdup(mbuf
[i
].f_mntonname
);
330 # warning Disc device to mount point not implemented
331 VLC_UNUSED( device
);
335 static void blurayReleaseVout(demux_t
*p_demux
)
337 demux_sys_t
*p_sys
= p_demux
->p_sys
;
339 if (p_sys
->p_vout
!= NULL
) {
340 var_DelCallback(p_sys
->p_vout
, "mouse-moved", onMouseEvent
, p_demux
);
341 var_DelCallback(p_sys
->p_vout
, "mouse-clicked", onMouseEvent
, p_demux
);
343 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
344 bluray_overlay_t
*p_ov
= p_sys
->p_overlays
[i
];
346 vlc_mutex_lock(&p_ov
->lock
);
347 if (p_ov
->i_channel
!= -1) {
348 msg_Err(p_demux
, "blurayReleaseVout: subpicture channel exists\n");
349 vout_FlushSubpictureChannel(p_sys
->p_vout
, p_ov
->i_channel
);
351 p_ov
->i_channel
= -1;
352 p_ov
->status
= ToDisplay
;
353 vlc_mutex_unlock(&p_ov
->lock
);
355 if (p_ov
->p_updater
) {
356 unref_subpicture_updater(p_ov
->p_updater
);
357 p_ov
->p_updater
= NULL
;
362 vlc_object_release(p_sys
->p_vout
);
363 p_sys
->p_vout
= NULL
;
367 /*****************************************************************************
368 * BD-J background video
369 *****************************************************************************/
371 static void startBackground(demux_t
*p_demux
)
373 demux_sys_t
*p_sys
= p_demux
->p_sys
;
375 if (p_sys
->p_dummy_video
) {
379 msg_Info(p_demux
, "Start background");
383 es_format_Init( &fmt
, VIDEO_ES
, VLC_CODEC_I420
);
384 video_format_Setup( &fmt
.video
, VLC_CODEC_I420
,
385 1920, 1080, 1920, 1080, 1, 1);
386 fmt
.i_priority
= ES_PRIORITY_SELECTABLE_MIN
;
387 fmt
.i_id
= 4115; /* 4113 = main video. 4114 = MVC. 4115 = unused. */
390 p_sys
->p_dummy_video
= es_out_Add(p_demux
->out
, &fmt
);
392 if (!p_sys
->p_dummy_video
) {
393 msg_Err(p_demux
, "Error adding background ES");
397 block_t
*p_block
= block_Alloc(fmt
.video
.i_width
* fmt
.video
.i_height
*
398 fmt
.video
.i_bits_per_pixel
/ 8);
400 msg_Err(p_demux
, "Error allocating block for background video");
404 // XXX TODO: what would be correct timestamp ???
405 p_block
->i_dts
= p_block
->i_pts
= mdate() + CLOCK_FREQ
/25;
407 uint8_t *p
= p_block
->p_buffer
;
408 memset(p
, 0, fmt
.video
.i_width
* fmt
.video
.i_height
);
409 p
+= fmt
.video
.i_width
* fmt
.video
.i_height
;
410 memset(p
, 0x80, fmt
.video
.i_width
* fmt
.video
.i_height
/ 2);
412 es_out_Send(p_demux
->out
, p_sys
->p_dummy_video
, p_block
);
415 es_format_Clean(&fmt
);
418 static void stopBackground(demux_t
*p_demux
)
420 demux_sys_t
*p_sys
= p_demux
->p_sys
;
422 if (!p_sys
->p_dummy_video
) {
426 msg_Info(p_demux
, "Stop background");
428 es_out_Del(p_demux
->out
, p_sys
->p_dummy_video
);
429 p_sys
->p_dummy_video
= NULL
;
432 /*****************************************************************************
433 * cache current playlist (title) information
434 *****************************************************************************/
436 static void setTitleInfo(demux_sys_t
*p_sys
, BLURAY_TITLE_INFO
*info
)
438 vlc_mutex_lock(&p_sys
->pl_info_lock
);
440 if (p_sys
->p_pl_info
) {
441 bd_free_title_info(p_sys
->p_pl_info
);
443 p_sys
->p_pl_info
= info
;
444 p_sys
->p_clip_info
= NULL
;
446 if (p_sys
->p_pl_info
&& p_sys
->p_pl_info
->clip_count
) {
447 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[0];
450 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
453 /*****************************************************************************
454 * create input attachment for thumbnail
455 *****************************************************************************/
457 static void attachThumbnail(demux_t
*p_demux
)
459 demux_sys_t
*p_sys
= p_demux
->p_sys
;
464 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,9,0)
465 if (p_sys
->p_meta
->thumb_count
> 0 && p_sys
->p_meta
->thumbnails
) {
468 if (bd_get_meta_file(p_sys
->bluray
, p_sys
->p_meta
->thumbnails
[0].path
, &data
, &size
) > 0) {
470 input_attachment_t
*p_attachment
;
472 snprintf(psz_name
, sizeof(psz_name
), "picture%d_%s", p_sys
->i_attachments
, p_sys
->p_meta
->thumbnails
[0].path
);
474 p_attachment
= vlc_input_attachment_New(psz_name
, NULL
, "Album art", data
, size
);
476 p_sys
->i_cover_idx
= p_sys
->i_attachments
;
477 TAB_APPEND(p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
485 /*****************************************************************************
487 *****************************************************************************/
489 static int probeStream(demux_t
*p_demux
)
491 /* input must be seekable */
492 bool b_canseek
= false;
493 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_canseek
);
498 /* first sector(s) should be filled with zeros */
500 const uint8_t *p_peek
;
501 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 2048 );
502 if( i_peek
!= 2048 ) {
506 if (p_peek
[ --i_peek
]) {
515 static int blurayReadBlock(void *object
, void *buf
, int lba
, int num_blocks
)
517 demux_t
*p_demux
= (demux_t
*)object
;
518 demux_sys_t
*p_sys
= p_demux
->p_sys
;
521 assert(p_demux
->s
!= NULL
);
523 vlc_mutex_lock(&p_sys
->read_block_lock
);
525 if (vlc_stream_Seek( p_demux
->s
, lba
* INT64_C(2048) ) == VLC_SUCCESS
) {
526 size_t req
= (size_t)2048 * num_blocks
;
529 got
= vlc_stream_Read( p_demux
->s
, buf
, req
);
531 msg_Err(p_demux
, "read from lba %d failed", lba
);
536 msg_Err(p_demux
, "seek to lba %d failed", lba
);
539 vlc_mutex_unlock(&p_sys
->read_block_lock
);
545 /*****************************************************************************
546 * probing of local files
547 *****************************************************************************/
549 /* Descriptor Tag (ECMA 167, 3/7.2) */
550 static int decode_descriptor_tag(const uint8_t *buf
)
553 uint8_t checksum
= 0;
556 id
= buf
[0] | (buf
[1] << 8);
558 /* calculate tag checksum */
559 for (i
= 0; i
< 4; i
++) {
560 checksum
= (uint8_t)(checksum
+ buf
[i
]);
562 for (i
= 5; i
< 16; i
++) {
563 checksum
= (uint8_t)(checksum
+ buf
[i
]);
566 if (checksum
!= buf
[4]) {
573 static int probeFile(const char *psz_name
)
575 struct stat stat_info
;
578 int ret
= VLC_EGENERIC
;
581 fd
= vlc_open(psz_name
, O_RDONLY
| O_NONBLOCK
);
586 if (fstat(fd
, &stat_info
) == -1) {
589 if (!S_ISREG(stat_info
.st_mode
) && !S_ISBLK(stat_info
.st_mode
)) {
593 /* first sector should be filled with zeros */
594 if (read(fd
, peek
, sizeof(peek
)) != sizeof(peek
)) {
597 for (i
= 0; i
< sizeof(peek
); i
++) {
603 /* Check AVDP tag checksum */
604 if (lseek(fd
, 256 * 2048, SEEK_SET
) == -1 ||
605 read(fd
, peek
, 16) != 16 ||
606 decode_descriptor_tag(peek
) != 2) {
617 /*****************************************************************************
618 * blurayOpen: module init function
619 *****************************************************************************/
620 static int blurayOpen(vlc_object_t
*object
)
622 demux_t
*p_demux
= (demux_t
*)object
;
625 uint64_t i_init_pos
= 0;
627 const char *error_msg
= NULL
;
628 #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
630 forced
= !strcasecmp(p_demux
->psz_access
, "bluray");
633 if (!strcasecmp(p_demux
->psz_access
, "file")) {
634 /* use access_demux for local files */
638 if (probeStream(p_demux
) != VLC_SUCCESS
) {
642 } else if (!forced
) {
643 if (!p_demux
->psz_file
) {
647 if (probeFile(p_demux
->psz_file
) != VLC_SUCCESS
) {
653 p_demux
->p_sys
= p_sys
= calloc(1, sizeof(*p_sys
));
654 if (unlikely(!p_sys
))
657 p_sys
->i_audio_stream_idx
= -1;
658 p_sys
->i_spu_stream_idx
= -1;
659 p_sys
->i_video_stream
= -1;
660 p_sys
->i_still_end_time
= 0;
662 /* init demux info fields */
663 p_demux
->info
.i_update
= 0;
664 p_demux
->info
.i_title
= 0;
665 p_demux
->info
.i_seekpoint
= 0;
667 TAB_INIT(p_sys
->i_title
, p_sys
->pp_title
);
668 TAB_INIT(p_sys
->i_attachments
, p_sys
->attachments
);
670 vlc_mutex_init(&p_sys
->pl_info_lock
);
671 vlc_mutex_init(&p_sys
->bdj_overlay_lock
);
672 vlc_mutex_init(&p_sys
->read_block_lock
); /* used during bd_open_stream() */
674 var_AddCallback( p_demux
->p_input
, "intf-event", onIntfEvent
, p_demux
);
679 i_init_pos
= vlc_stream_Tell(p_demux
->s
);
681 p_sys
->bluray
= bd_init();
682 if (!bd_open_stream(p_sys
->bluray
, p_demux
, blurayReadBlock
)) {
683 bd_close(p_sys
->bluray
);
684 p_sys
->bluray
= NULL
;
689 if (!p_demux
->psz_file
) {
690 /* no path provided (bluray://). use default DVD device. */
691 p_sys
->psz_bd_path
= var_InheritString(object
, "dvd");
693 /* store current bd path */
694 p_sys
->psz_bd_path
= strdup(p_demux
->psz_file
);
697 /* If we're passed a block device, try to convert it to the mount point. */
698 FindMountPoint(&p_sys
->psz_bd_path
);
700 p_sys
->bluray
= bd_open(p_sys
->psz_bd_path
, NULL
);
702 if (!p_sys
->bluray
) {
706 /* Warning the user about AACS/BD+ */
707 const BLURAY_DISC_INFO
*disc_info
= bd_get_disc_info(p_sys
->bluray
);
709 /* Is it a bluray? */
710 if (!disc_info
->bluray_detected
) {
712 BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
717 msg_Info(p_demux
, "First play: %i, Top menu: %i\n"
718 "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
719 disc_info
->first_play_supported
, disc_info
->top_menu_supported
,
720 disc_info
->num_hdmv_titles
, disc_info
->num_bdj_titles
,
721 disc_info
->num_unsupported_titles
);
724 if (disc_info
->aacs_detected
) {
725 msg_Dbg(p_demux
, "Disc is using AACS");
726 if (!disc_info
->libaacs_detected
)
727 BLURAY_ERROR(_("This Blu-ray Disc needs a library for AACS decoding"
728 ", and your system does not have it."));
729 if (!disc_info
->aacs_handled
) {
730 if (disc_info
->aacs_error_code
) {
731 switch (disc_info
->aacs_error_code
) {
732 case BD_AACS_CORRUPTED_DISC
:
733 BLURAY_ERROR(_("Blu-ray Disc is corrupted."));
734 case BD_AACS_NO_CONFIG
:
735 BLURAY_ERROR(_("Missing AACS configuration file!"));
737 BLURAY_ERROR(_("No valid processing key found in AACS config file."));
738 case BD_AACS_NO_CERT
:
739 BLURAY_ERROR(_("No valid host certificate found in AACS config file."));
740 case BD_AACS_CERT_REVOKED
:
741 BLURAY_ERROR(_("AACS Host certificate revoked."));
742 case BD_AACS_MMC_FAILED
:
743 BLURAY_ERROR(_("AACS MMC failed."));
750 if (disc_info
->bdplus_detected
) {
751 msg_Dbg(p_demux
, "Disc is using BD+");
752 if (!disc_info
->libbdplus_detected
)
753 BLURAY_ERROR(_("This Blu-ray Disc needs a library for BD+ decoding"
754 ", and your system does not have it."));
755 if (!disc_info
->bdplus_handled
)
756 BLURAY_ERROR(_("Your system BD+ decoding library does not work. "
757 "Missing configuration?"));
760 /* set player region code */
761 char *psz_region
= var_InheritString(p_demux
, "bluray-region");
762 unsigned int region
= psz_region
? (psz_region
[0] - 'A') : REGION_DEFAULT
;
764 bd_set_player_setting(p_sys
->bluray
, BLURAY_PLAYER_SETTING_REGION_CODE
, 1<<region
);
766 /* set preferred languages */
767 const char *psz_code
= DemuxGetLanguageCode( p_demux
, "audio-language" );
768 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
, psz_code
);
769 psz_code
= DemuxGetLanguageCode( p_demux
, "sub-language" );
770 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
, psz_code
);
771 psz_code
= DemuxGetLanguageCode( p_demux
, "menu-language" );
772 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_MENU_LANG
, psz_code
);
774 /* Get disc metadata */
775 p_sys
->p_meta
= bd_get_meta(p_sys
->bluray
);
777 msg_Warn(p_demux
, "Failed to get meta info.");
779 p_sys
->i_cover_idx
= -1;
780 attachThumbnail(p_demux
);
782 p_sys
->b_menu
= var_InheritBool(p_demux
, "bluray-menu");
784 /* Check BD-J capability */
785 if (p_sys
->b_menu
&& disc_info
->bdj_detected
&& !disc_info
->bdj_handled
) {
786 msg_Err(p_demux
, "BD-J menus not supported. Playing without menus. "
787 "BD-J support: %d, JVM found: %d, JVM usable: %d",
788 disc_info
->bdj_supported
, disc_info
->libjvm_detected
, disc_info
->bdj_handled
);
789 vlc_dialog_display_error(p_demux
, _("Java required"),
790 _("This Blu-ray disc needs Java for menus.%s\nDisc is played without menus."),
791 !disc_info
->libjvm_detected
? _(" Java was not found from your system.") : "");
792 p_sys
->b_menu
= false;
795 /* Get titles and chapters */
796 blurayInitTitles(p_demux
, disc_info
->num_hdmv_titles
+ disc_info
->num_bdj_titles
+ 1/*Top Menu*/ + 1/*First Play*/);
799 * Initialize the event queue, so we can receive events in blurayDemux(Menu).
801 bd_get_event(p_sys
->bluray
, NULL
);
803 /* Registering overlay event handler */
804 bd_register_overlay_proc(p_sys
->bluray
, p_demux
, blurayOverlayProc
);
805 if (unlikely(!p_demux
->p_input
)) {
806 msg_Err(p_demux
, "Could not get parent input");
812 /* Register ARGB overlay handler for BD-J */
813 if (disc_info
->num_bdj_titles
)
814 bd_register_argb_overlay_proc(p_sys
->bluray
, p_demux
, blurayArgbOverlayProc
, NULL
);
816 /* libbluray will start playback from "First-Title" title */
817 if (bd_play(p_sys
->bluray
) == 0)
818 BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support."));
821 /* set start title number */
822 if (bluraySetTitle(p_demux
, p_sys
->i_longest_title
) != VLC_SUCCESS
) {
823 msg_Err(p_demux
, "Could not set the title %d", p_sys
->i_longest_title
);
828 vlc_array_init(&p_sys
->es
);
829 p_sys
->p_out
= esOutNew(p_demux
);
830 if (unlikely(p_sys
->p_out
== NULL
))
833 blurayResetParser(p_demux
);
834 if (!p_sys
->p_parser
) {
835 msg_Err(p_demux
, "Failed to create TS demuxer");
839 p_demux
->pf_control
= blurayControl
;
840 p_demux
->pf_demux
= blurayDemux
;
846 vlc_dialog_display_error(p_demux
, _("Blu-ray error"), "%s", error_msg
);
849 if (p_demux
->s
!= NULL
) {
850 /* restore stream position */
851 if (vlc_stream_Seek(p_demux
->s
, i_init_pos
) != VLC_SUCCESS
) {
852 msg_Err(p_demux
, "Failed to seek back to stream start");
862 /*****************************************************************************
863 * blurayClose: module destroy function
864 *****************************************************************************/
865 static void blurayClose(vlc_object_t
*object
)
867 demux_t
*p_demux
= (demux_t
*)object
;
868 demux_sys_t
*p_sys
= p_demux
->p_sys
;
870 var_DelCallback( p_demux
->p_input
, "intf-event", onIntfEvent
, p_demux
);
872 setTitleInfo(p_sys
, NULL
);
875 * Close libbluray first.
876 * This will close all the overlays before we release p_vout
877 * bd_close(NULL) can crash
880 bd_close(p_sys
->bluray
);
883 blurayReleaseVout(p_demux
);
886 vlc_demux_chained_Delete(p_sys
->p_parser
);
887 if (p_sys
->p_out
!= NULL
)
888 es_out_Delete(p_sys
->p_out
);
889 assert(vlc_array_count(&p_sys
->es
) == 0);
890 vlc_array_clear(&p_sys
->es
);
893 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
894 vlc_input_title_Delete(p_sys
->pp_title
[i
]);
895 TAB_CLEAN(p_sys
->i_title
, p_sys
->pp_title
);
897 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
898 vlc_input_attachment_Delete(p_sys
->attachments
[i
]);
899 TAB_CLEAN(p_sys
->i_attachments
, p_sys
->attachments
);
901 vlc_mutex_destroy(&p_sys
->pl_info_lock
);
902 vlc_mutex_destroy(&p_sys
->bdj_overlay_lock
);
903 vlc_mutex_destroy(&p_sys
->read_block_lock
);
905 free(p_sys
->psz_bd_path
);
909 /*****************************************************************************
910 * Elementary streams handling
911 *****************************************************************************/
913 struct es_out_sys_t
{
917 typedef struct fmt_es_pair
{
922 static int findEsPairIndex(demux_sys_t
*p_sys
, int i_id
)
924 for (size_t i
= 0; i
< vlc_array_count(&p_sys
->es
); ++i
)
925 if (((fmt_es_pair_t
*)vlc_array_item_at_index(&p_sys
->es
, i
))->i_id
== i_id
)
931 static int findEsPairIndexByEs(demux_sys_t
*p_sys
, es_out_id_t
*p_es
)
933 for (size_t i
= 0; i
< vlc_array_count(&p_sys
->es
); ++i
)
934 if (((fmt_es_pair_t
*)vlc_array_item_at_index(&p_sys
->es
, i
))->p_es
== p_es
)
940 static void setStreamLang(demux_sys_t
*p_sys
, es_format_t
*p_fmt
)
942 const BLURAY_STREAM_INFO
*p_streams
;
943 int i_stream_count
= 0;
945 vlc_mutex_lock(&p_sys
->pl_info_lock
);
947 if (p_sys
->p_clip_info
) {
948 if (p_fmt
->i_cat
== AUDIO_ES
) {
949 p_streams
= p_sys
->p_clip_info
->audio_streams
;
950 i_stream_count
= p_sys
->p_clip_info
->audio_stream_count
;
951 } else if (p_fmt
->i_cat
== SPU_ES
) {
952 p_streams
= p_sys
->p_clip_info
->pg_streams
;
953 i_stream_count
= p_sys
->p_clip_info
->pg_stream_count
;
957 for (int i
= 0; i
< i_stream_count
; i
++) {
958 if (p_fmt
->i_id
== p_streams
[i
].pid
) {
959 free(p_fmt
->psz_language
);
960 p_fmt
->psz_language
= strndup((const char *)p_streams
[i
].lang
, 3);
965 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
968 static int blurayEsPid(demux_sys_t
*p_sys
, int es_type
, int i_es_idx
)
972 vlc_mutex_lock(&p_sys
->pl_info_lock
);
974 if (p_sys
->p_clip_info
) {
975 if (es_type
== AUDIO_ES
) {
976 if (i_es_idx
>= 0 && i_es_idx
< p_sys
->p_clip_info
->audio_stream_count
) {
977 i_pid
= p_sys
->p_clip_info
->audio_streams
[i_es_idx
].pid
;
979 } else if (es_type
== SPU_ES
) {
980 if (i_es_idx
>= 0 && i_es_idx
< p_sys
->p_clip_info
->pg_stream_count
) {
981 i_pid
= p_sys
->p_clip_info
->pg_streams
[i_es_idx
].pid
;
986 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
991 static es_out_id_t
*esOutAdd(es_out_t
*p_out
, const es_format_t
*p_fmt
)
993 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
994 demux_sys_t
*p_sys
= p_demux
->p_sys
;
996 bool b_select
= false;
998 es_format_Copy(&fmt
, p_fmt
);
1000 switch (fmt
.i_cat
) {
1002 if (p_sys
->i_video_stream
!= -1 && p_sys
->i_video_stream
!= p_fmt
->i_id
)
1003 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1006 if (p_sys
->i_audio_stream_idx
!= -1) {
1007 if (blurayEsPid(p_sys
, AUDIO_ES
, p_sys
->i_audio_stream_idx
) == p_fmt
->i_id
)
1009 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1011 setStreamLang(p_sys
, &fmt
);
1014 if (p_sys
->i_spu_stream_idx
!= -1) {
1015 if (blurayEsPid(p_sys
, SPU_ES
, p_sys
->i_spu_stream_idx
) == p_fmt
->i_id
)
1017 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1019 setStreamLang(p_sys
, &fmt
);
1023 es_out_id_t
*p_es
= es_out_Add(p_demux
->out
, &fmt
);
1024 if (p_fmt
->i_id
>= 0) {
1025 /* Ensure we are not overriding anything */
1026 int idx
= findEsPairIndex(p_sys
, p_fmt
->i_id
);
1028 fmt_es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
1029 if (likely(p_pair
!= NULL
)) {
1030 p_pair
->i_id
= p_fmt
->i_id
;
1031 p_pair
->p_es
= p_es
;
1032 msg_Info(p_demux
, "Adding ES %d", p_fmt
->i_id
);
1033 vlc_array_append(&p_sys
->es
, p_pair
);
1036 if (fmt
.i_cat
== AUDIO_ES
) {
1037 var_SetInteger( p_demux
->p_input
, "audio-es", p_fmt
->i_id
);
1038 } else if (fmt
.i_cat
== SPU_ES
) {
1039 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? p_fmt
->i_id
: -1 );
1045 es_format_Clean(&fmt
);
1049 static int esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1051 return es_out_Send(p_out
->p_sys
->p_demux
->out
, p_es
, p_block
);
1054 static void esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1056 int idx
= findEsPairIndexByEs(p_out
->p_sys
->p_demux
->p_sys
, p_es
);
1058 free(vlc_array_item_at_index(&p_out
->p_sys
->p_demux
->p_sys
->es
, idx
));
1059 vlc_array_remove(&p_out
->p_sys
->p_demux
->p_sys
->es
, idx
);
1061 es_out_Del(p_out
->p_sys
->p_demux
->out
, p_es
);
1064 static int esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1066 return es_out_vaControl(p_out
->p_sys
->p_demux
->out
, i_query
, args
);
1069 static void esOutDestroy(es_out_t
*p_out
)
1071 for (size_t i
= 0; i
< vlc_array_count(&p_out
->p_sys
->p_demux
->p_sys
->es
); ++i
)
1072 free(vlc_array_item_at_index(&p_out
->p_sys
->p_demux
->p_sys
->es
, i
));
1073 vlc_array_clear(&p_out
->p_sys
->p_demux
->p_sys
->es
);
1078 static es_out_t
*esOutNew(demux_t
*p_demux
)
1080 assert(vlc_array_count(&p_demux
->p_sys
->es
) == 0);
1081 es_out_t
*p_out
= malloc(sizeof(*p_out
));
1082 if (unlikely(p_out
== NULL
))
1085 p_out
->pf_add
= esOutAdd
;
1086 p_out
->pf_control
= esOutControl
;
1087 p_out
->pf_del
= esOutDel
;
1088 p_out
->pf_destroy
= esOutDestroy
;
1089 p_out
->pf_send
= esOutSend
;
1091 p_out
->p_sys
= malloc(sizeof(*p_out
->p_sys
));
1092 if (unlikely(p_out
->p_sys
== NULL
)) {
1096 p_out
->p_sys
->p_demux
= p_demux
;
1100 /*****************************************************************************
1101 * subpicture_updater_t functions:
1102 *****************************************************************************/
1104 static bluray_overlay_t
*updater_lock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1106 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1107 vlc_mutex_lock(&p_upd_sys
->lock
);
1109 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1111 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1112 vlc_mutex_lock(&ov
->lock
);
1116 /* overlay has been closed */
1117 vlc_mutex_unlock(&p_upd_sys
->lock
);
1121 static void updater_unlock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1123 assert (p_upd_sys
->p_overlay
);
1125 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1126 vlc_mutex_unlock(&p_upd_sys
->lock
);
1129 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1130 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1131 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1134 VLC_UNUSED(b_fmt_src
);
1135 VLC_UNUSED(b_fmt_dst
);
1136 VLC_UNUSED(p_fmt_src
);
1137 VLC_UNUSED(p_fmt_dst
);
1140 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1141 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1147 int res
= p_overlay
->status
== Outdated
;
1149 updater_unlock_overlay(p_upd_sys
);
1154 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1155 const video_format_t
*p_fmt_src
,
1156 const video_format_t
*p_fmt_dst
,
1159 VLC_UNUSED(p_fmt_src
);
1160 VLC_UNUSED(p_fmt_dst
);
1162 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1163 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1170 * When this function is called, all p_subpic regions are gone.
1171 * We need to duplicate our regions (stored internaly) to this subpic.
1173 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1175 updater_unlock_overlay(p_upd_sys
);
1179 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1180 while (p_src
!= NULL
) {
1181 *p_dst
= subpicture_region_Copy(p_src
);
1184 p_dst
= &(*p_dst
)->p_next
;
1185 p_src
= p_src
->p_next
;
1188 (*p_dst
)->p_next
= NULL
;
1189 p_overlay
->status
= Displayed
;
1191 updater_unlock_overlay(p_upd_sys
);
1194 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1196 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1197 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1200 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1201 p_overlay
->status
= ToDisplay
;
1202 p_overlay
->i_channel
= -1;
1203 updater_unlock_overlay(p_upd_sys
);
1206 unref_subpicture_updater(p_upd_sys
);
1209 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1211 subpicture_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1212 if (unlikely(p_upd_sys
== NULL
)) {
1216 p_upd_sys
->p_overlay
= p_ov
;
1218 subpicture_updater_t updater
= {
1219 .pf_validate
= subpictureUpdaterValidate
,
1220 .pf_update
= subpictureUpdaterUpdate
,
1221 .pf_destroy
= subpictureUpdaterDestroy
,
1225 subpicture_t
*p_pic
= subpicture_New(&updater
);
1226 if (p_pic
== NULL
) {
1231 p_pic
->i_original_picture_width
= p_ov
->width
;
1232 p_pic
->i_original_picture_height
= p_ov
->height
;
1233 p_pic
->b_ephemer
= true;
1234 p_pic
->b_absolute
= true;
1236 vlc_mutex_init(&p_upd_sys
->lock
);
1237 p_upd_sys
->ref_cnt
= 2;
1239 p_ov
->p_updater
= p_upd_sys
;
1244 /*****************************************************************************
1245 * User input events:
1246 *****************************************************************************/
1247 static int onMouseEvent(vlc_object_t
*p_vout
, const char *psz_var
, vlc_value_t old
,
1248 vlc_value_t val
, void *p_data
)
1250 demux_t
*p_demux
= (demux_t
*)p_data
;
1251 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1255 if (psz_var
[6] == 'm') //Mouse moved
1256 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1257 else if (psz_var
[6] == 'c') {
1258 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1259 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1261 vlc_assert_unreachable();
1266 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1268 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1269 return VLC_EGENERIC
;
1274 /*****************************************************************************
1275 * libbluray overlay handling:
1276 *****************************************************************************/
1278 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1280 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1281 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1285 /* drop overlay from vout */
1286 if (ov
->p_updater
) {
1287 unref_subpicture_updater(ov
->p_updater
);
1289 /* no references to this overlay exist in vo anymore */
1290 if (p_sys
->p_vout
&& ov
->i_channel
!= -1) {
1291 vout_FlushSubpictureChannel(p_sys
->p_vout
, ov
->i_channel
);
1294 vlc_mutex_destroy(&ov
->lock
);
1295 subpicture_region_ChainDelete(ov
->p_regions
);
1298 p_sys
->p_overlays
[plane
] = NULL
;
1301 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1302 if (p_sys
->p_overlays
[i
])
1305 /* All overlays have been closed */
1306 blurayReleaseVout(p_demux
);
1310 * Mark the overlay as "ToDisplay" status.
1311 * This will not send the overlay to the vout instantly, as the vout
1312 * may not be acquired (not acquirable) yet.
1313 * If is has already been acquired, the overlay has already been sent to it,
1314 * therefore, we only flag the overlay as "Outdated"
1316 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1318 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1319 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1322 * If the overlay is already displayed, mark the picture as outdated.
1323 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1325 vlc_mutex_lock(&ov
->lock
);
1326 if (ov
->status
>= Displayed
&& p_sys
->p_vout
) {
1327 ov
->status
= Outdated
;
1328 vlc_mutex_unlock(&ov
->lock
);
1333 * Mark the overlay as available, but don't display it right now.
1334 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1335 * the overlay is computed
1337 ov
->status
= ToDisplay
;
1338 vlc_mutex_unlock(&ov
->lock
);
1341 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1343 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1345 assert(p_sys
->p_overlays
[plane
] == NULL
);
1347 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1348 if (unlikely(ov
== NULL
))
1352 ov
->height
= height
;
1355 vlc_mutex_init(&ov
->lock
);
1357 p_sys
->p_overlays
[plane
] = ov
;
1361 * Destroy every regions in the subpicture.
1362 * This is done in two steps:
1363 * - Wiping our private regions list
1364 * - Flagging the overlay as outdated, so the changes are replicated from
1365 * the subpicture_updater_t::pf_update
1366 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1368 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1370 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1371 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1373 vlc_mutex_lock(&ov
->lock
);
1375 subpicture_region_ChainDelete(ov
->p_regions
);
1376 ov
->p_regions
= NULL
;
1377 ov
->status
= Outdated
;
1379 vlc_mutex_unlock(&ov
->lock
);
1383 * This will draw to the overlay by adding a region to our region list
1384 * This will have to be copied to the subpicture used to render the overlay.
1386 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1388 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1391 * Compute a subpicture_region_t.
1392 * It will be copied and sent to the vout later.
1394 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1396 /* Find a region to update */
1397 subpicture_region_t
**pp_reg
= &p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1398 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1399 subpicture_region_t
*p_last
= NULL
;
1400 while (p_reg
!= NULL
) {
1402 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1403 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1405 pp_reg
= &p_reg
->p_next
;
1406 p_reg
= p_reg
->p_next
;
1412 *pp_reg
= p_reg
->p_next
;
1413 subpicture_region_Delete(p_reg
);
1415 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1419 /* If there is no region to update, create a new one. */
1422 video_format_Init(&fmt
, 0);
1423 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1425 p_reg
= subpicture_region_New(&fmt
);
1428 /* Append it to our list. */
1430 p_last
->p_next
= p_reg
;
1431 else /* If we don't have a last region, then our list empty */
1432 p_sys
->p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1435 /* Now we can update the region, regardless it's an update or an insert */
1436 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1437 for (int y
= 0; y
< ov
->h
; y
++)
1438 for (int x
= 0; x
< ov
->w
;) {
1439 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1440 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1446 p_reg
->fmt
.p_palette
->i_entries
= 256;
1447 for (int i
= 0; i
< 256; ++i
) {
1448 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1449 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1450 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1451 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1455 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1457 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1461 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1463 demux_t
*p_demux
= (demux_t
*)ptr
;
1464 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1467 msg_Info(p_demux
, "Closing overlays.");
1469 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1470 blurayCloseOverlay(p_demux
, i
);
1474 switch (overlay
->cmd
) {
1475 case BD_OVERLAY_INIT
:
1476 msg_Info(p_demux
, "Initializing overlay");
1477 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1478 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1479 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1481 case BD_OVERLAY_CLOSE
:
1482 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1483 blurayClearOverlay(p_demux
, overlay
->plane
);
1484 blurayCloseOverlay(p_demux
, overlay
->plane
);
1485 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1487 case BD_OVERLAY_CLEAR
:
1488 blurayClearOverlay(p_demux
, overlay
->plane
);
1490 case BD_OVERLAY_FLUSH
:
1491 blurayActivateOverlay(p_demux
, overlay
->plane
);
1493 case BD_OVERLAY_DRAW
:
1494 case BD_OVERLAY_WIPE
:
1495 blurayDrawOverlay(p_demux
, overlay
);
1498 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
1504 * ARGB overlay (BD-J)
1506 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1508 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1510 blurayInitOverlay(p_demux
, plane
, width
, height
);
1512 if (!p_sys
->p_overlays
[plane
]->p_regions
) {
1514 video_format_Init(&fmt
, 0);
1515 video_format_Setup(&fmt
, VLC_CODEC_RGBA
, width
, height
, width
, height
, 1, 1);
1517 p_sys
->p_overlays
[plane
]->p_regions
= subpicture_region_New(&fmt
);
1521 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
1523 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1525 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1527 /* Find a region to update */
1528 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1530 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1534 /* Now we can update the region */
1535 const uint32_t *src0
= ov
->argb
;
1536 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
1537 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
1540 for (int y
= 0; y
< ov
->h
; y
++) {
1541 // XXX: add support for this format ? Should be possible with OPENGL/VDPAU/...
1542 // - or add libbluray option to select the format ?
1543 for (int x
= 0; x
< ov
->w
; x
++) {
1544 dst0
[x
*4 ] = src0
[x
]>>16; /* R */
1545 dst0
[x
*4+1] = src0
[x
]>>8; /* G */
1546 dst0
[x
*4+2] = src0
[x
]; /* B */
1547 dst0
[x
*4+3] = src0
[x
]>>24; /* A */
1551 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
1554 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1556 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1560 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
1562 demux_t
*p_demux
= (demux_t
*)ptr
;
1563 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1565 switch (overlay
->cmd
) {
1566 case BD_ARGB_OVERLAY_INIT
:
1567 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1568 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1569 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1571 case BD_ARGB_OVERLAY_CLOSE
:
1572 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1573 blurayClearOverlay(p_demux
, overlay
->plane
);
1574 blurayCloseOverlay(p_demux
, overlay
->plane
);
1575 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1577 case BD_ARGB_OVERLAY_FLUSH
:
1578 blurayActivateOverlay(p_demux
, overlay
->plane
);
1580 case BD_ARGB_OVERLAY_DRAW
:
1581 blurayDrawArgbOverlay(p_demux
, overlay
);
1584 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
1589 static void bluraySendOverlayToVout(demux_t
*p_demux
, bluray_overlay_t
*p_ov
)
1591 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1593 assert(p_ov
!= NULL
);
1594 assert(p_ov
->i_channel
== -1);
1596 if (p_ov
->p_updater
) {
1597 unref_subpicture_updater(p_ov
->p_updater
);
1598 p_ov
->p_updater
= NULL
;
1601 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
1603 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
1607 p_pic
->i_start
= p_pic
->i_stop
= mdate();
1608 p_pic
->i_channel
= vout_RegisterSubpictureChannel(p_sys
->p_vout
);
1609 p_ov
->i_channel
= p_pic
->i_channel
;
1612 * After this point, the picture should not be accessed from the demux thread,
1613 * as it is held by the vout thread.
1614 * This must be done only once per subpicture, ie. only once between each
1615 * blurayInitOverlay & blurayCloseOverlay call.
1617 vout_PutSubpicture(p_sys
->p_vout
, p_pic
);
1620 * Mark the picture as Outdated, as it contains no region for now.
1621 * This will make the subpicture_updater_t call pf_update
1623 p_ov
->status
= Outdated
;
1626 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
1628 t
->i_length
= FROM_TICKS(title_info
->duration
);
1630 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
1631 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
1632 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
1634 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
1635 seekpoint_t
*s
= vlc_seekpoint_New();
1639 s
->i_time_offset
= FROM_TICKS(title_info
->chapters
[j
].start
);
1641 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
1645 static void blurayInitTitles(demux_t
*p_demux
, int menu_titles
)
1647 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1648 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
1650 /* get and set the titles */
1651 unsigned i_title
= menu_titles
;
1653 if (!p_sys
->b_menu
) {
1654 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
1655 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
1658 for (unsigned int i
= 0; i
< i_title
; i
++) {
1659 input_title_t
*t
= vlc_input_title_New();
1663 if (!p_sys
->b_menu
) {
1664 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
1665 blurayUpdateTitleInfo(t
, title_info
);
1666 bd_free_title_info(title_info
);
1668 } else if (i
== 0) {
1669 t
->psz_name
= strdup(_("Top Menu"));
1670 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
1671 } else if (i
== i_title
- 1) {
1672 t
->psz_name
= strdup(_("First Play"));
1673 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
1674 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1677 /* add possible title name from disc metadata */
1678 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
1679 if (di
->titles
[i
]->name
) {
1680 t
->psz_name
= strdup(di
->titles
[i
]->name
);
1682 if (di
->titles
[i
]->interactive
) {
1683 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1688 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
1692 static void blurayResetParser(demux_t
*p_demux
)
1695 * This is a hack and will have to be removed.
1696 * The parser should be flushed, and not destroy/created each time
1697 * we are changing title.
1699 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1700 if (p_sys
->p_parser
)
1701 vlc_demux_chained_Delete(p_sys
->p_parser
);
1703 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
1705 if (!p_sys
->p_parser
)
1706 msg_Err(p_demux
, "Failed to create TS demuxer");
1709 /*****************************************************************************
1710 * bluraySetTitle: select new BD title
1711 *****************************************************************************/
1712 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
1714 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1716 if (p_sys
->b_menu
) {
1719 msg_Dbg(p_demux
, "Playing TopMenu Title");
1720 result
= bd_menu_call(p_sys
->bluray
, -1);
1721 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
1722 msg_Dbg(p_demux
, "Playing FirstPlay Title");
1723 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
1725 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
1726 result
= bd_play_title(p_sys
->bluray
, i_title
);
1730 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
1731 return VLC_EGENERIC
;
1737 /* Looking for the main title, ie the longest duration */
1739 i_title
= p_sys
->i_longest_title
;
1740 else if ((unsigned)i_title
> p_sys
->i_title
)
1741 return VLC_EGENERIC
;
1743 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
1745 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
1746 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
1747 return VLC_EGENERIC
;
1750 blurayResetParser(p_demux
);
1755 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
1756 # define BLURAY_AUDIO_STREAM 0
1759 static void blurayStreamSelected(demux_sys_t
*p_sys
, int i_pid
)
1761 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1763 if (p_sys
->p_clip_info
) {
1764 if ((i_pid
& 0xff00) == 0x1100) {
1766 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
1767 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
1768 p_sys
->i_audio_stream_idx
= i_id
;
1769 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
1773 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
1775 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
1776 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
1777 p_sys
->i_spu_stream_idx
= i_id
;
1778 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
1785 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1788 /*****************************************************************************
1789 * blurayControl: handle the controls
1790 *****************************************************************************/
1791 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
1793 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1798 case DEMUX_CAN_SEEK
:
1799 case DEMUX_CAN_PAUSE
:
1800 case DEMUX_CAN_CONTROL_PACE
:
1801 pb_bool
= va_arg(args
, bool *);
1805 case DEMUX_GET_PTS_DELAY
:
1806 pi_64
= va_arg(args
, int64_t *);
1807 *pi_64
= INT64_C(1000) * var_InheritInteger(p_demux
, "disc-caching");
1810 case DEMUX_SET_PAUSE_STATE
:
1812 #ifdef BLURAY_RATE_NORMAL
1813 bool b_paused
= (bool)va_arg(args
, int);
1814 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
1815 return VLC_EGENERIC
;
1822 int i_id
= va_arg(args
, int);
1823 blurayStreamSelected(p_sys
, i_id
);
1826 case DEMUX_SET_TITLE
:
1828 int i_title
= va_arg(args
, int);
1829 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
1830 /* make sure GUI restores the old setting in title menu ... */
1831 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
1832 notifyDiscontinuity( p_sys
);
1833 return VLC_EGENERIC
;
1837 case DEMUX_SET_SEEKPOINT
:
1839 int i_chapter
= va_arg(args
, int);
1840 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
1841 notifyDiscontinuity( p_sys
);
1842 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
1846 case DEMUX_GET_TITLE_INFO
:
1848 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
1849 int *pi_int
= va_arg(args
, int *);
1850 int *pi_title_offset
= va_arg(args
, int *);
1851 int *pi_chapter_offset
= va_arg(args
, int *);
1854 *pi_title_offset
= 0;
1855 *pi_chapter_offset
= 0;
1857 /* Duplicate local title infos */
1858 *pi_int
= p_sys
->i_title
;
1859 *ppp_title
= malloc(p_sys
->i_title
* sizeof(input_title_t
*));
1860 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1861 (*ppp_title
)[i
] = vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
1866 case DEMUX_GET_LENGTH
:
1868 int64_t *pi_length
= va_arg(args
, int64_t *);
1869 *pi_length
= p_demux
->info
.i_title
< (int)p_sys
->i_title
? CUR_LENGTH
: 0;
1872 case DEMUX_SET_TIME
:
1874 int64_t i_time
= va_arg(args
, int64_t);
1875 bd_seek_time(p_sys
->bluray
, TO_TICKS(i_time
));
1876 notifyDiscontinuity( p_sys
);
1879 case DEMUX_GET_TIME
:
1881 int64_t *pi_time
= va_arg(args
, int64_t *);
1882 *pi_time
= (int64_t)FROM_TICKS(bd_tell_time(p_sys
->bluray
));
1886 case DEMUX_GET_POSITION
:
1888 double *pf_position
= va_arg(args
, double *);
1889 *pf_position
= p_demux
->info
.i_title
< (int)p_sys
->i_title
&& CUR_LENGTH
> 0 ?
1890 (double)FROM_TICKS(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
1893 case DEMUX_SET_POSITION
:
1895 double f_position
= va_arg(args
, double);
1896 bd_seek_time(p_sys
->bluray
, TO_TICKS(f_position
*CUR_LENGTH
));
1897 notifyDiscontinuity( p_sys
);
1901 case DEMUX_GET_META
:
1903 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
1904 const META_DL
*meta
= p_sys
->p_meta
;
1906 return VLC_EGENERIC
;
1908 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
1910 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
1911 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
1912 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
1914 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
1915 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
1917 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
1919 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
1920 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
1921 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
1923 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
1924 char *psz_thumbpath
;
1925 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
1926 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > 0) {
1927 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
1928 if (unlikely(psz_thumburl
== NULL
)) {
1929 free(psz_thumbpath
);
1933 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
1936 free(psz_thumbpath
);
1942 case DEMUX_GET_ATTACHMENTS
:
1944 input_attachment_t
***ppp_attach
=
1945 va_arg(args
, input_attachment_t
***);
1946 int *pi_int
= va_arg(args
, int *);
1948 if (p_sys
->i_attachments
<= 0)
1949 return VLC_EGENERIC
;
1951 *pi_int
= p_sys
->i_attachments
;
1952 *ppp_attach
= xmalloc(sizeof(input_attachment_t
*) * p_sys
->i_attachments
);
1953 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1954 (*ppp_attach
)[i
] = vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
1958 case DEMUX_NAV_ACTIVATE
:
1959 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
1960 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1962 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
1964 return sendKeyEvent(p_sys
, BD_VK_UP
);
1965 case DEMUX_NAV_DOWN
:
1966 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
1967 case DEMUX_NAV_LEFT
:
1968 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
1969 case DEMUX_NAV_RIGHT
:
1970 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
1971 case DEMUX_NAV_POPUP
:
1972 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1973 case DEMUX_NAV_MENU
:
1974 if (p_sys
->b_menu
) {
1975 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
1976 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
1979 msg_Err(p_demux
, "Can't select Top Menu title");
1980 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1982 return VLC_EGENERIC
;
1984 case DEMUX_CAN_RECORD
:
1986 case DEMUX_SET_GROUP
:
1987 case DEMUX_HAS_UNSUPPORTED_META
:
1989 return VLC_EGENERIC
;
1994 /*****************************************************************************
1995 * libbluray event handling
1996 *****************************************************************************/
1997 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
1998 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
2000 for( size_t i
=0; i
< i_sinfo
; i
++ )
2002 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2004 block_t
*p_block
= block_Alloc(192);
2008 uint8_t ts_header
[] = {
2009 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2011 (i_pid
& 0x1f00) >> 8, i_pid
& 0xFF, /* PID */
2012 0x20, /* adaptation field, no payload */
2013 183, /* adaptation field length */
2014 0x80, /* adaptation field: discontinuity indicator */
2017 memcpy(p_block
->p_buffer
, ts_header
, sizeof(ts_header
));
2018 memset(&p_block
->p_buffer
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
));
2019 p_block
->i_buffer
= 192;
2021 vlc_demux_chained_Send(p_parser
, p_block
);
2025 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2026 p_clip->memb##_stream_count )
2028 static void notifyDiscontinuity( demux_sys_t
*p_sys
)
2030 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2037 DONOTIFY(sec_audio
);
2038 DONOTIFY(sec_video
);
2044 static void streamFlush( demux_sys_t
*p_sys
)
2047 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2048 * Packet is flushed only when TS packet with PUSI flag set is received.
2050 * Fix this by emitting (video) ts packet with PUSI flag set.
2051 * Add video sequence end code to payload so that also video decoder is flushed.
2052 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2055 if (p_sys
->b_flushed
)
2058 block_t
*p_block
= block_Alloc(192);
2062 static const uint8_t seq_end_pes
[] = {
2063 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2064 0x00, 0x00, 0x01, 0xb7, /* PES payload: sequence end */
2066 static const uint8_t vid_pusi_ts
[] = {
2067 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2068 0x47, 0x50, 0x11, 0x30, /* TP header */
2069 (192 - (4 + 5) - sizeof(seq_end_pes
)), /* adaptation field length */
2070 0x80, /* adaptation field: discontinuity indicator */
2073 memset(p_block
->p_buffer
, 0, 192);
2074 memcpy(p_block
->p_buffer
, vid_pusi_ts
, sizeof(vid_pusi_ts
));
2075 memcpy(p_block
->p_buffer
+ 192 - sizeof(seq_end_pes
), seq_end_pes
, sizeof(seq_end_pes
));
2076 p_block
->i_buffer
= 192;
2078 /* set correct sequence end code */
2079 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2080 if (p_sys
->p_clip_info
!= NULL
) {
2081 if (p_sys
->p_clip_info
->video_streams
[0].coding_type
> 2) {
2082 /* VC1 / H.264 sequence end */
2083 p_block
->p_buffer
[191] = 0x0a;
2086 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2088 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2089 p_sys
->b_flushed
= true;
2092 static void blurayResetStillImage( demux_t
*p_demux
)
2094 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2096 if (p_sys
->i_still_end_time
) {
2097 p_sys
->i_still_end_time
= 0;
2099 blurayResetParser(p_demux
);
2100 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2104 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2106 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2108 /* time period elapsed ? */
2109 if (p_sys
->i_still_end_time
> 0 && p_sys
->i_still_end_time
<= mdate()) {
2110 msg_Dbg(p_demux
, "Still image end");
2111 bd_read_skip_still(p_sys
->bluray
);
2113 blurayResetStillImage(p_demux
);
2117 /* show last frame as still image */
2118 if (!p_sys
->i_still_end_time
) {
2120 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2121 p_sys
->i_still_end_time
= mdate() + i_timeout
* CLOCK_FREQ
;
2123 msg_Dbg(p_demux
, "Still image (infinite)");
2124 p_sys
->i_still_end_time
= -1;
2127 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2130 /* stop buffering */
2132 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2135 /* avoid busy loops (read returns no data) */
2139 static void blurayStreamSelect(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2141 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2144 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2147 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2148 p_sys
->i_audio_stream_idx
= i_id
;
2149 i_pid
= blurayEsPid(p_sys
, AUDIO_ES
, i_id
);
2150 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2151 p_sys
->i_spu_stream_idx
= i_id
;
2152 i_pid
= blurayEsPid(p_sys
, SPU_ES
, i_id
);
2156 int i_idx
= findEsPairIndex(p_sys
, i_pid
);
2158 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2159 var_SetInteger( p_demux
->p_input
, "audio-es", i_pid
);
2160 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2161 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? i_pid
: -1 );
2167 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2169 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2171 blurayResetParser(p_demux
);
2173 /* read title info and init some values */
2175 p_demux
->info
.i_title
= bd_get_current_title(p_sys
->bluray
);
2176 p_demux
->info
.i_seekpoint
= 0;
2177 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2179 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2181 blurayUpdateTitleInfo(p_sys
->pp_title
[p_demux
->info
.i_title
], p_title_info
);
2183 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE_LIST
;
2185 setTitleInfo(p_sys
, p_title_info
);
2187 blurayResetStillImage(p_demux
);
2190 static void blurayUpdateCurrentClip(demux_t
*p_demux
, uint32_t clip
)
2192 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2194 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2196 p_sys
->p_clip_info
= NULL
;
2197 p_sys
->i_video_stream
= -1;
2199 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2201 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2203 /* Let's assume a single video track for now.
2204 * This may brake later, but it's enough for now.
2206 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2207 p_sys
->i_video_stream
= p_sys
->p_clip_info
->video_streams
[0].pid
;
2210 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2212 blurayResetStillImage(p_demux
);
2215 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
)
2217 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2220 case BD_EVENT_TITLE
:
2221 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2222 p_demux
->info
.i_title
= p_sys
->i_title
- 1;
2224 p_demux
->info
.i_title
= e
->param
;
2225 /* this is feature title, we don't know yet which playlist it will play (if any) */
2226 setTitleInfo(p_sys
, NULL
);
2227 /* reset title infos here ? */
2228 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
; /* might be BD-J title with no video */
2230 case BD_EVENT_PLAYLIST
:
2231 /* Start of playlist playback (?????.mpls) */
2232 blurayUpdatePlaylist(p_demux
, e
->param
);
2233 if (p_sys
->b_pl_playing
) {
2234 /* previous playlist was stopped in middle. flush to avoid delay */
2235 msg_Info(p_demux
, "Stopping playlist playback");
2236 blurayResetParser(p_demux
);
2237 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2239 p_sys
->b_pl_playing
= true;
2241 case BD_EVENT_PLAYITEM
:
2242 blurayUpdateCurrentClip(p_demux
, e
->param
);
2244 case BD_EVENT_CHAPTER
:
2245 if (e
->param
&& e
->param
< 0xffff)
2246 p_demux
->info
.i_seekpoint
= e
->param
- 1;
2248 p_demux
->info
.i_seekpoint
= 0;
2249 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
2251 case BD_EVENT_PLAYMARK
:
2252 case BD_EVENT_ANGLE
:
2254 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2255 case BD_EVENT_UO_MASK_CHANGED
:
2256 /* This event could be used to grey out unselectable items in title menu */
2260 p_sys
->b_menu_open
= e
->param
;
2262 case BD_EVENT_POPUP
:
2263 p_sys
->b_popup_available
= e
->param
;
2264 /* TODO: show / hide pop-up menu button in gui ? */
2270 case BD_EVENT_ERROR
:
2271 /* fatal error (with menus) */
2272 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2273 "Playback with BluRay menus failed");
2274 p_sys
->b_fatal_error
= true;
2276 case BD_EVENT_ENCRYPTED
:
2277 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2278 "This disc seems to be encrypted");
2279 p_sys
->b_fatal_error
= true;
2281 case BD_EVENT_READ_ERROR
:
2282 msg_Err(p_demux
, "bluray: read error\n");
2286 * stream selection events
2288 case BD_EVENT_PG_TEXTST
:
2289 p_sys
->b_spu_enable
= e
->param
;
2291 case BD_EVENT_AUDIO_STREAM
:
2292 case BD_EVENT_PG_TEXTST_STREAM
:
2293 blurayStreamSelect(p_demux
, e
->event
, e
->param
);
2295 case BD_EVENT_IG_STREAM
:
2296 case BD_EVENT_SECONDARY_AUDIO
:
2297 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2298 case BD_EVENT_SECONDARY_VIDEO
:
2299 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2300 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2304 * playback control events
2306 case BD_EVENT_STILL_TIME
:
2307 blurayStillImage(p_demux
, e
->param
);
2309 case BD_EVENT_DISCONTINUITY
:
2310 /* reset demuxer (partially decoded PES packets must be dropped) */
2311 blurayResetParser(p_demux
);
2313 case BD_EVENT_END_OF_TITLE
:
2314 p_sys
->b_pl_playing
= false;
2317 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2318 /* avoid busy loop (bd_read() returns no data) */
2323 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2328 static bool blurayIsBdjTitle(demux_t
*p_demux
)
2330 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2331 unsigned int i_title
= p_demux
->info
.i_title
;
2332 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2334 if (di
&& di
->titles
) {
2335 if ((i_title
<= di
->num_titles
&& di
->titles
[i_title
] && di
->titles
[i_title
]->bdj
) ||
2336 (i_title
== p_sys
->i_title
- 1 && di
->first_play
&& di
->first_play
->bdj
)) {
2344 static void blurayHandleOverlays(demux_t
*p_demux
, int nread
)
2346 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2348 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2350 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
2351 bluray_overlay_t
*ov
= p_sys
->p_overlays
[i
];
2355 vlc_mutex_lock(&ov
->lock
);
2356 bool display
= ov
->status
== ToDisplay
;
2357 vlc_mutex_unlock(&ov
->lock
);
2359 if (p_sys
->p_vout
== NULL
) {
2360 p_sys
->p_vout
= input_GetVout(p_demux
->p_input
);
2361 if (p_sys
->p_vout
!= NULL
) {
2362 var_AddCallback(p_sys
->p_vout
, "mouse-moved", onMouseEvent
, p_demux
);
2363 var_AddCallback(p_sys
->p_vout
, "mouse-clicked", onMouseEvent
, p_demux
);
2367 /* NOTE: we might want to enable background video always when there's no video stream playing.
2368 Now, with some discs, there are perioids (even seconds) during which the video window
2369 disappears and just playlist is shown.
2370 (sometimes BD-J runs slowly ...)
2372 if (!p_sys
->p_vout
&& !p_sys
->p_dummy_video
&& p_sys
->b_menu
&&
2373 !p_sys
->p_pl_info
&& nread
== 0 &&
2374 blurayIsBdjTitle(p_demux
)) {
2376 /* Looks like there's no video stream playing.
2377 Emit blank frame so that BD-J overlay can be drawn. */
2378 startBackground(p_demux
);
2381 if (p_sys
->p_vout
!= NULL
) {
2382 bluraySendOverlayToVout(p_demux
, ov
);
2387 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2390 static int onIntfEvent( vlc_object_t
*p_input
, char const *psz_var
,
2391 vlc_value_t oldval
, vlc_value_t val
, void *p_data
)
2393 (void)p_input
; (void) psz_var
; (void) oldval
;
2394 demux_t
*p_demux
= p_data
;
2395 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2397 if (val
.i_int
== INPUT_EVENT_VOUT
) {
2399 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2400 if( p_sys
->p_vout
!= NULL
) {
2401 blurayReleaseVout(p_demux
);
2403 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2405 blurayHandleOverlays(p_demux
, 1);
2411 #define BD_TS_PACKET_SIZE (192)
2412 #define NB_TS_PACKETS (200)
2414 static int blurayDemux(demux_t
*p_demux
)
2416 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2419 block_t
*p_block
= block_Alloc(NB_TS_PACKETS
* (int64_t)BD_TS_PACKET_SIZE
);
2421 return VLC_DEMUXER_EGENERIC
;
2425 if (p_sys
->b_menu
== false) {
2426 while (bd_get_event(p_sys
->bluray
, &e
))
2427 blurayHandleEvent(p_demux
, &e
);
2429 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
,
2430 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
);
2432 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
,
2433 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
, &e
);
2434 while (e
.event
!= BD_EVENT_NONE
) {
2435 blurayHandleEvent(p_demux
, &e
);
2436 bd_get_event(p_sys
->bluray
, &e
);
2440 blurayHandleOverlays(p_demux
, nread
);
2443 block_Release(p_block
);
2444 if (p_sys
->b_fatal_error
|| nread
< 0) {
2445 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
2446 return VLC_DEMUXER_EGENERIC
;
2448 if (!p_sys
->b_menu
) {
2449 return VLC_DEMUXER_EOF
;
2451 return VLC_DEMUXER_SUCCESS
;
2454 p_block
->i_buffer
= nread
;
2456 stopBackground(p_demux
);
2458 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2460 p_sys
->b_flushed
= false;
2462 return VLC_DEMUXER_SUCCESS
;