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 #ifdef BLURAY_HAS_BDJO_DATA_H
137 /* System version check menu freeze. See
138 * https://code.videolan.org/videolan/libbluray/issues/1
139 * To be removed with fix[ed,able] libbluray */
140 # include <libbluray/bdjo_data.h>
141 # include <strings.h>
142 static int BDJO_FileSelect( const char *psz_filename
)
144 int i_len
= strlen( psz_filename
);
148 return ! strcasecmp( &psz_filename
[i_len
- 5], ".bdjo" );
151 static bool BDJO_IsBlacklisted(demux_t
*p_demux
, const char *psz_bd_path
)
153 const char * rgsz_class_blacklist
[] =
155 "com.macrovision.bdplus.Handshake",
160 if(-1 == asprintf(&psz_bdjo_dir
, "%s/BDMV/BDJO", psz_bd_path
))
163 char **ppsz_filenames
= NULL
;
164 int i_files
= vlc_scandir(psz_bdjo_dir
, &ppsz_filenames
, BDJO_FileSelect
, NULL
);
171 for( int i
=0; i
<i_files
&& !b_ret
; i
++ )
174 if(-1 < asprintf(&psz_bdjo_file
, "%s/%s", psz_bdjo_dir
, ppsz_filenames
[i
]))
176 struct bdjo_data
*bdjo
= bd_read_bdjo(psz_bdjo_file
);
180 for(uint8_t j
=0; j
<bdjo
->app_table
.num_app
&& !b_ret
; j
++)
181 for(; k
<ARRAY_SIZE(rgsz_class_blacklist
) && !b_ret
; k
++)
182 b_ret
= (!strcmp(rgsz_class_blacklist
[k
],
183 bdjo
->app_table
.app
[j
].initial_class
));
186 msg_Warn(p_demux
, "Found blacklisted class %s in %s",
187 rgsz_class_blacklist
[k
],
200 for( int i
=0; i
<i_files
; i
++ )
201 free(ppsz_filenames
[i
]);
202 free(ppsz_filenames
);
207 # define BDJO_IsBlacklisted(foo, bar) (0)
210 /*****************************************************************************
212 *****************************************************************************/
214 #define BD_MENU_TEXT N_("Blu-ray menus")
215 #define BD_MENU_LONGTEXT N_("Use Blu-ray menus. If disabled, "\
216 "the movie will start directly")
217 #define BD_REGION_TEXT N_("Region code")
218 #define BD_REGION_LONGTEXT N_("Blu-Ray player region code. "\
219 "Some discs can be played only with a correct region code.")
221 static const char *const ppsz_region_code
[] = {
223 static const char *const ppsz_region_code_text
[] = {
224 "Region A", "Region B", "Region C" };
226 #define REGION_DEFAULT 1 /* Index to region list. Actual region code is (1<<REGION_DEFAULT) */
227 #define LANGUAGE_DEFAULT ("eng")
229 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,0)
230 # define BLURAY_DEMUX
233 #ifndef BD_STREAM_TYPE_VIDEO_HEVC
234 # define BD_STREAM_TYPE_VIDEO_HEVC 0x24
237 #define BD_CLUSTER_SIZE 6144
238 #define BD_READ_SIZE (10 * BD_CLUSTER_SIZE)
241 static int blurayOpen (vlc_object_t
*);
242 static void blurayClose(vlc_object_t
*);
245 set_shortname(N_("Blu-ray"))
246 set_description(N_("Blu-ray Disc support (libbluray)"))
248 set_category(CAT_INPUT
)
249 set_subcategory(SUBCAT_INPUT_ACCESS
)
250 set_capability("access", 500)
251 add_bool("bluray-menu", true, BD_MENU_TEXT
, BD_MENU_LONGTEXT
, false)
252 add_string("bluray-region", ppsz_region_code
[REGION_DEFAULT
], BD_REGION_TEXT
, BD_REGION_LONGTEXT
, false)
253 change_string_list(ppsz_region_code
, ppsz_region_code_text
)
255 add_shortcut("bluray", "file")
257 set_callbacks(blurayOpen
, blurayClose
)
262 set_description( "BluRay demuxer" )
263 set_category( CAT_INPUT
)
264 set_subcategory( SUBCAT_INPUT_DEMUX
)
265 set_capability( "demux", 5 )
266 set_callbacks( blurayOpen
, blurayClose
)
271 /* libbluray's overlay.h defines 2 types of overlay (bd_overlay_plane_e). */
272 #define MAX_OVERLAY 2
274 typedef enum OverlayStatus
{
276 ToDisplay
, //Used to mark the overlay to be displayed the first time.
278 Outdated
//used to update the overlay after it has been sent to the vout
281 typedef struct bluray_spu_updater_sys_t bluray_spu_updater_sys_t
;
283 typedef struct bluray_overlay_t
287 OverlayStatus status
;
288 subpicture_region_t
*p_regions
;
291 /* pointer to last subpicture updater.
292 * used to disconnect this overlay from vout when:
293 * - the overlay is closed
294 * - vout is changed and this overlay is sent to the new vout
296 bluray_spu_updater_sys_t
*p_updater
;
305 unsigned int i_title
;
306 unsigned int i_longest_title
;
307 input_title_t
**pp_title
;
309 unsigned cur_seekpoint
;
313 DECL_ARRAY(BD_EVENT
) events_delayed
;
315 vlc_mutex_t pl_info_lock
;
316 BLURAY_TITLE_INFO
*p_pl_info
;
317 const BLURAY_CLIP_INFO
*p_clip_info
;
320 BD_CLIP_APP_TYPE_TS_MAIN_PATH_MOVIE
= 1,
321 BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
= 2,
322 BD_CLIP_APP_TYPE_TS_MAIN_PATH_BROWSABLE_SLIDESHOW
= 3,
323 BD_CLIP_APP_TYPE_TS_SUB_PATH_BROWSABLE_SLIDESHOW
= 4,
324 BD_CLIP_APP_TYPE_TS_SUB_PATH_INTERACTIVE_MENU
= 5,
325 BD_CLIP_APP_TYPE_TS_SUB_PATH_TEXT_SUBTITLE
= 6,
326 BD_CLIP_APP_TYPE_TS_SUB_PATH_ELEMENTARY_STREAM_PATH
= 7,
327 } clip_application_type
;
331 input_attachment_t
**attachments
;
334 /* Meta information */
335 const META_DL
*p_meta
;
341 bool b_popup_available
;
342 vlc_tick_t i_still_end_time
;
345 bluray_overlay_t
*p_overlays
[MAX_OVERLAY
];
346 vlc_mutex_t lock
; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
350 vlc_mouse_t oldmouse
;
355 bool b_spu_enable
; /* enabled / disabled */
356 vlc_demux_chained_t
*p_parser
;
358 bool b_pl_playing
; /* true when playing playlist */
361 vlc_mutex_t read_block_lock
;
363 /* Used to store bluray disc path */
368 * Local ES index storage
374 int i_next_block_flags
;
376 bool b_restart_decoders_on_reuse
;
379 static bool es_pair_Add(vlc_array_t
*p_array
, const es_format_t
*p_fmt
,
382 es_pair_t
*p_pair
= malloc(sizeof(*p_pair
));
383 if (likely(p_pair
!= NULL
))
386 p_pair
->i_next_block_flags
= 0;
387 p_pair
->b_recyling
= false;
388 p_pair
->b_restart_decoders_on_reuse
= true;
389 if(vlc_array_append(p_array
, p_pair
) != VLC_SUCCESS
)
396 es_format_Init(&p_pair
->fmt
, p_fmt
->i_cat
, p_fmt
->i_codec
);
397 es_format_Copy(&p_pair
->fmt
, p_fmt
);
400 return p_pair
!= NULL
;
403 static void es_pair_Remove(vlc_array_t
*p_array
, es_pair_t
*p_pair
)
405 vlc_array_remove(p_array
, vlc_array_index_of_item(p_array
, p_pair
));
406 es_format_Clean(&p_pair
->fmt
);
410 static es_pair_t
*getEsPair(vlc_array_t
*p_array
,
411 bool (*match
)(const es_pair_t
*, const void *),
414 for (size_t i
= 0; i
< vlc_array_count(p_array
); ++i
)
416 es_pair_t
*p_pair
= vlc_array_item_at_index(p_array
, i
);
417 if(match(p_pair
, param
))
423 static bool es_pair_compare_PID(const es_pair_t
*p_pair
, const void *p_pid
)
425 return p_pair
->fmt
.i_id
== *((const int *)p_pid
);
428 static bool es_pair_compare_ES(const es_pair_t
*p_pair
, const void *p_es
)
430 return p_pair
->p_es
== (const es_out_id_t
*)p_es
;
433 static bool es_pair_compare_Unused(const es_pair_t
*p_pair
, const void *priv
)
436 return p_pair
->b_recyling
;
439 static es_pair_t
*getEsPairByPID(vlc_array_t
*p_array
, int i_pid
)
441 return getEsPair(p_array
, es_pair_compare_PID
, &i_pid
);
444 static es_pair_t
*getEsPairByES(vlc_array_t
*p_array
, const es_out_id_t
*p_es
)
446 return getEsPair(p_array
, es_pair_compare_ES
, p_es
);
449 static es_pair_t
*getUnusedEsPair(vlc_array_t
*p_array
)
451 return getEsPair(p_array
, es_pair_compare_Unused
, 0);
457 struct bluray_spu_updater_sys_t
459 vlc_mutex_t lock
; // protect p_overlay pointer and ref_cnt
460 bluray_overlay_t
*p_overlay
; // NULL if overlay has been closed
461 int ref_cnt
; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
465 * cut the connection between vout and overlay.
466 * - called when vout is closed or overlay is closed.
467 * - frees bluray_spu_updater_sys_t when both sides have been closed.
469 static void unref_subpicture_updater(bluray_spu_updater_sys_t
*p_sys
)
471 vlc_mutex_lock(&p_sys
->lock
);
472 int refs
= --p_sys
->ref_cnt
;
473 p_sys
->p_overlay
= NULL
;
474 vlc_mutex_unlock(&p_sys
->lock
);
477 vlc_mutex_destroy(&p_sys
->lock
);
483 * FIXME: partiallyy duplicated from src/input/es_out.c
485 static const char *DemuxGetLanguageCode( demux_t
*p_demux
, const char *psz_var
)
487 const iso639_lang_t
*pl
;
491 psz_lang
= var_CreateGetString( p_demux
, psz_var
);
493 return LANGUAGE_DEFAULT
;
495 /* XXX: we will use only the first value
496 * (and ignore other ones in case of a list) */
497 if( ( p
= strchr( psz_lang
, ',' ) ) )
500 for( pl
= p_languages
; pl
->psz_eng_name
!= NULL
; pl
++ )
502 if( *psz_lang
== '\0' )
504 if( !strcasecmp( pl
->psz_eng_name
, psz_lang
) ||
505 !strcasecmp( pl
->psz_iso639_1
, psz_lang
) ||
506 !strcasecmp( pl
->psz_iso639_2T
, psz_lang
) ||
507 !strcasecmp( pl
->psz_iso639_2B
, psz_lang
) )
513 if( pl
->psz_eng_name
!= NULL
)
514 return pl
->psz_iso639_2T
;
516 return LANGUAGE_DEFAULT
;
519 /*****************************************************************************
521 *****************************************************************************/
522 static es_out_t
*esOutNew(vlc_object_t
*, es_out_t
*, void *);
524 static int blurayControl(demux_t
*, int, va_list);
525 static int blurayDemux(demux_t
*);
527 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
);
528 static int bluraySetTitle(demux_t
*p_demux
, int i_title
);
530 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
* const overlay
);
531 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
* const overlay
);
532 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
);
534 static void onMouseEvent(const vlc_mouse_t
*mouse
, void *user_data
);
535 static void blurayRestartParser(demux_t
*p_demux
, bool, bool);
536 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
);
538 #define STILL_IMAGE_NOT_SET 0
539 #define STILL_IMAGE_INFINITE -1
541 #define CURRENT_TITLE p_sys->pp_title[p_sys->cur_title]
542 #define CUR_LENGTH CURRENT_TITLE->i_length
545 static void FindMountPoint(char **file
)
547 char *device
= *file
;
548 #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H)
549 /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure
550 * we look up the real device */
551 char *bd_device
= realpath(device
, NULL
);
552 if (bd_device
== NULL
)
556 if (lstat (bd_device
, &st
) == 0 && S_ISBLK (st
.st_mode
)) {
557 FILE *mtab
= setmntent ("/proc/self/mounts", "r");
559 struct mntent
*m
, mbuf
;
562 while ((m
= getmntent_r (mtab
, &mbuf
, buf
, sizeof(buf
))) != NULL
) {
563 if (!strcmp (m
->mnt_fsname
, bd_device
)) {
565 *file
= strdup(m
->mnt_dir
);
574 #elif defined(__APPLE__)
576 if (!stat (device
, &st
) && S_ISBLK (st
.st_mode
)) {
577 int fs_count
= getfsstat (NULL
, 0, MNT_NOWAIT
);
579 struct statfs mbuf
[128];
580 getfsstat (mbuf
, fs_count
* sizeof(mbuf
[0]), MNT_NOWAIT
);
581 for (int i
= 0; i
< fs_count
; ++i
)
582 if (!strcmp (mbuf
[i
].f_mntfromname
, device
)) {
584 *file
= strdup(mbuf
[i
].f_mntonname
);
590 # warning Disc device to mount point not implemented
591 VLC_UNUSED( device
);
595 /*****************************************************************************
596 * BD-J background video
597 *****************************************************************************/
599 static void bluraySendBackgroundImage(vlc_object_t
*p_obj
,
602 const es_format_t
*p_fmt
)
604 msg_Info(p_obj
, "Start background");
606 block_t
*p_block
= block_Alloc(p_fmt
->video
.i_width
* p_fmt
->video
.i_height
*
607 p_fmt
->video
.i_bits_per_pixel
/ 8);
609 msg_Err(p_obj
, "Error allocating block for background video");
613 // XXX TODO: what would be correct timestamp ???
614 p_block
->i_dts
= p_block
->i_pts
= vlc_tick_now() + VLC_TICK_FROM_MS(40);
616 uint8_t *p
= p_block
->p_buffer
;
617 memset(p
, 0, p_fmt
->video
.i_width
* p_fmt
->video
.i_height
);
618 p
+= p_fmt
->video
.i_width
* p_fmt
->video
.i_height
;
619 memset(p
, 0x80, p_fmt
->video
.i_width
* p_fmt
->video
.i_height
/ 2);
621 es_out_SetPCR(p_dst_out
, p_block
->i_dts
- VLC_TICK_FROM_MS(40));
622 es_out_Control(p_dst_out
, ES_OUT_SET_ES
, p_es
);
623 es_out_Send(p_dst_out
, p_es
, p_block
);
624 es_out_Control( p_dst_out
, ES_OUT_VOUT_SET_MOUSE_EVENT
, p_es
, onMouseEvent
, p_obj
);
625 es_out_SetPCR(p_dst_out
, p_block
->i_dts
);
628 /*****************************************************************************
629 * cache current playlist (title) information
630 *****************************************************************************/
632 static void setTitleInfo(demux_sys_t
*p_sys
, BLURAY_TITLE_INFO
*info
)
634 vlc_mutex_lock(&p_sys
->pl_info_lock
);
636 if (p_sys
->p_pl_info
) {
637 bd_free_title_info(p_sys
->p_pl_info
);
639 p_sys
->p_pl_info
= info
;
640 p_sys
->p_clip_info
= NULL
;
642 if (p_sys
->p_pl_info
&& p_sys
->p_pl_info
->clip_count
) {
643 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[0];
646 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
649 /*****************************************************************************
650 * create input attachment for thumbnail
651 *****************************************************************************/
653 static void attachThumbnail(demux_t
*p_demux
)
655 demux_sys_t
*p_sys
= p_demux
->p_sys
;
660 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,9,0)
661 if (p_sys
->p_meta
->thumb_count
> 0 && p_sys
->p_meta
->thumbnails
) {
664 if (bd_get_meta_file(p_sys
->bluray
, p_sys
->p_meta
->thumbnails
[0].path
, &data
, &size
) > 0) {
666 input_attachment_t
*p_attachment
;
668 snprintf(psz_name
, sizeof(psz_name
), "picture%d_%s", p_sys
->i_attachments
, p_sys
->p_meta
->thumbnails
[0].path
);
670 p_attachment
= vlc_input_attachment_New(psz_name
, NULL
, "Album art", data
, size
);
672 p_sys
->i_cover_idx
= p_sys
->i_attachments
;
673 TAB_APPEND(p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
681 /*****************************************************************************
683 *****************************************************************************/
685 static int probeStream(demux_t
*p_demux
)
687 /* input must be seekable */
688 bool b_canseek
= false;
689 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_canseek
);
694 /* first sector(s) should be filled with zeros */
696 const uint8_t *p_peek
;
697 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 2048 );
698 if( i_peek
!= 2048 ) {
702 if (p_peek
[ --i_peek
]) {
711 static int blurayReadBlock(void *object
, void *buf
, int lba
, int num_blocks
)
713 demux_t
*p_demux
= (demux_t
*)object
;
714 demux_sys_t
*p_sys
= p_demux
->p_sys
;
717 assert(p_demux
->s
!= NULL
);
719 vlc_mutex_lock(&p_sys
->read_block_lock
);
721 if (vlc_stream_Seek( p_demux
->s
, lba
* INT64_C(2048) ) == VLC_SUCCESS
) {
722 size_t req
= (size_t)2048 * num_blocks
;
725 got
= vlc_stream_Read( p_demux
->s
, buf
, req
);
727 msg_Err(p_demux
, "read from lba %d failed", lba
);
732 msg_Err(p_demux
, "seek to lba %d failed", lba
);
735 vlc_mutex_unlock(&p_sys
->read_block_lock
);
741 /*****************************************************************************
742 * probing of local files
743 *****************************************************************************/
745 /* Descriptor Tag (ECMA 167, 3/7.2) */
746 static int decode_descriptor_tag(const uint8_t *buf
)
749 uint8_t checksum
= 0;
752 id
= buf
[0] | (buf
[1] << 8);
754 /* calculate tag checksum */
755 for (i
= 0; i
< 4; i
++) {
756 checksum
= (uint8_t)(checksum
+ buf
[i
]);
758 for (i
= 5; i
< 16; i
++) {
759 checksum
= (uint8_t)(checksum
+ buf
[i
]);
762 if (checksum
!= buf
[4]) {
769 static int probeFile(const char *psz_name
)
771 struct stat stat_info
;
774 int ret
= VLC_EGENERIC
;
777 fd
= vlc_open(psz_name
, O_RDONLY
| O_NONBLOCK
);
782 if (fstat(fd
, &stat_info
) == -1) {
785 if (!S_ISREG(stat_info
.st_mode
) && !S_ISBLK(stat_info
.st_mode
)) {
789 /* first sector should be filled with zeros */
790 if (read(fd
, peek
, sizeof(peek
)) != sizeof(peek
)) {
793 for (i
= 0; i
< sizeof(peek
); i
++) {
799 /* Check AVDP tag checksum */
800 if (lseek(fd
, 256 * 2048, SEEK_SET
) == -1 ||
801 read(fd
, peek
, 16) != 16 ||
802 decode_descriptor_tag(peek
) != 2) {
813 /*****************************************************************************
814 * blurayOpen: module init function
815 *****************************************************************************/
816 static int blurayOpen(vlc_object_t
*object
)
818 demux_t
*p_demux
= (demux_t
*)object
;
821 uint64_t i_init_pos
= 0;
823 const char *error_msg
= NULL
;
824 #define BLURAY_ERROR(s) do { error_msg = s; goto error; } while(0)
826 if (p_demux
->out
== NULL
)
829 forced
= !strncasecmp(p_demux
->psz_url
, "bluray:", 7);
832 if (!strncasecmp(p_demux
->psz_url
, "file:", 5)) {
833 /* use access_demux for local files */
837 if (probeStream(p_demux
) != VLC_SUCCESS
) {
841 } else if (!forced
) {
842 if (!p_demux
->psz_filepath
) {
846 if (probeFile(p_demux
->psz_filepath
) != VLC_SUCCESS
) {
852 p_demux
->p_sys
= p_sys
= vlc_obj_calloc(object
, 1, sizeof(*p_sys
));
853 if (unlikely(!p_sys
))
856 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
858 /* init demux info fields */
861 TAB_INIT(p_sys
->i_title
, p_sys
->pp_title
);
862 TAB_INIT(p_sys
->i_attachments
, p_sys
->attachments
);
863 ARRAY_INIT(p_sys
->events_delayed
);
865 vlc_mouse_Init(&p_sys
->oldmouse
);
867 vlc_mutex_init(&p_sys
->pl_info_lock
);
868 vlc_mutex_init(&p_sys
->bdj
.lock
);
869 vlc_mutex_init(&p_sys
->read_block_lock
); /* used during bd_open_stream() */
871 /* request sub demuxers to skip continuity check as some split
872 file concatenation are just resetting counters... */
873 var_Create( p_demux
, "ts-cc-check", VLC_VAR_BOOL
);
874 var_SetBool( p_demux
, "ts-cc-check", false );
875 var_Create( p_demux
, "ts-standard", VLC_VAR_STRING
);
876 var_SetString( p_demux
, "ts-standard", "mpeg" );
877 var_Create( p_demux
, "ts-pmtfix-waitdata", VLC_VAR_BOOL
);
878 var_SetBool( p_demux
, "ts-pmtfix-waitdata", false );
879 var_Create( p_demux
, "ts-patfix", VLC_VAR_BOOL
);
880 var_SetBool( p_demux
, "ts-patfix", false );
881 var_Create( p_demux
, "ts-pcr-offsetfix", VLC_VAR_BOOL
);
882 var_SetBool( p_demux
, "ts-pcr-offsetfix", false );
885 p_bluray_DebugObject
= VLC_OBJECT(p_demux
);
886 bd_set_debug_mask(BLURAY_DEBUG_MASK
);
887 bd_set_debug_handler(bluray_DebugHandler
);
893 i_init_pos
= vlc_stream_Tell(p_demux
->s
);
895 p_sys
->bluray
= bd_init();
896 if (!bd_open_stream(p_sys
->bluray
, p_demux
, blurayReadBlock
)) {
897 bd_close(p_sys
->bluray
);
898 p_sys
->bluray
= NULL
;
903 if (!p_demux
->psz_filepath
) {
904 /* no path provided (bluray://). use default DVD device. */
905 p_sys
->psz_bd_path
= var_InheritString(object
, "dvd");
907 /* store current bd path */
908 p_sys
->psz_bd_path
= strdup(p_demux
->psz_filepath
);
911 /* If we're passed a block device, try to convert it to the mount point. */
912 FindMountPoint(&p_sys
->psz_bd_path
);
914 p_sys
->bluray
= bd_open(p_sys
->psz_bd_path
, NULL
);
916 if (!p_sys
->bluray
) {
920 /* Warning the user about AACS/BD+ */
921 const BLURAY_DISC_INFO
*disc_info
= bd_get_disc_info(p_sys
->bluray
);
923 /* Is it a bluray? */
924 if (!disc_info
->bluray_detected
) {
926 BLURAY_ERROR(_("Path doesn't appear to be a Blu-ray"));
931 msg_Info(p_demux
, "First play: %i, Top menu: %i\n"
932 "HDMV Titles: %i, BD-J Titles: %i, Other: %i",
933 disc_info
->first_play_supported
, disc_info
->top_menu_supported
,
934 disc_info
->num_hdmv_titles
, disc_info
->num_bdj_titles
,
935 disc_info
->num_unsupported_titles
);
938 if (disc_info
->aacs_detected
) {
939 msg_Dbg(p_demux
, "Disc is using AACS");
940 if (!disc_info
->libaacs_detected
)
941 BLURAY_ERROR(_("This Blu-ray Disc needs a library for AACS decoding"
942 ", and your system does not have it."));
943 if (!disc_info
->aacs_handled
) {
944 if (disc_info
->aacs_error_code
) {
945 switch (disc_info
->aacs_error_code
) {
946 case BD_AACS_CORRUPTED_DISC
:
947 BLURAY_ERROR(_("Blu-ray Disc is corrupted."));
948 case BD_AACS_NO_CONFIG
:
949 BLURAY_ERROR(_("Missing AACS configuration file!"));
951 BLURAY_ERROR(_("No valid processing key found in AACS config file."));
952 case BD_AACS_NO_CERT
:
953 BLURAY_ERROR(_("No valid host certificate found in AACS config file."));
954 case BD_AACS_CERT_REVOKED
:
955 BLURAY_ERROR(_("AACS Host certificate revoked."));
956 case BD_AACS_MMC_FAILED
:
957 BLURAY_ERROR(_("AACS MMC failed."));
964 if (disc_info
->bdplus_detected
) {
965 msg_Dbg(p_demux
, "Disc is using BD+");
966 if (!disc_info
->libbdplus_detected
)
967 BLURAY_ERROR(_("This Blu-ray Disc needs a library for BD+ decoding"
968 ", and your system does not have it."));
969 if (!disc_info
->bdplus_handled
)
970 BLURAY_ERROR(_("Your system BD+ decoding library does not work. "
971 "Missing configuration?"));
974 /* set player region code */
975 char *psz_region
= var_InheritString(p_demux
, "bluray-region");
976 unsigned int region
= psz_region
? (psz_region
[0] - 'A') : REGION_DEFAULT
;
978 bd_set_player_setting(p_sys
->bluray
, BLURAY_PLAYER_SETTING_REGION_CODE
, 1<<region
);
980 /* set preferred languages */
981 const char *psz_code
= DemuxGetLanguageCode( p_demux
, "audio-language" );
982 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
, psz_code
);
983 psz_code
= DemuxGetLanguageCode( p_demux
, "sub-language" );
984 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
, psz_code
);
985 psz_code
= DemuxGetLanguageCode( p_demux
, "menu-language" );
986 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_MENU_LANG
, psz_code
);
988 /* Get disc metadata */
989 p_sys
->p_meta
= bd_get_meta(p_sys
->bluray
);
991 msg_Warn(p_demux
, "Failed to get meta info.");
993 p_sys
->i_cover_idx
= -1;
994 attachThumbnail(p_demux
);
996 p_sys
->b_menu
= var_InheritBool(p_demux
, "bluray-menu");
998 /* Check BD-J capability */
999 if (p_sys
->b_menu
&& disc_info
->bdj_detected
&& !disc_info
->bdj_handled
) {
1000 msg_Err(p_demux
, "BD-J menus not supported. Playing without menus. "
1001 "BD-J support: %d, JVM found: %d, JVM usable: %d",
1002 disc_info
->bdj_supported
, disc_info
->libjvm_detected
, disc_info
->bdj_handled
);
1003 vlc_dialog_display_error(p_demux
, _("Java required"),
1004 _("This Blu-ray disc requires Java for menus support.%s\nThe disc will be played without menus."),
1005 !disc_info
->libjvm_detected
? _("Java was not found on your system.") : "");
1006 p_sys
->b_menu
= false;
1009 if(disc_info
->bdj_detected
&&p_sys
->b_menu
&&
1010 BDJO_IsBlacklisted(p_demux
, p_sys
->psz_bd_path
))
1012 p_sys
->b_menu
= vlc_dialog_wait_question( p_demux
,
1013 VLC_DIALOG_QUESTION_NORMAL
,
1014 _("Play without Menus"),
1017 _("BDJO Menu check"),
1019 _("Incompatible Java Menu detected"));
1022 /* Get titles and chapters */
1023 blurayInitTitles(p_demux
, disc_info
->num_hdmv_titles
+ disc_info
->num_bdj_titles
+ 1/*Top Menu*/ + 1/*First Play*/);
1026 * Initialize the event queue, so we can receive events in blurayDemux(Menu).
1028 bd_get_event(p_sys
->bluray
, NULL
);
1030 /* Registering overlay event handler */
1031 bd_register_overlay_proc(p_sys
->bluray
, p_demux
, blurayOverlayProc
);
1033 if (p_sys
->b_menu
) {
1035 /* Register ARGB overlay handler for BD-J */
1036 if (disc_info
->num_bdj_titles
)
1037 bd_register_argb_overlay_proc(p_sys
->bluray
, p_demux
, blurayArgbOverlayProc
, NULL
);
1039 /* libbluray will start playback from "First-Title" title */
1040 if (bd_play(p_sys
->bluray
) == 0)
1041 BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support."));
1044 /* set start title number */
1045 if (bluraySetTitle(p_demux
, p_sys
->i_longest_title
) != VLC_SUCCESS
) {
1046 msg_Err(p_demux
, "Could not set the title %d", p_sys
->i_longest_title
);
1051 p_sys
->p_tf_out
= timestamps_filter_es_out_New(p_demux
->out
);
1052 if(unlikely(!p_sys
->p_tf_out
))
1055 p_sys
->p_out
= esOutNew(VLC_OBJECT(p_demux
), p_sys
->p_tf_out
, p_demux
);
1056 if (unlikely(p_sys
->p_out
== NULL
))
1059 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
1060 if (!p_sys
->p_parser
) {
1061 msg_Err(p_demux
, "Failed to create TS demuxer");
1065 p_demux
->pf_control
= blurayControl
;
1066 p_demux
->pf_demux
= blurayDemux
;
1072 vlc_dialog_display_error(p_demux
, _("Blu-ray error"), "%s", error_msg
);
1073 blurayClose(object
);
1075 if (p_demux
->s
!= NULL
) {
1076 /* restore stream position */
1077 if (vlc_stream_Seek(p_demux
->s
, i_init_pos
) != VLC_SUCCESS
) {
1078 msg_Err(p_demux
, "Failed to seek back to stream start");
1079 return VLC_ETIMEOUT
;
1083 return VLC_EGENERIC
;
1088 /*****************************************************************************
1089 * blurayClose: module destroy function
1090 *****************************************************************************/
1091 static void blurayClose(vlc_object_t
*object
)
1093 demux_t
*p_demux
= (demux_t
*)object
;
1094 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1096 setTitleInfo(p_sys
, NULL
);
1099 * Close libbluray first.
1100 * This will close all the overlays before we release p_vout
1101 * bd_close(NULL) can crash
1103 if (p_sys
->bluray
) {
1104 bd_close(p_sys
->bluray
);
1107 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1108 for(int i
= 0; i
< MAX_OVERLAY
; i
++)
1109 blurayCloseOverlay(p_demux
, i
);
1110 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1112 if (p_sys
->p_parser
)
1113 vlc_demux_chained_Delete(p_sys
->p_parser
);
1115 if (p_sys
->p_out
!= NULL
)
1116 es_out_Delete(p_sys
->p_out
);
1118 timestamps_filter_es_out_Delete(p_sys
->p_tf_out
);
1121 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
1122 vlc_input_title_Delete(p_sys
->pp_title
[i
]);
1123 TAB_CLEAN(p_sys
->i_title
, p_sys
->pp_title
);
1125 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
1126 vlc_input_attachment_Delete(p_sys
->attachments
[i
]);
1127 TAB_CLEAN(p_sys
->i_attachments
, p_sys
->attachments
);
1129 ARRAY_RESET(p_sys
->events_delayed
);
1131 vlc_mutex_destroy(&p_sys
->pl_info_lock
);
1132 vlc_mutex_destroy(&p_sys
->bdj
.lock
);
1133 vlc_mutex_destroy(&p_sys
->read_block_lock
);
1135 free(p_sys
->psz_bd_path
);
1138 /*****************************************************************************
1139 * Elementary streams handling
1140 *****************************************************************************/
1141 static uint8_t blurayGetStreamsUnlocked(demux_sys_t
*p_sys
,
1143 BLURAY_STREAM_INFO
**pp_streams
)
1145 if(!p_sys
->p_clip_info
)
1148 switch(i_stream_type
)
1150 case BD_EVENT_AUDIO_STREAM
:
1151 *pp_streams
= p_sys
->p_clip_info
->audio_streams
;
1152 return p_sys
->p_clip_info
->audio_stream_count
;
1153 case BD_EVENT_PG_TEXTST_STREAM
:
1154 *pp_streams
= p_sys
->p_clip_info
->pg_streams
;
1155 return p_sys
->p_clip_info
->pg_stream_count
;
1161 static BLURAY_STREAM_INFO
* blurayGetStreamInfoUnlocked(demux_sys_t
*p_sys
,
1163 uint8_t i_stream_idx
)
1165 BLURAY_STREAM_INFO
*p_streams
= NULL
;
1166 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_stream_type
, &p_streams
);
1167 if(i_stream_idx
< i_streams_count
)
1168 return &p_streams
[i_stream_idx
];
1173 static BLURAY_STREAM_INFO
* blurayGetStreamInfoByPIDUnlocked(demux_sys_t
*p_sys
,
1176 for(int i_type
=BD_EVENT_AUDIO_STREAM
; i_type
<=BD_EVENT_SECONDARY_VIDEO_STREAM
; i_type
++)
1178 BLURAY_STREAM_INFO
*p_streams
;
1179 uint8_t i_streams_count
= blurayGetStreamsUnlocked(p_sys
, i_type
, &p_streams
);
1180 for(uint8_t i
=0; i
<i_streams_count
; i
++)
1182 if(p_streams
[i
].pid
== i_pid
)
1183 return &p_streams
[i
];
1189 static void setStreamLang(demux_sys_t
*p_sys
, es_format_t
*p_fmt
)
1191 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1193 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoByPIDUnlocked(p_sys
, p_fmt
->i_id
);
1196 free(p_fmt
->psz_language
);
1197 p_fmt
->psz_language
= strndup((const char *)p_stream
->lang
, 3);
1200 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1203 static int blurayGetStreamPID(demux_sys_t
*p_sys
, int i_stream_type
, uint8_t i_stream_idx
)
1205 vlc_mutex_lock(&p_sys
->pl_info_lock
);
1207 BLURAY_STREAM_INFO
*p_stream
= blurayGetStreamInfoUnlocked(p_sys
,
1210 int i_pid
= p_stream
? p_stream
->pid
: -1;
1212 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
1217 /*****************************************************************************
1218 * bluray fake es_out
1219 *****************************************************************************/
1222 es_out_t
*p_dst_out
;
1223 vlc_object_t
*p_obj
;
1224 vlc_array_t es
; /* es_pair_t */
1225 bool b_entered_recycling
;
1226 bool b_restart_decoders_on_reuse
;
1228 bool b_discontinuity
;
1229 bool b_disable_output
;
1234 int i_audio_pid
; /* Selected audio stream. -1 if default */
1235 int i_spu_pid
; /* Selected spu stream. -1 if default */
1239 es_out_id_t
*p_video_es
;
1240 int channels
[MAX_OVERLAY
];
1243 } bluray_esout_priv_t
;
1247 BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
= ES_OUT_PRIVATE_START
,
1248 BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
,
1249 BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
,
1250 BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
,
1251 BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
,
1252 BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
,
1253 BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
,
1254 BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
,
1255 BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
,
1256 BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
,
1259 static es_out_id_t
*bluray_esOutAddUnlocked(bluray_esout_priv_t
*esout_priv
,
1260 const es_format_t
*p_fmt
)
1262 demux_t
*p_demux
= esout_priv
->priv
;
1263 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1265 bool b_select
= false;
1267 es_format_Copy(&fmt
, p_fmt
);
1269 switch (fmt
.i_cat
) {
1271 if(esout_priv
->b_lowdelay
)
1273 fmt
.video
.i_frame_rate
= 1; fmt
.video
.i_frame_rate_base
= 1;
1274 fmt
.b_packetized
= true;
1276 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1277 b_select
= (p_fmt
->i_id
== 0x1011);
1280 if (esout_priv
->selected
.i_audio_pid
!= -1) {
1281 if (esout_priv
->selected
.i_audio_pid
== p_fmt
->i_id
)
1283 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1285 setStreamLang(p_sys
, &fmt
);
1288 if (esout_priv
->selected
.i_spu_pid
!= -1) {
1289 if (esout_priv
->selected
.i_spu_pid
== p_fmt
->i_id
)
1290 b_select
= p_sys
->b_spu_enable
;
1291 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1293 setStreamLang(p_sys
, &fmt
);
1299 es_out_id_t
*p_es
= NULL
;
1300 if (p_fmt
->i_id
>= 0) {
1301 /* Ensure we are not overriding anything */
1302 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, p_fmt
->i_id
);
1305 msg_Info(p_demux
, "Adding ES %d select %d", p_fmt
->i_id
, b_select
);
1306 p_es
= es_out_Add(esout_priv
->p_dst_out
, &fmt
);
1307 es_pair_Add(&esout_priv
->es
, &fmt
, p_es
);
1311 msg_Info(p_demux
, "Reusing ES %d", p_fmt
->i_id
);
1312 p_pair
->b_recyling
= false;
1313 p_es
= p_pair
->p_es
;
1314 if(!es_format_IsSimilar(p_fmt
, &p_pair
->fmt
) ||
1315 p_fmt
->b_packetized
!= p_pair
->fmt
.b_packetized
||
1316 esout_priv
->b_restart_decoders_on_reuse
)
1317 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_SET_ES_FMT
, p_pair
->p_es
, &fmt
);
1318 es_format_Clean(&p_pair
->fmt
);
1319 es_format_Copy(&p_pair
->fmt
, &fmt
);
1322 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_SET_ES
, p_es
);
1325 if (p_es
&& fmt
.i_cat
== VIDEO_ES
&& b_select
)
1327 es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_SET_MOUSE_EVENT
, p_es
,
1328 onMouseEvent
, p_demux
);
1329 esout_priv
->overlay
.p_video_es
= p_es
;
1332 es_format_Clean(&fmt
);
1337 static es_out_id_t
*bluray_esOutAdd(es_out_t
*p_out
, const es_format_t
*p_fmt
)
1339 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1341 vlc_mutex_lock(&esout_priv
->lock
);
1342 es_out_id_t
*p_es
= bluray_esOutAddUnlocked(esout_priv
, p_fmt
);
1343 vlc_mutex_unlock(&esout_priv
->lock
);
1348 static void bluray_esOutDeleteNonReusedESUnlocked(es_out_t
*p_out
)
1350 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1352 if(!esout_priv
->b_entered_recycling
)
1354 esout_priv
->b_entered_recycling
= false;
1355 esout_priv
->b_restart_decoders_on_reuse
= true;
1358 while((p_pair
= getUnusedEsPair(&esout_priv
->es
)))
1360 msg_Info(esout_priv
->p_obj
, "Trashing unused ES %d", p_pair
->fmt
.i_id
);
1362 if(esout_priv
->overlay
.p_video_es
== p_pair
->p_es
)
1363 esout_priv
->overlay
.p_video_es
= NULL
;
1365 es_out_Del(esout_priv
->p_dst_out
, p_pair
->p_es
);
1367 es_pair_Remove(&esout_priv
->es
, p_pair
);
1371 static int bluray_esOutSend(es_out_t
*p_out
, es_out_id_t
*p_es
, block_t
*p_block
)
1373 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1374 vlc_mutex_lock(&esout_priv
->lock
);
1376 bluray_esOutDeleteNonReusedESUnlocked(p_out
);
1378 if(esout_priv
->b_discontinuity
)
1379 esout_priv
->b_discontinuity
= false;
1381 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1382 if(p_pair
&& p_pair
->i_next_block_flags
)
1384 p_block
->i_flags
|= p_pair
->i_next_block_flags
;
1385 p_pair
->i_next_block_flags
= 0;
1387 if(esout_priv
->b_disable_output
)
1389 block_Release(p_block
);
1392 vlc_mutex_unlock(&esout_priv
->lock
);
1393 return (p_block
) ? es_out_Send(esout_priv
->p_dst_out
, p_es
, p_block
) : VLC_SUCCESS
;
1396 static void bluray_esOutDel(es_out_t
*p_out
, es_out_id_t
*p_es
)
1398 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1399 vlc_mutex_lock(&esout_priv
->lock
);
1401 if(esout_priv
->b_discontinuity
)
1402 esout_priv
->b_discontinuity
= false;
1404 es_pair_t
*p_pair
= getEsPairByES(&esout_priv
->es
, p_es
);
1407 p_pair
->b_recyling
= true;
1408 esout_priv
->b_entered_recycling
= true;
1411 vlc_mutex_unlock(&esout_priv
->lock
);
1414 static int bluray_esOutControl(es_out_t
*p_out
, int i_query
, va_list args
)
1416 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1418 vlc_mutex_lock(&esout_priv
->lock
);
1420 if(esout_priv
->b_disable_output
&&
1421 i_query
< ES_OUT_PRIVATE_START
)
1423 vlc_mutex_unlock(&esout_priv
->lock
);
1424 return VLC_EGENERIC
;
1427 if(esout_priv
->b_discontinuity
)
1428 esout_priv
->b_discontinuity
= false;
1432 case BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
:
1433 case BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
:
1435 bool b_select
= (i_query
== BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
);
1436 const int i_bluray_stream_type
= va_arg(args
, int);
1437 const int i_pid
= va_arg(args
, int);
1438 switch(i_bluray_stream_type
)
1440 case BD_EVENT_AUDIO_STREAM
:
1441 esout_priv
->selected
.i_audio_pid
= i_pid
;
1443 case BD_EVENT_PG_TEXTST_STREAM
:
1444 esout_priv
->selected
.i_spu_pid
= i_pid
;
1450 es_pair_t
*p_pair
= getEsPairByPID(&esout_priv
->es
, i_pid
);
1451 if(unlikely(!p_pair
))
1453 vlc_mutex_unlock(&esout_priv
->lock
);
1454 return VLC_EGENERIC
;
1457 i_ret
= es_out_Control(esout_priv
->p_dst_out
,
1458 b_select
? ES_OUT_SET_ES
: ES_OUT_UNSET_ES
,
1462 case BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
:
1464 esout_priv
->b_discontinuity
= true;
1465 i_ret
= VLC_SUCCESS
;
1468 case BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
:
1470 esout_priv
->b_restart_decoders_on_reuse
= !va_arg(args
, int);
1471 i_ret
= VLC_SUCCESS
;
1474 case BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
:
1475 case BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
:
1477 esout_priv
->b_disable_output
= (i_query
== BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
1478 i_ret
= VLC_SUCCESS
;
1481 case BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
:
1482 case BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
:
1484 esout_priv
->b_lowdelay
= (i_query
== BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
);
1485 i_ret
= VLC_SUCCESS
;
1488 case BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
:
1490 int i_plane
= va_arg(args
, int);
1491 subpicture_t
*p_pic
= va_arg(args
, subpicture_t
*);
1492 if(!esout_priv
->overlay
.p_video_es
)
1495 es_format_Init(&fmt
, VIDEO_ES
, VLC_CODEC_I420
);
1496 video_format_Setup(&fmt
.video
, VLC_CODEC_I420
,
1497 1920, 1080, 1920, 1080, 1, 1);
1498 fmt
.i_priority
= ES_PRIORITY_NOT_SELECTABLE
;
1501 fmt
.video
.i_frame_rate
= 1; fmt
.video
.i_frame_rate_base
= 1;
1502 fmt
.b_packetized
= true;
1503 esout_priv
->overlay
.p_video_es
= bluray_esOutAddUnlocked(esout_priv
, &fmt
);
1504 if(esout_priv
->overlay
.p_video_es
)
1506 bluraySendBackgroundImage(esout_priv
->p_obj
,
1507 esout_priv
->p_dst_out
,
1508 esout_priv
->overlay
.p_video_es
,
1511 es_format_Clean(&fmt
);
1514 if(esout_priv
->overlay
.p_video_es
&& i_plane
< MAX_OVERLAY
)
1516 i_ret
= es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_ADD_OVERLAY
,
1517 esout_priv
->overlay
.p_video_es
, p_pic
,
1518 &esout_priv
->overlay
.channels
[i_plane
]);
1522 i_ret
= VLC_EGENERIC
;
1527 case BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
:
1529 int i_plane
= va_arg(args
, int);
1530 if(esout_priv
->overlay
.p_video_es
&&
1531 i_plane
< MAX_OVERLAY
&&
1532 esout_priv
->overlay
.channels
[i_plane
] != VOUT_SPU_CHANNEL_INVALID
)
1534 i_ret
= es_out_Control(esout_priv
->p_dst_out
, ES_OUT_VOUT_FLUSH_OVERLAY
,
1535 esout_priv
->overlay
.p_video_es
,
1536 esout_priv
->overlay
.channels
[i_plane
]);
1537 esout_priv
->overlay
.channels
[i_plane
] = VOUT_SPU_CHANNEL_INVALID
;
1541 assert(esout_priv
->overlay
.channels
[i_plane
] == VOUT_SPU_CHANNEL_INVALID
);
1542 i_ret
= VLC_EGENERIC
;
1547 case ES_OUT_SET_ES_DEFAULT
:
1549 case ES_OUT_UNSET_ES
:
1550 case ES_OUT_SET_ES_STATE
:
1551 i_ret
= VLC_EGENERIC
;
1554 case ES_OUT_GET_ES_STATE
:
1555 va_arg(args
, es_out_id_t
*);
1556 *va_arg(args
, bool *) = true;
1557 i_ret
= VLC_SUCCESS
;
1561 i_ret
= es_out_vaControl(esout_priv
->p_dst_out
, i_query
, args
);
1564 vlc_mutex_unlock(&esout_priv
->lock
);
1568 static void bluray_esOutDestroy(es_out_t
*p_out
)
1570 bluray_esout_priv_t
*esout_priv
= container_of(p_out
, bluray_esout_priv_t
, es_out
);
1572 for (size_t i
= 0; i
< vlc_array_count(&esout_priv
->es
); ++i
)
1573 free(vlc_array_item_at_index(&esout_priv
->es
, i
));
1574 vlc_array_clear(&esout_priv
->es
);
1575 vlc_mutex_destroy(&esout_priv
->lock
);
1579 static const struct es_out_callbacks bluray_esOutCallbacks
= {
1580 .add
= bluray_esOutAdd
,
1581 .send
= bluray_esOutSend
,
1582 .del
= bluray_esOutDel
,
1583 .control
= bluray_esOutControl
,
1584 .destroy
= bluray_esOutDestroy
,
1587 static es_out_t
*esOutNew(vlc_object_t
*p_obj
, es_out_t
*p_dst_out
, void *priv
)
1589 bluray_esout_priv_t
*esout_priv
= malloc(sizeof(*esout_priv
));
1590 if (unlikely(esout_priv
== NULL
))
1593 vlc_array_init(&esout_priv
->es
);
1594 esout_priv
->p_dst_out
= p_dst_out
;
1595 esout_priv
->p_obj
= p_obj
;
1596 esout_priv
->priv
= priv
;
1597 esout_priv
->es_out
.cbs
= &bluray_esOutCallbacks
;
1598 esout_priv
->b_discontinuity
= false;
1599 esout_priv
->b_disable_output
= false;
1600 esout_priv
->b_entered_recycling
= false;
1601 esout_priv
->b_restart_decoders_on_reuse
= true;
1602 esout_priv
->b_lowdelay
= false;
1603 esout_priv
->selected
.i_audio_pid
= -1;
1604 esout_priv
->selected
.i_spu_pid
= -1;
1605 esout_priv
->overlay
.p_video_es
= NULL
;
1606 for(size_t i
=0; i
<MAX_OVERLAY
; i
++)
1607 esout_priv
->overlay
.channels
[i
] = VOUT_SPU_CHANNEL_INVALID
;
1608 vlc_mutex_init(&esout_priv
->lock
);
1609 return &esout_priv
->es_out
;
1612 /*****************************************************************************
1613 * subpicture_updater_t functions:
1614 *****************************************************************************/
1616 static bluray_overlay_t
*updater_lock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1618 /* this lock is held while vout accesses overlay. => overlay can't be closed. */
1619 vlc_mutex_lock(&p_upd_sys
->lock
);
1621 bluray_overlay_t
*ov
= p_upd_sys
->p_overlay
;
1623 /* this lock is held while vout accesses overlay. => overlay can't be modified. */
1624 vlc_mutex_lock(&ov
->lock
);
1628 /* overlay has been closed */
1629 vlc_mutex_unlock(&p_upd_sys
->lock
);
1633 static void updater_unlock_overlay(bluray_spu_updater_sys_t
*p_upd_sys
)
1635 assert (p_upd_sys
->p_overlay
);
1637 vlc_mutex_unlock(&p_upd_sys
->p_overlay
->lock
);
1638 vlc_mutex_unlock(&p_upd_sys
->lock
);
1641 static int subpictureUpdaterValidate(subpicture_t
*p_subpic
,
1642 bool b_fmt_src
, const video_format_t
*p_fmt_src
,
1643 bool b_fmt_dst
, const video_format_t
*p_fmt_dst
,
1646 VLC_UNUSED(b_fmt_src
);
1647 VLC_UNUSED(b_fmt_dst
);
1648 VLC_UNUSED(p_fmt_src
);
1649 VLC_UNUSED(p_fmt_dst
);
1652 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1653 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1659 int res
= p_overlay
->status
== Outdated
;
1661 updater_unlock_overlay(p_upd_sys
);
1666 static void subpictureUpdaterUpdate(subpicture_t
*p_subpic
,
1667 const video_format_t
*p_fmt_src
,
1668 const video_format_t
*p_fmt_dst
,
1671 VLC_UNUSED(p_fmt_src
);
1672 VLC_UNUSED(p_fmt_dst
);
1674 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1675 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1682 * When this function is called, all p_subpic regions are gone.
1683 * We need to duplicate our regions (stored internaly) to this subpic.
1685 subpicture_region_t
*p_src
= p_overlay
->p_regions
;
1687 updater_unlock_overlay(p_upd_sys
);
1691 subpicture_region_t
**p_dst
= &p_subpic
->p_region
;
1692 while (p_src
!= NULL
) {
1693 *p_dst
= subpicture_region_Copy(p_src
);
1696 p_dst
= &(*p_dst
)->p_next
;
1697 p_src
= p_src
->p_next
;
1700 (*p_dst
)->p_next
= NULL
;
1701 p_overlay
->status
= Displayed
;
1703 updater_unlock_overlay(p_upd_sys
);
1706 static void subpictureUpdaterDestroy(subpicture_t
*p_subpic
)
1708 bluray_spu_updater_sys_t
*p_upd_sys
= p_subpic
->updater
.p_sys
;
1709 bluray_overlay_t
*p_overlay
= updater_lock_overlay(p_upd_sys
);
1712 /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
1713 p_overlay
->status
= ToDisplay
;
1714 p_overlay
->b_on_vout
= false;
1715 updater_unlock_overlay(p_upd_sys
);
1718 unref_subpicture_updater(p_upd_sys
);
1721 static subpicture_t
*bluraySubpictureCreate(bluray_overlay_t
*p_ov
)
1723 bluray_spu_updater_sys_t
*p_upd_sys
= malloc(sizeof(*p_upd_sys
));
1724 if (unlikely(p_upd_sys
== NULL
)) {
1728 p_upd_sys
->p_overlay
= p_ov
;
1730 subpicture_updater_t updater
= {
1731 .pf_validate
= subpictureUpdaterValidate
,
1732 .pf_update
= subpictureUpdaterUpdate
,
1733 .pf_destroy
= subpictureUpdaterDestroy
,
1737 subpicture_t
*p_pic
= subpicture_New(&updater
);
1738 if (p_pic
== NULL
) {
1743 p_pic
->i_original_picture_width
= p_ov
->width
;
1744 p_pic
->i_original_picture_height
= p_ov
->height
;
1745 p_pic
->b_absolute
= true;
1747 vlc_mutex_init(&p_upd_sys
->lock
);
1748 p_upd_sys
->ref_cnt
= 2;
1750 p_ov
->p_updater
= p_upd_sys
;
1755 /*****************************************************************************
1756 * User input events:
1757 *****************************************************************************/
1758 static void onMouseEvent(const vlc_mouse_t
*newmouse
, void *user_data
)
1760 demux_t
*p_demux
= user_data
;
1761 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1764 vlc_mouse_Init(&p_sys
->oldmouse
);
1768 if (vlc_mouse_HasMoved(&p_sys
->oldmouse
, newmouse
))
1769 bd_mouse_select(p_sys
->bluray
, -1, newmouse
->i_x
, newmouse
->i_y
);
1771 if (vlc_mouse_HasPressed( &p_sys
->oldmouse
, newmouse
, MOUSE_BUTTON_LEFT
))
1772 bd_user_input(p_sys
->bluray
, -1, BD_VK_MOUSE_ACTIVATE
);
1773 p_sys
->oldmouse
= *newmouse
;
1776 static int sendKeyEvent(demux_sys_t
*p_sys
, unsigned int key
)
1778 if (bd_user_input(p_sys
->bluray
, -1, key
) < 0)
1779 return VLC_EGENERIC
;
1784 /*****************************************************************************
1785 * libbluray overlay handling:
1786 *****************************************************************************/
1788 static void blurayCloseOverlay(demux_t
*p_demux
, int plane
)
1790 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1791 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1795 /* drop overlay from vout */
1796 if (ov
->p_updater
) {
1797 unref_subpicture_updater(ov
->p_updater
);
1800 /* no references to this overlay exist in vo anymore */
1801 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY
, plane
);
1803 vlc_mutex_destroy(&ov
->lock
);
1804 subpicture_region_ChainDelete(ov
->p_regions
);
1807 p_sys
->bdj
.p_overlays
[plane
] = NULL
;
1812 * Mark the overlay as "ToDisplay" status.
1813 * This will not send the overlay to the vout instantly, as the vout
1814 * may not be acquired (not acquirable) yet.
1815 * If is has already been acquired, the overlay has already been sent to it,
1816 * therefore, we only flag the overlay as "Outdated"
1818 static void blurayActivateOverlay(demux_t
*p_demux
, int plane
)
1820 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1821 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1824 * If the overlay is already displayed, mark the picture as outdated.
1825 * We must NOT use vout_PutSubpicture if a picture is already displayed.
1827 vlc_mutex_lock(&ov
->lock
);
1828 if (ov
->status
>= Displayed
&& ov
->b_on_vout
) {
1829 ov
->status
= Outdated
;
1830 vlc_mutex_unlock(&ov
->lock
);
1835 * Mark the overlay as available, but don't display it right now.
1836 * the blurayDemuxMenu will send it to vout, as it may be unavailable when
1837 * the overlay is computed
1839 ov
->status
= ToDisplay
;
1840 vlc_mutex_unlock(&ov
->lock
);
1843 static void blurayInitOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
1845 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1847 assert(p_sys
->bdj
.p_overlays
[plane
] == NULL
);
1849 bluray_overlay_t
*ov
= calloc(1, sizeof(*ov
));
1850 if (unlikely(ov
== NULL
))
1854 ov
->height
= height
;
1855 ov
->b_on_vout
= false;
1857 vlc_mutex_init(&ov
->lock
);
1859 p_sys
->bdj
.p_overlays
[plane
] = ov
;
1863 * Destroy every regions in the subpicture.
1864 * This is done in two steps:
1865 * - Wiping our private regions list
1866 * - Flagging the overlay as outdated, so the changes are replicated from
1867 * the subpicture_updater_t::pf_update
1868 * This doesn't destroy the subpicture, as the overlay may be used again by libbluray.
1870 static void blurayClearOverlay(demux_t
*p_demux
, int plane
)
1872 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1873 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[plane
];
1875 vlc_mutex_lock(&ov
->lock
);
1877 subpicture_region_ChainDelete(ov
->p_regions
);
1878 ov
->p_regions
= NULL
;
1879 ov
->status
= Outdated
;
1881 vlc_mutex_unlock(&ov
->lock
);
1885 * This will draw to the overlay by adding a region to our region list
1886 * This will have to be copied to the subpicture used to render the overlay.
1888 static void blurayDrawOverlay(demux_t
*p_demux
, const BD_OVERLAY
* const ov
)
1890 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1893 * Compute a subpicture_region_t.
1894 * It will be copied and sent to the vout later.
1896 vlc_mutex_lock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1898 /* Find a region to update */
1899 subpicture_region_t
**pp_reg
= &p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
;
1900 subpicture_region_t
*p_reg
= p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
;
1901 subpicture_region_t
*p_last
= NULL
;
1902 while (p_reg
!= NULL
) {
1904 if (p_reg
->i_x
== ov
->x
&& p_reg
->i_y
== ov
->y
&&
1905 p_reg
->fmt
.i_width
== ov
->w
&& p_reg
->fmt
.i_height
== ov
->h
)
1907 pp_reg
= &p_reg
->p_next
;
1908 p_reg
= p_reg
->p_next
;
1914 *pp_reg
= p_reg
->p_next
;
1915 subpicture_region_Delete(p_reg
);
1917 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1921 /* If there is no region to update, create a new one. */
1924 video_format_Init(&fmt
, 0);
1925 video_format_Setup(&fmt
, VLC_CODEC_YUVP
, ov
->w
, ov
->h
, ov
->w
, ov
->h
, 1, 1);
1927 p_reg
= subpicture_region_New(&fmt
);
1931 /* Append it to our list. */
1933 p_last
->p_next
= p_reg
;
1934 else /* If we don't have a last region, then our list empty */
1935 p_sys
->bdj
.p_overlays
[ov
->plane
]->p_regions
= p_reg
;
1939 /* Now we can update the region, regardless it's an update or an insert */
1940 const BD_PG_RLE_ELEM
*img
= ov
->img
;
1941 for (int y
= 0; y
< ov
->h
; y
++)
1942 for (int x
= 0; x
< ov
->w
;) {
1943 plane_t
*p
= &p_reg
->p_picture
->p
[0];
1944 memset(&p
->p_pixels
[y
* p
->i_pitch
+ x
], img
->color
, img
->len
);
1950 p_reg
->fmt
.p_palette
->i_entries
= 256;
1951 for (int i
= 0; i
< 256; ++i
) {
1952 p_reg
->fmt
.p_palette
->palette
[i
][0] = ov
->palette
[i
].Y
;
1953 p_reg
->fmt
.p_palette
->palette
[i
][1] = ov
->palette
[i
].Cb
;
1954 p_reg
->fmt
.p_palette
->palette
[i
][2] = ov
->palette
[i
].Cr
;
1955 p_reg
->fmt
.p_palette
->palette
[i
][3] = ov
->palette
[i
].T
;
1959 vlc_mutex_unlock(&p_sys
->bdj
.p_overlays
[ov
->plane
]->lock
);
1961 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
1965 static void blurayOverlayProc(void *ptr
, const BD_OVERLAY
*const overlay
)
1967 demux_t
*p_demux
= (demux_t
*)ptr
;
1968 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1970 vlc_mutex_lock(&p_sys
->bdj
.lock
);
1973 msg_Info(p_demux
, "Closing overlays.");
1974 for (int i
= 0; i
< MAX_OVERLAY
; i
++)
1975 blurayCloseOverlay(p_demux
, i
);
1976 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
1980 switch (overlay
->cmd
) {
1981 case BD_OVERLAY_INIT
:
1982 msg_Info(p_demux
, "Initializing overlay");
1983 blurayInitOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
1985 case BD_OVERLAY_CLOSE
:
1986 blurayClearOverlay(p_demux
, overlay
->plane
);
1987 blurayCloseOverlay(p_demux
, overlay
->plane
);
1989 case BD_OVERLAY_CLEAR
:
1990 blurayClearOverlay(p_demux
, overlay
->plane
);
1992 case BD_OVERLAY_FLUSH
:
1993 blurayActivateOverlay(p_demux
, overlay
->plane
);
1995 case BD_OVERLAY_DRAW
:
1996 case BD_OVERLAY_WIPE
:
1997 blurayDrawOverlay(p_demux
, overlay
);
2000 msg_Warn(p_demux
, "Unknown BD overlay command: %u", overlay
->cmd
);
2004 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
2008 * ARGB overlay (BD-J)
2010 static void blurayInitArgbOverlay(demux_t
*p_demux
, int plane
, int width
, int height
)
2012 blurayInitOverlay(p_demux
, plane
, width
, height
);
2015 static void blurayDrawArgbOverlay(demux_t
*p_demux
, const BD_ARGB_OVERLAY
* const ov
)
2017 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2019 bluray_overlay_t
*bdov
= p_sys
->bdj
.p_overlays
[ov
->plane
];
2020 vlc_mutex_lock(&bdov
->lock
);
2022 if (!bdov
->p_regions
)
2025 video_format_Init(&fmt
, 0);
2026 video_format_Setup(&fmt
,
2027 /* ARGB in word order -> byte order */
2028 #ifdef WORDS_BIG_ENDIAN
2033 ov
->stride
, bdov
->height
,
2034 bdov
->width
, bdov
->height
, 1, 1);
2035 bdov
->p_regions
= subpicture_region_New(&fmt
);
2038 /* Find a region to update */
2039 subpicture_region_t
*p_reg
= bdov
->p_regions
;
2041 vlc_mutex_unlock(&bdov
->lock
);
2045 /* Now we can update the region */
2046 const uint32_t *src0
= ov
->argb
;
2047 uint8_t *dst0
= p_reg
->p_picture
->p
[0].p_pixels
+
2048 p_reg
->p_picture
->p
[0].i_pitch
* ov
->y
+
2051 for (int y
= 0; y
< ov
->h
; y
++)
2053 memcpy(dst0
, src0
, ov
->w
* 4);
2055 dst0
+= p_reg
->p_picture
->p
[0].i_pitch
;
2058 vlc_mutex_unlock(&bdov
->lock
);
2060 * /!\ The region is now stored in our internal list, but not in the subpicture /!\
2064 static void blurayArgbOverlayProc(void *ptr
, const BD_ARGB_OVERLAY
*const overlay
)
2066 demux_t
*p_demux
= (demux_t
*)ptr
;
2067 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2069 switch (overlay
->cmd
) {
2070 case BD_ARGB_OVERLAY_INIT
:
2071 vlc_mutex_lock(&p_sys
->bdj
.lock
);
2072 blurayInitArgbOverlay(p_demux
, overlay
->plane
, overlay
->w
, overlay
->h
);
2073 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
2075 case BD_ARGB_OVERLAY_CLOSE
:
2076 vlc_mutex_lock(&p_sys
->bdj
.lock
);
2077 blurayClearOverlay(p_demux
, overlay
->plane
);
2078 blurayCloseOverlay(p_demux
, overlay
->plane
);
2079 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
2081 case BD_ARGB_OVERLAY_FLUSH
:
2082 blurayActivateOverlay(p_demux
, overlay
->plane
);
2084 case BD_ARGB_OVERLAY_DRAW
:
2085 blurayDrawArgbOverlay(p_demux
, overlay
);
2088 msg_Warn(p_demux
, "Unknown BD ARGB overlay command: %u", overlay
->cmd
);
2093 static void bluraySendOverlayToVout(demux_t
*p_demux
, int plane
, bluray_overlay_t
*p_ov
)
2095 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2097 assert(p_ov
!= NULL
);
2098 assert(!p_ov
->b_on_vout
);
2100 if (p_ov
->p_updater
) {
2101 unref_subpicture_updater(p_ov
->p_updater
);
2102 p_ov
->p_updater
= NULL
;
2105 subpicture_t
*p_pic
= bluraySubpictureCreate(p_ov
);
2107 msg_Err(p_demux
, "bluraySubpictureCreate() failed");
2112 * After this point, the picture should not be accessed from the demux thread,
2113 * as it is held by the vout thread.
2114 * This must be done only once per subpicture, ie. only once between each
2115 * blurayInitOverlay & blurayCloseOverlay call.
2117 int ret
= es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY
,
2119 if (ret
!= VLC_SUCCESS
)
2121 unref_subpicture_updater(p_ov
->p_updater
);
2122 p_ov
->p_updater
= NULL
;
2123 p_ov
->b_on_vout
= false;
2124 subpicture_Delete(p_pic
);
2127 p_ov
->b_on_vout
= true;
2130 * Mark the picture as Outdated, as it contains no region for now.
2131 * This will make the subpicture_updater_t call pf_update
2133 p_ov
->status
= Outdated
;
2136 static bool blurayTitleIsRepeating(BLURAY_TITLE_INFO
*title_info
,
2137 unsigned repeats
, unsigned ratio
)
2139 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(1, 0, 0)
2140 const BLURAY_CLIP_INFO
*prev
= NULL
;
2141 unsigned maxrepeats
= 0;
2142 unsigned sequence
= 0;
2143 if(!title_info
->chapter_count
)
2146 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++)
2148 unsigned i
= title_info
->chapters
[j
].clip_ref
;
2149 if(i
< title_info
->clip_count
)
2152 /* non repeated does not need start time offset */
2153 title_info
->clips
[i
].start_time
== 0 ||
2154 /* repeats occurs on same segment */
2155 memcmp(title_info
->clips
[i
].clip_id
, prev
->clip_id
, 6) ||
2156 prev
->in_time
!= title_info
->clips
[i
].in_time
||
2157 prev
->pkt_count
!= title_info
->clips
[i
].pkt_count
)
2160 prev
= &title_info
->clips
[i
];
2165 if(maxrepeats
< sequence
++)
2166 maxrepeats
= sequence
;
2170 return (maxrepeats
> repeats
&&
2171 (100 * maxrepeats
/ title_info
->chapter_count
) >= ratio
);
2177 static void blurayUpdateTitleInfo(input_title_t
*t
, BLURAY_TITLE_INFO
*title_info
)
2179 t
->i_length
= FROM_SCALE_NZ(title_info
->duration
);
2181 for (int i
= 0; i
< t
->i_seekpoint
; i
++)
2182 vlc_seekpoint_Delete( t
->seekpoint
[i
] );
2183 TAB_CLEAN(t
->i_seekpoint
, t
->seekpoint
);
2185 /* FIXME: have libbluray expose repeating titles */
2186 if(blurayTitleIsRepeating(title_info
, 50, 90))
2189 for (unsigned int j
= 0; j
< title_info
->chapter_count
; j
++) {
2190 seekpoint_t
*s
= vlc_seekpoint_New();
2194 s
->i_time_offset
= FROM_SCALE_NZ(title_info
->chapters
[j
].start
);
2196 TAB_APPEND(t
->i_seekpoint
, t
->seekpoint
, s
);
2200 static void blurayInitTitles(demux_t
*p_demux
, uint32_t menu_titles
)
2202 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2203 const BLURAY_DISC_INFO
*di
= bd_get_disc_info(p_sys
->bluray
);
2205 /* get and set the titles */
2206 uint32_t i_title
= menu_titles
;
2208 if (!p_sys
->b_menu
) {
2209 i_title
= bd_get_titles(p_sys
->bluray
, TITLES_RELEVANT
, 60);
2210 p_sys
->i_longest_title
= bd_get_main_title(p_sys
->bluray
);
2213 for (uint32_t i
= 0; i
< i_title
; i
++) {
2214 input_title_t
*t
= vlc_input_title_New();
2218 if (!p_sys
->b_menu
) {
2219 BLURAY_TITLE_INFO
*title_info
= bd_get_title_info(p_sys
->bluray
, i
, 0);
2220 blurayUpdateTitleInfo(t
, title_info
);
2221 bd_free_title_info(title_info
);
2223 } else if (i
== 0) {
2224 t
->psz_name
= strdup(_("Top Menu"));
2225 t
->i_flags
= INPUT_TITLE_MENU
| INPUT_TITLE_INTERACTIVE
;
2226 } else if (i
== i_title
- 1) {
2227 t
->psz_name
= strdup(_("First Play"));
2228 if (di
&& di
->first_play
&& di
->first_play
->interactive
) {
2229 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
2232 /* add possible title name from disc metadata */
2233 if (di
&& di
->titles
&& i
<= di
->num_titles
) {
2234 if (di
->titles
[i
]->name
) {
2235 t
->psz_name
= strdup(di
->titles
[i
]->name
);
2237 if (di
->titles
[i
]->interactive
) {
2238 t
->i_flags
= INPUT_TITLE_INTERACTIVE
;
2243 TAB_APPEND(p_sys
->i_title
, p_sys
->pp_title
, t
);
2247 static void blurayRestartParser(demux_t
*p_demux
, bool b_flush
, bool b_random_access
)
2250 * This is a hack and will have to be removed.
2251 * The parser should be flushed, and not destroy/created each time
2252 * we are changing title.
2254 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2257 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT
);
2259 if (p_sys
->p_parser
)
2260 vlc_demux_chained_Delete(p_sys
->p_parser
);
2263 es_out_Control(p_sys
->p_tf_out
, ES_OUT_TF_FILTER_RESET
);
2265 p_sys
->p_parser
= vlc_demux_chained_New(VLC_OBJECT(p_demux
), "ts", p_sys
->p_out
);
2266 if (!p_sys
->p_parser
)
2267 msg_Err(p_demux
, "Failed to create TS demuxer");
2269 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_ENABLE_OUTPUT
);
2271 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_RANDOM_ACCESS
, b_random_access
);
2274 /*****************************************************************************
2275 * bluraySetTitle: select new BD title
2276 *****************************************************************************/
2277 static int bluraySetTitle(demux_t
*p_demux
, int i_title
)
2279 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2281 if (p_sys
->b_menu
) {
2284 msg_Dbg(p_demux
, "Playing TopMenu Title");
2285 result
= bd_menu_call(p_sys
->bluray
, -1);
2286 } else if (i_title
>= (int)p_sys
->i_title
- 1) {
2287 msg_Dbg(p_demux
, "Playing FirstPlay Title");
2288 result
= bd_play_title(p_sys
->bluray
, BLURAY_TITLE_FIRST_PLAY
);
2290 msg_Dbg(p_demux
, "Playing Title %i", i_title
);
2291 result
= bd_play_title(p_sys
->bluray
, i_title
);
2295 msg_Err(p_demux
, "cannot play bd title '%d'", i_title
);
2296 return VLC_EGENERIC
;
2302 /* Looking for the main title, ie the longest duration */
2304 i_title
= p_sys
->i_longest_title
;
2305 else if ((unsigned)i_title
> p_sys
->i_title
)
2306 return VLC_EGENERIC
;
2308 msg_Dbg(p_demux
, "Selecting Title %i", i_title
);
2310 if (bd_select_title(p_sys
->bluray
, i_title
) == 0) {
2311 msg_Err(p_demux
, "cannot select bd title '%d'", i_title
);
2312 return VLC_EGENERIC
;
2318 #if BLURAY_VERSION < BLURAY_VERSION_CODE(0,9,2)
2319 # define BLURAY_AUDIO_STREAM 0
2322 static void blurayOnUserStreamSelection(demux_sys_t
*p_sys
, int i_pid
)
2324 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2326 if(i_pid
== -AUDIO_ES
)
2327 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, 0, 0);
2328 else if(i_pid
== -SPU_ES
)
2329 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, 0, 0);
2330 else if (p_sys
->p_clip_info
)
2333 if ((i_pid
& 0xff00) == 0x1100) {
2335 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->audio_stream_count
; i_id
++) {
2336 if (i_pid
== p_sys
->p_clip_info
->audio_streams
[i_id
].pid
) {
2337 bd_select_stream(p_sys
->bluray
, BLURAY_AUDIO_STREAM
, i_id
+ 1, 1);
2339 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_AUDIO_LANG
,
2340 (const char *) p_sys
->p_clip_info
->audio_streams
[i_id
].lang
);
2344 } else if ((i_pid
& 0xff00) == 0x1400 || i_pid
== 0x1800) {
2346 for (int i_id
= 0; i_id
< p_sys
->p_clip_info
->pg_stream_count
; i_id
++) {
2347 if (i_pid
== p_sys
->p_clip_info
->pg_streams
[i_id
].pid
) {
2348 bd_select_stream(p_sys
->bluray
, BLURAY_PG_TEXTST_STREAM
, i_id
+ 1, 1);
2350 bd_set_player_setting_str(p_sys
->bluray
, BLURAY_PLAYER_SETTING_PG_LANG
,
2351 (const char *) p_sys
->p_clip_info
->pg_streams
[i_id
].lang
);
2358 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2361 /*****************************************************************************
2362 * blurayControl: handle the controls
2363 *****************************************************************************/
2364 static int blurayControl(demux_t
*p_demux
, int query
, va_list args
)
2366 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2370 case DEMUX_CAN_SEEK
:
2371 case DEMUX_CAN_PAUSE
:
2372 case DEMUX_CAN_CONTROL_PACE
:
2373 pb_bool
= va_arg(args
, bool *);
2377 case DEMUX_GET_PTS_DELAY
:
2378 *va_arg(args
, vlc_tick_t
*) =
2379 VLC_TICK_FROM_MS(var_InheritInteger(p_demux
, "disc-caching"));
2382 case DEMUX_SET_PAUSE_STATE
:
2384 #ifdef BLURAY_RATE_NORMAL
2385 bool b_paused
= (bool)va_arg(args
, int);
2386 if (bd_set_rate(p_sys
->bluray
, BLURAY_RATE_NORMAL
* (!b_paused
)) < 0) {
2387 return VLC_EGENERIC
;
2394 int i_id
= va_arg(args
, int);
2395 blurayOnUserStreamSelection(p_sys
, i_id
);
2398 case DEMUX_SET_TITLE
:
2400 int i_title
= va_arg(args
, int);
2401 if (bluraySetTitle(p_demux
, i_title
) != VLC_SUCCESS
) {
2402 /* make sure GUI restores the old setting in title menu ... */
2403 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2404 return VLC_EGENERIC
;
2406 blurayRestartParser(p_demux
, true, false);
2407 notifyDiscontinuityToParser(p_sys
);
2408 p_sys
->b_draining
= false;
2409 es_out_Control(p_demux
->out
, ES_OUT_RESET_PCR
);
2410 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2413 case DEMUX_SET_SEEKPOINT
:
2415 int i_chapter
= va_arg(args
, int);
2416 bd_seek_chapter(p_sys
->bluray
, i_chapter
);
2417 blurayRestartParser(p_demux
, true, false);
2418 notifyDiscontinuityToParser(p_sys
);
2419 p_sys
->b_draining
= false;
2420 es_out_Control(p_demux
->out
, ES_OUT_RESET_PCR
);
2421 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2424 case DEMUX_TEST_AND_CLEAR_FLAGS
:
2426 unsigned *restrict flags
= va_arg(args
, unsigned *);
2427 *flags
&= p_sys
->updates
;
2428 p_sys
->updates
&= ~*flags
;
2431 case DEMUX_GET_TITLE
:
2432 *va_arg(args
, int *) = p_sys
->cur_title
;
2435 case DEMUX_GET_SEEKPOINT
:
2436 *va_arg(args
, int *) = p_sys
->cur_seekpoint
;
2439 case DEMUX_GET_TITLE_INFO
:
2441 input_title_t
***ppp_title
= va_arg(args
, input_title_t
***);
2442 int *pi_int
= va_arg(args
, int *);
2443 int *pi_title_offset
= va_arg(args
, int *);
2444 int *pi_chapter_offset
= va_arg(args
, int *);
2447 *pi_title_offset
= 0;
2448 *pi_chapter_offset
= 0;
2450 /* Duplicate local title infos */
2452 *ppp_title
= vlc_alloc(p_sys
->i_title
, sizeof(input_title_t
*));
2454 return VLC_EGENERIC
;
2455 for (unsigned int i
= 0; i
< p_sys
->i_title
; i
++)
2457 input_title_t
*p_dup
= vlc_input_title_Duplicate(p_sys
->pp_title
[i
]);
2459 (*ppp_title
)[(*pi_int
)++] = p_dup
;
2465 case DEMUX_GET_LENGTH
:
2467 if(p_sys
->cur_title
< p_sys
->i_title
&&
2468 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2469 return VLC_EGENERIC
;
2470 *va_arg(args
, vlc_tick_t
*) = p_sys
->cur_title
< p_sys
->i_title
? CUR_LENGTH
: 0;
2473 case DEMUX_SET_TIME
:
2475 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(va_arg(args
, vlc_tick_t
)));
2476 blurayRestartParser(p_demux
, true, true);
2477 notifyDiscontinuityToParser(p_sys
);
2478 p_sys
->b_draining
= false;
2479 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2482 case DEMUX_GET_TIME
:
2484 vlc_tick_t
*pi_time
= va_arg(args
, vlc_tick_t
*);
2485 if(p_sys
->cur_title
< p_sys
->i_title
&&
2486 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2487 return VLC_EGENERIC
;
2488 *pi_time
= FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
));
2492 case DEMUX_GET_POSITION
:
2494 double *pf_position
= va_arg(args
, double *);
2495 if(p_sys
->cur_title
< p_sys
->i_title
&&
2496 (CURRENT_TITLE
->i_flags
& INPUT_TITLE_INTERACTIVE
))
2497 return VLC_EGENERIC
;
2498 *pf_position
= p_sys
->cur_title
< p_sys
->i_title
&& CUR_LENGTH
> 0 ?
2499 (double)FROM_SCALE_NZ(bd_tell_time(p_sys
->bluray
))/CUR_LENGTH
: 0.0;
2502 case DEMUX_SET_POSITION
:
2504 double f_position
= va_arg(args
, double);
2505 bd_seek_time(p_sys
->bluray
, TO_SCALE_NZ(f_position
*CUR_LENGTH
));
2506 blurayRestartParser(p_demux
, true, true);
2507 notifyDiscontinuityToParser(p_sys
);
2508 p_sys
->b_draining
= false;
2509 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2513 case DEMUX_GET_META
:
2515 vlc_meta_t
*p_meta
= va_arg(args
, vlc_meta_t
*);
2516 const META_DL
*meta
= p_sys
->p_meta
;
2518 return VLC_EGENERIC
;
2520 if (!EMPTY_STR(meta
->di_name
)) vlc_meta_SetTitle(p_meta
, meta
->di_name
);
2522 if (!EMPTY_STR(meta
->language_code
)) vlc_meta_AddExtra(p_meta
, "Language", meta
->language_code
);
2523 if (!EMPTY_STR(meta
->filename
)) vlc_meta_AddExtra(p_meta
, "Filename", meta
->filename
);
2524 if (!EMPTY_STR(meta
->di_alternative
)) vlc_meta_AddExtra(p_meta
, "Alternative", meta
->di_alternative
);
2526 // if (meta->di_set_number > 0) vlc_meta_SetTrackNum(p_meta, meta->di_set_number);
2527 // if (meta->di_num_sets > 0) vlc_meta_AddExtra(p_meta, "Discs numbers in Set", meta->di_num_sets);
2529 if (p_sys
->i_cover_idx
>= 0 && p_sys
->i_cover_idx
< p_sys
->i_attachments
) {
2531 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
2532 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
2533 vlc_meta_Set( p_meta
, vlc_meta_ArtworkURL
, psz_url
);
2535 else if (meta
->thumb_count
> 0 && meta
->thumbnails
&& p_sys
->psz_bd_path
) {
2536 char *psz_thumbpath
;
2537 if (asprintf(&psz_thumbpath
, "%s" DIR_SEP
"BDMV" DIR_SEP
"META" DIR_SEP
"DL" DIR_SEP
"%s",
2538 p_sys
->psz_bd_path
, meta
->thumbnails
[0].path
) > -1) {
2539 char *psz_thumburl
= vlc_path2uri(psz_thumbpath
, "file");
2540 free(psz_thumbpath
);
2541 if (unlikely(psz_thumburl
== NULL
))
2544 vlc_meta_SetArtURL(p_meta
, psz_thumburl
);
2552 case DEMUX_GET_ATTACHMENTS
:
2554 input_attachment_t
***ppp_attach
=
2555 va_arg(args
, input_attachment_t
***);
2556 int *pi_int
= va_arg(args
, int *);
2558 if (p_sys
->i_attachments
<= 0)
2559 return VLC_EGENERIC
;
2562 *ppp_attach
= vlc_alloc(p_sys
->i_attachments
, sizeof(input_attachment_t
*));
2564 return VLC_EGENERIC
;
2565 for (int i
= 0; i
< p_sys
->i_attachments
; i
++)
2567 input_attachment_t
*p_dup
= vlc_input_attachment_Duplicate(p_sys
->attachments
[i
]);
2569 (*ppp_attach
)[(*pi_int
)++] = p_dup
;
2574 case DEMUX_NAV_ACTIVATE
:
2575 if (p_sys
->b_popup_available
&& !p_sys
->b_menu_open
) {
2576 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2578 return sendKeyEvent(p_sys
, BD_VK_ENTER
);
2580 return sendKeyEvent(p_sys
, BD_VK_UP
);
2581 case DEMUX_NAV_DOWN
:
2582 return sendKeyEvent(p_sys
, BD_VK_DOWN
);
2583 case DEMUX_NAV_LEFT
:
2584 return sendKeyEvent(p_sys
, BD_VK_LEFT
);
2585 case DEMUX_NAV_RIGHT
:
2586 return sendKeyEvent(p_sys
, BD_VK_RIGHT
);
2587 case DEMUX_NAV_POPUP
:
2588 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2589 case DEMUX_NAV_MENU
:
2590 if (p_sys
->b_menu
) {
2591 if (bd_menu_call(p_sys
->bluray
, -1) == 1) {
2592 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2595 msg_Err(p_demux
, "Can't select Top Menu title");
2596 return sendKeyEvent(p_sys
, BD_VK_POPUP
);
2598 return VLC_EGENERIC
;
2600 case DEMUX_CAN_RECORD
:
2602 case DEMUX_SET_GROUP_DEFAULT
:
2603 case DEMUX_SET_GROUP_ALL
:
2604 case DEMUX_SET_GROUP_LIST
:
2605 case DEMUX_HAS_UNSUPPORTED_META
:
2607 return VLC_EGENERIC
;
2612 /*****************************************************************************
2613 * libbluray event handling
2614 *****************************************************************************/
2615 static void writeTsPacketWDiscontinuity( uint8_t *p_buf
, uint16_t i_pid
,
2616 const uint8_t *p_payload
, uint8_t i_payload
)
2618 uint8_t ts_header
[] = {
2619 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */
2621 0x40 | ((i_pid
& 0x1f00) >> 8), i_pid
& 0xFF, /* PUSI + PID */
2622 i_payload
? 0x30 : 0x20, /* adaptation field, payload / no payload */
2623 192 - (4 + 5) - i_payload
, /* adaptation field length */
2624 0x82, /* af: discontinuity indicator + priv data */
2625 0x0E, /* priv data size */
2627 'D', 'I', 'S', 'C', 'O', 'N', 'T', 'I', 'N', 'U',
2630 memcpy( p_buf
, ts_header
, sizeof(ts_header
) );
2631 memset( &p_buf
[sizeof(ts_header
)], 0xFF, 192 - sizeof(ts_header
) - i_payload
);
2633 memcpy( &p_buf
[192 - i_payload
], p_payload
, i_payload
);
2636 static void notifyStreamsDiscontinuity( vlc_demux_chained_t
*p_parser
,
2637 const BLURAY_STREAM_INFO
*p_sinfo
, size_t i_sinfo
)
2639 for( size_t i
=0; i
< i_sinfo
; i
++ )
2641 const uint16_t i_pid
= p_sinfo
[i
].pid
;
2643 block_t
*p_block
= block_Alloc(192);
2647 writeTsPacketWDiscontinuity( p_block
->p_buffer
, i_pid
, NULL
, 0 );
2649 vlc_demux_chained_Send(p_parser
, p_block
);
2653 #define DONOTIFY(memb) notifyStreamsDiscontinuity( p_sys->p_parser, p_clip->memb##_streams, \
2654 p_clip->memb##_stream_count )
2656 static void notifyDiscontinuityToParser( demux_sys_t
*p_sys
)
2658 const BLURAY_CLIP_INFO
*p_clip
= p_sys
->p_clip_info
;
2665 DONOTIFY(sec_audio
);
2666 DONOTIFY(sec_video
);
2672 static void streamFlush( demux_sys_t
*p_sys
)
2675 * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown.
2676 * Packet is flushed only when TS packet with PUSI flag set is received.
2678 * Fix this by emitting (video) ts packet with PUSI flag set.
2679 * Add video sequence end code to payload so that also video decoder is flushed.
2680 * Set PES packet size in the payload so that it will be sent to decoder immediately.
2683 if (p_sys
->b_flushed
)
2686 block_t
*p_block
= block_Alloc(192);
2690 bd_stream_type_e i_coding_type
;
2692 /* set correct sequence end code */
2693 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2694 if (p_sys
->p_clip_info
!= NULL
)
2695 i_coding_type
= p_sys
->p_clip_info
->video_streams
[0].coding_type
;
2698 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2701 switch( i_coding_type
)
2703 case BLURAY_STREAM_TYPE_VIDEO_MPEG1
:
2704 case BLURAY_STREAM_TYPE_VIDEO_MPEG2
:
2706 i_eos
= 0xB7; /* MPEG2 sequence end */
2708 case BLURAY_STREAM_TYPE_VIDEO_VC1
:
2709 case BLURAY_STREAM_TYPE_VIDEO_H264
:
2710 i_eos
= 0x0A; /* VC1 / H.264 sequence end */
2712 case BD_STREAM_TYPE_VIDEO_HEVC
:
2713 i_eos
= 0x48; /* HEVC sequence end NALU */
2717 uint8_t seq_end_pes
[] = {
2718 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */
2719 0x00, 0x00, 0x01, i_eos
, /* PES payload: sequence end */
2720 0x00, /* 2nd byte for HEVC NAL, pads others */
2723 writeTsPacketWDiscontinuity( p_block
->p_buffer
, 0x1011, seq_end_pes
, sizeof(seq_end_pes
) );
2725 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
2726 p_sys
->b_flushed
= true;
2729 static void blurayResetStillImage( demux_t
*p_demux
)
2731 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2733 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
) {
2734 p_sys
->i_still_end_time
= STILL_IMAGE_NOT_SET
;
2736 blurayRestartParser(p_demux
, false, false);
2737 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2741 static void blurayStillImage( demux_t
*p_demux
, unsigned i_timeout
)
2743 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2745 /* time period elapsed ? */
2746 if (p_sys
->i_still_end_time
!= STILL_IMAGE_NOT_SET
&&
2747 p_sys
->i_still_end_time
!= STILL_IMAGE_INFINITE
&&
2748 p_sys
->i_still_end_time
<= vlc_tick_now()) {
2749 msg_Dbg(p_demux
, "Still image end");
2750 bd_read_skip_still(p_sys
->bluray
);
2752 blurayResetStillImage(p_demux
);
2756 /* show last frame as still image */
2757 if (p_sys
->i_still_end_time
== STILL_IMAGE_NOT_SET
) {
2759 msg_Dbg(p_demux
, "Still image (%d seconds)", i_timeout
);
2760 p_sys
->i_still_end_time
= vlc_tick_now() + vlc_tick_from_sec( i_timeout
);
2762 msg_Dbg(p_demux
, "Still image (infinite)");
2763 p_sys
->i_still_end_time
= STILL_IMAGE_INFINITE
;
2766 /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */
2769 /* stop buffering */
2771 es_out_Control( p_demux
->out
, ES_OUT_GET_EMPTY
, &b_empty
);
2774 /* avoid busy loops (read returns no data) */
2775 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2778 static void blurayOnStreamSelectedEvent(demux_t
*p_demux
, uint32_t i_type
, uint32_t i_id
)
2780 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2783 /* The param we get is the real stream id, not an index, ie. it starts from 1 */
2786 if (i_type
== BD_EVENT_AUDIO_STREAM
) {
2787 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2788 } else if (i_type
== BD_EVENT_PG_TEXTST_STREAM
) {
2789 i_pid
= blurayGetStreamPID(p_sys
, i_type
, i_id
);
2794 if (i_type
== BD_EVENT_PG_TEXTST_STREAM
&& !p_sys
->b_spu_enable
)
2795 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_UNSET_ES_BY_PID
, (int)i_type
, i_pid
);
2797 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_SET_ES_BY_PID
, (int)i_type
, i_pid
);
2801 static void blurayUpdatePlaylist(demux_t
*p_demux
, unsigned i_playlist
)
2803 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2805 blurayRestartParser(p_demux
, true, false);
2807 /* read title info and init some values */
2809 p_sys
->cur_title
= bd_get_current_title(p_sys
->bluray
);
2810 p_sys
->cur_seekpoint
= 0;
2811 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2813 BLURAY_TITLE_INFO
*p_title_info
= bd_get_playlist_info(p_sys
->bluray
, i_playlist
, 0);
2815 blurayUpdateTitleInfo(p_sys
->pp_title
[p_sys
->cur_title
], p_title_info
);
2817 p_sys
->updates
|= INPUT_UPDATE_TITLE_LIST
;
2819 setTitleInfo(p_sys
, p_title_info
);
2821 blurayResetStillImage(p_demux
);
2824 static void blurayOnClipUpdate(demux_t
*p_demux
, uint32_t clip
)
2826 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2828 vlc_mutex_lock(&p_sys
->pl_info_lock
);
2830 p_sys
->p_clip_info
= NULL
;
2832 if (p_sys
->p_pl_info
&& clip
< p_sys
->p_pl_info
->clip_count
) {
2834 p_sys
->p_clip_info
= &p_sys
->p_pl_info
->clips
[clip
];
2836 /* Let's assume a single video track for now.
2837 * This may brake later, but it's enough for now.
2839 assert(p_sys
->p_clip_info
->video_stream_count
>= 1);
2842 CLPI_CL
*clpi
= bd_get_clpi(p_sys
->bluray
, clip
);
2843 if(clpi
&& clpi
->clip
.application_type
!= p_sys
->clip_application_type
)
2845 if(p_sys
->clip_application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
||
2846 clpi
->clip
.application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
)
2847 blurayRestartParser(p_demux
, false, false);
2849 if(clpi
->clip
.application_type
== BD_CLIP_APP_TYPE_TS_MAIN_PATH_TIMED_SLIDESHOW
)
2850 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY
);
2852 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY
);
2856 vlc_mutex_unlock(&p_sys
->pl_info_lock
);
2858 blurayResetStillImage(p_demux
);
2861 static void blurayHandleEvent(demux_t
*p_demux
, const BD_EVENT
*e
, bool b_delayed
)
2863 demux_sys_t
*p_sys
= p_demux
->p_sys
;
2865 blurayDebugEvent(e
->event
, e
->param
);
2868 case BD_EVENT_TITLE
:
2869 if (e
->param
== BLURAY_TITLE_FIRST_PLAY
)
2870 p_sys
->cur_title
= p_sys
->i_title
- 1;
2872 p_sys
->cur_title
= e
->param
;
2873 /* this is feature title, we don't know yet which playlist it will play (if any) */
2874 setTitleInfo(p_sys
, NULL
);
2875 /* reset title infos here ? */
2876 p_sys
->updates
|= INPUT_UPDATE_TITLE
| INPUT_UPDATE_SEEKPOINT
;
2877 /* might be BD-J title with no video */
2879 case BD_EVENT_PLAYLIST
:
2880 /* Start of playlist playback (?????.mpls) */
2881 blurayUpdatePlaylist(p_demux
, e
->param
);
2882 if (p_sys
->b_pl_playing
) {
2883 /* previous playlist was stopped in middle. flush to avoid delay */
2884 msg_Info(p_demux
, "Stopping playlist playback");
2885 blurayRestartParser(p_demux
, false, false);
2886 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
2888 p_sys
->b_pl_playing
= true;
2890 case BD_EVENT_PLAYITEM
:
2891 notifyDiscontinuityToParser(p_sys
);
2892 blurayOnClipUpdate(p_demux
, e
->param
);
2894 case BD_EVENT_CHAPTER
:
2895 if (e
->param
&& e
->param
< 0xffff)
2896 p_sys
->cur_seekpoint
= e
->param
- 1;
2898 p_sys
->cur_seekpoint
= 0;
2899 p_sys
->updates
|= INPUT_UPDATE_SEEKPOINT
;
2901 case BD_EVENT_PLAYMARK
:
2902 case BD_EVENT_ANGLE
:
2905 /* Seek will happen with any chapter/title or bd_seek(),
2906 but also BD-J initiated. We can't make the difference
2907 between input or vm ones, better double flush/pcr reset
2908 than break the clock by throwing post random access PCR */
2909 blurayRestartParser(p_demux
, true, true);
2910 notifyDiscontinuityToParser(p_sys
);
2911 es_out_Control(p_sys
->p_out
, ES_OUT_RESET_PCR
);
2913 #if BLURAY_VERSION >= BLURAY_VERSION_CODE(0,8,1)
2914 case BD_EVENT_UO_MASK_CHANGED
:
2915 /* This event could be used to grey out unselectable items in title menu */
2919 p_sys
->b_menu_open
= e
->param
;
2921 case BD_EVENT_POPUP
:
2922 p_sys
->b_popup_available
= e
->param
;
2923 /* TODO: show / hide pop-up menu button in gui ? */
2929 case BD_EVENT_ERROR
:
2930 /* fatal error (with menus) */
2931 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2932 "Playback with BluRay menus failed");
2933 p_sys
->b_fatal_error
= true;
2935 case BD_EVENT_ENCRYPTED
:
2936 vlc_dialog_display_error(p_demux
, _("Blu-ray error"),
2937 "This disc seems to be encrypted");
2938 p_sys
->b_fatal_error
= true;
2940 case BD_EVENT_READ_ERROR
:
2941 msg_Err(p_demux
, "bluray: read error\n");
2945 * stream selection events
2947 case BD_EVENT_PG_TEXTST
:
2948 p_sys
->b_spu_enable
= e
->param
;
2950 case BD_EVENT_AUDIO_STREAM
:
2951 case BD_EVENT_PG_TEXTST_STREAM
:
2953 blurayOnStreamSelectedEvent(p_demux
, e
->event
, e
->param
);
2955 ARRAY_APPEND(p_sys
->events_delayed
, *e
);
2957 case BD_EVENT_IG_STREAM
:
2958 case BD_EVENT_SECONDARY_AUDIO
:
2959 case BD_EVENT_SECONDARY_AUDIO_STREAM
:
2960 case BD_EVENT_SECONDARY_VIDEO
:
2961 case BD_EVENT_SECONDARY_VIDEO_STREAM
:
2962 case BD_EVENT_SECONDARY_VIDEO_SIZE
:
2966 * playback control events
2968 case BD_EVENT_STILL_TIME
:
2969 blurayStillImage(p_demux
, e
->param
);
2971 case BD_EVENT_DISCONTINUITY
:
2972 /* reset demuxer (partially decoded PES packets must be dropped) */
2973 blurayRestartParser(p_demux
, false, true);
2974 es_out_Control(p_sys
->p_out
, BLURAY_ES_OUT_CONTROL_FLAG_DISCONTINUITY
);
2976 case BD_EVENT_END_OF_TITLE
:
2977 if(p_sys
->b_pl_playing
)
2979 notifyDiscontinuityToParser(p_sys
);
2980 blurayRestartParser(p_demux
, false, false);
2981 p_sys
->b_draining
= true;
2982 p_sys
->b_pl_playing
= false;
2986 /* nothing to do (ex. BD-J is preparing menus, waiting user input or running animation) */
2987 /* avoid busy loop (bd_read() returns no data) */
2988 vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
2992 msg_Warn(p_demux
, "event: %d param: %d", e
->event
, e
->param
);
2997 static void blurayHandleOverlays(demux_t
*p_demux
)
2999 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3000 vlc_mutex_lock(&p_sys
->bdj
.lock
);
3002 for (int i
= 0; i
< MAX_OVERLAY
; i
++) {
3003 bluray_overlay_t
*ov
= p_sys
->bdj
.p_overlays
[i
];
3007 vlc_mutex_lock(&ov
->lock
);
3008 bool display
= ov
->status
== ToDisplay
;
3009 vlc_mutex_unlock(&ov
->lock
);
3010 if (display
&& !ov
->b_on_vout
)
3012 /* NOTE: we might want to enable background video always when there's no video stream playing.
3013 Now, with some discs, there are perioids (even seconds) during which the video window
3014 disappears and just playlist is shown.
3015 (sometimes BD-J runs slowly ...)
3017 bluraySendOverlayToVout(p_demux
, i
, ov
);
3021 vlc_mutex_unlock(&p_sys
->bdj
.lock
);
3024 static int blurayDemux(demux_t
*p_demux
)
3026 demux_sys_t
*p_sys
= p_demux
->p_sys
;
3029 if(p_sys
->b_draining
)
3031 bool b_empty
= false;
3032 if(es_out_Control(p_sys
->p_out
, ES_OUT_GET_EMPTY
, &b_empty
) != VLC_SUCCESS
|| b_empty
)
3034 es_out_Control(p_sys
->p_out
, ES_OUT_RESET_PCR
);
3035 p_sys
->b_draining
= false;
3039 msg_Dbg(p_demux
, "Draining...");
3040 vlc_tick_sleep(VLC_TICK_FROM_MS(40));
3041 return VLC_DEMUXER_SUCCESS
;
3045 block_t
*p_block
= block_Alloc(BD_READ_SIZE
);
3047 return VLC_DEMUXER_EGENERIC
;
3051 if (p_sys
->b_menu
== false) {
3052 nread
= bd_read(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
);
3053 while (bd_get_event(p_sys
->bluray
, &e
))
3054 blurayHandleEvent(p_demux
, &e
, false);
3056 nread
= bd_read_ext(p_sys
->bluray
, p_block
->p_buffer
, BD_READ_SIZE
, &e
);
3057 while (e
.event
!= BD_EVENT_NONE
) {
3058 blurayHandleEvent(p_demux
, &e
, false);
3059 bd_get_event(p_sys
->bluray
, &e
);
3063 /* Process delayed selections events */
3064 for(int i
=0; i
<p_sys
->events_delayed
.i_size
; i
++)
3065 blurayHandleEvent(p_demux
, &p_sys
->events_delayed
.p_elems
[i
], true);
3066 p_sys
->events_delayed
.i_size
= 0;
3068 blurayHandleOverlays(p_demux
);
3071 block_Release(p_block
);
3072 if (p_sys
->b_fatal_error
|| nread
< 0) {
3073 msg_Err(p_demux
, "bluray: stopping playback after fatal error\n");
3074 return VLC_DEMUXER_EGENERIC
;
3076 if (!p_sys
->b_menu
) {
3077 return VLC_DEMUXER_EOF
;
3079 return VLC_DEMUXER_SUCCESS
;
3082 p_block
->i_buffer
= nread
;
3084 vlc_demux_chained_Send(p_sys
->p_parser
, p_block
);
3086 p_sys
->b_flushed
= false;
3088 return VLC_DEMUXER_SUCCESS
;