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 unsigned cur_seekpoint
;
155 vlc_mutex_t pl_info_lock
;
156 BLURAY_TITLE_INFO
*p_pl_info
;
157 const BLURAY_CLIP_INFO
*p_clip_info
;
161 input_attachment_t
**attachments
;
164 /* Meta information */
165 const META_DL
*p_meta
;
168 bluray_overlay_t
*p_overlays
[MAX_OVERLAY
];
172 bool b_popup_available
;
173 mtime_t i_still_end_time
;
175 vlc_mutex_t bdj_overlay_lock
; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
178 vout_thread_t
*p_vout
;
180 es_out_id_t
*p_dummy_video
;
185 int i_audio_stream_idx
; /* Selected audio stream. -1 if default */
186 int i_spu_stream_idx
; /* Selected subtitle stream. -1 if default */
187 bool b_spu_enable
; /* enabled / disabled */
189 vlc_demux_chained_t
*p_parser
;
191 bool b_pl_playing
; /* true when playing playlist */
194 vlc_mutex_t read_block_lock
;
196 /* Used to store bluray disc path */
200 struct subpicture_updater_sys_t
202 vlc_mutex_t lock
; // protect p_overlay pointer and ref_cnt
203 bluray_overlay_t
*p_overlay
; // NULL if overlay has been closed
204 int ref_cnt
; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
208 * cut the connection between vout and overlay.
209 * - called when vout is closed or overlay is closed.
210 * - frees subpicture_updater_sys_t when both sides have been closed.
212 static void unref_subpicture_updater(subpicture_updater_sys_t
*p_sys
)
214 vlc_mutex_lock(&p_sys
->lock
);
215 int refs
= --p_sys
->ref_cnt
;
216 p_sys
->p_overlay
= NULL
;
217 vlc_mutex_unlock(&p_sys
->lock
);
220 vlc_mutex_destroy(&p_sys
->lock
);
226 * FIXME: partiallyy duplicated from src/input/es_out.c
228 static const char *DemuxGetLanguageCode( demux_t
*p_demux
, const char *psz_var
)
230 const iso639_lang_t
*pl
;
234 psz_lang
= var_CreateGetString( p_demux
, psz_var
);
236 return LANGUAGE_DEFAULT
;
238 /* XXX: we will use only the first value
239 * (and ignore other ones in case of a list) */
240 if( ( p
= strchr( psz_lang
, ',' ) ) )
243 for( pl
= p_languages
; pl
->psz_eng_name
!= NULL
; pl
++ )
245 if( *psz_lang
== '\0' )
247 if( !strcasecmp( pl
->psz_eng_name
, psz_lang
) ||
248 !strcasecmp( pl
->psz_iso639_1
, psz_lang
) ||
249 !strcasecmp( pl
->psz_iso639_2T
, psz_lang
) ||
250 !strcasecmp( pl
->psz_iso639_2B
, psz_lang
) )
256 if( pl
->psz_eng_name
!= NULL
)
257 return pl
->psz_iso639_2T
;
259 return LANGUAGE_DEFAULT
;
262 /*****************************************************************************
264 *****************************************************************************/
265 static es_out_t
*esOutNew(demux_t
*p_demux
);
267 static int blurayControl(demux_t
*, int, va_list);
268 static int blurayDemux(demux_t
*);
270 static void blurayInitTitles(demux_t
*p_demux
, int menu_titles
);
271 static int bluraySetTitle(demux_t
*p_demux
, int i_title
);
273 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
* const overlay
);
274 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
* const overlay
);
276 static int onMouseEvent(vlc_object_t
*p_vout
, const char *psz_var
,
277 vlc_value_t old
, vlc_value_t val
, void *p_data
);
278 static int onIntfEvent(vlc_object_t
*, char const *,
279 vlc_value_t
, vlc_value_t
, void *);
281 static void blurayResetParser(demux_t
*p_demux
);
282 static void notifyDiscontinuity( demux_sys_t
*p_sys
);
284 #define FROM_TICKS(a) ((a)*CLOCK_FREQ / INT64_C(90000))
285 #define TO_TICKS(a) ((a)*INT64_C(90000)/CLOCK_FREQ)
286 #define CUR_LENGTH p_sys->pp_title[p_sys->cur_title]->i_length
289 static void FindMountPoint(char **file
)
291 char *device
= *file
;
292 #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H)
293 /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
294 * we look up the real device */
295 char *bd_device
= realpath(device
, NULL
);
296 if (bd_device
== NULL
)
300 if (lstat (bd_device
, &st
) == 0 && S_ISBLK (st
.st_mode
)) {
301 FILE *mtab
= setmntent ("/proc/self/mounts", "r");
302 struct mntent
*m
, mbuf
;
305 while ((m
= getmntent_r (mtab
, &mbuf
, buf
, sizeof(buf
))) != NULL
) {
306 if (!strcmp (m
->mnt_fsname
, bd_device
)) {
308 *file
= strdup(m
->mnt_dir
);
316 #elif defined(__APPLE__)
318 if (!stat (device
, &st
) && S_ISBLK (st
.st_mode
)) {
319 int fs_count
= getfsstat (NULL
, 0, MNT_NOWAIT
);
321 struct statfs mbuf
[128];
322 getfsstat (mbuf
, fs_count
* sizeof(mbuf
[0]), MNT_NOWAIT
);
323 for (int i
= 0; i
< fs_count
; ++i
)
324 if (!strcmp (mbuf
[i
].f_mntfromname
, device
)) {
326 *file
= strdup(mbuf
[i
].f_mntonname
);
332 # warning Disc device to mount point not implemented
333 VLC_UNUSED( device
);
337 static void blurayReleaseVout(demux_t
*p_demux
)
339 demux_sys_t
*p_sys
= p_demux
->p_sys
;
341 if (p_sys
->p_vout
!= NULL
) {
342 var_DelCallback(p_sys
->p_vout
, "mouse-moved", onMouseEvent
, p_demux
);
343 var_DelCallback(p_sys
->p_vout
, "mouse-clicked", onMouseEvent
, p_demux
);
345 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
346 bluray_overlay_t
*p_ov
= p_sys
->p_overlays
[i
];
348 vlc_mutex_lock(&p_ov
->lock
);
349 if (p_ov
->i_channel
!= -1) {
350 msg_Err(p_demux
, "blurayReleaseVout: subpicture channel exists\n");
351 vout_FlushSubpictureChannel(p_sys
->p_vout
, p_ov
->i_channel
);
353 p_ov
->i_channel
= -1;
354 p_ov
->status
= ToDisplay
;
355 vlc_mutex_unlock(&p_ov
->lock
);
357 if (p_ov
->p_updater
) {
358 unref_subpicture_updater(p_ov
->p_updater
);
359 p_ov
->p_updater
= NULL
;
364 vlc_object_release(p_sys
->p_vout
);
365 p_sys
->p_vout
= NULL
;
369 /*****************************************************************************
370 * BD-J background video
371 *****************************************************************************/
373 static void startBackground(demux_t
*p_demux
)
375 demux_sys_t
*p_sys
= p_demux
->p_sys
;
377 if (p_sys
->p_dummy_video
) {
381 msg_Info(p_demux
, "Start background");
385 es_format_Init( &fmt
, VIDEO_ES
, VLC_CODEC_I420
);
386 video_format_Setup( &fmt
.video
, VLC_CODEC_I420
,
387 1920, 1080, 1920, 1080, 1, 1);
388 fmt
.i_priority
= ES_PRIORITY_SELECTABLE_MIN
;
389 fmt
.i_id
= 4115; /* 4113 = main video. 4114 = MVC. 4115 = unused. */
392 p_sys
->p_dummy_video
= es_out_Add(p_demux
->out
, &fmt
);
394 if (!p_sys
->p_dummy_video
) {
395 msg_Err(p_demux
, "Error adding background ES");
399 block_t
*p_block
= block_Alloc(fmt
.video
.i_width
* fmt
.video
.i_height
*
400 fmt
.video
.i_bits_per_pixel
/ 8);
402 msg_Err(p_demux
, "Error allocating block for background video");
406 // XXX TODO: what would be correct timestamp ???
407 p_block
->i_dts
= p_block
->i_pts
= mdate() + CLOCK_FREQ
/25;
409 uint8_t *p
= p_block
->p_buffer
;
410 memset(p
, 0, fmt
.video
.i_width
* fmt
.video
.i_height
);
411 p
+= fmt
.video
.i_width
* fmt
.video
.i_height
;
412 memset(p
, 0x80, fmt
.video
.i_width
* fmt
.video
.i_height
/ 2);
414 es_out_Send(p_demux
->out
, p_sys
->p_dummy_video
, p_block
);
417 es_format_Clean(&fmt
);
420 static void stopBackground(demux_t
*p_demux
)
422 demux_sys_t
*p_sys
= p_demux
->p_sys
;
424 if (!p_sys
->p_dummy_video
) {
428 msg_Info(p_demux
, "Stop background");
430 es_out_Del(p_demux
->out
, p_sys
->p_dummy_video
);
431 p_sys
->p_dummy_video
= NULL
;
434 /*****************************************************************************
435 * cache current playlist (title) information
436 *****************************************************************************/
438 static void setTitleInfo(demux_sys_t
*p_sys
, BLURAY_TITLE_INFO
*info
)
440 vlc_mutex_lock(&p_sys
->pl_info_lock
);
442 if (p_sys
->p_pl_info
) {
443 bd_free_title_info(p_sys
->p_pl_info
);
445 p_sys
->p_pl_info
= info
;
446 p_sys
->p_clip_info
= NULL
;
448 if (p_sys
->p_pl_info
&& p_sys
->p_pl_info
->clip_count
) {
449 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[0];
452 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
455 /*****************************************************************************
456 * create input attachment for thumbnail
457 *****************************************************************************/
459 static void attachThumbnail(demux_t
*p_demux
)
461 demux_sys_t
*p_sys
= p_demux
->p_sys
;
466 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,9,0)
467 if (p_sys
->p_meta
->thumb_count
> 0 && p_sys
->p_meta
->thumbnails
) {
470 if (bd_get_meta_file(p_sys
->bluray
, p_sys
->p_meta
->thumbnails
[0].path
, &data
, &size
) > 0) {
472 input_attachment_t
*p_attachment
;
474 snprintf(psz_name
, sizeof(psz_name
), "picture%d_%s", p_sys
->i_attachments
, p_sys
->p_meta
->thumbnails
[0].path
);
476 p_attachment
= vlc_input_attachment_New(psz_name
, NULL
, "Album art", data
, size
);
478 p_sys
->i_cover_idx
= p_sys
->i_attachments
;
479 TAB_APPEND(p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
487 /*****************************************************************************
489 *****************************************************************************/
491 static int probeStream(demux_t
*p_demux
)
493 /* input must be seekable */
494 bool b_canseek
= false;
495 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_canseek
);
500 /* first sector(s) should be filled with zeros */
502 const uint8_t *p_peek
;
503 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 2048 );
504 if( i_peek
!= 2048 ) {
508 if (p_peek
[ --i_peek
]) {
517 static int blurayReadBlock(void *object
, void *buf
, int lba
, int num_blocks
)
519 demux_t
*p_demux
= (demux_t
*)object
;
520 demux_sys_t
*p_sys
= p_demux
->p_sys
;
523 assert(p_demux
->s
!= NULL
);
525 vlc_mutex_lock(&p_sys
->read_block_lock
);
527 if (vlc_stream_Seek( p_demux
->s
, lba
* INT64_C(2048) ) == VLC_SUCCESS
) {
528 size_t req
= (size_t)2048 * num_blocks
;
531 got
= vlc_stream_Read( p_demux
->s
, buf
, req
);
533 msg_Err(p_demux
, "read from lba %d failed", lba
);
538 msg_Err(p_demux
, "seek to lba %d failed", lba
);
541 vlc_mutex_unlock(&p_sys
->read_block_lock
);
547 /*****************************************************************************
548 * probing of local files
549 *****************************************************************************/
551 /* Descriptor Tag (ECMA 167, 3/7.2) */
552 static int decode_descriptor_tag(const uint8_t *buf
)
555 uint8_t checksum
= 0;
558 id
= buf
[0] | (buf
[1] << 8);
560 /* calculate tag checksum */
561 for (i
= 0; i
< 4; i
++) {
562 checksum
= (uint8_t)(checksum
+ buf
[i
]);
564 for (i
= 5; i
< 16; i
++) {
565 checksum
= (uint8_t)(checksum
+ buf
[i
]);
568 if (checksum
!= buf
[4]) {
575 static int probeFile(const char *psz_name
)
577 struct stat stat_info
;
580 int ret
= VLC_EGENERIC
;
583 fd
= vlc_open(psz_name
, O_RDONLY
| O_NONBLOCK
);
588 if (fstat(fd
, &stat_info
) == -1) {
591 if (!S_ISREG(stat_info
.st_mode
) && !S_ISBLK(stat_info
.st_mode
)) {
595 /* first sector should be filled with zeros */
596 if (read(fd
, peek
, sizeof(peek
)) != sizeof(peek
)) {
599 for (i
= 0; i
< sizeof(peek
); i
++) {
605 /* Check AVDP tag checksum */
606 if (lseek(fd
, 256 * 2048, SEEK_SET
) == -1 ||
607 read(fd
, peek
, 16) != 16 ||
608 decode_descriptor_tag(peek
) != 2) {
619 /*****************************************************************************
620 * blurayOpen: module init function
621 *****************************************************************************/
622 static int blurayOpen(vlc_object_t
*object
)
624 demux_t
*p_demux
= (demux_t
*)object
;
627 uint64_t i_init_pos
= 0;
629 const char *error_msg
= NULL
;
630 #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
632 if (unlikely(!p_demux
->p_input
))
635 forced
= !strncasecmp(p_demux
->psz_url
, "bluray:", 7);
638 if (!strncasecmp(p_demux
->psz_url
, "file:", 5)) {
639 /* use access_demux for local files */
643 if (probeStream(p_demux
) != VLC_SUCCESS
) {
647 } else if (!forced
) {
648 if (!p_demux
->psz_filepath
) {
652 if (probeFile(p_demux
->psz_filepath
) != VLC_SUCCESS
) {
658 p_demux
->p_sys
= p_sys
= vlc_obj_calloc(object
, 1, sizeof(*p_sys
));
659 if (unlikely(!p_sys
))
662 p_sys
->i_audio_stream_idx
= -1;
663 p_sys
->i_spu_stream_idx
= -1;
664 p_sys
->i_video_stream
= -1;
665 p_sys
->i_still_end_time
= 0;
667 /* init demux info fields */
668 p_demux
->info
.i_update
= 0;
670 TAB_INIT(p_sys
->i_title
, p_sys
->pp_title
);
671 TAB_INIT(p_sys
->i_attachments
, p_sys
->attachments
);
673 vlc_mutex_init(&p_sys
->pl_info_lock
);
674 vlc_mutex_init(&p_sys
->bdj_overlay_lock
);
675 vlc_mutex_init(&p_sys
->read_block_lock
); /* used during bd_open_stream() */
677 var_AddCallback( p_demux
->p_input
, "intf-event", onIntfEvent
, p_demux
);
682 i_init_pos
= vlc_stream_Tell(p_demux
->s
);
684 p_sys
->bluray
= bd_init();
685 if (!bd_open_stream(p_sys
->bluray
, p_demux
, blurayReadBlock
)) {
686 bd_close(p_sys
->bluray
);
687 p_sys
->bluray
= NULL
;
692 if (!p_demux
->psz_filepath
) {
693 /* no path provided (bluray://). use default DVD device. */
694 p_sys
->psz_bd_path
= var_InheritString(object
, "dvd");
696 /* store current bd path */
697 p_sys
->psz_bd_path
= strdup(p_demux
->psz_filepath
);
700 /* If we're passed a block device, try to convert it to the mount point. */
701 FindMountPoint(&p_sys
->psz_bd_path
);
703 p_sys
->bluray
= bd_open(p_sys
->psz_bd_path
, NULL
);
705 if (!p_sys
->bluray
) {
709 /* Warning the user about AACS/BD+ */
710 const BLURAY_DISC_INFO
*disc_info
= bd_get_disc_info(p_sys
->bluray
);
712 /* Is it a bluray? */
713 if (!disc_info
->bluray_detected
) {
715 BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
720 msg_Info(p_demux
, "First play: %i, Top menu: %i\n"
721 "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
722 disc_info
->first_play_supported
, disc_info
->top_menu_supported
,
723 disc_info
->num_hdmv_titles
, disc_info
->num_bdj_titles
,
724 disc_info
->num_unsupported_titles
);
727 if (disc_info
->aacs_detected
) {
728 msg_Dbg(p_demux
, "Disc is using AACS");
729 if (!disc_info
->libaacs_detected
)
730 BLURAY_ERROR(_("This Blu-ray Disc needs a library for AACS decoding"
731 ", and your system does not have it."));
732 if (!disc_info
->aacs_handled
) {
733 if (disc_info
->aacs_error_code
) {
734 switch (disc_info
->aacs_error_code
) {
735 case BD_AACS_CORRUPTED_DISC
:
736 BLURAY_ERROR(_("Blu-ray Disc is corrupted."));
737 case BD_AACS_NO_CONFIG
:
738 BLURAY_ERROR(_("Missing AACS configuration file!"));
740 BLURAY_ERROR(_("No valid processing key found in AACS config file."));
741 case BD_AACS_NO_CERT
:
742 BLURAY_ERROR(_("No valid host certificate found in AACS config file."));
743 case BD_AACS_CERT_REVOKED
:
744 BLURAY_ERROR(_("AACS Host certificate revoked."));
745 case BD_AACS_MMC_FAILED
:
746 BLURAY_ERROR(_("AACS MMC failed."));
753 if (disc_info
->bdplus_detected
) {
754 msg_Dbg(p_demux
, "Disc is using BD+");
755 if (!disc_info
->libbdplus_detected
)
756 BLURAY_ERROR(_("This Blu-ray Disc needs a library for BD+ decoding"
757 ", and your system does not have it."));
758 if (!disc_info
->bdplus_handled
)
759 BLURAY_ERROR(_("Your system BD+ decoding library does not work. "
760 "Missing configuration?"));
763 /* set player region code */
764 char *psz_region
= var_InheritString(p_demux
, "bluray-region");
765 unsigned int region
= psz_region
? (psz_region
[0] - 'A') : REGION_DEFAULT
;
767 bd_set_player_setting(p_sys
->bluray
, BLURAY_PLAYER_SETTING_REGION_CODE
, 1<<region
);
769 /* set preferred languages */
770 const char *psz_code
= DemuxGetLanguageCode( p_demux
, "audio-language" );
771 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
, psz_code
);
772 psz_code
= DemuxGetLanguageCode( p_demux
, "sub-language" );
773 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
, psz_code
);
774 psz_code
= DemuxGetLanguageCode( p_demux
, "menu-language" );
775 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_MENU_LANG
, psz_code
);
777 /* Get disc metadata */
778 p_sys
->p_meta
= bd_get_meta(p_sys
->bluray
);
780 msg_Warn(p_demux
, "Failed to get meta info.");
782 p_sys
->i_cover_idx
= -1;
783 attachThumbnail(p_demux
);
785 p_sys
->b_menu
= var_InheritBool(p_demux
, "bluray-menu");
787 /* Check BD-J capability */
788 if (p_sys
->b_menu
&& disc_info
->bdj_detected
&& !disc_info
->bdj_handled
) {
789 msg_Err(p_demux
, "BD-J menus not supported. Playing without menus. "
790 "BD-J support: %d, JVM found: %d, JVM usable: %d",
791 disc_info
->bdj_supported
, disc_info
->libjvm_detected
, disc_info
->bdj_handled
);
792 vlc_dialog_display_error(p_demux
, _("Java required"),
793 _("This Blu-ray disc requires Java for menus support.%s\nThe disc will be played without menus."),
794 !disc_info
->libjvm_detected
? _("Java was not found on your system.") : "");
795 p_sys
->b_menu
= false;
798 /* Get titles and chapters */
799 blurayInitTitles(p_demux
, disc_info
->num_hdmv_titles
+ disc_info
->num_bdj_titles
+ 1/*Top Menu*/ + 1/*First Play*/);
802 * Initialize the event queue, so we can receive events in blurayDemux(Menu).
804 bd_get_event(p_sys
->bluray
, NULL
);
806 /* Registering overlay event handler */
807 bd_register_overlay_proc(p_sys
->bluray
, p_demux
, blurayOverlayProc
);
811 /* Register ARGB overlay handler for BD-J */
812 if (disc_info
->num_bdj_titles
)
813 bd_register_argb_overlay_proc(p_sys
->bluray
, p_demux
, blurayArgbOverlayProc
, NULL
);
815 /* libbluray will start playback from "First-Title" title */
816 if (bd_play(p_sys
->bluray
) == 0)
817 BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support."));
820 /* set start title number */
821 if (bluraySetTitle(p_demux
, p_sys
->i_longest_title
) != VLC_SUCCESS
) {
822 msg_Err(p_demux
, "Could not set the title %d", p_sys
->i_longest_title
);
827 vlc_array_init(&p_sys
->es
);
828 p_sys
->p_out
= esOutNew(p_demux
);
829 if (unlikely(p_sys
->p_out
== NULL
))
832 blurayResetParser(p_demux
);
833 if (!p_sys
->p_parser
) {
834 msg_Err(p_demux
, "Failed to create TS demuxer");
838 p_demux
->pf_control
= blurayControl
;
839 p_demux
->pf_demux
= blurayDemux
;
845 vlc_dialog_display_error(p_demux
, _("Blu-ray error"), "%s", error_msg
);
848 if (p_demux
->s
!= NULL
) {
849 /* restore stream position */
850 if (vlc_stream_Seek(p_demux
->s
, i_init_pos
) != VLC_SUCCESS
) {
851 msg_Err(p_demux
, "Failed to seek back to stream start");
861 /*****************************************************************************
862 * blurayClose: module destroy function
863 *****************************************************************************/
864 static void blurayClose(vlc_object_t
*object
)
866 demux_t
*p_demux
= (demux_t
*)object
;
867 demux_sys_t
*p_sys
= p_demux
->p_sys
;
869 var_DelCallback( p_demux
->p_input
, "intf-event", onIntfEvent
, p_demux
);
871 setTitleInfo(p_sys
, NULL
);
874 * Close libbluray first.
875 * This will close all the overlays before we release p_vout
876 * bd_close(NULL) can crash
879 bd_close(p_sys
->bluray
);
882 blurayReleaseVout(p_demux
);
885 vlc_demux_chained_Delete(p_sys
->p_parser
);
886 if (p_sys
->p_out
!= NULL
)
887 es_out_Delete(p_sys
->p_out
);
888 assert(vlc_array_count(&p_sys
->es
) == 0);
889 vlc_array_clear(&p_sys
->es
);
892 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
893 vlc_input_title_Delete(p_sys
->pp_title
[i
]);
894 TAB_CLEAN(p_sys
->i_title
, p_sys
->pp_title
);
896 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
897 vlc_input_attachment_Delete(p_sys
->attachments
[i
]);
898 TAB_CLEAN(p_sys
->i_attachments
, p_sys
->attachments
);
900 vlc_mutex_destroy(&p_sys
->pl_info_lock
);
901 vlc_mutex_destroy(&p_sys
->bdj_overlay_lock
);
902 vlc_mutex_destroy(&p_sys
->read_block_lock
);
904 free(p_sys
->psz_bd_path
);
907 /*****************************************************************************
908 * Elementary streams handling
909 *****************************************************************************/
911 struct es_out_sys_t
{
915 typedef struct fmt_es_pair
{
920 static int findEsPairIndex(demux_sys_t
*p_sys
, int i_id
)
922 for (size_t i
= 0; i
< vlc_array_count(&p_sys
->es
); ++i
)
923 if (((fmt_es_pair_t
*)vlc_array_item_at_index(&p_sys
->es
, i
))->i_id
== i_id
)
929 static int findEsPairIndexByEs(demux_sys_t
*p_sys
, es_out_id_t
*p_es
)
931 for (size_t i
= 0; i
< vlc_array_count(&p_sys
->es
); ++i
)
932 if (((fmt_es_pair_t
*)vlc_array_item_at_index(&p_sys
->es
, i
))->p_es
== p_es
)
938 static void setStreamLang(demux_sys_t
*p_sys
, es_format_t
*p_fmt
)
940 const BLURAY_STREAM_INFO
*p_streams
;
941 int i_stream_count
= 0;
943 vlc_mutex_lock(&p_sys
->pl_info_lock
);
945 if (p_sys
->p_clip_info
) {
946 if (p_fmt
->i_cat
== AUDIO_ES
) {
947 p_streams
= p_sys
->p_clip_info
->audio_streams
;
948 i_stream_count
= p_sys
->p_clip_info
->audio_stream_count
;
949 } else if (p_fmt
->i_cat
== SPU_ES
) {
950 p_streams
= p_sys
->p_clip_info
->pg_streams
;
951 i_stream_count
= p_sys
->p_clip_info
->pg_stream_count
;
955 for (int i
= 0; i
< i_stream_count
; i
++) {
956 if (p_fmt
->i_id
== p_streams
[i
].pid
) {
957 free(p_fmt
->psz_language
);
958 p_fmt
->psz_language
= strndup((const char *)p_streams
[i
].lang
, 3);
963 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
966 static int blurayEsPid(demux_sys_t
*p_sys
, int es_type
, int i_es_idx
)
970 vlc_mutex_lock(&p_sys
->pl_info_lock
);
972 if (p_sys
->p_clip_info
) {
973 if (es_type
== AUDIO_ES
) {
974 if (i_es_idx
>= 0 && i_es_idx
< p_sys
->p_clip_info
->audio_stream_count
) {
975 i_pid
= p_sys
->p_clip_info
->audio_streams
[i_es_idx
].pid
;
977 } else if (es_type
== SPU_ES
) {
978 if (i_es_idx
>= 0 && i_es_idx
< p_sys
->p_clip_info
->pg_stream_count
) {
979 i_pid
= p_sys
->p_clip_info
->pg_streams
[i_es_idx
].pid
;
984 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
989 static es_out_id_t
*esOutAdd(es_out_t
*p_out
, const es_format_t
*p_fmt
)
991 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
992 demux_sys_t
*p_sys
= p_demux
->p_sys
;
994 bool b_select
= false;
996 es_format_Copy(&fmt
, p_fmt
);
1000 if (p_sys
->i_video_stream
!= -1 && p_sys
->i_video_stream
!= p_fmt
->i_id
)
1001 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1004 if (p_sys
->i_audio_stream_idx
!= -1) {
1005 if (blurayEsPid(p_sys
, AUDIO_ES
, p_sys
->i_audio_stream_idx
) == p_fmt
->i_id
)
1007 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1009 setStreamLang(p_sys
, &fmt
);
1012 if (p_sys
->i_spu_stream_idx
!= -1) {
1013 if (blurayEsPid(p_sys
, SPU_ES
, p_sys
->i_spu_stream_idx
) == p_fmt
->i_id
)
1015 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1017 setStreamLang(p_sys
, &fmt
);
1021 es_out_id_t
*p_es
= es_out_Add(p_demux
->out
, &fmt
);
1022 if (p_fmt
->i_id
>= 0) {
1023 /* Ensure we are not overriding anything */
1024 int idx
= findEsPairIndex(p_sys
, p_fmt
->i_id
);
1026 fmt_es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
1027 if (likely(p_pair
!= NULL
)) {
1028 p_pair
->i_id
= p_fmt
->i_id
;
1029 p_pair
->p_es
= p_es
;
1030 msg_Info(p_demux
, "Adding ES %d", p_fmt
->i_id
);
1031 vlc_array_append_or_abort(&p_sys
->es
, p_pair
);
1034 if (fmt
.i_cat
== AUDIO_ES
) {
1035 var_SetInteger( p_demux
->p_input
, "audio-es", p_fmt
->i_id
);
1036 } else if (fmt
.i_cat
== SPU_ES
) {
1037 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? p_fmt
->i_id
: -1 );
1043 es_format_Clean(&fmt
);
1047 static int esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1049 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
1051 return es_out_Send(p_demux
->out
, p_es
, p_block
);
1054 static void esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1056 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
1057 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1059 int idx
= findEsPairIndexByEs(p_sys
, p_es
);
1061 free(vlc_array_item_at_index(&p_sys
->es
, idx
));
1062 vlc_array_remove(&p_sys
->es
, idx
);
1064 es_out_Del(p_demux
->out
, p_es
);
1067 static int esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1069 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
1071 return es_out_vaControl(p_demux
->out
, i_query
, args
);
1074 static void esOutDestroy(es_out_t
*p_out
)
1076 demux_t
*p_demux
= p_out
->p_sys
->p_demux
;
1077 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1079 for (size_t i
= 0; i
< vlc_array_count(&p_sys
->es
); ++i
)
1080 free(vlc_array_item_at_index(&p_sys
->es
, i
));
1081 vlc_array_clear(&p_sys
->es
);
1086 static es_out_t
*esOutNew(demux_t
*p_demux
)
1089 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1090 assert(vlc_array_count(&p_sys
->es
) == 0);
1092 es_out_t
*p_out
= malloc(sizeof(*p_out
));
1093 if (unlikely(p_out
== NULL
))
1096 p_out
->pf_add
= esOutAdd
;
1097 p_out
->pf_control
= esOutControl
;
1098 p_out
->pf_del
= esOutDel
;
1099 p_out
->pf_destroy
= esOutDestroy
;
1100 p_out
->pf_send
= esOutSend
;
1102 p_out
->p_sys
= malloc(sizeof(*p_out
->p_sys
));
1103 if (unlikely(p_out
->p_sys
== NULL
)) {
1107 p_out
->p_sys
->p_demux
= p_demux
;
1111 /*****************************************************************************
1112 * subpicture_updater_t functions:
1113 *****************************************************************************/
1115 static bluray_overlay_t
*updater_lock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1117 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1118 vlc_mutex_lock(&p_upd_sys
->lock
);
1120 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1122 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1123 vlc_mutex_lock(&ov
->lock
);
1127 /* overlay has been closed */
1128 vlc_mutex_unlock(&p_upd_sys
->lock
);
1132 static void updater_unlock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1134 assert (p_upd_sys
->p_overlay
);
1136 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1137 vlc_mutex_unlock(&p_upd_sys
->lock
);
1140 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1141 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1142 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1145 VLC_UNUSED(b_fmt_src
);
1146 VLC_UNUSED(b_fmt_dst
);
1147 VLC_UNUSED(p_fmt_src
);
1148 VLC_UNUSED(p_fmt_dst
);
1151 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1152 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1158 int res
= p_overlay
->status
== Outdated
;
1160 updater_unlock_overlay(p_upd_sys
);
1165 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1166 const video_format_t
*p_fmt_src
,
1167 const video_format_t
*p_fmt_dst
,
1170 VLC_UNUSED(p_fmt_src
);
1171 VLC_UNUSED(p_fmt_dst
);
1173 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1174 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1181 * When this function is called, all p_subpic regions are gone.
1182 * We need to duplicate our regions (stored internaly) to this subpic.
1184 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1186 updater_unlock_overlay(p_upd_sys
);
1190 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1191 while (p_src
!= NULL
) {
1192 *p_dst
= subpicture_region_Copy(p_src
);
1195 p_dst
= &(*p_dst
)->p_next
;
1196 p_src
= p_src
->p_next
;
1199 (*p_dst
)->p_next
= NULL
;
1200 p_overlay
->status
= Displayed
;
1202 updater_unlock_overlay(p_upd_sys
);
1205 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1207 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1208 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1211 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1212 p_overlay
->status
= ToDisplay
;
1213 p_overlay
->i_channel
= -1;
1214 updater_unlock_overlay(p_upd_sys
);
1217 unref_subpicture_updater(p_upd_sys
);
1220 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1222 subpicture_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1223 if (unlikely(p_upd_sys
== NULL
)) {
1227 p_upd_sys
->p_overlay
= p_ov
;
1229 subpicture_updater_t updater
= {
1230 .pf_validate
= subpictureUpdaterValidate
,
1231 .pf_update
= subpictureUpdaterUpdate
,
1232 .pf_destroy
= subpictureUpdaterDestroy
,
1236 subpicture_t
*p_pic
= subpicture_New(&updater
);
1237 if (p_pic
== NULL
) {
1242 p_pic
->i_original_picture_width
= p_ov
->width
;
1243 p_pic
->i_original_picture_height
= p_ov
->height
;
1244 p_pic
->b_ephemer
= true;
1245 p_pic
->b_absolute
= true;
1247 vlc_mutex_init(&p_upd_sys
->lock
);
1248 p_upd_sys
->ref_cnt
= 2;
1250 p_ov
->p_updater
= p_upd_sys
;
1255 /*****************************************************************************
1256 * User input events:
1257 *****************************************************************************/
1258 static int onMouseEvent(vlc_object_t
*p_vout
, const char *psz_var
, vlc_value_t old
,
1259 vlc_value_t val
, void *p_data
)
1261 demux_t
*p_demux
= (demux_t
*)p_data
;
1262 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1266 if (psz_var
[6] == 'm') //Mouse moved
1267 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1268 else if (psz_var
[6] == 'c') {
1269 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1270 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1272 vlc_assert_unreachable();
1277 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1279 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1280 return VLC_EGENERIC
;
1285 /*****************************************************************************
1286 * libbluray overlay handling:
1287 *****************************************************************************/
1289 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1291 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1292 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1296 /* drop overlay from vout */
1297 if (ov
->p_updater
) {
1298 unref_subpicture_updater(ov
->p_updater
);
1300 /* no references to this overlay exist in vo anymore */
1301 if (p_sys
->p_vout
&& ov
->i_channel
!= -1) {
1302 vout_FlushSubpictureChannel(p_sys
->p_vout
, ov
->i_channel
);
1305 vlc_mutex_destroy(&ov
->lock
);
1306 subpicture_region_ChainDelete(ov
->p_regions
);
1309 p_sys
->p_overlays
[plane
] = NULL
;
1312 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1313 if (p_sys
->p_overlays
[i
])
1316 /* All overlays have been closed */
1317 blurayReleaseVout(p_demux
);
1321 * Mark the overlay as "ToDisplay" status.
1322 * This will not send the overlay to the vout instantly, as the vout
1323 * may not be acquired (not acquirable) yet.
1324 * If is has already been acquired, the overlay has already been sent to it,
1325 * therefore, we only flag the overlay as "Outdated"
1327 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1329 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1330 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1333 * If the overlay is already displayed, mark the picture as outdated.
1334 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1336 vlc_mutex_lock(&ov
->lock
);
1337 if (ov
->status
>= Displayed
&& p_sys
->p_vout
) {
1338 ov
->status
= Outdated
;
1339 vlc_mutex_unlock(&ov
->lock
);
1344 * Mark the overlay as available, but don't display it right now.
1345 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1346 * the overlay is computed
1348 ov
->status
= ToDisplay
;
1349 vlc_mutex_unlock(&ov
->lock
);
1352 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1354 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1356 assert(p_sys
->p_overlays
[plane
] == NULL
);
1358 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1359 if (unlikely(ov
== NULL
))
1363 ov
->height
= height
;
1366 vlc_mutex_init(&ov
->lock
);
1368 p_sys
->p_overlays
[plane
] = ov
;
1372 * Destroy every regions in the subpicture.
1373 * This is done in two steps:
1374 * - Wiping our private regions list
1375 * - Flagging the overlay as outdated, so the changes are replicated from
1376 * the subpicture_updater_t::pf_update
1377 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1379 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1381 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1382 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1384 vlc_mutex_lock(&ov
->lock
);
1386 subpicture_region_ChainDelete(ov
->p_regions
);
1387 ov
->p_regions
= NULL
;
1388 ov
->status
= Outdated
;
1390 vlc_mutex_unlock(&ov
->lock
);
1394 * This will draw to the overlay by adding a region to our region list
1395 * This will have to be copied to the subpicture used to render the overlay.
1397 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1399 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1402 * Compute a subpicture_region_t.
1403 * It will be copied and sent to the vout later.
1405 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1407 /* Find a region to update */
1408 subpicture_region_t
**pp_reg
= &p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1409 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1410 subpicture_region_t
*p_last
= NULL
;
1411 while (p_reg
!= NULL
) {
1413 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1414 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1416 pp_reg
= &p_reg
->p_next
;
1417 p_reg
= p_reg
->p_next
;
1423 *pp_reg
= p_reg
->p_next
;
1424 subpicture_region_Delete(p_reg
);
1426 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1430 /* If there is no region to update, create a new one. */
1433 video_format_Init(&fmt
, 0);
1434 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1436 p_reg
= subpicture_region_New(&fmt
);
1439 /* Append it to our list. */
1441 p_last
->p_next
= p_reg
;
1442 else /* If we don't have a last region, then our list empty */
1443 p_sys
->p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1446 /* Now we can update the region, regardless it's an update or an insert */
1447 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1448 for (int y
= 0; y
< ov
->h
; y
++)
1449 for (int x
= 0; x
< ov
->w
;) {
1450 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1451 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1457 p_reg
->fmt
.p_palette
->i_entries
= 256;
1458 for (int i
= 0; i
< 256; ++i
) {
1459 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1460 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1461 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1462 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1466 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1468 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1472 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1474 demux_t
*p_demux
= (demux_t
*)ptr
;
1475 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1478 msg_Info(p_demux
, "Closing overlays.");
1480 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1481 blurayCloseOverlay(p_demux
, i
);
1485 switch (overlay
->cmd
) {
1486 case BD_OVERLAY_INIT
:
1487 msg_Info(p_demux
, "Initializing overlay");
1488 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1489 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1490 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1492 case BD_OVERLAY_CLOSE
:
1493 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1494 blurayClearOverlay(p_demux
, overlay
->plane
);
1495 blurayCloseOverlay(p_demux
, overlay
->plane
);
1496 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1498 case BD_OVERLAY_CLEAR
:
1499 blurayClearOverlay(p_demux
, overlay
->plane
);
1501 case BD_OVERLAY_FLUSH
:
1502 blurayActivateOverlay(p_demux
, overlay
->plane
);
1504 case BD_OVERLAY_DRAW
:
1505 case BD_OVERLAY_WIPE
:
1506 blurayDrawOverlay(p_demux
, overlay
);
1509 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
1515 * ARGB overlay (BD-J)
1517 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1519 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1521 blurayInitOverlay(p_demux
, plane
, width
, height
);
1523 if (!p_sys
->p_overlays
[plane
]->p_regions
) {
1525 video_format_Init(&fmt
, 0);
1526 video_format_Setup(&fmt
, VLC_CODEC_RGBA
, width
, height
, width
, height
, 1, 1);
1528 p_sys
->p_overlays
[plane
]->p_regions
= subpicture_region_New(&fmt
);
1532 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
1534 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1536 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1538 /* Find a region to update */
1539 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1541 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1545 /* Now we can update the region */
1546 const uint32_t *src0
= ov
->argb
;
1547 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
1548 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
1551 for (int y
= 0; y
< ov
->h
; y
++) {
1552 // XXX: add support for this format ? Should be possible with OPENGL/VDPAU/...
1553 // - or add libbluray option to select the format ?
1554 for (int x
= 0; x
< ov
->w
; x
++) {
1555 dst0
[x
*4 ] = src0
[x
]>>16; /* R */
1556 dst0
[x
*4+1] = src0
[x
]>>8; /* G */
1557 dst0
[x
*4+2] = src0
[x
]; /* B */
1558 dst0
[x
*4+3] = src0
[x
]>>24; /* A */
1562 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
1565 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1567 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1571 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
1573 demux_t
*p_demux
= (demux_t
*)ptr
;
1574 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1576 switch (overlay
->cmd
) {
1577 case BD_ARGB_OVERLAY_INIT
:
1578 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1579 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1580 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1582 case BD_ARGB_OVERLAY_CLOSE
:
1583 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1584 blurayClearOverlay(p_demux
, overlay
->plane
);
1585 blurayCloseOverlay(p_demux
, overlay
->plane
);
1586 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1588 case BD_ARGB_OVERLAY_FLUSH
:
1589 blurayActivateOverlay(p_demux
, overlay
->plane
);
1591 case BD_ARGB_OVERLAY_DRAW
:
1592 blurayDrawArgbOverlay(p_demux
, overlay
);
1595 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
1600 static void bluraySendOverlayToVout(demux_t
*p_demux
, bluray_overlay_t
*p_ov
)
1602 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1604 assert(p_ov
!= NULL
);
1605 assert(p_ov
->i_channel
== -1);
1607 if (p_ov
->p_updater
) {
1608 unref_subpicture_updater(p_ov
->p_updater
);
1609 p_ov
->p_updater
= NULL
;
1612 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
1614 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
1618 p_pic
->i_start
= p_pic
->i_stop
= mdate();
1619 p_pic
->i_channel
= vout_RegisterSubpictureChannel(p_sys
->p_vout
);
1620 p_ov
->i_channel
= p_pic
->i_channel
;
1623 * After this point, the picture should not be accessed from the demux thread,
1624 * as it is held by the vout thread.
1625 * This must be done only once per subpicture, ie. only once between each
1626 * blurayInitOverlay & blurayCloseOverlay call.
1628 vout_PutSubpicture(p_sys
->p_vout
, p_pic
);
1631 * Mark the picture as Outdated, as it contains no region for now.
1632 * This will make the subpicture_updater_t call pf_update
1634 p_ov
->status
= Outdated
;
1637 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
1639 t
->i_length
= FROM_TICKS(title_info
->duration
);
1641 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
1642 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
1643 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
1645 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
1646 seekpoint_t
*s
= vlc_seekpoint_New();
1650 s
->i_time_offset
= FROM_TICKS(title_info
->chapters
[j
].start
);
1652 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
1656 static void blurayInitTitles(demux_t
*p_demux
, int menu_titles
)
1658 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1659 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
1661 /* get and set the titles */
1662 unsigned i_title
= menu_titles
;
1664 if (!p_sys
->b_menu
) {
1665 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
1666 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
1669 for (unsigned int i
= 0; i
< i_title
; i
++) {
1670 input_title_t
*t
= vlc_input_title_New();
1674 if (!p_sys
->b_menu
) {
1675 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
1676 blurayUpdateTitleInfo(t
, title_info
);
1677 bd_free_title_info(title_info
);
1679 } else if (i
== 0) {
1680 t
->psz_name
= strdup(_("Top Menu"));
1681 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
1682 } else if (i
== i_title
- 1) {
1683 t
->psz_name
= strdup(_("First Play"));
1684 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
1685 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1688 /* add possible title name from disc metadata */
1689 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
1690 if (di
->titles
[i
]->name
) {
1691 t
->psz_name
= strdup(di
->titles
[i
]->name
);
1693 if (di
->titles
[i
]->interactive
) {
1694 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1699 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
1703 static void blurayResetParser(demux_t
*p_demux
)
1706 * This is a hack and will have to be removed.
1707 * The parser should be flushed, and not destroy/created each time
1708 * we are changing title.
1710 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1711 if (p_sys
->p_parser
)
1712 vlc_demux_chained_Delete(p_sys
->p_parser
);
1714 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
1716 if (!p_sys
->p_parser
)
1717 msg_Err(p_demux
, "Failed to create TS demuxer");
1720 /*****************************************************************************
1721 * bluraySetTitle: select new BD title
1722 *****************************************************************************/
1723 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
1725 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1727 if (p_sys
->b_menu
) {
1730 msg_Dbg(p_demux
, "Playing TopMenu Title");
1731 result
= bd_menu_call(p_sys
->bluray
, -1);
1732 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
1733 msg_Dbg(p_demux
, "Playing FirstPlay Title");
1734 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
1736 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
1737 result
= bd_play_title(p_sys
->bluray
, i_title
);
1741 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
1742 return VLC_EGENERIC
;
1748 /* Looking for the main title, ie the longest duration */
1750 i_title
= p_sys
->i_longest_title
;
1751 else if ((unsigned)i_title
> p_sys
->i_title
)
1752 return VLC_EGENERIC
;
1754 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
1756 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
1757 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
1758 return VLC_EGENERIC
;
1764 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
1765 # define BLURAY_AUDIO_STREAM 0
1768 static void blurayStreamSelected(demux_sys_t
*p_sys
, int i_pid
)
1770 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1772 if (p_sys
->p_clip_info
) {
1773 if ((i_pid
& 0xff00) == 0x1100) {
1775 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
1776 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
1777 p_sys
->i_audio_stream_idx
= i_id
;
1778 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
1782 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
1784 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
1785 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
1786 p_sys
->i_spu_stream_idx
= i_id
;
1787 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
1794 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1797 /*****************************************************************************
1798 * blurayControl: handle the controls
1799 *****************************************************************************/
1800 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
1802 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1807 case DEMUX_CAN_SEEK
:
1808 case DEMUX_CAN_PAUSE
:
1809 case DEMUX_CAN_CONTROL_PACE
:
1810 pb_bool
= va_arg(args
, bool *);
1814 case DEMUX_GET_PTS_DELAY
:
1815 pi_64
= va_arg(args
, int64_t *);
1816 *pi_64
= INT64_C(1000) * var_InheritInteger(p_demux
, "disc-caching");
1819 case DEMUX_SET_PAUSE_STATE
:
1821 #ifdef BLURAY_RATE_NORMAL
1822 bool b_paused
= (bool)va_arg(args
, int);
1823 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
1824 return VLC_EGENERIC
;
1831 int i_id
= va_arg(args
, int);
1832 blurayStreamSelected(p_sys
, i_id
);
1835 case DEMUX_SET_TITLE
:
1837 int i_title
= va_arg(args
, int);
1838 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
1839 /* make sure GUI restores the old setting in title menu ... */
1840 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
1841 return VLC_EGENERIC
;
1843 blurayResetParser( p_demux
);
1844 notifyDiscontinuity( p_sys
);
1847 case DEMUX_SET_SEEKPOINT
:
1849 int i_chapter
= va_arg(args
, int);
1850 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
1851 notifyDiscontinuity( p_sys
);
1852 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
1856 case DEMUX_GET_TITLE
:
1857 *va_arg(args
, int *) = p_sys
->cur_title
;
1860 case DEMUX_GET_SEEKPOINT
:
1861 *va_arg(args
, int *) = p_sys
->cur_seekpoint
;
1864 case DEMUX_GET_TITLE_INFO
:
1866 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
1867 int *pi_int
= va_arg(args
, int *);
1868 int *pi_title_offset
= va_arg(args
, int *);
1869 int *pi_chapter_offset
= va_arg(args
, int *);
1872 *pi_title_offset
= 0;
1873 *pi_chapter_offset
= 0;
1875 /* Duplicate local title infos */
1877 *ppp_title
= vlc_alloc(p_sys
->i_title
, sizeof(input_title_t
*));
1879 return VLC_EGENERIC
;
1880 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1882 input_title_t
*p_dup
= vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
1884 (*ppp_title
)[(*pi_int
)++] = p_dup
;
1890 case DEMUX_GET_LENGTH
:
1892 int64_t *pi_length
= va_arg(args
, int64_t *);
1893 *pi_length
= p_sys
->cur_title
< p_sys
->i_title
? CUR_LENGTH
: 0;
1896 case DEMUX_SET_TIME
:
1898 int64_t i_time
= va_arg(args
, int64_t);
1899 bd_seek_time(p_sys
->bluray
, TO_TICKS(i_time
));
1900 notifyDiscontinuity( p_sys
);
1903 case DEMUX_GET_TIME
:
1905 int64_t *pi_time
= va_arg(args
, int64_t *);
1906 *pi_time
= (int64_t)FROM_TICKS(bd_tell_time(p_sys
->bluray
));
1910 case DEMUX_GET_POSITION
:
1912 double *pf_position
= va_arg(args
, double *);
1913 *pf_position
= p_sys
->cur_title
< p_sys
->i_title
&& CUR_LENGTH
> 0 ?
1914 (double)FROM_TICKS(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
1917 case DEMUX_SET_POSITION
:
1919 double f_position
= va_arg(args
, double);
1920 bd_seek_time(p_sys
->bluray
, TO_TICKS(f_position
*CUR_LENGTH
));
1921 notifyDiscontinuity( p_sys
);
1925 case DEMUX_GET_META
:
1927 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
1928 const META_DL
*meta
= p_sys
->p_meta
;
1930 return VLC_EGENERIC
;
1932 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
1934 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
1935 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
1936 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
1938 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
1939 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
1941 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
1943 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
1944 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
1945 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
1947 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
1948 char *psz_thumbpath
;
1949 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
1950 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > -1) {
1951 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
1952 free(psz_thumbpath
);
1953 if (unlikely(psz_thumburl
== NULL
))
1956 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
1964 case DEMUX_GET_ATTACHMENTS
:
1966 input_attachment_t
***ppp_attach
=
1967 va_arg(args
, input_attachment_t
***);
1968 int *pi_int
= va_arg(args
, int *);
1970 if (p_sys
->i_attachments
<= 0)
1971 return VLC_EGENERIC
;
1974 *ppp_attach
= vlc_alloc(p_sys
->i_attachments
, sizeof(input_attachment_t
*));
1976 return VLC_EGENERIC
;
1977 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1979 input_attachment_t
*p_dup
= vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
1981 (*ppp_attach
)[(*pi_int
)++] = p_dup
;
1986 case DEMUX_NAV_ACTIVATE
:
1987 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
1988 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1990 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
1992 return sendKeyEvent(p_sys
, BD_VK_UP
);
1993 case DEMUX_NAV_DOWN
:
1994 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
1995 case DEMUX_NAV_LEFT
:
1996 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
1997 case DEMUX_NAV_RIGHT
:
1998 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
1999 case DEMUX_NAV_POPUP
:
2000 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2001 case DEMUX_NAV_MENU
:
2002 if (p_sys
->b_menu
) {
2003 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
2004 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2007 msg_Err(p_demux
, "Can't select Top Menu title");
2008 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2010 return VLC_EGENERIC
;
2012 case DEMUX_CAN_RECORD
:
2014 case DEMUX_SET_GROUP
:
2015 case DEMUX_HAS_UNSUPPORTED_META
:
2017 return VLC_EGENERIC
;
2022 /*****************************************************************************
2023 * libbluray event handling
2024 *****************************************************************************/
2025 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
2026 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
2028 for( size_t i
=0; i
< i_sinfo
; i
++ )
2030 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2032 block_t
*p_block
= block_Alloc(192);
2036 uint8_t ts_header
[] = {
2037 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2039 (i_pid
& 0x1f00) >> 8, i_pid
& 0xFF, /* PID */
2040 0x20, /* adaptation field, no payload */
2041 183, /* adaptation field length */
2042 0x80, /* adaptation field: discontinuity indicator */
2045 memcpy(p_block
->p_buffer
, ts_header
, sizeof(ts_header
));
2046 memset(&p_block
->p_buffer
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
));
2047 p_block
->i_buffer
= 192;
2049 vlc_demux_chained_Send(p_parser
, p_block
);
2053 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2054 p_clip->memb##_stream_count )
2056 static void notifyDiscontinuity( demux_sys_t
*p_sys
)
2058 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2065 DONOTIFY(sec_audio
);
2066 DONOTIFY(sec_video
);
2072 static void streamFlush( demux_sys_t
*p_sys
)
2075 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2076 * Packet is flushed only when TS packet with PUSI flag set is received.
2078 * Fix this by emitting (video) ts packet with PUSI flag set.
2079 * Add video sequence end code to payload so that also video decoder is flushed.
2080 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2083 if (p_sys
->b_flushed
)
2086 block_t
*p_block
= block_Alloc(192);
2090 static const uint8_t seq_end_pes
[] = {
2091 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2092 0x00, 0x00, 0x01, 0xb7, /* PES payload: sequence end */
2094 static const uint8_t vid_pusi_ts
[] = {
2095 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2096 0x47, 0x50, 0x11, 0x30, /* TP header */
2097 (192 - (4 + 5) - sizeof(seq_end_pes
)), /* adaptation field length */
2098 0x80, /* adaptation field: discontinuity indicator */
2101 memset(p_block
->p_buffer
, 0, 192);
2102 memcpy(p_block
->p_buffer
, vid_pusi_ts
, sizeof(vid_pusi_ts
));
2103 memcpy(p_block
->p_buffer
+ 192 - sizeof(seq_end_pes
), seq_end_pes
, sizeof(seq_end_pes
));
2104 p_block
->i_buffer
= 192;
2106 /* set correct sequence end code */
2107 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2108 if (p_sys
->p_clip_info
!= NULL
) {
2109 if (p_sys
->p_clip_info
->video_streams
[0].coding_type
> 2) {
2110 /* VC1 / H.264 sequence end */
2111 p_block
->p_buffer
[191] = 0x0a;
2114 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2116 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2117 p_sys
->b_flushed
= true;
2120 static void blurayResetStillImage( demux_t
*p_demux
)
2122 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2124 if (p_sys
->i_still_end_time
) {
2125 p_sys
->i_still_end_time
= 0;
2127 blurayResetParser(p_demux
);
2128 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2132 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2134 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2136 /* time period elapsed ? */
2137 if (p_sys
->i_still_end_time
> 0 && p_sys
->i_still_end_time
<= mdate()) {
2138 msg_Dbg(p_demux
, "Still image end");
2139 bd_read_skip_still(p_sys
->bluray
);
2141 blurayResetStillImage(p_demux
);
2145 /* show last frame as still image */
2146 if (!p_sys
->i_still_end_time
) {
2148 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2149 p_sys
->i_still_end_time
= mdate() + i_timeout
* CLOCK_FREQ
;
2151 msg_Dbg(p_demux
, "Still image (infinite)");
2152 p_sys
->i_still_end_time
= -1;
2155 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2158 /* stop buffering */
2160 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2163 /* avoid busy loops (read returns no data) */
2167 static void blurayStreamSelect(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2169 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2172 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2175 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2176 p_sys
->i_audio_stream_idx
= i_id
;
2177 i_pid
= blurayEsPid(p_sys
, AUDIO_ES
, i_id
);
2178 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2179 p_sys
->i_spu_stream_idx
= i_id
;
2180 i_pid
= blurayEsPid(p_sys
, SPU_ES
, i_id
);
2184 int i_idx
= findEsPairIndex(p_sys
, i_pid
);
2186 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2187 var_SetInteger( p_demux
->p_input
, "audio-es", i_pid
);
2188 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2189 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? i_pid
: -1 );
2195 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2197 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2199 blurayResetParser(p_demux
);
2201 /* read title info and init some values */
2203 p_sys
->cur_title
= bd_get_current_title(p_sys
->bluray
);
2204 p_sys
->cur_seekpoint
= 0;
2205 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2207 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2209 blurayUpdateTitleInfo(p_sys
->pp_title
[p_sys
->cur_title
], p_title_info
);
2211 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE_LIST
;
2213 setTitleInfo(p_sys
, p_title_info
);
2215 blurayResetStillImage(p_demux
);
2218 static void blurayUpdateCurrentClip(demux_t
*p_demux
, uint32_t clip
)
2220 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2222 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2224 p_sys
->p_clip_info
= NULL
;
2225 p_sys
->i_video_stream
= -1;
2227 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2229 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2231 /* Let's assume a single video track for now.
2232 * This may brake later, but it's enough for now.
2234 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2235 p_sys
->i_video_stream
= p_sys
->p_clip_info
->video_streams
[0].pid
;
2238 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2240 blurayResetStillImage(p_demux
);
2243 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
)
2245 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2248 case BD_EVENT_TITLE
:
2249 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2250 p_sys
->cur_title
= p_sys
->i_title
- 1;
2252 p_sys
->cur_title
= e
->param
;
2253 /* this is feature title, we don't know yet which playlist it will play (if any) */
2254 setTitleInfo(p_sys
, NULL
);
2255 /* reset title infos here ? */
2256 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
; /* might be BD-J title with no video */
2258 case BD_EVENT_PLAYLIST
:
2259 /* Start of playlist playback (?????.mpls) */
2260 blurayUpdatePlaylist(p_demux
, e
->param
);
2261 if (p_sys
->b_pl_playing
) {
2262 /* previous playlist was stopped in middle. flush to avoid delay */
2263 msg_Info(p_demux
, "Stopping playlist playback");
2264 blurayResetParser(p_demux
);
2265 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2267 p_sys
->b_pl_playing
= true;
2269 case BD_EVENT_PLAYITEM
:
2270 blurayUpdateCurrentClip(p_demux
, e
->param
);
2272 case BD_EVENT_CHAPTER
:
2273 if (e
->param
&& e
->param
< 0xffff)
2274 p_sys
->cur_seekpoint
= e
->param
- 1;
2276 p_sys
->cur_seekpoint
= 0;
2277 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
2279 case BD_EVENT_PLAYMARK
:
2280 case BD_EVENT_ANGLE
:
2282 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2283 case BD_EVENT_UO_MASK_CHANGED
:
2284 /* This event could be used to grey out unselectable items in title menu */
2288 p_sys
->b_menu_open
= e
->param
;
2290 case BD_EVENT_POPUP
:
2291 p_sys
->b_popup_available
= e
->param
;
2292 /* TODO: show / hide pop-up menu button in gui ? */
2298 case BD_EVENT_ERROR
:
2299 /* fatal error (with menus) */
2300 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2301 "Playback with BluRay menus failed");
2302 p_sys
->b_fatal_error
= true;
2304 case BD_EVENT_ENCRYPTED
:
2305 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2306 "This disc seems to be encrypted");
2307 p_sys
->b_fatal_error
= true;
2309 case BD_EVENT_READ_ERROR
:
2310 msg_Err(p_demux
, "bluray: read error\n");
2314 * stream selection events
2316 case BD_EVENT_PG_TEXTST
:
2317 p_sys
->b_spu_enable
= e
->param
;
2319 case BD_EVENT_AUDIO_STREAM
:
2320 case BD_EVENT_PG_TEXTST_STREAM
:
2321 blurayStreamSelect(p_demux
, e
->event
, e
->param
);
2323 case BD_EVENT_IG_STREAM
:
2324 case BD_EVENT_SECONDARY_AUDIO
:
2325 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2326 case BD_EVENT_SECONDARY_VIDEO
:
2327 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2328 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2332 * playback control events
2334 case BD_EVENT_STILL_TIME
:
2335 blurayStillImage(p_demux
, e
->param
);
2337 case BD_EVENT_DISCONTINUITY
:
2338 /* reset demuxer (partially decoded PES packets must be dropped) */
2339 blurayResetParser(p_demux
);
2341 case BD_EVENT_END_OF_TITLE
:
2342 p_sys
->b_pl_playing
= false;
2345 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2346 /* avoid busy loop (bd_read() returns no data) */
2351 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2356 static bool blurayIsBdjTitle(demux_t
*p_demux
)
2358 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2359 unsigned int i_title
= p_sys
->cur_title
;
2360 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2362 if (di
&& di
->titles
) {
2363 if ((i_title
<= di
->num_titles
&& di
->titles
[i_title
] && di
->titles
[i_title
]->bdj
) ||
2364 (i_title
== p_sys
->i_title
- 1 && di
->first_play
&& di
->first_play
->bdj
)) {
2372 static void blurayHandleOverlays(demux_t
*p_demux
, int nread
)
2374 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2376 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2378 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
2379 bluray_overlay_t
*ov
= p_sys
->p_overlays
[i
];
2383 vlc_mutex_lock(&ov
->lock
);
2384 bool display
= ov
->status
== ToDisplay
;
2385 vlc_mutex_unlock(&ov
->lock
);
2387 if (p_sys
->p_vout
== NULL
) {
2388 p_sys
->p_vout
= input_GetVout(p_demux
->p_input
);
2389 if (p_sys
->p_vout
!= NULL
) {
2390 var_AddCallback(p_sys
->p_vout
, "mouse-moved", onMouseEvent
, p_demux
);
2391 var_AddCallback(p_sys
->p_vout
, "mouse-clicked", onMouseEvent
, p_demux
);
2395 /* NOTE: we might want to enable background video always when there's no video stream playing.
2396 Now, with some discs, there are perioids (even seconds) during which the video window
2397 disappears and just playlist is shown.
2398 (sometimes BD-J runs slowly ...)
2400 if (!p_sys
->p_vout
&& !p_sys
->p_dummy_video
&& p_sys
->b_menu
&&
2401 !p_sys
->p_pl_info
&& nread
== 0 &&
2402 blurayIsBdjTitle(p_demux
)) {
2404 /* Looks like there's no video stream playing.
2405 Emit blank frame so that BD-J overlay can be drawn. */
2406 startBackground(p_demux
);
2409 if (p_sys
->p_vout
!= NULL
) {
2410 bluraySendOverlayToVout(p_demux
, ov
);
2415 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2418 static int onIntfEvent( vlc_object_t
*p_input
, char const *psz_var
,
2419 vlc_value_t oldval
, vlc_value_t val
, void *p_data
)
2421 (void)p_input
; (void) psz_var
; (void) oldval
;
2422 demux_t
*p_demux
= p_data
;
2423 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2425 if (val
.i_int
== INPUT_EVENT_VOUT
) {
2427 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2428 if( p_sys
->p_vout
!= NULL
) {
2429 blurayReleaseVout(p_demux
);
2431 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2433 blurayHandleOverlays(p_demux
, 1);
2439 #define BD_TS_PACKET_SIZE (192)
2440 #define NB_TS_PACKETS (200)
2442 static int blurayDemux(demux_t
*p_demux
)
2444 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2447 block_t
*p_block
= block_Alloc(NB_TS_PACKETS
* (int64_t)BD_TS_PACKET_SIZE
);
2449 return VLC_DEMUXER_EGENERIC
;
2453 if (p_sys
->b_menu
== false) {
2454 while (bd_get_event(p_sys
->bluray
, &e
))
2455 blurayHandleEvent(p_demux
, &e
);
2457 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
,
2458 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
);
2460 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
,
2461 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
, &e
);
2462 while (e
.event
!= BD_EVENT_NONE
) {
2463 blurayHandleEvent(p_demux
, &e
);
2464 bd_get_event(p_sys
->bluray
, &e
);
2468 blurayHandleOverlays(p_demux
, nread
);
2471 block_Release(p_block
);
2472 if (p_sys
->b_fatal_error
|| nread
< 0) {
2473 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
2474 return VLC_DEMUXER_EGENERIC
;
2476 if (!p_sys
->b_menu
) {
2477 return VLC_DEMUXER_EOF
;
2479 return VLC_DEMUXER_SUCCESS
;
2482 p_block
->i_buffer
= nread
;
2484 stopBackground(p_demux
);
2486 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2488 p_sys
->b_flushed
= false;
2490 return VLC_DEMUXER_SUCCESS
;