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 if (unlikely(!p_demux
->p_input
))
633 forced
= !strcasecmp(p_demux
->psz_access
, "bluray");
636 if (!strcasecmp(p_demux
->psz_access
, "file")) {
637 /* use access_demux for local files */
641 if (probeStream(p_demux
) != VLC_SUCCESS
) {
645 } else if (!forced
) {
646 if (!p_demux
->psz_file
) {
650 if (probeFile(p_demux
->psz_file
) != VLC_SUCCESS
) {
656 p_demux
->p_sys
= p_sys
= vlc_calloc(object
, 1, sizeof(*p_sys
));
657 if (unlikely(!p_sys
))
660 p_sys
->i_audio_stream_idx
= -1;
661 p_sys
->i_spu_stream_idx
= -1;
662 p_sys
->i_video_stream
= -1;
663 p_sys
->i_still_end_time
= 0;
665 /* init demux info fields */
666 p_demux
->info
.i_update
= 0;
667 p_demux
->info
.i_title
= 0;
668 p_demux
->info
.i_seekpoint
= 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_file
) {
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_file
);
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 needs Java for menus.%s\nDisc is played without menus."),
794 !disc_info
->libjvm_detected
? _(" Java was not found from 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_Init(&fmt
, p_fmt
->i_cat
, p_fmt
->i_codec
);
997 es_format_Copy(&fmt
, p_fmt
);
1001 if (p_sys
->i_video_stream
!= -1 && p_sys
->i_video_stream
!= p_fmt
->i_id
)
1002 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1005 if (p_sys
->i_audio_stream_idx
!= -1) {
1006 if (blurayEsPid(p_sys
, AUDIO_ES
, p_sys
->i_audio_stream_idx
) == p_fmt
->i_id
)
1008 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1010 setStreamLang(p_sys
, &fmt
);
1013 if (p_sys
->i_spu_stream_idx
!= -1) {
1014 if (blurayEsPid(p_sys
, SPU_ES
, p_sys
->i_spu_stream_idx
) == p_fmt
->i_id
)
1016 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1018 setStreamLang(p_sys
, &fmt
);
1022 es_out_id_t
*p_es
= es_out_Add(p_demux
->out
, &fmt
);
1023 if (p_fmt
->i_id
>= 0) {
1024 /* Ensure we are not overriding anything */
1025 int idx
= findEsPairIndex(p_sys
, p_fmt
->i_id
);
1027 fmt_es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
1028 if (likely(p_pair
!= NULL
)) {
1029 p_pair
->i_id
= p_fmt
->i_id
;
1030 p_pair
->p_es
= p_es
;
1031 msg_Info(p_demux
, "Adding ES %d", p_fmt
->i_id
);
1032 vlc_array_append(&p_sys
->es
, p_pair
);
1035 if (fmt
.i_cat
== AUDIO_ES
) {
1036 var_SetInteger( p_demux
->p_input
, "audio-es", p_fmt
->i_id
);
1037 } else if (fmt
.i_cat
== SPU_ES
) {
1038 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? p_fmt
->i_id
: -1 );
1044 es_format_Clean(&fmt
);
1048 static int esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1050 return es_out_Send(p_out
->p_sys
->p_demux
->out
, p_es
, p_block
);
1053 static void esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1055 int idx
= findEsPairIndexByEs(p_out
->p_sys
->p_demux
->p_sys
, p_es
);
1057 free(vlc_array_item_at_index(&p_out
->p_sys
->p_demux
->p_sys
->es
, idx
));
1058 vlc_array_remove(&p_out
->p_sys
->p_demux
->p_sys
->es
, idx
);
1060 es_out_Del(p_out
->p_sys
->p_demux
->out
, p_es
);
1063 static int esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1065 return es_out_vaControl(p_out
->p_sys
->p_demux
->out
, i_query
, args
);
1068 static void esOutDestroy(es_out_t
*p_out
)
1070 for (size_t i
= 0; i
< vlc_array_count(&p_out
->p_sys
->p_demux
->p_sys
->es
); ++i
)
1071 free(vlc_array_item_at_index(&p_out
->p_sys
->p_demux
->p_sys
->es
, i
));
1072 vlc_array_clear(&p_out
->p_sys
->p_demux
->p_sys
->es
);
1077 static es_out_t
*esOutNew(demux_t
*p_demux
)
1079 assert(vlc_array_count(&p_demux
->p_sys
->es
) == 0);
1080 es_out_t
*p_out
= malloc(sizeof(*p_out
));
1081 if (unlikely(p_out
== NULL
))
1084 p_out
->pf_add
= esOutAdd
;
1085 p_out
->pf_control
= esOutControl
;
1086 p_out
->pf_del
= esOutDel
;
1087 p_out
->pf_destroy
= esOutDestroy
;
1088 p_out
->pf_send
= esOutSend
;
1090 p_out
->p_sys
= malloc(sizeof(*p_out
->p_sys
));
1091 if (unlikely(p_out
->p_sys
== NULL
)) {
1095 p_out
->p_sys
->p_demux
= p_demux
;
1099 /*****************************************************************************
1100 * subpicture_updater_t functions:
1101 *****************************************************************************/
1103 static bluray_overlay_t
*updater_lock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1105 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1106 vlc_mutex_lock(&p_upd_sys
->lock
);
1108 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1110 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1111 vlc_mutex_lock(&ov
->lock
);
1115 /* overlay has been closed */
1116 vlc_mutex_unlock(&p_upd_sys
->lock
);
1120 static void updater_unlock_overlay(subpicture_updater_sys_t
*p_upd_sys
)
1122 assert (p_upd_sys
->p_overlay
);
1124 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1125 vlc_mutex_unlock(&p_upd_sys
->lock
);
1128 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1129 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1130 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1133 VLC_UNUSED(b_fmt_src
);
1134 VLC_UNUSED(b_fmt_dst
);
1135 VLC_UNUSED(p_fmt_src
);
1136 VLC_UNUSED(p_fmt_dst
);
1139 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1140 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1146 int res
= p_overlay
->status
== Outdated
;
1148 updater_unlock_overlay(p_upd_sys
);
1153 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1154 const video_format_t
*p_fmt_src
,
1155 const video_format_t
*p_fmt_dst
,
1158 VLC_UNUSED(p_fmt_src
);
1159 VLC_UNUSED(p_fmt_dst
);
1161 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1162 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1169 * When this function is called, all p_subpic regions are gone.
1170 * We need to duplicate our regions (stored internaly) to this subpic.
1172 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1174 updater_unlock_overlay(p_upd_sys
);
1178 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1179 while (p_src
!= NULL
) {
1180 *p_dst
= subpicture_region_Copy(p_src
);
1183 p_dst
= &(*p_dst
)->p_next
;
1184 p_src
= p_src
->p_next
;
1187 (*p_dst
)->p_next
= NULL
;
1188 p_overlay
->status
= Displayed
;
1190 updater_unlock_overlay(p_upd_sys
);
1193 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1195 subpicture_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1196 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1199 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1200 p_overlay
->status
= ToDisplay
;
1201 p_overlay
->i_channel
= -1;
1202 updater_unlock_overlay(p_upd_sys
);
1205 unref_subpicture_updater(p_upd_sys
);
1208 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1210 subpicture_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1211 if (unlikely(p_upd_sys
== NULL
)) {
1215 p_upd_sys
->p_overlay
= p_ov
;
1217 subpicture_updater_t updater
= {
1218 .pf_validate
= subpictureUpdaterValidate
,
1219 .pf_update
= subpictureUpdaterUpdate
,
1220 .pf_destroy
= subpictureUpdaterDestroy
,
1224 subpicture_t
*p_pic
= subpicture_New(&updater
);
1225 if (p_pic
== NULL
) {
1230 p_pic
->i_original_picture_width
= p_ov
->width
;
1231 p_pic
->i_original_picture_height
= p_ov
->height
;
1232 p_pic
->b_ephemer
= true;
1233 p_pic
->b_absolute
= true;
1235 vlc_mutex_init(&p_upd_sys
->lock
);
1236 p_upd_sys
->ref_cnt
= 2;
1238 p_ov
->p_updater
= p_upd_sys
;
1243 /*****************************************************************************
1244 * User input events:
1245 *****************************************************************************/
1246 static int onMouseEvent(vlc_object_t
*p_vout
, const char *psz_var
, vlc_value_t old
,
1247 vlc_value_t val
, void *p_data
)
1249 demux_t
*p_demux
= (demux_t
*)p_data
;
1250 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1254 if (psz_var
[6] == 'm') //Mouse moved
1255 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1256 else if (psz_var
[6] == 'c') {
1257 bd_mouse_select(p_sys
->bluray
, -1, val
.coords
.x
, val
.coords
.y
);
1258 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1260 vlc_assert_unreachable();
1265 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1267 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1268 return VLC_EGENERIC
;
1273 /*****************************************************************************
1274 * libbluray overlay handling:
1275 *****************************************************************************/
1277 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1279 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1280 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1284 /* drop overlay from vout */
1285 if (ov
->p_updater
) {
1286 unref_subpicture_updater(ov
->p_updater
);
1288 /* no references to this overlay exist in vo anymore */
1289 if (p_sys
->p_vout
&& ov
->i_channel
!= -1) {
1290 vout_FlushSubpictureChannel(p_sys
->p_vout
, ov
->i_channel
);
1293 vlc_mutex_destroy(&ov
->lock
);
1294 subpicture_region_ChainDelete(ov
->p_regions
);
1297 p_sys
->p_overlays
[plane
] = NULL
;
1300 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1301 if (p_sys
->p_overlays
[i
])
1304 /* All overlays have been closed */
1305 blurayReleaseVout(p_demux
);
1309 * Mark the overlay as "ToDisplay" status.
1310 * This will not send the overlay to the vout instantly, as the vout
1311 * may not be acquired (not acquirable) yet.
1312 * If is has already been acquired, the overlay has already been sent to it,
1313 * therefore, we only flag the overlay as "Outdated"
1315 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1317 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1318 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1321 * If the overlay is already displayed, mark the picture as outdated.
1322 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1324 vlc_mutex_lock(&ov
->lock
);
1325 if (ov
->status
>= Displayed
&& p_sys
->p_vout
) {
1326 ov
->status
= Outdated
;
1327 vlc_mutex_unlock(&ov
->lock
);
1332 * Mark the overlay as available, but don't display it right now.
1333 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1334 * the overlay is computed
1336 ov
->status
= ToDisplay
;
1337 vlc_mutex_unlock(&ov
->lock
);
1340 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1342 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1344 assert(p_sys
->p_overlays
[plane
] == NULL
);
1346 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1347 if (unlikely(ov
== NULL
))
1351 ov
->height
= height
;
1354 vlc_mutex_init(&ov
->lock
);
1356 p_sys
->p_overlays
[plane
] = ov
;
1360 * Destroy every regions in the subpicture.
1361 * This is done in two steps:
1362 * - Wiping our private regions list
1363 * - Flagging the overlay as outdated, so the changes are replicated from
1364 * the subpicture_updater_t::pf_update
1365 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1367 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1369 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1370 bluray_overlay_t
*ov
= p_sys
->p_overlays
[plane
];
1372 vlc_mutex_lock(&ov
->lock
);
1374 subpicture_region_ChainDelete(ov
->p_regions
);
1375 ov
->p_regions
= NULL
;
1376 ov
->status
= Outdated
;
1378 vlc_mutex_unlock(&ov
->lock
);
1382 * This will draw to the overlay by adding a region to our region list
1383 * This will have to be copied to the subpicture used to render the overlay.
1385 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1387 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1390 * Compute a subpicture_region_t.
1391 * It will be copied and sent to the vout later.
1393 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1395 /* Find a region to update */
1396 subpicture_region_t
**pp_reg
= &p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1397 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1398 subpicture_region_t
*p_last
= NULL
;
1399 while (p_reg
!= NULL
) {
1401 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1402 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1404 pp_reg
= &p_reg
->p_next
;
1405 p_reg
= p_reg
->p_next
;
1411 *pp_reg
= p_reg
->p_next
;
1412 subpicture_region_Delete(p_reg
);
1414 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1418 /* If there is no region to update, create a new one. */
1421 video_format_Init(&fmt
, 0);
1422 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1424 p_reg
= subpicture_region_New(&fmt
);
1427 /* Append it to our list. */
1429 p_last
->p_next
= p_reg
;
1430 else /* If we don't have a last region, then our list empty */
1431 p_sys
->p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1434 /* Now we can update the region, regardless it's an update or an insert */
1435 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1436 for (int y
= 0; y
< ov
->h
; y
++)
1437 for (int x
= 0; x
< ov
->w
;) {
1438 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1439 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1445 p_reg
->fmt
.p_palette
->i_entries
= 256;
1446 for (int i
= 0; i
< 256; ++i
) {
1447 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1448 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1449 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1450 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1454 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1456 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1460 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1462 demux_t
*p_demux
= (demux_t
*)ptr
;
1463 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1466 msg_Info(p_demux
, "Closing overlays.");
1468 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1469 blurayCloseOverlay(p_demux
, i
);
1473 switch (overlay
->cmd
) {
1474 case BD_OVERLAY_INIT
:
1475 msg_Info(p_demux
, "Initializing overlay");
1476 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1477 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1478 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1480 case BD_OVERLAY_CLOSE
:
1481 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1482 blurayClearOverlay(p_demux
, overlay
->plane
);
1483 blurayCloseOverlay(p_demux
, overlay
->plane
);
1484 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1486 case BD_OVERLAY_CLEAR
:
1487 blurayClearOverlay(p_demux
, overlay
->plane
);
1489 case BD_OVERLAY_FLUSH
:
1490 blurayActivateOverlay(p_demux
, overlay
->plane
);
1492 case BD_OVERLAY_DRAW
:
1493 case BD_OVERLAY_WIPE
:
1494 blurayDrawOverlay(p_demux
, overlay
);
1497 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
1503 * ARGB overlay (BD-J)
1505 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1507 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1509 blurayInitOverlay(p_demux
, plane
, width
, height
);
1511 if (!p_sys
->p_overlays
[plane
]->p_regions
) {
1513 video_format_Init(&fmt
, 0);
1514 video_format_Setup(&fmt
, VLC_CODEC_RGBA
, width
, height
, width
, height
, 1, 1);
1516 p_sys
->p_overlays
[plane
]->p_regions
= subpicture_region_New(&fmt
);
1520 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
1522 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1524 vlc_mutex_lock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1526 /* Find a region to update */
1527 subpicture_region_t
*p_reg
= p_sys
->p_overlays
[ov
->plane
]->p_regions
;
1529 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1533 /* Now we can update the region */
1534 const uint32_t *src0
= ov
->argb
;
1535 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
1536 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
1539 for (int y
= 0; y
< ov
->h
; y
++) {
1540 // XXX: add support for this format ? Should be possible with OPENGL/VDPAU/...
1541 // - or add libbluray option to select the format ?
1542 for (int x
= 0; x
< ov
->w
; x
++) {
1543 dst0
[x
*4 ] = src0
[x
]>>16; /* R */
1544 dst0
[x
*4+1] = src0
[x
]>>8; /* G */
1545 dst0
[x
*4+2] = src0
[x
]; /* B */
1546 dst0
[x
*4+3] = src0
[x
]>>24; /* A */
1550 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
1553 vlc_mutex_unlock(&p_sys
->p_overlays
[ov
->plane
]->lock
);
1555 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1559 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
1561 demux_t
*p_demux
= (demux_t
*)ptr
;
1562 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1564 switch (overlay
->cmd
) {
1565 case BD_ARGB_OVERLAY_INIT
:
1566 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1567 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1568 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1570 case BD_ARGB_OVERLAY_CLOSE
:
1571 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
1572 blurayClearOverlay(p_demux
, overlay
->plane
);
1573 blurayCloseOverlay(p_demux
, overlay
->plane
);
1574 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
1576 case BD_ARGB_OVERLAY_FLUSH
:
1577 blurayActivateOverlay(p_demux
, overlay
->plane
);
1579 case BD_ARGB_OVERLAY_DRAW
:
1580 blurayDrawArgbOverlay(p_demux
, overlay
);
1583 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
1588 static void bluraySendOverlayToVout(demux_t
*p_demux
, bluray_overlay_t
*p_ov
)
1590 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1592 assert(p_ov
!= NULL
);
1593 assert(p_ov
->i_channel
== -1);
1595 if (p_ov
->p_updater
) {
1596 unref_subpicture_updater(p_ov
->p_updater
);
1597 p_ov
->p_updater
= NULL
;
1600 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
1602 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
1606 p_pic
->i_start
= p_pic
->i_stop
= mdate();
1607 p_pic
->i_channel
= vout_RegisterSubpictureChannel(p_sys
->p_vout
);
1608 p_ov
->i_channel
= p_pic
->i_channel
;
1611 * After this point, the picture should not be accessed from the demux thread,
1612 * as it is held by the vout thread.
1613 * This must be done only once per subpicture, ie. only once between each
1614 * blurayInitOverlay & blurayCloseOverlay call.
1616 vout_PutSubpicture(p_sys
->p_vout
, p_pic
);
1619 * Mark the picture as Outdated, as it contains no region for now.
1620 * This will make the subpicture_updater_t call pf_update
1622 p_ov
->status
= Outdated
;
1625 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
1627 t
->i_length
= FROM_TICKS(title_info
->duration
);
1629 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
1630 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
1631 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
1633 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
1634 seekpoint_t
*s
= vlc_seekpoint_New();
1638 s
->i_time_offset
= FROM_TICKS(title_info
->chapters
[j
].start
);
1640 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
1644 static void blurayInitTitles(demux_t
*p_demux
, int menu_titles
)
1646 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1647 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
1649 /* get and set the titles */
1650 unsigned i_title
= menu_titles
;
1652 if (!p_sys
->b_menu
) {
1653 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
1654 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
1657 for (unsigned int i
= 0; i
< i_title
; i
++) {
1658 input_title_t
*t
= vlc_input_title_New();
1662 if (!p_sys
->b_menu
) {
1663 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
1664 blurayUpdateTitleInfo(t
, title_info
);
1665 bd_free_title_info(title_info
);
1667 } else if (i
== 0) {
1668 t
->psz_name
= strdup(_("Top Menu"));
1669 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
1670 } else if (i
== i_title
- 1) {
1671 t
->psz_name
= strdup(_("First Play"));
1672 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
1673 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1676 /* add possible title name from disc metadata */
1677 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
1678 if (di
->titles
[i
]->name
) {
1679 t
->psz_name
= strdup(di
->titles
[i
]->name
);
1681 if (di
->titles
[i
]->interactive
) {
1682 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
1687 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
1691 static void blurayResetParser(demux_t
*p_demux
)
1694 * This is a hack and will have to be removed.
1695 * The parser should be flushed, and not destroy/created each time
1696 * we are changing title.
1698 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1699 if (p_sys
->p_parser
)
1700 vlc_demux_chained_Delete(p_sys
->p_parser
);
1702 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
1704 if (!p_sys
->p_parser
)
1705 msg_Err(p_demux
, "Failed to create TS demuxer");
1708 /*****************************************************************************
1709 * bluraySetTitle: select new BD title
1710 *****************************************************************************/
1711 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
1713 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1715 if (p_sys
->b_menu
) {
1718 msg_Dbg(p_demux
, "Playing TopMenu Title");
1719 result
= bd_menu_call(p_sys
->bluray
, -1);
1720 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
1721 msg_Dbg(p_demux
, "Playing FirstPlay Title");
1722 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
1724 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
1725 result
= bd_play_title(p_sys
->bluray
, i_title
);
1729 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
1730 return VLC_EGENERIC
;
1736 /* Looking for the main title, ie the longest duration */
1738 i_title
= p_sys
->i_longest_title
;
1739 else if ((unsigned)i_title
> p_sys
->i_title
)
1740 return VLC_EGENERIC
;
1742 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
1744 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
1745 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
1746 return VLC_EGENERIC
;
1752 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
1753 # define BLURAY_AUDIO_STREAM 0
1756 static void blurayStreamSelected(demux_sys_t
*p_sys
, int i_pid
)
1758 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1760 if (p_sys
->p_clip_info
) {
1761 if ((i_pid
& 0xff00) == 0x1100) {
1763 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
1764 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
1765 p_sys
->i_audio_stream_idx
= i_id
;
1766 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
1770 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
1772 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
1773 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
1774 p_sys
->i_spu_stream_idx
= i_id
;
1775 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
1782 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1785 /*****************************************************************************
1786 * blurayControl: handle the controls
1787 *****************************************************************************/
1788 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
1790 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1795 case DEMUX_CAN_SEEK
:
1796 case DEMUX_CAN_PAUSE
:
1797 case DEMUX_CAN_CONTROL_PACE
:
1798 pb_bool
= va_arg(args
, bool *);
1802 case DEMUX_GET_PTS_DELAY
:
1803 pi_64
= va_arg(args
, int64_t *);
1804 *pi_64
= INT64_C(1000) * var_InheritInteger(p_demux
, "disc-caching");
1807 case DEMUX_SET_PAUSE_STATE
:
1809 #ifdef BLURAY_RATE_NORMAL
1810 bool b_paused
= (bool)va_arg(args
, int);
1811 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
1812 return VLC_EGENERIC
;
1819 int i_id
= va_arg(args
, int);
1820 blurayStreamSelected(p_sys
, i_id
);
1823 case DEMUX_SET_TITLE
:
1825 int i_title
= va_arg(args
, int);
1826 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
1827 /* make sure GUI restores the old setting in title menu ... */
1828 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
1829 return VLC_EGENERIC
;
1831 blurayResetParser( p_demux
);
1832 notifyDiscontinuity( p_sys
);
1835 case DEMUX_SET_SEEKPOINT
:
1837 int i_chapter
= va_arg(args
, int);
1838 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
1839 notifyDiscontinuity( p_sys
);
1840 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
1844 case DEMUX_GET_TITLE_INFO
:
1846 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
1847 int *pi_int
= va_arg(args
, int *);
1848 int *pi_title_offset
= va_arg(args
, int *);
1849 int *pi_chapter_offset
= va_arg(args
, int *);
1852 *pi_title_offset
= 0;
1853 *pi_chapter_offset
= 0;
1855 /* Duplicate local title infos */
1856 *pi_int
= p_sys
->i_title
;
1857 *ppp_title
= malloc(p_sys
->i_title
* sizeof(input_title_t
*));
1858 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1859 (*ppp_title
)[i
] = vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
1864 case DEMUX_GET_LENGTH
:
1866 int64_t *pi_length
= va_arg(args
, int64_t *);
1867 *pi_length
= p_demux
->info
.i_title
< (int)p_sys
->i_title
? CUR_LENGTH
: 0;
1870 case DEMUX_SET_TIME
:
1872 int64_t i_time
= va_arg(args
, int64_t);
1873 bd_seek_time(p_sys
->bluray
, TO_TICKS(i_time
));
1874 notifyDiscontinuity( p_sys
);
1877 case DEMUX_GET_TIME
:
1879 int64_t *pi_time
= va_arg(args
, int64_t *);
1880 *pi_time
= (int64_t)FROM_TICKS(bd_tell_time(p_sys
->bluray
));
1884 case DEMUX_GET_POSITION
:
1886 double *pf_position
= va_arg(args
, double *);
1887 *pf_position
= p_demux
->info
.i_title
< (int)p_sys
->i_title
&& CUR_LENGTH
> 0 ?
1888 (double)FROM_TICKS(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
1891 case DEMUX_SET_POSITION
:
1893 double f_position
= va_arg(args
, double);
1894 bd_seek_time(p_sys
->bluray
, TO_TICKS(f_position
*CUR_LENGTH
));
1895 notifyDiscontinuity( p_sys
);
1899 case DEMUX_GET_META
:
1901 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
1902 const META_DL
*meta
= p_sys
->p_meta
;
1904 return VLC_EGENERIC
;
1906 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
1908 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
1909 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
1910 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
1912 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
1913 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
1915 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
1917 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
1918 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
1919 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
1921 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
1922 char *psz_thumbpath
;
1923 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
1924 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > -1) {
1925 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
1926 free(psz_thumbpath
);
1927 if (unlikely(psz_thumburl
== NULL
))
1930 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
1938 case DEMUX_GET_ATTACHMENTS
:
1940 input_attachment_t
***ppp_attach
=
1941 va_arg(args
, input_attachment_t
***);
1942 int *pi_int
= va_arg(args
, int *);
1944 if (p_sys
->i_attachments
<= 0)
1945 return VLC_EGENERIC
;
1947 *pi_int
= p_sys
->i_attachments
;
1948 *ppp_attach
= xmalloc(sizeof(input_attachment_t
*) * p_sys
->i_attachments
);
1949 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1950 (*ppp_attach
)[i
] = vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
1954 case DEMUX_NAV_ACTIVATE
:
1955 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
1956 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1958 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
1960 return sendKeyEvent(p_sys
, BD_VK_UP
);
1961 case DEMUX_NAV_DOWN
:
1962 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
1963 case DEMUX_NAV_LEFT
:
1964 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
1965 case DEMUX_NAV_RIGHT
:
1966 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
1967 case DEMUX_NAV_POPUP
:
1968 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1969 case DEMUX_NAV_MENU
:
1970 if (p_sys
->b_menu
) {
1971 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
1972 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
1975 msg_Err(p_demux
, "Can't select Top Menu title");
1976 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
1978 return VLC_EGENERIC
;
1980 case DEMUX_CAN_RECORD
:
1982 case DEMUX_SET_GROUP
:
1983 case DEMUX_HAS_UNSUPPORTED_META
:
1985 return VLC_EGENERIC
;
1990 /*****************************************************************************
1991 * libbluray event handling
1992 *****************************************************************************/
1993 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
1994 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
1996 for( size_t i
=0; i
< i_sinfo
; i
++ )
1998 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2000 block_t
*p_block
= block_Alloc(192);
2004 uint8_t ts_header
[] = {
2005 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2007 (i_pid
& 0x1f00) >> 8, i_pid
& 0xFF, /* PID */
2008 0x20, /* adaptation field, no payload */
2009 183, /* adaptation field length */
2010 0x80, /* adaptation field: discontinuity indicator */
2013 memcpy(p_block
->p_buffer
, ts_header
, sizeof(ts_header
));
2014 memset(&p_block
->p_buffer
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
));
2015 p_block
->i_buffer
= 192;
2017 vlc_demux_chained_Send(p_parser
, p_block
);
2021 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2022 p_clip->memb##_stream_count )
2024 static void notifyDiscontinuity( demux_sys_t
*p_sys
)
2026 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2033 DONOTIFY(sec_audio
);
2034 DONOTIFY(sec_video
);
2040 static void streamFlush( demux_sys_t
*p_sys
)
2043 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2044 * Packet is flushed only when TS packet with PUSI flag set is received.
2046 * Fix this by emitting (video) ts packet with PUSI flag set.
2047 * Add video sequence end code to payload so that also video decoder is flushed.
2048 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2051 if (p_sys
->b_flushed
)
2054 block_t
*p_block
= block_Alloc(192);
2058 static const uint8_t seq_end_pes
[] = {
2059 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2060 0x00, 0x00, 0x01, 0xb7, /* PES payload: sequence end */
2062 static const uint8_t vid_pusi_ts
[] = {
2063 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2064 0x47, 0x50, 0x11, 0x30, /* TP header */
2065 (192 - (4 + 5) - sizeof(seq_end_pes
)), /* adaptation field length */
2066 0x80, /* adaptation field: discontinuity indicator */
2069 memset(p_block
->p_buffer
, 0, 192);
2070 memcpy(p_block
->p_buffer
, vid_pusi_ts
, sizeof(vid_pusi_ts
));
2071 memcpy(p_block
->p_buffer
+ 192 - sizeof(seq_end_pes
), seq_end_pes
, sizeof(seq_end_pes
));
2072 p_block
->i_buffer
= 192;
2074 /* set correct sequence end code */
2075 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2076 if (p_sys
->p_clip_info
!= NULL
) {
2077 if (p_sys
->p_clip_info
->video_streams
[0].coding_type
> 2) {
2078 /* VC1 / H.264 sequence end */
2079 p_block
->p_buffer
[191] = 0x0a;
2082 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2084 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2085 p_sys
->b_flushed
= true;
2088 static void blurayResetStillImage( demux_t
*p_demux
)
2090 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2092 if (p_sys
->i_still_end_time
) {
2093 p_sys
->i_still_end_time
= 0;
2095 blurayResetParser(p_demux
);
2096 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2100 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2102 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2104 /* time period elapsed ? */
2105 if (p_sys
->i_still_end_time
> 0 && p_sys
->i_still_end_time
<= mdate()) {
2106 msg_Dbg(p_demux
, "Still image end");
2107 bd_read_skip_still(p_sys
->bluray
);
2109 blurayResetStillImage(p_demux
);
2113 /* show last frame as still image */
2114 if (!p_sys
->i_still_end_time
) {
2116 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2117 p_sys
->i_still_end_time
= mdate() + i_timeout
* CLOCK_FREQ
;
2119 msg_Dbg(p_demux
, "Still image (infinite)");
2120 p_sys
->i_still_end_time
= -1;
2123 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2126 /* stop buffering */
2128 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2131 /* avoid busy loops (read returns no data) */
2135 static void blurayStreamSelect(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2137 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2140 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2143 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2144 p_sys
->i_audio_stream_idx
= i_id
;
2145 i_pid
= blurayEsPid(p_sys
, AUDIO_ES
, i_id
);
2146 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2147 p_sys
->i_spu_stream_idx
= i_id
;
2148 i_pid
= blurayEsPid(p_sys
, SPU_ES
, i_id
);
2152 int i_idx
= findEsPairIndex(p_sys
, i_pid
);
2154 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2155 var_SetInteger( p_demux
->p_input
, "audio-es", i_pid
);
2156 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2157 var_SetInteger( p_demux
->p_input
, "spu-es", p_sys
->b_spu_enable
? i_pid
: -1 );
2163 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2165 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2167 blurayResetParser(p_demux
);
2169 /* read title info and init some values */
2171 p_demux
->info
.i_title
= bd_get_current_title(p_sys
->bluray
);
2172 p_demux
->info
.i_seekpoint
= 0;
2173 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2175 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2177 blurayUpdateTitleInfo(p_sys
->pp_title
[p_demux
->info
.i_title
], p_title_info
);
2179 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE_LIST
;
2181 setTitleInfo(p_sys
, p_title_info
);
2183 blurayResetStillImage(p_demux
);
2186 static void blurayUpdateCurrentClip(demux_t
*p_demux
, uint32_t clip
)
2188 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2190 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2192 p_sys
->p_clip_info
= NULL
;
2193 p_sys
->i_video_stream
= -1;
2195 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2197 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2199 /* Let's assume a single video track for now.
2200 * This may brake later, but it's enough for now.
2202 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2203 p_sys
->i_video_stream
= p_sys
->p_clip_info
->video_streams
[0].pid
;
2206 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2208 blurayResetStillImage(p_demux
);
2211 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
)
2213 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2216 case BD_EVENT_TITLE
:
2217 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2218 p_demux
->info
.i_title
= p_sys
->i_title
- 1;
2220 p_demux
->info
.i_title
= e
->param
;
2221 /* this is feature title, we don't know yet which playlist it will play (if any) */
2222 setTitleInfo(p_sys
, NULL
);
2223 /* reset title infos here ? */
2224 p_demux
->info
.i_update
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
; /* might be BD-J title with no video */
2226 case BD_EVENT_PLAYLIST
:
2227 /* Start of playlist playback (?????.mpls) */
2228 blurayUpdatePlaylist(p_demux
, e
->param
);
2229 if (p_sys
->b_pl_playing
) {
2230 /* previous playlist was stopped in middle. flush to avoid delay */
2231 msg_Info(p_demux
, "Stopping playlist playback");
2232 blurayResetParser(p_demux
);
2233 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2235 p_sys
->b_pl_playing
= true;
2237 case BD_EVENT_PLAYITEM
:
2238 blurayUpdateCurrentClip(p_demux
, e
->param
);
2240 case BD_EVENT_CHAPTER
:
2241 if (e
->param
&& e
->param
< 0xffff)
2242 p_demux
->info
.i_seekpoint
= e
->param
- 1;
2244 p_demux
->info
.i_seekpoint
= 0;
2245 p_demux
->info
.i_update
|= INPUT_UPDATE_SEEKPOINT
;
2247 case BD_EVENT_PLAYMARK
:
2248 case BD_EVENT_ANGLE
:
2250 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2251 case BD_EVENT_UO_MASK_CHANGED
:
2252 /* This event could be used to grey out unselectable items in title menu */
2256 p_sys
->b_menu_open
= e
->param
;
2258 case BD_EVENT_POPUP
:
2259 p_sys
->b_popup_available
= e
->param
;
2260 /* TODO: show / hide pop-up menu button in gui ? */
2266 case BD_EVENT_ERROR
:
2267 /* fatal error (with menus) */
2268 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2269 "Playback with BluRay menus failed");
2270 p_sys
->b_fatal_error
= true;
2272 case BD_EVENT_ENCRYPTED
:
2273 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2274 "This disc seems to be encrypted");
2275 p_sys
->b_fatal_error
= true;
2277 case BD_EVENT_READ_ERROR
:
2278 msg_Err(p_demux
, "bluray: read error\n");
2282 * stream selection events
2284 case BD_EVENT_PG_TEXTST
:
2285 p_sys
->b_spu_enable
= e
->param
;
2287 case BD_EVENT_AUDIO_STREAM
:
2288 case BD_EVENT_PG_TEXTST_STREAM
:
2289 blurayStreamSelect(p_demux
, e
->event
, e
->param
);
2291 case BD_EVENT_IG_STREAM
:
2292 case BD_EVENT_SECONDARY_AUDIO
:
2293 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2294 case BD_EVENT_SECONDARY_VIDEO
:
2295 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2296 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2300 * playback control events
2302 case BD_EVENT_STILL_TIME
:
2303 blurayStillImage(p_demux
, e
->param
);
2305 case BD_EVENT_DISCONTINUITY
:
2306 /* reset demuxer (partially decoded PES packets must be dropped) */
2307 blurayResetParser(p_demux
);
2309 case BD_EVENT_END_OF_TITLE
:
2310 p_sys
->b_pl_playing
= false;
2313 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2314 /* avoid busy loop (bd_read() returns no data) */
2319 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2324 static bool blurayIsBdjTitle(demux_t
*p_demux
)
2326 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2327 unsigned int i_title
= p_demux
->info
.i_title
;
2328 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2330 if (di
&& di
->titles
) {
2331 if ((i_title
<= di
->num_titles
&& di
->titles
[i_title
] && di
->titles
[i_title
]->bdj
) ||
2332 (i_title
== p_sys
->i_title
- 1 && di
->first_play
&& di
->first_play
->bdj
)) {
2340 static void blurayHandleOverlays(demux_t
*p_demux
, int nread
)
2342 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2344 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2346 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
2347 bluray_overlay_t
*ov
= p_sys
->p_overlays
[i
];
2351 vlc_mutex_lock(&ov
->lock
);
2352 bool display
= ov
->status
== ToDisplay
;
2353 vlc_mutex_unlock(&ov
->lock
);
2355 if (p_sys
->p_vout
== NULL
) {
2356 p_sys
->p_vout
= input_GetVout(p_demux
->p_input
);
2357 if (p_sys
->p_vout
!= NULL
) {
2358 var_AddCallback(p_sys
->p_vout
, "mouse-moved", onMouseEvent
, p_demux
);
2359 var_AddCallback(p_sys
->p_vout
, "mouse-clicked", onMouseEvent
, p_demux
);
2363 /* NOTE: we might want to enable background video always when there's no video stream playing.
2364 Now, with some discs, there are perioids (even seconds) during which the video window
2365 disappears and just playlist is shown.
2366 (sometimes BD-J runs slowly ...)
2368 if (!p_sys
->p_vout
&& !p_sys
->p_dummy_video
&& p_sys
->b_menu
&&
2369 !p_sys
->p_pl_info
&& nread
== 0 &&
2370 blurayIsBdjTitle(p_demux
)) {
2372 /* Looks like there's no video stream playing.
2373 Emit blank frame so that BD-J overlay can be drawn. */
2374 startBackground(p_demux
);
2377 if (p_sys
->p_vout
!= NULL
) {
2378 bluraySendOverlayToVout(p_demux
, ov
);
2383 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2386 static int onIntfEvent( vlc_object_t
*p_input
, char const *psz_var
,
2387 vlc_value_t oldval
, vlc_value_t val
, void *p_data
)
2389 (void)p_input
; (void) psz_var
; (void) oldval
;
2390 demux_t
*p_demux
= p_data
;
2391 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2393 if (val
.i_int
== INPUT_EVENT_VOUT
) {
2395 vlc_mutex_lock(&p_sys
->bdj_overlay_lock
);
2396 if( p_sys
->p_vout
!= NULL
) {
2397 blurayReleaseVout(p_demux
);
2399 vlc_mutex_unlock(&p_sys
->bdj_overlay_lock
);
2401 blurayHandleOverlays(p_demux
, 1);
2407 #define BD_TS_PACKET_SIZE (192)
2408 #define NB_TS_PACKETS (200)
2410 static int blurayDemux(demux_t
*p_demux
)
2412 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2415 block_t
*p_block
= block_Alloc(NB_TS_PACKETS
* (int64_t)BD_TS_PACKET_SIZE
);
2417 return VLC_DEMUXER_EGENERIC
;
2421 if (p_sys
->b_menu
== false) {
2422 while (bd_get_event(p_sys
->bluray
, &e
))
2423 blurayHandleEvent(p_demux
, &e
);
2425 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
,
2426 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
);
2428 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
,
2429 NB_TS_PACKETS
* BD_TS_PACKET_SIZE
, &e
);
2430 while (e
.event
!= BD_EVENT_NONE
) {
2431 blurayHandleEvent(p_demux
, &e
);
2432 bd_get_event(p_sys
->bluray
, &e
);
2436 blurayHandleOverlays(p_demux
, nread
);
2439 block_Release(p_block
);
2440 if (p_sys
->b_fatal_error
|| nread
< 0) {
2441 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
2442 return VLC_DEMUXER_EGENERIC
;
2444 if (!p_sys
->b_menu
) {
2445 return VLC_DEMUXER_EOF
;
2447 return VLC_DEMUXER_SUCCESS
;
2450 p_block
->i_buffer
= nread
;
2452 stopBackground(p_demux
);
2454 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2456 p_sys
->b_flushed
= false;
2458 return VLC_DEMUXER_SUCCESS
;