1 /*****************************************************************************
2 * bluray.c: Blu-ray disc support plugin
3 *****************************************************************************
4 * Copyright © 2010-2012 VideoLAN, VLC authors and libbluray AUTHORS
6 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
7 * Hugo Beauzée-Luyssen <hugo@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
29 #include <stdatomic.h>
31 #if defined (HAVE_MNTENT_H) && defined(HAVE_SYS_STAT_H)
34 #include <fcntl.h> /* O_* */
35 #include <unistd.h> /* close() */
39 # include <sys/param.h>
40 # include <sys/ucred.h>
41 # include <sys/mount.h>
44 #include <vlc_common.h>
45 #include <vlc_mouse.h>
46 #include <vlc_plugin.h>
47 #include <vlc_demux.h> /* demux_t */
48 #include <vlc_input.h> /* Seekpoints, chapters */
49 #include <vlc_dialog.h> /* BD+/AACS warnings */
50 #include <vlc_url.h> /* vlc_path2uri */
51 #include <vlc_iso_lang.h>
54 #include "../demux/mpeg/timestamps.h"
55 #include "../demux/timestamps_filter.h"
57 /* FIXME we should find a better way than including that */
58 #include "../../src/text/iso-639_def.h"
61 #include <libbluray/bluray.h>
62 #include <libbluray/bluray-version.h>
63 #include <libbluray/keys.h>
64 #include <libbluray/meta_data.h>
65 #include <libbluray/overlay.h>
66 #include <libbluray/clpi_data.h>
68 //#define DEBUG_BLURAY
69 //#define DEBUG_BLURAY_EVENTS
72 # include <libbluray/log_control.h>
73 # define BLURAY_DEBUG_MASK (0xFFFFF & ~DBG_STREAM)
74 static vlc_object_t
*p_bluray_DebugObject
;
75 static void bluray_DebugHandler(const char *psz
)
77 size_t len
= strlen(psz
);
80 if(psz
[len
- 1] == '\n')
81 psz_log
= strndup(psz
, len
- 1);
82 msg_Dbg(p_bluray_DebugObject
, "%s", psz_log
? psz_log
: psz
);
87 #ifdef DEBUG_BLURAY_EVENTS
88 # define BD_DEBUG_EVENT_ENTRY(a) [a]=#a
89 static const char * bluray_event_debug_strings
[] =
91 BD_DEBUG_EVENT_ENTRY(BD_EVENT_NONE
),
92 BD_DEBUG_EVENT_ENTRY(BD_EVENT_ERROR
),
93 BD_DEBUG_EVENT_ENTRY(BD_EVENT_READ_ERROR
),
94 BD_DEBUG_EVENT_ENTRY(BD_EVENT_ENCRYPTED
),
95 BD_DEBUG_EVENT_ENTRY(BD_EVENT_ANGLE
),
96 BD_DEBUG_EVENT_ENTRY(BD_EVENT_TITLE
),
97 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PLAYLIST
),
98 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PLAYITEM
),
99 BD_DEBUG_EVENT_ENTRY(BD_EVENT_CHAPTER
),
100 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PLAYMARK
),
101 BD_DEBUG_EVENT_ENTRY(BD_EVENT_END_OF_TITLE
),
102 BD_DEBUG_EVENT_ENTRY(BD_EVENT_AUDIO_STREAM
),
103 BD_DEBUG_EVENT_ENTRY(BD_EVENT_IG_STREAM
),
104 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PG_TEXTST_STREAM
),
105 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PIP_PG_TEXTST_STREAM
),
106 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SECONDARY_AUDIO_STREAM
),
107 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SECONDARY_VIDEO_STREAM
),
108 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PG_TEXTST
),
109 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PIP_PG_TEXTST
),
110 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SECONDARY_AUDIO
),
111 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SECONDARY_VIDEO
),
112 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SECONDARY_VIDEO_SIZE
),
113 BD_DEBUG_EVENT_ENTRY(BD_EVENT_PLAYLIST_STOP
),
114 BD_DEBUG_EVENT_ENTRY(BD_EVENT_DISCONTINUITY
),
115 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SEEK
),
116 BD_DEBUG_EVENT_ENTRY(BD_EVENT_STILL
),
117 BD_DEBUG_EVENT_ENTRY(BD_EVENT_STILL_TIME
),
118 BD_DEBUG_EVENT_ENTRY(BD_EVENT_SOUND_EFFECT
),
119 BD_DEBUG_EVENT_ENTRY(BD_EVENT_IDLE
),
120 BD_DEBUG_EVENT_ENTRY(BD_EVENT_POPUP
),
121 BD_DEBUG_EVENT_ENTRY(BD_EVENT_MENU
),
122 BD_DEBUG_EVENT_ENTRY(BD_EVENT_STEREOSCOPIC_STATUS
),
123 BD_DEBUG_EVENT_ENTRY(BD_EVENT_KEY_INTEREST_TABLE
),
124 BD_DEBUG_EVENT_ENTRY(BD_EVENT_UO_MASK_CHANGED
),
126 # define blurayDebugEvent(e, v) do {\
127 if(e < ARRAY_SIZE(bluray_event_debug_strings))\
128 msg_Dbg(p_demux, "Event %s %x", bluray_event_debug_strings[e], v);\
130 msg_Dbg(p_demux, "Event Unk 0x%x %x", e, v);\
133 # define blurayDebugEvent(e, v)
136 /*****************************************************************************
138 *****************************************************************************/
140 #define BD_MENU_TEXT N_("Blu-ray menus")
141 #define BD_MENU_LONGTEXT N_("Use Blu-ray menus. If disabled, "\
142 "the movie will start directly")
143 #define BD_REGION_TEXT N_("Region code")
144 #define BD_REGION_LONGTEXT N_("Blu-Ray player region code. "\
145 "Some discs can be played only with a correct region code.")
147 static const char *const ppsz_region_code
[] = {
149 static const char *const ppsz_region_code_text
[] = {
150 "Region A", "Region B", "Region C" };
152 #define REGION_DEFAULT 1 /* Index to region list. Actual region code is (1<<REGION_DEFAULT) */
153 #define LANGUAGE_DEFAULT ("eng")
155 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,0)
156 # define BLURAY_DEMUX
159 #ifndef BD_STREAM_TYPE_VIDEO_HEVC
160 # define BD_STREAM_TYPE_VIDEO_HEVC 0x24
163 #define BD_CLUSTER_SIZE 6144
164 #define BD_READ_SIZE (10 * BD_CLUSTER_SIZE)
167 static int blurayOpen (vlc_object_t
*);
168 static void blurayClose(vlc_object_t
*);
171 set_shortname(N_("Blu-ray"))
172 set_description(N_("Blu-ray Disc support (libbluray)"))
174 set_category(CAT_INPUT
)
175 set_subcategory(SUBCAT_INPUT_ACCESS
)
176 set_capability("access", 500)
177 add_bool("bluray-menu", true, BD_MENU_TEXT
, BD_MENU_LONGTEXT
, false)
178 add_string("bluray-region", ppsz_region_code
[REGION_DEFAULT
], BD_REGION_TEXT
, BD_REGION_LONGTEXT
, false)
179 change_string_list(ppsz_region_code
, ppsz_region_code_text
)
181 add_shortcut("bluray", "file")
183 set_callbacks(blurayOpen
, blurayClose
)
188 set_description( "BluRay demuxer" )
189 set_category( CAT_INPUT
)
190 set_subcategory( SUBCAT_INPUT_DEMUX
)
191 set_capability( "demux", 5 )
192 set_callbacks( blurayOpen
, blurayClose
)
197 /* libbluray's overlay.h defines 2 types of overlay (bd_overlay_plane_e). */
198 #define MAX_OVERLAY 2
200 typedef enum OverlayStatus
{
202 ToDisplay
, //Used to mark the overlay to be displayed the first time.
204 Outdated
//used to update the overlay after it has been sent to the vout
207 typedef struct bluray_spu_updater_sys_t bluray_spu_updater_sys_t
;
209 typedef struct bluray_overlay_t
213 OverlayStatus status
;
214 subpicture_region_t
*p_regions
;
217 /* pointer to last subpicture updater.
218 * used to disconnect this overlay from vout when:
219 * - the overlay is closed
220 * - vout is changed and this overlay is sent to the new vout
222 bluray_spu_updater_sys_t
*p_updater
;
231 unsigned int i_title
;
232 unsigned int i_longest_title
;
233 input_title_t
**pp_title
;
235 unsigned cur_seekpoint
;
238 vlc_mutex_t pl_info_lock
;
239 BLURAY_TITLE_INFO
*p_pl_info
;
240 const BLURAY_CLIP_INFO
*p_clip_info
;
243 BD_CLIP_APP_TYPE_TS_MAIN_PATH_MOVIE
= 1,
244 BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
= 2,
245 BD_CLIP_APP_TYPE_TS_MAIN_PATH_BROWSABLE_SLIDESHOW
= 3,
246 BD_CLIP_APP_TYPE_TS_SUB_PATH_BROWSABLE_SLIDESHOW
= 4,
247 BD_CLIP_APP_TYPE_TS_SUB_PATH_INTERACTIVE_MENU
= 5,
248 BD_CLIP_APP_TYPE_TS_SUB_PATH_TEXT_SUBTITLE
= 6,
249 BD_CLIP_APP_TYPE_TS_SUB_PATH_ELEMENTARY_STREAM_PATH
= 7,
250 } clip_application_type
;
254 input_attachment_t
**attachments
;
257 /* Meta information */
258 const META_DL
*p_meta
;
264 bool b_popup_available
;
265 vlc_tick_t i_still_end_time
;
268 bluray_overlay_t
*p_overlays
[MAX_OVERLAY
];
269 vlc_mutex_t lock
; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
273 vlc_mouse_t oldmouse
;
278 bool b_spu_enable
; /* enabled / disabled */
279 vlc_demux_chained_t
*p_parser
;
281 bool b_pl_playing
; /* true when playing playlist */
284 vlc_mutex_t read_block_lock
;
286 /* Used to store bluray disc path */
291 * Local ES index storage
297 int i_next_block_flags
;
299 bool b_restart_decoders_on_reuse
;
302 static bool es_pair_Add(vlc_array_t
*p_array
, const es_format_t
*p_fmt
,
305 es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
306 if (likely(p_pair
!= NULL
))
309 p_pair
->i_next_block_flags
= 0;
310 p_pair
->b_recyling
= false;
311 p_pair
->b_restart_decoders_on_reuse
= true;
312 if(vlc_array_append(p_array
, p_pair
) != VLC_SUCCESS
)
319 es_format_Init(&p_pair
->fmt
, p_fmt
->i_cat
, p_fmt
->i_codec
);
320 es_format_Copy(&p_pair
->fmt
, p_fmt
);
323 return p_pair
!= NULL
;
326 static void es_pair_Remove(vlc_array_t
*p_array
, es_pair_t
*p_pair
)
328 vlc_array_remove(p_array
, vlc_array_index_of_item(p_array
, p_pair
));
329 es_format_Clean(&p_pair
->fmt
);
333 static es_pair_t
*getEsPair(vlc_array_t
*p_array
,
334 bool (*match
)(const es_pair_t
*, const void *),
337 for (size_t i
= 0; i
< vlc_array_count(p_array
); ++i
)
339 es_pair_t
*p_pair
= vlc_array_item_at_index(p_array
, i
);
340 if(match(p_pair
, param
))
346 static bool es_pair_compare_PID(const es_pair_t
*p_pair
, const void *p_pid
)
348 return p_pair
->fmt
.i_id
== *((const int *)p_pid
);
351 static bool es_pair_compare_ES(const es_pair_t
*p_pair
, const void *p_es
)
353 return p_pair
->p_es
== (const es_out_id_t
*)p_es
;
356 static bool es_pair_compare_Unused(const es_pair_t
*p_pair
, const void *priv
)
359 return p_pair
->b_recyling
;
362 static es_pair_t
*getEsPairByPID(vlc_array_t
*p_array
, int i_pid
)
364 return getEsPair(p_array
, es_pair_compare_PID
, &i_pid
);
367 static es_pair_t
*getEsPairByES(vlc_array_t
*p_array
, const es_out_id_t
*p_es
)
369 return getEsPair(p_array
, es_pair_compare_ES
, p_es
);
372 static es_pair_t
*getUnusedEsPair(vlc_array_t
*p_array
)
374 return getEsPair(p_array
, es_pair_compare_Unused
, 0);
380 struct bluray_spu_updater_sys_t
382 vlc_mutex_t lock
; // protect p_overlay pointer and ref_cnt
383 bluray_overlay_t
*p_overlay
; // NULL if overlay has been closed
384 int ref_cnt
; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
388 * cut the connection between vout and overlay.
389 * - called when vout is closed or overlay is closed.
390 * - frees bluray_spu_updater_sys_t when both sides have been closed.
392 static void unref_subpicture_updater(bluray_spu_updater_sys_t
*p_sys
)
394 vlc_mutex_lock(&p_sys
->lock
);
395 int refs
= --p_sys
->ref_cnt
;
396 p_sys
->p_overlay
= NULL
;
397 vlc_mutex_unlock(&p_sys
->lock
);
400 vlc_mutex_destroy(&p_sys
->lock
);
406 * FIXME: partiallyy duplicated from src/input/es_out.c
408 static const char *DemuxGetLanguageCode( demux_t
*p_demux
, const char *psz_var
)
410 const iso639_lang_t
*pl
;
414 psz_lang
= var_CreateGetString( p_demux
, psz_var
);
416 return LANGUAGE_DEFAULT
;
418 /* XXX: we will use only the first value
419 * (and ignore other ones in case of a list) */
420 if( ( p
= strchr( psz_lang
, ',' ) ) )
423 for( pl
= p_languages
; pl
->psz_eng_name
!= NULL
; pl
++ )
425 if( *psz_lang
== '\0' )
427 if( !strcasecmp( pl
->psz_eng_name
, psz_lang
) ||
428 !strcasecmp( pl
->psz_iso639_1
, psz_lang
) ||
429 !strcasecmp( pl
->psz_iso639_2T
, psz_lang
) ||
430 !strcasecmp( pl
->psz_iso639_2B
, psz_lang
) )
436 if( pl
->psz_eng_name
!= NULL
)
437 return pl
->psz_iso639_2T
;
439 return LANGUAGE_DEFAULT
;
442 /*****************************************************************************
444 *****************************************************************************/
445 static es_out_t
*esOutNew(vlc_object_t
*, es_out_t
*, void *);
447 static int blurayControl(demux_t
*, int, va_list);
448 static int blurayDemux(demux_t
*);
450 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
);
451 static int bluraySetTitle(demux_t
*p_demux
, int i_title
);
453 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
* const overlay
);
454 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
* const overlay
);
455 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
);
457 static void onMouseEvent(const vlc_mouse_t
*mouse
, void *user_data
);
458 static void blurayRestartParser(demux_t
*p_demux
, bool, bool);
459 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
);
461 #define STILL_IMAGE_NOT_SET 0
462 #define STILL_IMAGE_INFINITE -1
464 #define CURRENT_TITLE p_sys->pp_title[p_sys->cur_title]
465 #define CUR_LENGTH CURRENT_TITLE->i_length
468 static void FindMountPoint(char **file
)
470 char *device
= *file
;
471 #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H)
472 /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
473 * we look up the real device */
474 char *bd_device
= realpath(device
, NULL
);
475 if (bd_device
== NULL
)
479 if (lstat (bd_device
, &st
) == 0 && S_ISBLK (st
.st_mode
)) {
480 FILE *mtab
= setmntent ("/proc/self/mounts", "r");
482 struct mntent
*m
, mbuf
;
485 while ((m
= getmntent_r (mtab
, &mbuf
, buf
, sizeof(buf
))) != NULL
) {
486 if (!strcmp (m
->mnt_fsname
, bd_device
)) {
488 *file
= strdup(m
->mnt_dir
);
497 #elif defined(__APPLE__)
499 if (!stat (device
, &st
) && S_ISBLK (st
.st_mode
)) {
500 int fs_count
= getfsstat (NULL
, 0, MNT_NOWAIT
);
502 struct statfs mbuf
[128];
503 getfsstat (mbuf
, fs_count
* sizeof(mbuf
[0]), MNT_NOWAIT
);
504 for (int i
= 0; i
< fs_count
; ++i
)
505 if (!strcmp (mbuf
[i
].f_mntfromname
, device
)) {
507 *file
= strdup(mbuf
[i
].f_mntonname
);
513 # warning Disc device to mount point not implemented
514 VLC_UNUSED( device
);
518 /*****************************************************************************
519 * BD-J background video
520 *****************************************************************************/
522 static void bluraySendBackgroundImage(vlc_object_t
*p_obj
,
525 const es_format_t
*p_fmt
)
527 msg_Info(p_obj
, "Start background");
529 block_t
*p_block
= block_Alloc(p_fmt
->video
.i_width
* p_fmt
->video
.i_height
*
530 p_fmt
->video
.i_bits_per_pixel
/ 8);
532 msg_Err(p_obj
, "Error allocating block for background video");
536 // XXX TODO: what would be correct timestamp ???
537 p_block
->i_dts
= p_block
->i_pts
= vlc_tick_now() + VLC_TICK_FROM_MS(40);
539 uint8_t *p
= p_block
->p_buffer
;
540 memset(p
, 0, p_fmt
->video
.i_width
* p_fmt
->video
.i_height
);
541 p
+= p_fmt
->video
.i_width
* p_fmt
->video
.i_height
;
542 memset(p
, 0x80, p_fmt
->video
.i_width
* p_fmt
->video
.i_height
/ 2);
544 es_out_SetPCR(p_dst_out
, p_block
->i_dts
- VLC_TICK_FROM_MS(40));
545 es_out_Control(p_dst_out
, ES_OUT_SET_ES
, p_es
);
546 es_out_Send(p_dst_out
, p_es
, p_block
);
547 es_out_Control( p_dst_out
, ES_OUT_VOUT_SET_MOUSE_EVENT
, p_es
, onMouseEvent
, p_obj
);
548 es_out_SetPCR(p_dst_out
, p_block
->i_dts
);
551 /*****************************************************************************
552 * cache current playlist (title) information
553 *****************************************************************************/
555 static void setTitleInfo(demux_sys_t
*p_sys
, BLURAY_TITLE_INFO
*info
)
557 vlc_mutex_lock(&p_sys
->pl_info_lock
);
559 if (p_sys
->p_pl_info
) {
560 bd_free_title_info(p_sys
->p_pl_info
);
562 p_sys
->p_pl_info
= info
;
563 p_sys
->p_clip_info
= NULL
;
565 if (p_sys
->p_pl_info
&& p_sys
->p_pl_info
->clip_count
) {
566 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[0];
569 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
572 /*****************************************************************************
573 * create input attachment for thumbnail
574 *****************************************************************************/
576 static void attachThumbnail(demux_t
*p_demux
)
578 demux_sys_t
*p_sys
= p_demux
->p_sys
;
583 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,9,0)
584 if (p_sys
->p_meta
->thumb_count
> 0 && p_sys
->p_meta
->thumbnails
) {
587 if (bd_get_meta_file(p_sys
->bluray
, p_sys
->p_meta
->thumbnails
[0].path
, &data
, &size
) > 0) {
589 input_attachment_t
*p_attachment
;
591 snprintf(psz_name
, sizeof(psz_name
), "picture%d_%s", p_sys
->i_attachments
, p_sys
->p_meta
->thumbnails
[0].path
);
593 p_attachment
= vlc_input_attachment_New(psz_name
, NULL
, "Album art", data
, size
);
595 p_sys
->i_cover_idx
= p_sys
->i_attachments
;
596 TAB_APPEND(p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
604 /*****************************************************************************
606 *****************************************************************************/
608 static int probeStream(demux_t
*p_demux
)
610 /* input must be seekable */
611 bool b_canseek
= false;
612 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_canseek
);
617 /* first sector(s) should be filled with zeros */
619 const uint8_t *p_peek
;
620 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 2048 );
621 if( i_peek
!= 2048 ) {
625 if (p_peek
[ --i_peek
]) {
634 static int blurayReadBlock(void *object
, void *buf
, int lba
, int num_blocks
)
636 demux_t
*p_demux
= (demux_t
*)object
;
637 demux_sys_t
*p_sys
= p_demux
->p_sys
;
640 assert(p_demux
->s
!= NULL
);
642 vlc_mutex_lock(&p_sys
->read_block_lock
);
644 if (vlc_stream_Seek( p_demux
->s
, lba
* INT64_C(2048) ) == VLC_SUCCESS
) {
645 size_t req
= (size_t)2048 * num_blocks
;
648 got
= vlc_stream_Read( p_demux
->s
, buf
, req
);
650 msg_Err(p_demux
, "read from lba %d failed", lba
);
655 msg_Err(p_demux
, "seek to lba %d failed", lba
);
658 vlc_mutex_unlock(&p_sys
->read_block_lock
);
664 /*****************************************************************************
665 * probing of local files
666 *****************************************************************************/
668 /* Descriptor Tag (ECMA 167, 3/7.2) */
669 static int decode_descriptor_tag(const uint8_t *buf
)
672 uint8_t checksum
= 0;
675 id
= buf
[0] | (buf
[1] << 8);
677 /* calculate tag checksum */
678 for (i
= 0; i
< 4; i
++) {
679 checksum
= (uint8_t)(checksum
+ buf
[i
]);
681 for (i
= 5; i
< 16; i
++) {
682 checksum
= (uint8_t)(checksum
+ buf
[i
]);
685 if (checksum
!= buf
[4]) {
692 static int probeFile(const char *psz_name
)
694 struct stat stat_info
;
697 int ret
= VLC_EGENERIC
;
700 fd
= vlc_open(psz_name
, O_RDONLY
| O_NONBLOCK
);
705 if (fstat(fd
, &stat_info
) == -1) {
708 if (!S_ISREG(stat_info
.st_mode
) && !S_ISBLK(stat_info
.st_mode
)) {
712 /* first sector should be filled with zeros */
713 if (read(fd
, peek
, sizeof(peek
)) != sizeof(peek
)) {
716 for (i
= 0; i
< sizeof(peek
); i
++) {
722 /* Check AVDP tag checksum */
723 if (lseek(fd
, 256 * 2048, SEEK_SET
) == -1 ||
724 read(fd
, peek
, 16) != 16 ||
725 decode_descriptor_tag(peek
) != 2) {
736 /*****************************************************************************
737 * blurayOpen: module init function
738 *****************************************************************************/
739 static int blurayOpen(vlc_object_t
*object
)
741 demux_t
*p_demux
= (demux_t
*)object
;
744 uint64_t i_init_pos
= 0;
746 const char *error_msg
= NULL
;
747 #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
749 if (p_demux
->out
== NULL
)
752 forced
= !strncasecmp(p_demux
->psz_url
, "bluray:", 7);
755 if (!strncasecmp(p_demux
->psz_url
, "file:", 5)) {
756 /* use access_demux for local files */
760 if (probeStream(p_demux
) != VLC_SUCCESS
) {
764 } else if (!forced
) {
765 if (!p_demux
->psz_filepath
) {
769 if (probeFile(p_demux
->psz_filepath
) != VLC_SUCCESS
) {
775 p_demux
->p_sys
= p_sys
= vlc_obj_calloc(object
, 1, sizeof(*p_sys
));
776 if (unlikely(!p_sys
))
779 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
781 /* init demux info fields */
784 TAB_INIT(p_sys
->i_title
, p_sys
->pp_title
);
785 TAB_INIT(p_sys
->i_attachments
, p_sys
->attachments
);
787 vlc_mouse_Init(&p_sys
->oldmouse
);
789 vlc_mutex_init(&p_sys
->pl_info_lock
);
790 vlc_mutex_init(&p_sys
->bdj
.lock
);
791 vlc_mutex_init(&p_sys
->read_block_lock
); /* used during bd_open_stream() */
793 /* request sub demuxers to skip continuity check as some split
794 file concatenation are just resetting counters... */
795 var_Create( p_demux
, "ts-cc-check", VLC_VAR_BOOL
);
796 var_SetBool( p_demux
, "ts-cc-check", false );
797 var_Create( p_demux
, "ts-standard", VLC_VAR_STRING
);
798 var_SetString( p_demux
, "ts-standard", "mpeg" );
799 var_Create( p_demux
, "ts-pmtfix-waitdata", VLC_VAR_BOOL
);
800 var_SetBool( p_demux
, "ts-pmtfix-waitdata", false );
801 var_Create( p_demux
, "ts-patfix", VLC_VAR_BOOL
);
802 var_SetBool( p_demux
, "ts-patfix", false );
803 var_Create( p_demux
, "ts-pcr-offsetfix", VLC_VAR_BOOL
);
804 var_SetBool( p_demux
, "ts-pcr-offsetfix", false );
807 p_bluray_DebugObject
= VLC_OBJECT(p_demux
);
808 bd_set_debug_mask(BLURAY_DEBUG_MASK
);
809 bd_set_debug_handler(bluray_DebugHandler
);
815 i_init_pos
= vlc_stream_Tell(p_demux
->s
);
817 p_sys
->bluray
= bd_init();
818 if (!bd_open_stream(p_sys
->bluray
, p_demux
, blurayReadBlock
)) {
819 bd_close(p_sys
->bluray
);
820 p_sys
->bluray
= NULL
;
825 if (!p_demux
->psz_filepath
) {
826 /* no path provided (bluray://). use default DVD device. */
827 p_sys
->psz_bd_path
= var_InheritString(object
, "dvd");
829 /* store current bd path */
830 p_sys
->psz_bd_path
= strdup(p_demux
->psz_filepath
);
833 /* If we're passed a block device, try to convert it to the mount point. */
834 FindMountPoint(&p_sys
->psz_bd_path
);
836 p_sys
->bluray
= bd_open(p_sys
->psz_bd_path
, NULL
);
838 if (!p_sys
->bluray
) {
842 /* Warning the user about AACS/BD+ */
843 const BLURAY_DISC_INFO
*disc_info
= bd_get_disc_info(p_sys
->bluray
);
845 /* Is it a bluray? */
846 if (!disc_info
->bluray_detected
) {
848 BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
853 msg_Info(p_demux
, "First play: %i, Top menu: %i\n"
854 "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
855 disc_info
->first_play_supported
, disc_info
->top_menu_supported
,
856 disc_info
->num_hdmv_titles
, disc_info
->num_bdj_titles
,
857 disc_info
->num_unsupported_titles
);
860 if (disc_info
->aacs_detected
) {
861 msg_Dbg(p_demux
, "Disc is using AACS");
862 if (!disc_info
->libaacs_detected
)
863 BLURAY_ERROR(_("This Blu-ray Disc needs a library for AACS decoding"
864 ", and your system does not have it."));
865 if (!disc_info
->aacs_handled
) {
866 if (disc_info
->aacs_error_code
) {
867 switch (disc_info
->aacs_error_code
) {
868 case BD_AACS_CORRUPTED_DISC
:
869 BLURAY_ERROR(_("Blu-ray Disc is corrupted."));
870 case BD_AACS_NO_CONFIG
:
871 BLURAY_ERROR(_("Missing AACS configuration file!"));
873 BLURAY_ERROR(_("No valid processing key found in AACS config file."));
874 case BD_AACS_NO_CERT
:
875 BLURAY_ERROR(_("No valid host certificate found in AACS config file."));
876 case BD_AACS_CERT_REVOKED
:
877 BLURAY_ERROR(_("AACS Host certificate revoked."));
878 case BD_AACS_MMC_FAILED
:
879 BLURAY_ERROR(_("AACS MMC failed."));
886 if (disc_info
->bdplus_detected
) {
887 msg_Dbg(p_demux
, "Disc is using BD+");
888 if (!disc_info
->libbdplus_detected
)
889 BLURAY_ERROR(_("This Blu-ray Disc needs a library for BD+ decoding"
890 ", and your system does not have it."));
891 if (!disc_info
->bdplus_handled
)
892 BLURAY_ERROR(_("Your system BD+ decoding library does not work. "
893 "Missing configuration?"));
896 /* set player region code */
897 char *psz_region
= var_InheritString(p_demux
, "bluray-region");
898 unsigned int region
= psz_region
? (psz_region
[0] - 'A') : REGION_DEFAULT
;
900 bd_set_player_setting(p_sys
->bluray
, BLURAY_PLAYER_SETTING_REGION_CODE
, 1<<region
);
902 /* set preferred languages */
903 const char *psz_code
= DemuxGetLanguageCode( p_demux
, "audio-language" );
904 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
, psz_code
);
905 psz_code
= DemuxGetLanguageCode( p_demux
, "sub-language" );
906 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
, psz_code
);
907 psz_code
= DemuxGetLanguageCode( p_demux
, "menu-language" );
908 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_MENU_LANG
, psz_code
);
910 /* Get disc metadata */
911 p_sys
->p_meta
= bd_get_meta(p_sys
->bluray
);
913 msg_Warn(p_demux
, "Failed to get meta info.");
915 p_sys
->i_cover_idx
= -1;
916 attachThumbnail(p_demux
);
918 p_sys
->b_menu
= var_InheritBool(p_demux
, "bluray-menu");
920 /* Check BD-J capability */
921 if (p_sys
->b_menu
&& disc_info
->bdj_detected
&& !disc_info
->bdj_handled
) {
922 msg_Err(p_demux
, "BD-J menus not supported. Playing without menus. "
923 "BD-J support: %d, JVM found: %d, JVM usable: %d",
924 disc_info
->bdj_supported
, disc_info
->libjvm_detected
, disc_info
->bdj_handled
);
925 vlc_dialog_display_error(p_demux
, _("Java required"),
926 _("This Blu-ray disc requires Java for menus support.%s\nThe disc will be played without menus."),
927 !disc_info
->libjvm_detected
? _("Java was not found on your system.") : "");
928 p_sys
->b_menu
= false;
931 /* Get titles and chapters */
932 blurayInitTitles(p_demux
, disc_info
->num_hdmv_titles
+ disc_info
->num_bdj_titles
+ 1/*Top Menu*/ + 1/*First Play*/);
935 * Initialize the event queue, so we can receive events in blurayDemux(Menu).
937 bd_get_event(p_sys
->bluray
, NULL
);
939 /* Registering overlay event handler */
940 bd_register_overlay_proc(p_sys
->bluray
, p_demux
, blurayOverlayProc
);
944 /* Register ARGB overlay handler for BD-J */
945 if (disc_info
->num_bdj_titles
)
946 bd_register_argb_overlay_proc(p_sys
->bluray
, p_demux
, blurayArgbOverlayProc
, NULL
);
948 /* libbluray will start playback from "First-Title" title */
949 if (bd_play(p_sys
->bluray
) == 0)
950 BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support."));
953 /* set start title number */
954 if (bluraySetTitle(p_demux
, p_sys
->i_longest_title
) != VLC_SUCCESS
) {
955 msg_Err(p_demux
, "Could not set the title %d", p_sys
->i_longest_title
);
960 p_sys
->p_tf_out
= timestamps_filter_es_out_New(p_demux
->out
);
961 if(unlikely(!p_sys
->p_tf_out
))
964 p_sys
->p_out
= esOutNew(VLC_OBJECT(p_demux
), p_sys
->p_tf_out
, p_demux
);
965 if (unlikely(p_sys
->p_out
== NULL
))
968 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
969 if (!p_sys
->p_parser
) {
970 msg_Err(p_demux
, "Failed to create TS demuxer");
974 p_demux
->pf_control
= blurayControl
;
975 p_demux
->pf_demux
= blurayDemux
;
981 vlc_dialog_display_error(p_demux
, _("Blu-ray error"), "%s", error_msg
);
984 if (p_demux
->s
!= NULL
) {
985 /* restore stream position */
986 if (vlc_stream_Seek(p_demux
->s
, i_init_pos
) != VLC_SUCCESS
) {
987 msg_Err(p_demux
, "Failed to seek back to stream start");
997 /*****************************************************************************
998 * blurayClose: module destroy function
999 *****************************************************************************/
1000 static void blurayClose(vlc_object_t
*object
)
1002 demux_t
*p_demux
= (demux_t
*)object
;
1003 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1005 setTitleInfo(p_sys
, NULL
);
1008 * Close libbluray first.
1009 * This will close all the overlays before we release p_vout
1010 * bd_close(NULL) can crash
1012 if (p_sys
->bluray
) {
1013 bd_close(p_sys
->bluray
);
1016 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1017 for(int i
= 0; i
< MAX_OVERLAY
; i
++)
1018 blurayCloseOverlay(p_demux
, i
);
1019 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1021 if (p_sys
->p_parser
)
1022 vlc_demux_chained_Delete(p_sys
->p_parser
);
1024 if (p_sys
->p_out
!= NULL
)
1025 es_out_Delete(p_sys
->p_out
);
1027 timestamps_filter_es_out_Delete(p_sys
->p_tf_out
);
1030 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1031 vlc_input_title_Delete(p_sys
->pp_title
[i
]);
1032 TAB_CLEAN(p_sys
->i_title
, p_sys
->pp_title
);
1034 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1035 vlc_input_attachment_Delete(p_sys
->attachments
[i
]);
1036 TAB_CLEAN(p_sys
->i_attachments
, p_sys
->attachments
);
1038 vlc_mutex_destroy(&p_sys
->pl_info_lock
);
1039 vlc_mutex_destroy(&p_sys
->bdj
.lock
);
1040 vlc_mutex_destroy(&p_sys
->read_block_lock
);
1042 free(p_sys
->psz_bd_path
);
1045 /*****************************************************************************
1046 * Elementary streams handling
1047 *****************************************************************************/
1048 static uint8_t blurayGetStreamsUnlocked(demux_sys_t
*p_sys
,
1050 BLURAY_STREAM_INFO
**pp_streams
)
1052 if(!p_sys
->p_clip_info
)
1055 switch(i_stream_type
)
1057 case BD_EVENT_AUDIO_STREAM
:
1058 *pp_streams
= p_sys
->p_clip_info
->audio_streams
;
1059 return p_sys
->p_clip_info
->audio_stream_count
;
1060 case BD_EVENT_PG_TEXTST_STREAM
:
1061 *pp_streams
= p_sys
->p_clip_info
->pg_streams
;
1062 return p_sys
->p_clip_info
->pg_stream_count
;
1068 static BLURAY_STREAM_INFO
* blurayGetStreamInfoUnlocked(demux_sys_t
*p_sys
,
1070 uint8_t i_stream_idx
)
1072 BLURAY_STREAM_INFO
*p_streams
= NULL
;
1073 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_stream_type
, &p_streams
);
1074 if(i_stream_idx
< i_streams_count
)
1075 return &p_streams
[i_stream_idx
];
1080 static BLURAY_STREAM_INFO
* blurayGetStreamInfoByPIDUnlocked(demux_sys_t
*p_sys
,
1083 for(int i_type
=BD_EVENT_AUDIO_STREAM
; i_type
<=BD_EVENT_SECONDARY_VIDEO_STREAM
; i_type
++)
1085 BLURAY_STREAM_INFO
*p_streams
;
1086 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_type
, &p_streams
);
1087 for(uint8_t i
=0; i
<i_streams_count
; i
++)
1089 if(p_streams
[i
].pid
== i_pid
)
1090 return &p_streams
[i
];
1096 static void setStreamLang(demux_sys_t
*p_sys
, es_format_t
*p_fmt
)
1098 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1100 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoByPIDUnlocked(p_sys
, p_fmt
->i_id
);
1103 free(p_fmt
->psz_language
);
1104 p_fmt
->psz_language
= strndup((const char *)p_stream
->lang
, 3);
1107 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1110 static int blurayGetStreamPID(demux_sys_t
*p_sys
, int i_stream_type
, uint8_t i_stream_idx
)
1112 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1114 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoUnlocked(p_sys
,
1117 int i_pid
= p_stream
? p_stream
->pid
: -1;
1119 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1124 /*****************************************************************************
1125 * bluray fake es_out
1126 *****************************************************************************/
1129 es_out_t
*p_dst_out
;
1130 vlc_object_t
*p_obj
;
1131 vlc_array_t es
; /* es_pair_t */
1132 bool b_entered_recycling
;
1133 bool b_restart_decoders_on_reuse
;
1135 bool b_discontinuity
;
1136 bool b_disable_output
;
1141 int i_audio_pid
; /* Selected audio stream. -1 if default */
1143 int i_spu_pid
; /* Selected spu stream. -1 if default */
1147 es_out_id_t
*p_video_es
;
1148 int channels
[MAX_OVERLAY
];
1151 } bluray_esout_priv_t
;
1155 BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
= ES_OUT_PRIVATE_START
,
1156 BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
,
1157 BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
,
1158 BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
,
1159 BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
,
1160 BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
,
1161 BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
,
1162 BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
,
1163 BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
,
1164 BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
,
1167 static es_out_id_t
*bluray_esOutAddUnlocked(bluray_esout_priv_t
*esout_priv
,
1168 const es_format_t
*p_fmt
)
1170 demux_t
*p_demux
= esout_priv
->priv
;
1171 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1173 bool b_select
= false;
1175 es_format_Copy(&fmt
, p_fmt
);
1177 switch (fmt
.i_cat
) {
1179 if(esout_priv
->b_lowdelay
)
1181 fmt
.video
.i_frame_rate
= 1; fmt
.video
.i_frame_rate_base
= 1;
1182 fmt
.b_packetized
= true;
1184 if (esout_priv
->selected
.i_video_pid
!= -1 && esout_priv
->selected
.i_video_pid
!= p_fmt
->i_id
)
1185 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1186 b_select
= (p_fmt
->i_id
== 0x1011);
1189 if (esout_priv
->selected
.i_audio_pid
!= -1) {
1190 if (esout_priv
->selected
.i_audio_pid
== p_fmt
->i_id
)
1192 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1194 setStreamLang(p_sys
, &fmt
);
1197 if (esout_priv
->selected
.i_spu_pid
!= -1) {
1198 if (esout_priv
->selected
.i_spu_pid
== p_fmt
->i_id
)
1199 b_select
= p_sys
->b_spu_enable
;
1200 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1202 setStreamLang(p_sys
, &fmt
);
1208 es_out_id_t
*p_es
= NULL
;
1209 if (p_fmt
->i_id
>= 0) {
1210 /* Ensure we are not overriding anything */
1211 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, p_fmt
->i_id
);
1214 msg_Info(p_demux
, "Adding ES %d select %d", p_fmt
->i_id
, b_select
);
1215 p_es
= es_out_Add(esout_priv
->p_dst_out
, &fmt
);
1216 es_pair_Add(&esout_priv
->es
, &fmt
, p_es
);
1220 msg_Info(p_demux
, "Reusing ES %d", p_fmt
->i_id
);
1221 p_pair
->b_recyling
= false;
1222 p_es
= p_pair
->p_es
;
1223 if(!es_format_IsSimilar(p_fmt
, &p_pair
->fmt
) ||
1224 p_fmt
->b_packetized
!= p_pair
->fmt
.b_packetized
||
1225 esout_priv
->b_restart_decoders_on_reuse
)
1226 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_SET_ES_FMT
, p_pair
->p_es
, &fmt
);
1227 es_format_Clean(&p_pair
->fmt
);
1228 es_format_Copy(&p_pair
->fmt
, &fmt
);
1231 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_SET_ES
, p_es
);
1234 if (p_es
&& fmt
.i_cat
== VIDEO_ES
&& b_select
)
1236 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_SET_MOUSE_EVENT
, p_es
,
1237 onMouseEvent
, p_demux
);
1238 esout_priv
->overlay
.p_video_es
= p_es
;
1241 es_format_Clean(&fmt
);
1246 static es_out_id_t
*bluray_esOutAdd(es_out_t
*p_out
, const es_format_t
*p_fmt
)
1248 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1250 vlc_mutex_lock(&esout_priv
->lock
);
1251 es_out_id_t
*p_es
= bluray_esOutAddUnlocked(esout_priv
, p_fmt
);
1252 vlc_mutex_unlock(&esout_priv
->lock
);
1257 static void bluray_esOutDeleteNonReusedESUnlocked(es_out_t
*p_out
)
1259 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1261 if(!esout_priv
->b_entered_recycling
)
1263 esout_priv
->b_entered_recycling
= false;
1264 esout_priv
->b_restart_decoders_on_reuse
= true;
1267 while((p_pair
= getUnusedEsPair(&esout_priv
->es
)))
1269 msg_Info(esout_priv
->p_obj
, "Trashing unused ES %d", p_pair
->fmt
.i_id
);
1271 if(esout_priv
->overlay
.p_video_es
== p_pair
->p_es
)
1272 esout_priv
->overlay
.p_video_es
= NULL
;
1274 es_out_Del(esout_priv
->p_dst_out
, p_pair
->p_es
);
1276 es_pair_Remove(&esout_priv
->es
, p_pair
);
1280 static int bluray_esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1282 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1283 vlc_mutex_lock(&esout_priv
->lock
);
1285 bluray_esOutDeleteNonReusedESUnlocked(p_out
);
1287 if(esout_priv
->b_discontinuity
)
1288 esout_priv
->b_discontinuity
= false;
1290 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1291 if(p_pair
&& p_pair
->i_next_block_flags
)
1293 p_block
->i_flags
|= p_pair
->i_next_block_flags
;
1294 p_pair
->i_next_block_flags
= 0;
1296 if(esout_priv
->b_disable_output
)
1298 block_Release(p_block
);
1301 vlc_mutex_unlock(&esout_priv
->lock
);
1302 return (p_block
) ? es_out_Send(esout_priv
->p_dst_out
, p_es
, p_block
) : VLC_SUCCESS
;
1305 static void bluray_esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1307 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1308 vlc_mutex_lock(&esout_priv
->lock
);
1310 if(esout_priv
->b_discontinuity
)
1311 esout_priv
->b_discontinuity
= false;
1313 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1316 p_pair
->b_recyling
= true;
1317 esout_priv
->b_entered_recycling
= true;
1320 vlc_mutex_unlock(&esout_priv
->lock
);
1323 static int bluray_esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1325 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1327 vlc_mutex_lock(&esout_priv
->lock
);
1329 if(esout_priv
->b_disable_output
&&
1330 i_query
< ES_OUT_PRIVATE_START
)
1332 vlc_mutex_unlock(&esout_priv
->lock
);
1333 return VLC_EGENERIC
;
1336 if(esout_priv
->b_discontinuity
)
1337 esout_priv
->b_discontinuity
= false;
1341 case BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
:
1342 case BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
:
1344 bool b_select
= (i_query
== BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
);
1345 const int i_bluray_stream_type
= va_arg(args
, int);
1346 const int i_pid
= va_arg(args
, int);
1347 switch(i_bluray_stream_type
)
1349 case BD_EVENT_AUDIO_STREAM
:
1350 esout_priv
->selected
.i_audio_pid
= i_pid
;
1352 case BD_EVENT_PG_TEXTST_STREAM
:
1353 esout_priv
->selected
.i_spu_pid
= i_pid
;
1359 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, i_pid
);
1360 if(unlikely(!p_pair
))
1362 vlc_mutex_unlock(&esout_priv
->lock
);
1363 return VLC_EGENERIC
;
1366 i_ret
= es_out_Control(esout_priv
->p_dst_out
,
1367 b_select
? ES_OUT_SET_ES
: ES_OUT_UNSET_ES
,
1371 case BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
:
1373 esout_priv
->b_discontinuity
= true;
1374 i_ret
= VLC_SUCCESS
;
1377 case BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
:
1379 esout_priv
->b_restart_decoders_on_reuse
= !va_arg(args
, int);
1380 i_ret
= VLC_SUCCESS
;
1383 case BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
:
1384 case BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
:
1386 esout_priv
->b_disable_output
= (i_query
== BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
1387 i_ret
= VLC_SUCCESS
;
1390 case BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
:
1391 case BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
:
1393 esout_priv
->b_lowdelay
= (i_query
== BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
);
1394 i_ret
= VLC_SUCCESS
;
1397 case BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
:
1399 int i_plane
= va_arg(args
, int);
1400 subpicture_t
*p_pic
= va_arg(args
, subpicture_t
*);
1401 if(!esout_priv
->overlay
.p_video_es
)
1404 es_format_Init(&fmt
, VIDEO_ES
, VLC_CODEC_I420
);
1405 video_format_Setup(&fmt
.video
, VLC_CODEC_I420
,
1406 1920, 1080, 1920, 1080, 1, 1);
1407 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1410 fmt
.video
.i_frame_rate
= 1; fmt
.video
.i_frame_rate_base
= 1;
1411 fmt
.b_packetized
= true;
1412 esout_priv
->overlay
.p_video_es
= bluray_esOutAddUnlocked(esout_priv
, &fmt
);
1413 if(esout_priv
->overlay
.p_video_es
)
1415 bluraySendBackgroundImage(esout_priv
->p_obj
,
1416 esout_priv
->p_dst_out
,
1417 esout_priv
->overlay
.p_video_es
,
1420 es_format_Clean(&fmt
);
1423 if(esout_priv
->overlay
.p_video_es
&& i_plane
< MAX_OVERLAY
)
1425 i_ret
= es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_ADD_OVERLAY
,
1426 esout_priv
->overlay
.p_video_es
, p_pic
,
1427 &esout_priv
->overlay
.channels
[i_plane
]);
1431 i_ret
= VLC_EGENERIC
;
1436 case BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
:
1438 int i_plane
= va_arg(args
, int);
1439 if(esout_priv
->overlay
.p_video_es
&&
1440 i_plane
< MAX_OVERLAY
&&
1441 esout_priv
->overlay
.channels
[i_plane
] != VOUT_SPU_CHANNEL_INVALID
)
1443 i_ret
= es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_FLUSH_OVERLAY
,
1444 esout_priv
->overlay
.p_video_es
,
1445 esout_priv
->overlay
.channels
[i_plane
]);
1446 esout_priv
->overlay
.channels
[i_plane
] = VOUT_SPU_CHANNEL_INVALID
;
1450 assert(esout_priv
->overlay
.channels
[i_plane
] == VOUT_SPU_CHANNEL_INVALID
);
1451 i_ret
= VLC_EGENERIC
;
1456 case ES_OUT_SET_ES_DEFAULT
:
1458 case ES_OUT_UNSET_ES
:
1459 case ES_OUT_SET_ES_STATE
:
1460 i_ret
= VLC_EGENERIC
;
1463 case ES_OUT_GET_ES_STATE
:
1464 va_arg(args
, es_out_id_t
*);
1465 *va_arg(args
, bool *) = true;
1466 i_ret
= VLC_SUCCESS
;
1470 i_ret
= es_out_vaControl(esout_priv
->p_dst_out
, i_query
, args
);
1473 vlc_mutex_unlock(&esout_priv
->lock
);
1477 static void bluray_esOutDestroy(es_out_t
*p_out
)
1479 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1481 for (size_t i
= 0; i
< vlc_array_count(&esout_priv
->es
); ++i
)
1482 free(vlc_array_item_at_index(&esout_priv
->es
, i
));
1483 vlc_array_clear(&esout_priv
->es
);
1484 vlc_mutex_destroy(&esout_priv
->lock
);
1488 static const struct es_out_callbacks bluray_esOutCallbacks
= {
1489 .add
= bluray_esOutAdd
,
1490 .send
= bluray_esOutSend
,
1491 .del
= bluray_esOutDel
,
1492 .control
= bluray_esOutControl
,
1493 .destroy
= bluray_esOutDestroy
,
1496 static es_out_t
*esOutNew(vlc_object_t
*p_obj
, es_out_t
*p_dst_out
, void *priv
)
1498 bluray_esout_priv_t
*esout_priv
= malloc(sizeof(*esout_priv
));
1499 if (unlikely(esout_priv
== NULL
))
1502 vlc_array_init(&esout_priv
->es
);
1503 esout_priv
->p_dst_out
= p_dst_out
;
1504 esout_priv
->p_obj
= p_obj
;
1505 esout_priv
->priv
= priv
;
1506 esout_priv
->es_out
.cbs
= &bluray_esOutCallbacks
;
1507 esout_priv
->b_discontinuity
= false;
1508 esout_priv
->b_disable_output
= false;
1509 esout_priv
->b_entered_recycling
= false;
1510 esout_priv
->b_restart_decoders_on_reuse
= true;
1511 esout_priv
->b_lowdelay
= false;
1512 esout_priv
->selected
.i_audio_pid
= -1;
1513 esout_priv
->selected
.i_video_pid
= -1;
1514 esout_priv
->selected
.i_spu_pid
= -1;
1515 esout_priv
->overlay
.p_video_es
= NULL
;
1516 for(size_t i
=0; i
<MAX_OVERLAY
; i
++)
1517 esout_priv
->overlay
.channels
[i
] = VOUT_SPU_CHANNEL_INVALID
;
1518 vlc_mutex_init(&esout_priv
->lock
);
1519 return &esout_priv
->es_out
;
1522 /*****************************************************************************
1523 * subpicture_updater_t functions:
1524 *****************************************************************************/
1526 static bluray_overlay_t
*updater_lock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1528 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1529 vlc_mutex_lock(&p_upd_sys
->lock
);
1531 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1533 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1534 vlc_mutex_lock(&ov
->lock
);
1538 /* overlay has been closed */
1539 vlc_mutex_unlock(&p_upd_sys
->lock
);
1543 static void updater_unlock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1545 assert (p_upd_sys
->p_overlay
);
1547 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1548 vlc_mutex_unlock(&p_upd_sys
->lock
);
1551 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1552 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1553 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1556 VLC_UNUSED(b_fmt_src
);
1557 VLC_UNUSED(b_fmt_dst
);
1558 VLC_UNUSED(p_fmt_src
);
1559 VLC_UNUSED(p_fmt_dst
);
1562 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1563 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1569 int res
= p_overlay
->status
== Outdated
;
1571 updater_unlock_overlay(p_upd_sys
);
1576 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1577 const video_format_t
*p_fmt_src
,
1578 const video_format_t
*p_fmt_dst
,
1581 VLC_UNUSED(p_fmt_src
);
1582 VLC_UNUSED(p_fmt_dst
);
1584 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1585 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1592 * When this function is called, all p_subpic regions are gone.
1593 * We need to duplicate our regions (stored internaly) to this subpic.
1595 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1597 updater_unlock_overlay(p_upd_sys
);
1601 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1602 while (p_src
!= NULL
) {
1603 *p_dst
= subpicture_region_Copy(p_src
);
1606 p_dst
= &(*p_dst
)->p_next
;
1607 p_src
= p_src
->p_next
;
1610 (*p_dst
)->p_next
= NULL
;
1611 p_overlay
->status
= Displayed
;
1613 updater_unlock_overlay(p_upd_sys
);
1616 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1618 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1619 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1622 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1623 p_overlay
->status
= ToDisplay
;
1624 p_overlay
->b_on_vout
= false;
1625 updater_unlock_overlay(p_upd_sys
);
1628 unref_subpicture_updater(p_upd_sys
);
1631 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1633 bluray_spu_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1634 if (unlikely(p_upd_sys
== NULL
)) {
1638 p_upd_sys
->p_overlay
= p_ov
;
1640 subpicture_updater_t updater
= {
1641 .pf_validate
= subpictureUpdaterValidate
,
1642 .pf_update
= subpictureUpdaterUpdate
,
1643 .pf_destroy
= subpictureUpdaterDestroy
,
1647 subpicture_t
*p_pic
= subpicture_New(&updater
);
1648 if (p_pic
== NULL
) {
1653 p_pic
->i_original_picture_width
= p_ov
->width
;
1654 p_pic
->i_original_picture_height
= p_ov
->height
;
1655 p_pic
->b_absolute
= true;
1657 vlc_mutex_init(&p_upd_sys
->lock
);
1658 p_upd_sys
->ref_cnt
= 2;
1660 p_ov
->p_updater
= p_upd_sys
;
1665 /*****************************************************************************
1666 * User input events:
1667 *****************************************************************************/
1668 static void onMouseEvent(const vlc_mouse_t
*newmouse
, void *user_data
)
1670 demux_t
*p_demux
= user_data
;
1671 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1674 vlc_mouse_Init(&p_sys
->oldmouse
);
1678 if (vlc_mouse_HasMoved(&p_sys
->oldmouse
, newmouse
))
1679 bd_mouse_select(p_sys
->bluray
, -1, newmouse
->i_x
, newmouse
->i_y
);
1681 if (vlc_mouse_HasPressed( &p_sys
->oldmouse
, newmouse
, MOUSE_BUTTON_LEFT
))
1682 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1683 p_sys
->oldmouse
= *newmouse
;
1686 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1688 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1689 return VLC_EGENERIC
;
1694 /*****************************************************************************
1695 * libbluray overlay handling:
1696 *****************************************************************************/
1698 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1700 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1701 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1705 /* drop overlay from vout */
1706 if (ov
->p_updater
) {
1707 unref_subpicture_updater(ov
->p_updater
);
1710 /* no references to this overlay exist in vo anymore */
1711 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
, plane
);
1713 vlc_mutex_destroy(&ov
->lock
);
1714 subpicture_region_ChainDelete(ov
->p_regions
);
1717 p_sys
->bdj
.p_overlays
[plane
] = NULL
;
1722 * Mark the overlay as "ToDisplay" status.
1723 * This will not send the overlay to the vout instantly, as the vout
1724 * may not be acquired (not acquirable) yet.
1725 * If is has already been acquired, the overlay has already been sent to it,
1726 * therefore, we only flag the overlay as "Outdated"
1728 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1730 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1731 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1734 * If the overlay is already displayed, mark the picture as outdated.
1735 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1737 vlc_mutex_lock(&ov
->lock
);
1738 if (ov
->status
>= Displayed
&& ov
->b_on_vout
) {
1739 ov
->status
= Outdated
;
1740 vlc_mutex_unlock(&ov
->lock
);
1745 * Mark the overlay as available, but don't display it right now.
1746 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1747 * the overlay is computed
1749 ov
->status
= ToDisplay
;
1750 vlc_mutex_unlock(&ov
->lock
);
1753 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1755 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1757 assert(p_sys
->bdj
.p_overlays
[plane
] == NULL
);
1759 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1760 if (unlikely(ov
== NULL
))
1764 ov
->height
= height
;
1765 ov
->b_on_vout
= false;
1767 vlc_mutex_init(&ov
->lock
);
1769 p_sys
->bdj
.p_overlays
[plane
] = ov
;
1773 * Destroy every regions in the subpicture.
1774 * This is done in two steps:
1775 * - Wiping our private regions list
1776 * - Flagging the overlay as outdated, so the changes are replicated from
1777 * the subpicture_updater_t::pf_update
1778 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1780 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1782 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1783 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1785 vlc_mutex_lock(&ov
->lock
);
1787 subpicture_region_ChainDelete(ov
->p_regions
);
1788 ov
->p_regions
= NULL
;
1789 ov
->status
= Outdated
;
1791 vlc_mutex_unlock(&ov
->lock
);
1795 * This will draw to the overlay by adding a region to our region list
1796 * This will have to be copied to the subpicture used to render the overlay.
1798 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1800 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1803 * Compute a subpicture_region_t.
1804 * It will be copied and sent to the vout later.
1806 vlc_mutex_lock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1808 /* Find a region to update */
1809 subpicture_region_t
**pp_reg
= &p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
;
1810 subpicture_region_t
*p_reg
= p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
;
1811 subpicture_region_t
*p_last
= NULL
;
1812 while (p_reg
!= NULL
) {
1814 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1815 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1817 pp_reg
= &p_reg
->p_next
;
1818 p_reg
= p_reg
->p_next
;
1824 *pp_reg
= p_reg
->p_next
;
1825 subpicture_region_Delete(p_reg
);
1827 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1831 /* If there is no region to update, create a new one. */
1834 video_format_Init(&fmt
, 0);
1835 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1837 p_reg
= subpicture_region_New(&fmt
);
1840 /* Append it to our list. */
1842 p_last
->p_next
= p_reg
;
1843 else /* If we don't have a last region, then our list empty */
1844 p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1847 /* Now we can update the region, regardless it's an update or an insert */
1848 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1849 for (int y
= 0; y
< ov
->h
; y
++)
1850 for (int x
= 0; x
< ov
->w
;) {
1851 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1852 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1858 p_reg
->fmt
.p_palette
->i_entries
= 256;
1859 for (int i
= 0; i
< 256; ++i
) {
1860 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1861 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1862 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1863 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1867 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1869 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1873 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1875 demux_t
*p_demux
= (demux_t
*)ptr
;
1876 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1878 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1881 msg_Info(p_demux
, "Closing overlays.");
1882 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1883 blurayCloseOverlay(p_demux
, i
);
1884 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1888 switch (overlay
->cmd
) {
1889 case BD_OVERLAY_INIT
:
1890 msg_Info(p_demux
, "Initializing overlay");
1891 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1893 case BD_OVERLAY_CLOSE
:
1894 blurayClearOverlay(p_demux
, overlay
->plane
);
1895 blurayCloseOverlay(p_demux
, overlay
->plane
);
1897 case BD_OVERLAY_CLEAR
:
1898 blurayClearOverlay(p_demux
, overlay
->plane
);
1900 case BD_OVERLAY_FLUSH
:
1901 blurayActivateOverlay(p_demux
, overlay
->plane
);
1903 case BD_OVERLAY_DRAW
:
1904 case BD_OVERLAY_WIPE
:
1905 blurayDrawOverlay(p_demux
, overlay
);
1908 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
1912 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1916 * ARGB overlay (BD-J)
1918 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1920 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1922 blurayInitOverlay(p_demux
, plane
, width
, height
);
1924 if (!p_sys
->bdj
.p_overlays
[plane
]->p_regions
) {
1926 video_format_Init(&fmt
, 0);
1927 video_format_Setup(&fmt
, VLC_CODEC_RGBA
, width
, height
, width
, height
, 1, 1);
1929 p_sys
->bdj
.p_overlays
[plane
]->p_regions
= subpicture_region_New(&fmt
);
1933 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
1935 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1937 vlc_mutex_lock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1939 /* Find a region to update */
1940 subpicture_region_t
*p_reg
= p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
;
1942 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1946 /* Now we can update the region */
1947 const uint32_t *src0
= ov
->argb
;
1948 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
1949 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
1952 for (int y
= 0; y
< ov
->h
; y
++) {
1953 // XXX: add support for this format ? Should be possible with OPENGL/VDPAU/...
1954 // - or add libbluray option to select the format ?
1955 for (int x
= 0; x
< ov
->w
; x
++) {
1956 dst0
[x
*4 ] = src0
[x
]>>16; /* R */
1957 dst0
[x
*4+1] = src0
[x
]>>8; /* G */
1958 dst0
[x
*4+2] = src0
[x
]; /* B */
1959 dst0
[x
*4+3] = src0
[x
]>>24; /* A */
1963 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
1966 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1968 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1972 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
1974 demux_t
*p_demux
= (demux_t
*)ptr
;
1975 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1977 switch (overlay
->cmd
) {
1978 case BD_ARGB_OVERLAY_INIT
:
1979 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1980 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1981 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1983 case BD_ARGB_OVERLAY_CLOSE
:
1984 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1985 blurayClearOverlay(p_demux
, overlay
->plane
);
1986 blurayCloseOverlay(p_demux
, overlay
->plane
);
1987 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1989 case BD_ARGB_OVERLAY_FLUSH
:
1990 blurayActivateOverlay(p_demux
, overlay
->plane
);
1992 case BD_ARGB_OVERLAY_DRAW
:
1993 blurayDrawArgbOverlay(p_demux
, overlay
);
1996 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
2001 static void bluraySendOverlayToVout(demux_t
*p_demux
, int plane
, bluray_overlay_t
*p_ov
)
2003 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2005 assert(p_ov
!= NULL
);
2006 assert(!p_ov
->b_on_vout
);
2008 if (p_ov
->p_updater
) {
2009 unref_subpicture_updater(p_ov
->p_updater
);
2010 p_ov
->p_updater
= NULL
;
2013 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
2015 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
2020 * After this point, the picture should not be accessed from the demux thread,
2021 * as it is held by the vout thread.
2022 * This must be done only once per subpicture, ie. only once between each
2023 * blurayInitOverlay & blurayCloseOverlay call.
2025 int ret
= es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
,
2027 if (ret
!= VLC_SUCCESS
)
2029 unref_subpicture_updater(p_ov
->p_updater
);
2030 p_ov
->p_updater
= NULL
;
2031 p_ov
->b_on_vout
= false;
2032 subpicture_Delete(p_pic
);
2035 p_ov
->b_on_vout
= true;
2038 * Mark the picture as Outdated, as it contains no region for now.
2039 * This will make the subpicture_updater_t call pf_update
2041 p_ov
->status
= Outdated
;
2044 static bool blurayTitleIsRepeating(BLURAY_TITLE_INFO
*title_info
,
2045 unsigned repeats
, unsigned ratio
)
2047 const BLURAY_CLIP_INFO
*prev
= NULL
;
2048 unsigned maxrepeats
= 0;
2049 unsigned sequence
= 0;
2050 if(!title_info
->chapter_count
)
2053 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++)
2055 unsigned i
= title_info
->chapters
[j
].clip_ref
;
2056 if(i
< title_info
->clip_count
)
2059 /* non repeated does not need start time offset */
2060 title_info
->clips
[i
].start_time
== 0 ||
2061 /* repeats occurs on same segment */
2062 memcmp(title_info
->clips
[i
].clip_id
, prev
->clip_id
, 6) ||
2063 prev
->in_time
!= title_info
->clips
[i
].in_time
||
2064 prev
->pkt_count
!= title_info
->clips
[i
].pkt_count
)
2067 prev
= &title_info
->clips
[i
];
2072 if(maxrepeats
< sequence
++)
2073 maxrepeats
= sequence
;
2077 return (maxrepeats
> repeats
&&
2078 (100 * maxrepeats
/ title_info
->chapter_count
) >= ratio
);
2081 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
2083 t
->i_length
= FROM_SCALE_NZ(title_info
->duration
);
2085 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
2086 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
2087 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
2089 /* FIXME: have libbluray expose repeating titles */
2090 if(blurayTitleIsRepeating(title_info
, 50, 90))
2093 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
2094 seekpoint_t
*s
= vlc_seekpoint_New();
2098 s
->i_time_offset
= FROM_SCALE_NZ(title_info
->chapters
[j
].start
);
2100 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
2104 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
)
2106 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2107 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2109 /* get and set the titles */
2110 uint32_t i_title
= menu_titles
;
2112 if (!p_sys
->b_menu
) {
2113 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
2114 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
2117 for (uint32_t i
= 0; i
< i_title
; i
++) {
2118 input_title_t
*t
= vlc_input_title_New();
2122 if (!p_sys
->b_menu
) {
2123 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
2124 blurayUpdateTitleInfo(t
, title_info
);
2125 bd_free_title_info(title_info
);
2127 } else if (i
== 0) {
2128 t
->psz_name
= strdup(_("Top Menu"));
2129 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
2130 } else if (i
== i_title
- 1) {
2131 t
->psz_name
= strdup(_("First Play"));
2132 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
2133 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
2136 /* add possible title name from disc metadata */
2137 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
2138 if (di
->titles
[i
]->name
) {
2139 t
->psz_name
= strdup(di
->titles
[i
]->name
);
2141 if (di
->titles
[i
]->interactive
) {
2142 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
2147 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
2151 static void blurayRestartParser(demux_t
*p_demux
, bool b_flush
, bool b_random_access
)
2154 * This is a hack and will have to be removed.
2155 * The parser should be flushed, and not destroy/created each time
2156 * we are changing title.
2158 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2161 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
2163 if (p_sys
->p_parser
)
2164 vlc_demux_chained_Delete(p_sys
->p_parser
);
2167 es_out_Control(p_sys
->p_tf_out
, ES_OUT_TF_FILTER_RESET
);
2169 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
2170 if (!p_sys
->p_parser
)
2171 msg_Err(p_demux
, "Failed to create TS demuxer");
2173 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
);
2175 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
, b_random_access
);
2178 /*****************************************************************************
2179 * bluraySetTitle: select new BD title
2180 *****************************************************************************/
2181 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
2183 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2185 if (p_sys
->b_menu
) {
2188 msg_Dbg(p_demux
, "Playing TopMenu Title");
2189 result
= bd_menu_call(p_sys
->bluray
, -1);
2190 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
2191 msg_Dbg(p_demux
, "Playing FirstPlay Title");
2192 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
2194 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
2195 result
= bd_play_title(p_sys
->bluray
, i_title
);
2199 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
2200 return VLC_EGENERIC
;
2206 /* Looking for the main title, ie the longest duration */
2208 i_title
= p_sys
->i_longest_title
;
2209 else if ((unsigned)i_title
> p_sys
->i_title
)
2210 return VLC_EGENERIC
;
2212 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
2214 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
2215 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
2216 return VLC_EGENERIC
;
2222 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
2223 # define BLURAY_AUDIO_STREAM 0
2226 static void blurayOnUserStreamSelection(demux_sys_t
*p_sys
, int i_pid
)
2228 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2230 if (p_sys
->p_clip_info
) {
2232 if ((i_pid
& 0xff00) == 0x1100) {
2234 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
2235 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
2236 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
2238 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
,
2239 (const char *) p_sys
->p_clip_info
->audio_streams
[i_id
].lang
);
2243 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
2245 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
2246 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
2247 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
2249 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
,
2250 (const char *) p_sys
->p_clip_info
->pg_streams
[i_id
].lang
);
2257 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2260 /*****************************************************************************
2261 * blurayControl: handle the controls
2262 *****************************************************************************/
2263 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
2265 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2269 case DEMUX_CAN_SEEK
:
2270 case DEMUX_CAN_PAUSE
:
2271 case DEMUX_CAN_CONTROL_PACE
:
2272 pb_bool
= va_arg(args
, bool *);
2276 case DEMUX_GET_PTS_DELAY
:
2277 *va_arg(args
, vlc_tick_t
*) =
2278 VLC_TICK_FROM_MS(var_InheritInteger(p_demux
, "disc-caching"));
2281 case DEMUX_SET_PAUSE_STATE
:
2283 #ifdef BLURAY_RATE_NORMAL
2284 bool b_paused
= (bool)va_arg(args
, int);
2285 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
2286 return VLC_EGENERIC
;
2293 int i_id
= va_arg(args
, int);
2294 blurayOnUserStreamSelection(p_sys
, i_id
);
2297 case DEMUX_SET_TITLE
:
2299 int i_title
= va_arg(args
, int);
2300 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
2301 /* make sure GUI restores the old setting in title menu ... */
2302 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2303 return VLC_EGENERIC
;
2305 blurayRestartParser(p_demux
, true, false);
2306 notifyDiscontinuityToParser(p_sys
);
2307 p_sys
->b_draining
= false;
2308 es_out_Control(p_demux
->out
, ES_OUT_RESET_PCR
);
2309 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2312 case DEMUX_SET_SEEKPOINT
:
2314 int i_chapter
= va_arg(args
, int);
2315 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
2316 blurayRestartParser(p_demux
, true, false);
2317 notifyDiscontinuityToParser(p_sys
);
2318 p_sys
->b_draining
= false;
2319 es_out_Control(p_demux
->out
, ES_OUT_RESET_PCR
);
2320 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2323 case DEMUX_TEST_AND_CLEAR_FLAGS
:
2325 unsigned *restrict flags
= va_arg(args
, unsigned *);
2326 *flags
&= p_sys
->updates
;
2327 p_sys
->updates
&= ~*flags
;
2330 case DEMUX_GET_TITLE
:
2331 *va_arg(args
, int *) = p_sys
->cur_title
;
2334 case DEMUX_GET_SEEKPOINT
:
2335 *va_arg(args
, int *) = p_sys
->cur_seekpoint
;
2338 case DEMUX_GET_TITLE_INFO
:
2340 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
2341 int *pi_int
= va_arg(args
, int *);
2342 int *pi_title_offset
= va_arg(args
, int *);
2343 int *pi_chapter_offset
= va_arg(args
, int *);
2346 *pi_title_offset
= 0;
2347 *pi_chapter_offset
= 0;
2349 /* Duplicate local title infos */
2351 *ppp_title
= vlc_alloc(p_sys
->i_title
, sizeof(input_title_t
*));
2353 return VLC_EGENERIC
;
2354 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
2356 input_title_t
*p_dup
= vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
2358 (*ppp_title
)[(*pi_int
)++] = p_dup
;
2364 case DEMUX_GET_LENGTH
:
2366 if(p_sys
->cur_title
< p_sys
->i_title
&&
2367 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2368 return VLC_EGENERIC
;
2369 *va_arg(args
, vlc_tick_t
*) = p_sys
->cur_title
< p_sys
->i_title
? CUR_LENGTH
: 0;
2372 case DEMUX_SET_TIME
:
2374 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(va_arg(args
, vlc_tick_t
)));
2375 blurayRestartParser(p_demux
, true, true);
2376 notifyDiscontinuityToParser(p_sys
);
2377 p_sys
->b_draining
= false;
2378 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2381 case DEMUX_GET_TIME
:
2383 vlc_tick_t
*pi_time
= va_arg(args
, vlc_tick_t
*);
2384 if(p_sys
->cur_title
< p_sys
->i_title
&&
2385 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2386 return VLC_EGENERIC
;
2387 *pi_time
= FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
));
2391 case DEMUX_GET_POSITION
:
2393 double *pf_position
= va_arg(args
, double *);
2394 if(p_sys
->cur_title
< p_sys
->i_title
&&
2395 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2396 return VLC_EGENERIC
;
2397 *pf_position
= p_sys
->cur_title
< p_sys
->i_title
&& CUR_LENGTH
> 0 ?
2398 (double)FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
2401 case DEMUX_SET_POSITION
:
2403 double f_position
= va_arg(args
, double);
2404 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(f_position
*CUR_LENGTH
));
2405 blurayRestartParser(p_demux
, true, true);
2406 notifyDiscontinuityToParser(p_sys
);
2407 p_sys
->b_draining
= false;
2408 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2412 case DEMUX_GET_META
:
2414 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
2415 const META_DL
*meta
= p_sys
->p_meta
;
2417 return VLC_EGENERIC
;
2419 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
2421 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
2422 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
2423 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
2425 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
2426 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
2428 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
2430 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
2431 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
2432 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
2434 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
2435 char *psz_thumbpath
;
2436 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
2437 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > -1) {
2438 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
2439 free(psz_thumbpath
);
2440 if (unlikely(psz_thumburl
== NULL
))
2443 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
2451 case DEMUX_GET_ATTACHMENTS
:
2453 input_attachment_t
***ppp_attach
=
2454 va_arg(args
, input_attachment_t
***);
2455 int *pi_int
= va_arg(args
, int *);
2457 if (p_sys
->i_attachments
<= 0)
2458 return VLC_EGENERIC
;
2461 *ppp_attach
= vlc_alloc(p_sys
->i_attachments
, sizeof(input_attachment_t
*));
2463 return VLC_EGENERIC
;
2464 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
2466 input_attachment_t
*p_dup
= vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
2468 (*ppp_attach
)[(*pi_int
)++] = p_dup
;
2473 case DEMUX_NAV_ACTIVATE
:
2474 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
2475 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2477 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
2479 return sendKeyEvent(p_sys
, BD_VK_UP
);
2480 case DEMUX_NAV_DOWN
:
2481 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
2482 case DEMUX_NAV_LEFT
:
2483 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
2484 case DEMUX_NAV_RIGHT
:
2485 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
2486 case DEMUX_NAV_POPUP
:
2487 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2488 case DEMUX_NAV_MENU
:
2489 if (p_sys
->b_menu
) {
2490 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
2491 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2494 msg_Err(p_demux
, "Can't select Top Menu title");
2495 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2497 return VLC_EGENERIC
;
2499 case DEMUX_CAN_RECORD
:
2501 case DEMUX_SET_GROUP_DEFAULT
:
2502 case DEMUX_SET_GROUP_ALL
:
2503 case DEMUX_SET_GROUP_LIST
:
2504 case DEMUX_HAS_UNSUPPORTED_META
:
2506 return VLC_EGENERIC
;
2511 /*****************************************************************************
2512 * libbluray event handling
2513 *****************************************************************************/
2514 static void writeTsPacketWDiscontinuity( uint8_t *p_buf
, uint16_t i_pid
,
2515 const uint8_t *p_payload
, uint8_t i_payload
)
2517 uint8_t ts_header
[] = {
2518 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2520 0x40 | ((i_pid
& 0x1f00) >> 8), i_pid
& 0xFF, /* PUSI + PID */
2521 i_payload
? 0x30 : 0x20, /* adaptation field, payload / no payload */
2522 192 - (4 + 5) - i_payload
, /* adaptation field length */
2523 0x82, /* af: discontinuity indicator + priv data */
2524 0x0E, /* priv data size */
2526 'D', 'I', 'S', 'C', 'O', 'N', 'T', 'I', 'N', 'U',
2529 memcpy( p_buf
, ts_header
, sizeof(ts_header
) );
2530 memset( &p_buf
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
) - i_payload
);
2532 memcpy( &p_buf
[192 - i_payload
], p_payload
, i_payload
);
2535 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
2536 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
2538 for( size_t i
=0; i
< i_sinfo
; i
++ )
2540 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2542 block_t
*p_block
= block_Alloc(192);
2546 writeTsPacketWDiscontinuity( p_block
->p_buffer
, i_pid
, NULL
, 0 );
2548 vlc_demux_chained_Send(p_parser
, p_block
);
2552 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2553 p_clip->memb##_stream_count )
2555 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
)
2557 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2564 DONOTIFY(sec_audio
);
2565 DONOTIFY(sec_video
);
2571 static void streamFlush( demux_sys_t
*p_sys
)
2574 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2575 * Packet is flushed only when TS packet with PUSI flag set is received.
2577 * Fix this by emitting (video) ts packet with PUSI flag set.
2578 * Add video sequence end code to payload so that also video decoder is flushed.
2579 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2582 if (p_sys
->b_flushed
)
2585 block_t
*p_block
= block_Alloc(192);
2589 bd_stream_type_e i_coding_type
;
2591 /* set correct sequence end code */
2592 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2593 if (p_sys
->p_clip_info
!= NULL
)
2594 i_coding_type
= p_sys
->p_clip_info
->video_streams
[0].coding_type
;
2597 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2600 switch( i_coding_type
)
2602 case BLURAY_STREAM_TYPE_VIDEO_MPEG1
:
2603 case BLURAY_STREAM_TYPE_VIDEO_MPEG2
:
2605 i_eos
= 0xB7; /* MPEG2 sequence end */
2607 case BLURAY_STREAM_TYPE_VIDEO_VC1
:
2608 case BLURAY_STREAM_TYPE_VIDEO_H264
:
2609 i_eos
= 0x0A; /* VC1 / H.264 sequence end */
2611 case BD_STREAM_TYPE_VIDEO_HEVC
:
2612 i_eos
= 0x48; /* HEVC sequence end NALU */
2616 uint8_t seq_end_pes
[] = {
2617 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2618 0x00, 0x00, 0x01, i_eos
, /* PES payload: sequence end */
2619 0x00, /* 2nd byte for HEVC NAL, pads others */
2622 writeTsPacketWDiscontinuity( p_block
->p_buffer
, 0x1011, seq_end_pes
, sizeof(seq_end_pes
) );
2624 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2625 p_sys
->b_flushed
= true;
2628 static void blurayResetStillImage( demux_t
*p_demux
)
2630 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2632 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
) {
2633 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
2635 blurayRestartParser(p_demux
, false, false);
2636 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2640 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2642 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2644 /* time period elapsed ? */
2645 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
&&
2646 p_sys
->i_still_end_time
!= STILL_IMAGE_INFINITE
&&
2647 p_sys
->i_still_end_time
<= vlc_tick_now()) {
2648 msg_Dbg(p_demux
, "Still image end");
2649 bd_read_skip_still(p_sys
->bluray
);
2651 blurayResetStillImage(p_demux
);
2655 /* show last frame as still image */
2656 if (p_sys
->i_still_end_time
== STILL_IMAGE_NOT_SET
) {
2658 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2659 p_sys
->i_still_end_time
= vlc_tick_now() + vlc_tick_from_sec( i_timeout
);
2661 msg_Dbg(p_demux
, "Still image (infinite)");
2662 p_sys
->i_still_end_time
= STILL_IMAGE_INFINITE
;
2665 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2668 /* stop buffering */
2670 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2673 /* avoid busy loops (read returns no data) */
2674 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2677 static void blurayOnStreamSelectedEvent(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2679 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2682 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2685 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2686 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2687 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2688 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2693 if (i_type
== BD_EVENT_PG_TEXTST_STREAM
&& !p_sys
->b_spu_enable
)
2694 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
, (int)i_type
, i_pid
);
2696 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
, (int)i_type
, i_pid
);
2700 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2702 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2704 blurayRestartParser(p_demux
, true, false);
2706 /* read title info and init some values */
2708 p_sys
->cur_title
= bd_get_current_title(p_sys
->bluray
);
2709 p_sys
->cur_seekpoint
= 0;
2710 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2712 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2714 blurayUpdateTitleInfo(p_sys
->pp_title
[p_sys
->cur_title
], p_title_info
);
2716 p_sys
->updates
|= INPUT_UPDATE_TITLE_LIST
;
2718 setTitleInfo(p_sys
, p_title_info
);
2720 blurayResetStillImage(p_demux
);
2723 static void blurayOnClipUpdate(demux_t
*p_demux
, uint32_t clip
)
2725 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2727 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2729 p_sys
->p_clip_info
= NULL
;
2731 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2733 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2735 /* Let's assume a single video track for now.
2736 * This may brake later, but it's enough for now.
2738 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2741 CLPI_CL
*clpi
= bd_get_clpi(p_sys
->bluray
, clip
);
2742 if(clpi
&& clpi
->clip
.application_type
!= p_sys
->clip_application_type
)
2744 if(p_sys
->clip_application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
||
2745 clpi
->clip
.application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
)
2746 blurayRestartParser(p_demux
, false, false);
2748 if(clpi
->clip
.application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
)
2749 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
);
2751 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
);
2755 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2757 blurayResetStillImage(p_demux
);
2760 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
)
2762 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2764 blurayDebugEvent(e
->event
, e
->param
);
2767 case BD_EVENT_TITLE
:
2768 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2769 p_sys
->cur_title
= p_sys
->i_title
- 1;
2771 p_sys
->cur_title
= e
->param
;
2772 /* this is feature title, we don't know yet which playlist it will play (if any) */
2773 setTitleInfo(p_sys
, NULL
);
2774 /* reset title infos here ? */
2775 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2776 /* might be BD-J title with no video */
2778 case BD_EVENT_PLAYLIST
:
2779 /* Start of playlist playback (?????.mpls) */
2780 blurayUpdatePlaylist(p_demux
, e
->param
);
2781 if (p_sys
->b_pl_playing
) {
2782 /* previous playlist was stopped in middle. flush to avoid delay */
2783 msg_Info(p_demux
, "Stopping playlist playback");
2784 blurayRestartParser(p_demux
, false, false);
2785 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2787 p_sys
->b_pl_playing
= true;
2789 case BD_EVENT_PLAYITEM
:
2790 notifyDiscontinuityToParser(p_sys
);
2791 blurayOnClipUpdate(p_demux
, e
->param
);
2793 case BD_EVENT_CHAPTER
:
2794 if (e
->param
&& e
->param
< 0xffff)
2795 p_sys
->cur_seekpoint
= e
->param
- 1;
2797 p_sys
->cur_seekpoint
= 0;
2798 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2800 case BD_EVENT_PLAYMARK
:
2801 case BD_EVENT_ANGLE
:
2804 /* Seek will happen with any chapter/title or bd_seek(),
2805 but also BD-J initiated. We can't make the difference
2806 between input or vm ones, better double flush/pcr reset
2807 than break the clock by throwing post random access PCR */
2808 blurayRestartParser(p_demux
, true, true);
2809 notifyDiscontinuityToParser(p_sys
);
2810 es_out_Control(p_sys
->p_out
, ES_OUT_RESET_PCR
);
2812 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2813 case BD_EVENT_UO_MASK_CHANGED
:
2814 /* This event could be used to grey out unselectable items in title menu */
2818 p_sys
->b_menu_open
= e
->param
;
2820 case BD_EVENT_POPUP
:
2821 p_sys
->b_popup_available
= e
->param
;
2822 /* TODO: show / hide pop-up menu button in gui ? */
2828 case BD_EVENT_ERROR
:
2829 /* fatal error (with menus) */
2830 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2831 "Playback with BluRay menus failed");
2832 p_sys
->b_fatal_error
= true;
2834 case BD_EVENT_ENCRYPTED
:
2835 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2836 "This disc seems to be encrypted");
2837 p_sys
->b_fatal_error
= true;
2839 case BD_EVENT_READ_ERROR
:
2840 msg_Err(p_demux
, "bluray: read error\n");
2844 * stream selection events
2846 case BD_EVENT_PG_TEXTST
:
2847 p_sys
->b_spu_enable
= e
->param
;
2849 case BD_EVENT_AUDIO_STREAM
:
2850 case BD_EVENT_PG_TEXTST_STREAM
:
2851 blurayOnStreamSelectedEvent(p_demux
, e
->event
, e
->param
);
2853 case BD_EVENT_IG_STREAM
:
2854 case BD_EVENT_SECONDARY_AUDIO
:
2855 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2856 case BD_EVENT_SECONDARY_VIDEO
:
2857 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2858 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2862 * playback control events
2864 case BD_EVENT_STILL_TIME
:
2865 blurayStillImage(p_demux
, e
->param
);
2867 case BD_EVENT_DISCONTINUITY
:
2868 /* reset demuxer (partially decoded PES packets must be dropped) */
2869 blurayRestartParser(p_demux
, false, true);
2870 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2872 case BD_EVENT_END_OF_TITLE
:
2873 if(p_sys
->b_pl_playing
)
2875 notifyDiscontinuityToParser(p_sys
);
2876 blurayRestartParser(p_demux
, false, false);
2877 p_sys
->b_draining
= true;
2878 p_sys
->b_pl_playing
= false;
2882 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2883 /* avoid busy loop (bd_read() returns no data) */
2884 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2888 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2893 static void blurayHandleOverlays(demux_t
*p_demux
)
2895 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2896 vlc_mutex_lock(&p_sys
->bdj
.lock
);
2898 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
2899 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[i
];
2903 vlc_mutex_lock(&ov
->lock
);
2904 bool display
= ov
->status
== ToDisplay
;
2905 vlc_mutex_unlock(&ov
->lock
);
2906 if (display
&& !ov
->b_on_vout
)
2908 /* NOTE: we might want to enable background video always when there's no video stream playing.
2909 Now, with some discs, there are perioids (even seconds) during which the video window
2910 disappears and just playlist is shown.
2911 (sometimes BD-J runs slowly ...)
2913 bluraySendOverlayToVout(p_demux
, i
, ov
);
2917 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
2920 static int blurayDemux(demux_t
*p_demux
)
2922 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2925 if(p_sys
->b_draining
)
2927 bool b_empty
= false;
2928 if(es_out_Control(p_sys
->p_out
, ES_OUT_GET_EMPTY
, &b_empty
) != VLC_SUCCESS
|| b_empty
)
2930 es_out_Control(p_sys
->p_out
, ES_OUT_RESET_PCR
);
2931 p_sys
->b_draining
= false;
2935 msg_Dbg(p_demux
, "Draining...");
2936 vlc_tick_sleep(VLC_TICK_FROM_MS(40));
2937 return VLC_DEMUXER_SUCCESS
;
2941 block_t
*p_block
= block_Alloc(BD_READ_SIZE
);
2943 return VLC_DEMUXER_EGENERIC
;
2947 if (p_sys
->b_menu
== false) {
2948 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
);
2949 while (bd_get_event(p_sys
->bluray
, &e
))
2950 blurayHandleEvent(p_demux
, &e
);
2952 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
, &e
);
2953 while (e
.event
!= BD_EVENT_NONE
) {
2954 blurayHandleEvent(p_demux
, &e
);
2955 bd_get_event(p_sys
->bluray
, &e
);
2959 blurayHandleOverlays(p_demux
);
2962 block_Release(p_block
);
2963 if (p_sys
->b_fatal_error
|| nread
< 0) {
2964 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
2965 return VLC_DEMUXER_EGENERIC
;
2967 if (!p_sys
->b_menu
) {
2968 return VLC_DEMUXER_EOF
;
2970 return VLC_DEMUXER_SUCCESS
;
2973 p_block
->i_buffer
= nread
;
2975 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2977 p_sys
->b_flushed
= false;
2979 return VLC_DEMUXER_SUCCESS
;