X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fbluray.c;h=238cf6b661d9c69629f4c320175111dfcbe63e37;hb=refs%2Fheads%2Fmaster;hp=91c18f7f4aaceff6552b4b363bb2e051987fd7be;hpb=d4ee3d507f90f04566603a6db9ba6b45ce2faf60;p=vlc diff --git a/modules/access/bluray.c b/modules/access/bluray.c index 91c18f7f4a..238cf6b661 100644 --- a/modules/access/bluray.c +++ b/modules/access/bluray.c @@ -26,7 +26,6 @@ #endif #include -#include /* PATH_MAX */ #if defined (HAVE_MNTENT_H) && defined(HAVE_SYS_STAT_H) # include @@ -125,10 +124,12 @@ struct demux_sys_t /* Titles */ unsigned int i_title; unsigned int i_longest_title; - int i_playlist; /* -1 = no playlist playing */ - unsigned int i_current_clip; input_title_t **pp_title; + vlc_mutex_t pl_info_lock; + BLURAY_TITLE_INFO *p_pl_info; + const BLURAY_CLIP_INFO *p_clip_info; + /* Meta information */ const META_DL *p_meta; @@ -136,6 +137,9 @@ struct demux_sys_t bluray_overlay_t *p_overlays[MAX_OVERLAY]; int current_overlay; // -1 if no current overlay; bool b_menu; + bool b_menu_open; + bool b_popup_available; + mtime_t i_still_end_time; /* */ input_thread_t *p_input; @@ -148,6 +152,7 @@ struct demux_sys_t int i_spu_stream; /* Selected subtitle stream. -1 if default */ int i_video_stream; stream_t *p_parser; + bool b_flushed; /* Used to store bluray disc path */ char *psz_bd_path; @@ -223,16 +228,17 @@ static void FindMountPoint(char **file) { char *device = *file; #if defined (HAVE_MNTENT_H) && defined (HAVE_SYS_STAT_H) + /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make sure + * we look up the real device */ + char *bd_device = realpath(device, NULL); + if (bd_device == NULL) + return; + struct stat st; - if (!stat (device, &st) && S_ISBLK (st.st_mode)) { + if (lstat (bd_device, &st) == 0 && S_ISBLK (st.st_mode)) { FILE *mtab = setmntent ("/proc/self/mounts", "r"); struct mntent *m, mbuf; char buf [8192]; - /* bd path may be a symlink (e.g. /dev/dvd -> /dev/sr0), so make - * sure we look up the real device */ - char *bd_device = realpath(device, NULL); - if (!bd_device) - bd_device = strdup(device); while ((m = getmntent_r (mtab, &mbuf, buf, sizeof(buf))) != NULL) { if (!strcmp (m->mnt_fsname, bd_device)) { @@ -241,9 +247,10 @@ static void FindMountPoint(char **file) break; } } - free(bd_device); endmntent (mtab); } + free(bd_device); + #elif defined(__APPLE__) struct stat st; if (!stat (device, &st) && S_ISBLK (st.st_mode)) { @@ -264,6 +271,27 @@ static void FindMountPoint(char **file) #endif } +/***************************************************************************** + * cache current playlist (title) information + *****************************************************************************/ + +static void setTitleInfo(demux_sys_t *p_sys, BLURAY_TITLE_INFO *info) +{ + vlc_mutex_lock(&p_sys->pl_info_lock); + + if (p_sys->p_pl_info) { + bd_free_title_info(p_sys->p_pl_info); + } + p_sys->p_pl_info = info; + p_sys->p_clip_info = NULL; + + if (p_sys->p_pl_info && p_sys->p_pl_info->clip_count) { + p_sys->p_clip_info = &p_sys->p_pl_info->clips[0]; + } + + vlc_mutex_unlock(&p_sys->pl_info_lock); +} + /***************************************************************************** * blurayOpen: module init function *****************************************************************************/ @@ -289,6 +317,7 @@ static int blurayOpen(vlc_object_t *object) p_sys->i_audio_stream = -1; p_sys->i_spu_stream = -1; p_sys->i_video_stream = -1; + p_sys->i_still_end_time = 0; /* init demux info fields */ p_demux->info.i_update = 0; @@ -311,6 +340,8 @@ static int blurayOpen(vlc_object_t *object) return VLC_EGENERIC; } + vlc_mutex_init(&p_sys->pl_info_lock); + /* Warning the user about AACS/BD+ */ const BLURAY_DISC_INFO *disc_info = bd_get_disc_info(p_sys->bluray); @@ -389,12 +420,15 @@ static int blurayOpen(vlc_object_t *object) */ bd_get_event(p_sys->bluray, NULL); + /* Registering overlay event handler */ + bd_register_overlay_proc(p_sys->bluray, p_demux, blurayOverlayProc); + p_sys->p_input = demux_GetParentInput(p_demux); + if (unlikely(!p_sys->p_input)) { + msg_Err(p_demux, "Could not get parent input"); + goto error; + } + if (p_sys->b_menu) { - p_sys->p_input = demux_GetParentInput(p_demux); - if (unlikely(!p_sys->p_input)) { - msg_Err(p_demux, "Could not get parent input"); - goto error; - } /* Register ARGB overlay handler for BD-J */ if (disc_info->num_bdj_titles) @@ -404,8 +438,6 @@ static int blurayOpen(vlc_object_t *object) if (bd_play(p_sys->bluray) == 0) BLURAY_ERROR(_("Failed to start bluray playback. Please try without menu support.")); - /* Registering overlay event handler */ - bd_register_overlay_proc(p_sys->bluray, p_demux, blurayOverlayProc); } else { /* set start title number */ if (bluraySetTitle(p_demux, p_sys->i_longest_title) != VLC_SUCCESS) { @@ -447,6 +479,8 @@ static void blurayClose(vlc_object_t *object) demux_t *p_demux = (demux_t*)object; demux_sys_t *p_sys = p_demux->p_sys; + setTitleInfo(p_sys, NULL); + /* * Close libbluray first. * This will close all the overlays before we release p_vout @@ -474,6 +508,8 @@ static void blurayClose(vlc_object_t *object) vlc_input_title_Delete(p_sys->pp_title[i]); TAB_CLEAN(p_sys->i_title, p_sys->pp_title); + vlc_mutex_destroy(&p_sys->pl_info_lock); + free(p_sys->psz_bd_path); free(p_sys); } @@ -515,7 +551,7 @@ static void setStreamLang(es_format_t *p_fmt, for (int i = 0; i < i_stream_count; i++) { if (p_fmt->i_id == p_streams[i].pid) { free(p_fmt->psz_language); - p_fmt->psz_language = strndup(p_streams[i].lang, 3); + p_fmt->psz_language = strndup((const char *)p_streams[i].lang, 3); return; } } @@ -524,15 +560,12 @@ static void setStreamLang(es_format_t *p_fmt, static es_out_id_t *esOutAdd(es_out_t *p_out, const es_format_t *p_fmt) { demux_sys_t *p_sys = p_out->p_sys->p_demux->p_sys; - BLURAY_TITLE_INFO *title_info = bd_get_playlist_info(p_sys->bluray, p_sys->i_playlist, 0); - BLURAY_CLIP_INFO *clip_info = NULL; es_format_t fmt; - if (title_info && p_sys->i_current_clip < title_info->clip_count) { - clip_info = &title_info->clips[p_sys->i_current_clip]; - } - es_format_Copy(&fmt, p_fmt); + + vlc_mutex_lock(&p_sys->pl_info_lock); + switch (fmt.i_cat) { case VIDEO_ES: if (p_sys->i_video_stream != -1 && p_sys->i_video_stream != p_fmt->i_id) @@ -541,19 +574,18 @@ static es_out_id_t *esOutAdd(es_out_t *p_out, const es_format_t *p_fmt) case AUDIO_ES: if (p_sys->i_audio_stream != -1 && p_sys->i_audio_stream != p_fmt->i_id) fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE; - if (clip_info) - setStreamLang(&fmt, clip_info->audio_streams, clip_info->audio_stream_count); + if (p_sys->p_clip_info) + setStreamLang(&fmt, p_sys->p_clip_info->audio_streams, p_sys->p_clip_info->audio_stream_count); break ; case SPU_ES: if (p_sys->i_spu_stream != -1 && p_sys->i_spu_stream != p_fmt->i_id) fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE; - if (clip_info) - setStreamLang(&fmt, clip_info->pg_streams, clip_info->pg_stream_count); + if (p_sys->p_clip_info) + setStreamLang(&fmt, p_sys->p_clip_info->pg_streams, p_sys->p_clip_info->pg_stream_count); break ; } - if (title_info) - bd_free_title_info(title_info); + vlc_mutex_unlock(&p_sys->pl_info_lock); es_out_id_t *p_es = es_out_Add(p_out->p_sys->p_demux->out, &fmt); if (p_fmt->i_id >= 0) { @@ -740,7 +772,7 @@ static int onMouseEvent(vlc_object_t *p_vout, const char *psz_var, vlc_value_t o bd_mouse_select(p_sys->bluray, now, val.coords.x, val.coords.y); bd_user_input(p_sys->bluray, now, BD_VK_MOUSE_ACTIVATE); } else { - assert(0); + vlc_assert_unreachable(); } return VLC_SUCCESS; } @@ -790,10 +822,12 @@ static void blurayCloseOverlay(demux_t *p_demux, int plane) return; /* All overlays have been closed */ - var_DelCallback(p_sys->p_vout, "mouse-moved", onMouseEvent, p_demux); - var_DelCallback(p_sys->p_vout, "mouse-clicked", onMouseEvent, p_demux); - vlc_object_release(p_sys->p_vout); - p_sys->p_vout = NULL; + if (p_sys->p_vout != NULL) { + var_DelCallback(p_sys->p_vout, "mouse-moved", onMouseEvent, p_demux); + var_DelCallback(p_sys->p_vout, "mouse-clicked", onMouseEvent, p_demux); + vlc_object_release(p_sys->p_vout); + p_sys->p_vout = NULL; + } } /* @@ -835,20 +869,17 @@ static void blurayInitOverlay(demux_t *p_demux, int plane, int width, int height assert(p_sys->p_overlays[plane] == NULL); - p_sys->p_overlays[plane] = calloc(1, sizeof(**p_sys->p_overlays)); - if (unlikely(!p_sys->p_overlays[plane])) + bluray_overlay_t *ov = calloc(1, sizeof(*ov)); + if (unlikely(ov == NULL)) return; - bluray_overlay_t *ov = p_sys->p_overlays[plane]; - subpicture_updater_sys_t *p_upd_sys = malloc(sizeof(*p_upd_sys)); - if (unlikely(!p_upd_sys)) { + if (unlikely(p_upd_sys == NULL)) { free(ov); - p_sys->p_overlays[plane] = NULL; return; } /* two references: vout + demux */ - ov->released_once = ATOMIC_FLAG_INIT; + atomic_flag_clear(&ov->released_once); p_upd_sys->p_overlay = ov; subpicture_updater_t updater = { @@ -857,12 +888,22 @@ static void blurayInitOverlay(demux_t *p_demux, int plane, int width, int height .pf_destroy = subpictureUpdaterDestroy, .p_sys = p_upd_sys, }; - vlc_mutex_init(&ov->lock); + ov->p_pic = subpicture_New(&updater); + if (ov->p_pic == NULL) { + free(p_upd_sys); + free(ov); + return; + } + ov->p_pic->i_original_picture_width = width; ov->p_pic->i_original_picture_height = height; ov->p_pic->b_ephemer = true; ov->p_pic->b_absolute = true; + + vlc_mutex_init(&ov->lock); + + p_sys->p_overlays[plane] = ov; } /** @@ -1102,19 +1143,8 @@ static void bluraySendOverlayToVout(demux_t *p_demux) p_sys->p_overlays[p_sys->current_overlay]->status = Outdated; } -static void blurayUpdateTitleInfo(demux_t *p_demux, input_title_t *t, int i_title_idx, int i_playlist) +static void blurayUpdateTitleInfo(input_title_t *t, BLURAY_TITLE_INFO *title_info) { - demux_sys_t *p_sys = p_demux->p_sys; - BLURAY_TITLE_INFO *title_info = NULL; - - if (i_playlist >= 0) - title_info = bd_get_playlist_info(p_sys->bluray, i_playlist, 0); - else if (i_title_idx >= 0) - title_info = bd_get_title_info(p_sys->bluray, i_title_idx, 0); - if (!title_info) { - return; - } - t->i_length = FROM_TICKS(title_info->duration); if (!t->i_seekpoint) { @@ -1128,20 +1158,19 @@ static void blurayUpdateTitleInfo(demux_t *p_demux, input_title_t *t, int i_titl TAB_APPEND(t->i_seekpoint, t->seekpoint, s); } } - - bd_free_title_info(title_info); } static void blurayInitTitles(demux_t *p_demux, int menu_titles) { demux_sys_t *p_sys = p_demux->p_sys; - int64_t duration = 0; /* get and set the titles */ unsigned i_title = menu_titles; - if (!p_sys->b_menu) + if (!p_sys->b_menu) { i_title = bd_get_titles(p_sys->bluray, TITLES_RELEVANT, 60); + p_sys->i_longest_title = bd_get_main_title(p_sys->bluray); + } for (unsigned int i = 0; i < i_title; i++) { input_title_t *t = vlc_input_title_New(); @@ -1149,12 +1178,10 @@ static void blurayInitTitles(demux_t *p_demux, int menu_titles) break; if (!p_sys->b_menu) { - blurayUpdateTitleInfo(p_demux, t, i, -1); + BLURAY_TITLE_INFO *title_info = bd_get_title_info(p_sys->bluray, i, 0); + blurayUpdateTitleInfo(t, title_info); + bd_free_title_info(title_info); - if (t->i_length > duration) { - duration = t->i_length; - p_sys->i_longest_title = i; - } } else if (i == 0) { t->psz_name = strdup(_("Top Menu")); } else if (i == i_title - 1) { @@ -1182,34 +1209,6 @@ static void blurayResetParser(demux_t *p_demux) msg_Err(p_demux, "Failed to create TS demuxer"); } -static void blurayUpdateTitle(demux_t *p_demux, unsigned i_title) -{ - blurayResetParser(p_demux); - if (i_title >= p_demux->p_sys->i_title) - return; - - /* read title info and init some values */ - p_demux->info.i_title = i_title; - p_demux->info.i_seekpoint = 0; - p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; -} - -static void blurayUpdatePlaylist(demux_t *p_demux, unsigned i_playlist) -{ - blurayResetParser(p_demux); - - p_demux->p_sys->i_playlist = i_playlist; - p_demux->p_sys->i_current_clip = 0; - - /* read title info and init some values */ - if (!p_demux->p_sys->b_menu) - p_demux->info.i_title = bd_get_current_title(p_demux->p_sys->bluray); - p_demux->info.i_seekpoint = 0; - p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; - - blurayUpdateTitleInfo(p_demux, p_demux->p_sys->pp_title[p_demux->info.i_title], -1, i_playlist); -} - /***************************************************************************** * bluraySetTitle: select new BD title *****************************************************************************/ @@ -1227,7 +1226,7 @@ static int bluraySetTitle(demux_t *p_demux, int i_title) msg_Dbg(p_demux, "Playing Title %i", i_title); } - if (bd_play_title(p_demux->p_sys->bluray, i_title) == 0) { + if (bd_play_title(p_sys->bluray, i_title) == 0) { msg_Err(p_demux, "cannot play bd title '%d'", i_title); return VLC_EGENERIC; } @@ -1243,11 +1242,12 @@ static int bluraySetTitle(demux_t *p_demux, int i_title) msg_Dbg(p_demux, "Selecting Title %i", i_title); - if (bd_select_title(p_demux->p_sys->bluray, i_title) == 0) { + if (bd_select_title(p_sys->bluray, i_title) == 0) { msg_Err(p_demux, "cannot select bd title '%d'", i_title); return VLC_EGENERIC; } - blurayUpdateTitle(p_demux, i_title); + + blurayResetParser(p_demux); return VLC_SUCCESS; } @@ -1382,6 +1382,9 @@ static int blurayControl(demux_t *p_demux, int query, va_list args) } case DEMUX_NAV_ACTIVATE: + if (p_sys->b_popup_available && !p_sys->b_menu_open) { + return sendKeyEvent(p_sys, BD_VK_POPUP); + } return sendKeyEvent(p_sys, BD_VK_ENTER); case DEMUX_NAV_UP: return sendKeyEvent(p_sys, BD_VK_UP); @@ -1405,36 +1408,130 @@ static int blurayControl(demux_t *p_demux, int query, va_list args) return VLC_SUCCESS; } -static void blurayStreamSelect(demux_t *p_demux, uint32_t i_type, uint32_t i_id) +/***************************************************************************** + * libbluray event handling + *****************************************************************************/ + +static void streamFlush( demux_sys_t *p_sys ) { - demux_sys_t *p_sys = p_demux->p_sys; - int i_pid = -1; + /* + * MPEG-TS demuxer does not flush last video frame if size of PES packet is unknown. + * Packet is flushed only when TS packet with PUSI flag set is received. + * + * Fix this by emitting (video) ts packet with PUSI flag set. + * Add video sequence end code to payload so that also video decoder is flushed. + * Set PES packet size in the payload so that it will be sent to decoder immediately. + */ - if (p_sys->i_playlist < 0) + if (p_sys->b_flushed) return; - BLURAY_TITLE_INFO *title_info = bd_get_playlist_info(p_sys->bluray, p_sys->i_playlist, 0); - if (title_info == NULL) + block_t *p_block = block_Alloc(192); + if (!p_block) return; - if (p_sys->i_current_clip < title_info->clip_count) { - BLURAY_CLIP_INFO *clip_info = &title_info->clips[p_sys->i_current_clip]; + static const uint8_t seq_end_pes[] = { + 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07, 0x80, 0x00, 0x00, /* PES header */ + 0x00, 0x00, 0x01, 0xb7, /* PES payload: sequence end */ + }; + static const uint8_t vid_pusi_ts[] = { + 0x00, 0x00, 0x00, 0x00, /* TP extra header (ATC) */ + 0x47, 0x50, 0x11, 0x30, /* TP header */ + (192 - (4 + 5) - sizeof(seq_end_pes)), /* adaptation field length */ + 0x80, /* adaptation field: discontinuity indicator */ + }; + + memset(p_block->p_buffer, 0, 192); + memcpy(p_block->p_buffer, vid_pusi_ts, sizeof(vid_pusi_ts)); + memcpy(p_block->p_buffer + 192 - sizeof(seq_end_pes), seq_end_pes, sizeof(seq_end_pes)); + p_block->i_buffer = 192; + + /* set correct sequence end code */ + vlc_mutex_lock(&p_sys->pl_info_lock); + if (p_sys->p_clip_info != NULL) { + if (p_sys->p_clip_info->video_streams[0].coding_type > 2) { + /* VC1 / H.264 sequence end */ + p_block->p_buffer[191] = 0x0a; + } + } + vlc_mutex_unlock(&p_sys->pl_info_lock); + + stream_DemuxSend(p_sys->p_parser, p_block); + p_sys->b_flushed = true; +} + +static void blurayResetStillImage( demux_t *p_demux ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + + if (p_sys->i_still_end_time) { + p_sys->i_still_end_time = 0; + + blurayResetParser(p_demux); + es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); + } +} + +static void blurayStillImage( demux_t *p_demux, unsigned i_timeout ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + + /* time period elapsed ? */ + if (p_sys->i_still_end_time > 0 && p_sys->i_still_end_time <= mdate()) { + msg_Dbg(p_demux, "Still image end"); + bd_read_skip_still(p_sys->bluray); + + blurayResetStillImage(p_demux); + return; + } + + /* show last frame as still image */ + if (!p_sys->i_still_end_time) { + if (i_timeout) { + msg_Dbg(p_demux, "Still image (%d seconds)", i_timeout); + p_sys->i_still_end_time = mdate() + i_timeout * CLOCK_FREQ; + } else { + msg_Dbg(p_demux, "Still image (infinite)"); + p_sys->i_still_end_time = -1; + } + + /* flush demuxer and decoder (there won't be next video packet starting with ts PUSI) */ + streamFlush(p_sys); + + /* stop buffering */ + bool b_empty; + es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty ); + } + + /* avoid busy loops (read returns no data) */ + msleep( 40000 ); +} + +static void blurayStreamSelect(demux_t *p_demux, uint32_t i_type, uint32_t i_id) +{ + demux_sys_t *p_sys = p_demux->p_sys; + int i_pid = -1; + + vlc_mutex_lock(&p_sys->pl_info_lock); + + if (p_sys->p_clip_info) { /* The param we get is the real stream id, not an index, ie. it starts from 1 */ i_id--; if (i_type == BD_EVENT_AUDIO_STREAM) { - if (i_id < clip_info->audio_stream_count) { - i_pid = clip_info->audio_streams[i_id].pid; + if (i_id < p_sys->p_clip_info->audio_stream_count) { + i_pid = p_sys->p_clip_info->audio_streams[i_id].pid; p_sys->i_audio_stream = i_pid; } } else if (i_type == BD_EVENT_PG_TEXTST_STREAM) { - if (i_id < clip_info->pg_stream_count) { - i_pid = clip_info->pg_streams[i_id].pid; + if (i_id < p_sys->p_clip_info->pg_stream_count) { + i_pid = p_sys->p_clip_info->pg_streams[i_id].pid; p_sys->i_spu_stream = i_pid; } } } - bd_free_title_info(title_info); + + vlc_mutex_unlock(&p_sys->pl_info_lock); if (i_pid > 0) { int i_idx = findEsPairIndex(p_sys, i_pid); @@ -1445,22 +1542,50 @@ static void blurayStreamSelect(demux_t *p_demux, uint32_t i_type, uint32_t i_id) } } +static void blurayUpdatePlaylist(demux_t *p_demux, unsigned i_playlist) +{ + demux_sys_t *p_sys = p_demux->p_sys; + + blurayResetParser(p_demux); + + /* read title info and init some values */ + if (!p_sys->b_menu) + p_demux->info.i_title = bd_get_current_title(p_sys->bluray); + p_demux->info.i_seekpoint = 0; + p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; + + BLURAY_TITLE_INFO *p_title_info = bd_get_playlist_info(p_sys->bluray, i_playlist, 0); + if (p_title_info) { + blurayUpdateTitleInfo(p_sys->pp_title[p_demux->info.i_title], p_title_info); + } + setTitleInfo(p_sys, p_title_info); + + blurayResetStillImage(p_demux); +} + static void blurayUpdateCurrentClip(demux_t *p_demux, uint32_t clip) { - if (clip == 0xFF) - return ; demux_sys_t *p_sys = p_demux->p_sys; - p_sys->i_current_clip = clip; - BLURAY_TITLE_INFO *info = bd_get_playlist_info(p_sys->bluray, p_sys->i_playlist, 0); - if (info == NULL) - return ; + vlc_mutex_lock(&p_sys->pl_info_lock); + + p_sys->p_clip_info = NULL; + p_sys->i_video_stream = -1; + + if (p_sys->p_pl_info && clip < p_sys->p_pl_info->clip_count) { + + p_sys->p_clip_info = &p_sys->p_pl_info->clips[clip]; + /* Let's assume a single video track for now. * This may brake later, but it's enough for now. */ - assert(info->clips[p_sys->i_current_clip].video_stream_count >= 1); - p_sys->i_video_stream = info->clips[p_sys->i_current_clip].video_streams[0].pid; - bd_free_title_info(info); + assert(p_sys->p_clip_info->video_stream_count >= 1); + p_sys->i_video_stream = p_sys->p_clip_info->video_streams[0].pid; + } + + vlc_mutex_unlock(&p_sys->pl_info_lock); + + blurayResetStillImage(p_demux); } static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e) @@ -1474,7 +1599,7 @@ static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e) else p_demux->info.i_title = e->param; /* this is feature title, we don't know yet which playlist it will play (if any) */ - p_sys->i_playlist = -1; + setTitleInfo(p_sys, NULL); /* reset title infos here ? */ p_demux->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; /* might be BD-J title with no video */ break; @@ -1491,6 +1616,13 @@ static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e) break; case BD_EVENT_ANGLE: break; + case BD_EVENT_MENU: + p_sys->b_menu_open = e->param; + break; + case BD_EVENT_POPUP: + p_sys->b_popup_available = e->param; + /* TODO: show / hide pop-up menu button in gui ? */ + break; /* * stream selection events @@ -1502,6 +1634,12 @@ static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e) case BD_EVENT_IG_STREAM: break; + /* + * playback control events + */ + case BD_EVENT_STILL_TIME: + blurayStillImage(p_demux, e->param); + break; case BD_EVENT_DISCONTINUITY: /* reset demuxer (partially decoded PES packets must be dropped) */ blurayResetParser(p_demux); @@ -1533,15 +1671,11 @@ static int blurayDemux(demux_t *p_demux) int nread; if (p_sys->b_menu == false) { - while (bd_get_event(p_demux->p_sys->bluray, &e)) + while (bd_get_event(p_sys->bluray, &e)) blurayHandleEvent(p_demux, &e); nread = bd_read(p_sys->bluray, p_block->p_buffer, NB_TS_PACKETS * BD_TS_PACKET_SIZE); - if (nread < 0) { - block_Release(p_block); - return nread; - } } else { nread = bd_read_ext(p_sys->bluray, p_block->p_buffer, NB_TS_PACKETS * BD_TS_PACKET_SIZE, &e); @@ -1549,37 +1683,36 @@ static int blurayDemux(demux_t *p_demux) blurayHandleEvent(p_demux, &e); bd_get_event(p_sys->bluray, &e); } - if (nread < 0) { - block_Release(p_block); - return -1; - } - if (nread == 0) { - if (e.event == BD_EVENT_NONE) - msg_Info(p_demux, "We reached the end of a title"); - block_Release(p_block); - return 1; - } + } - if (p_sys->current_overlay != -1) { - bluray_overlay_t *ov = p_sys->p_overlays[p_sys->current_overlay]; - vlc_mutex_lock(&ov->lock); - bool display = ov->status == ToDisplay; - vlc_mutex_unlock(&ov->lock); - if (display) { - if (p_sys->p_vout == NULL) - p_sys->p_vout = input_GetVout(p_sys->p_input); - if (p_sys->p_vout != NULL) { - var_AddCallback(p_sys->p_vout, "mouse-moved", onMouseEvent, p_demux); - var_AddCallback(p_sys->p_vout, "mouse-clicked", onMouseEvent, p_demux); - bluraySendOverlayToVout(p_demux); - } + if (p_sys->current_overlay != -1) { + bluray_overlay_t *ov = p_sys->p_overlays[p_sys->current_overlay]; + vlc_mutex_lock(&ov->lock); + bool display = ov->status == ToDisplay; + vlc_mutex_unlock(&ov->lock); + if (display) { + if (p_sys->p_vout == NULL) + p_sys->p_vout = input_GetVout(p_sys->p_input); + if (p_sys->p_vout != NULL) { + var_AddCallback(p_sys->p_vout, "mouse-moved", onMouseEvent, p_demux); + var_AddCallback(p_sys->p_vout, "mouse-clicked", onMouseEvent, p_demux); + bluraySendOverlayToVout(p_demux); } } } + if (nread <= 0) { + block_Release(p_block); + if (nread < 0) + return -1; + return 1; + } + p_block->i_buffer = nread; stream_DemuxSend(p_sys->p_parser, p_block); + p_sys->b_flushed = false; + return 1; }