[vlc-commits] bluray: fix missing overlay after vout change
Petri Hintukainen
git at videolan.org
Tue Sep 8 14:48:37 CEST 2015
vlc | branch: master | Petri Hintukainen <phintuka at gmail.com> | Mon Aug 24 11:26:36 2015 +0300| [b8da66d611a4734d3bd4ccc2ea70c297dd8b813d] | committer: Jean-Baptiste Kempf
bluray: fix missing overlay after vout change
Overlay lifetime can be longer than vout lifetime.
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b8da66d611a4734d3bd4ccc2ea70c297dd8b813d
---
modules/access/bluray.c | 163 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 133 insertions(+), 30 deletions(-)
diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index 9b840d5..4f70587 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -110,12 +110,18 @@ typedef enum OverlayStatus {
typedef struct bluray_overlay_t
{
- atomic_flag released_once;
vlc_mutex_t lock;
int i_channel;
OverlayStatus status;
subpicture_region_t *p_regions;
int width, height;
+
+ /* pointer to last subpicture updater.
+ * used to disconnect this overlay from vout when:
+ * - the overlay is closed
+ * - vout is changed and this overlay is sent to the new vout
+ */
+ struct subpicture_updater_sys_t *p_updater;
} bluray_overlay_t;
struct demux_sys_t
@@ -161,9 +167,29 @@ struct demux_sys_t
struct subpicture_updater_sys_t
{
- bluray_overlay_t *p_overlay;
+ vlc_mutex_t lock; // protect p_overlay pointer and ref_cnt
+ bluray_overlay_t *p_overlay; // NULL if overlay has been closed
+ int ref_cnt; // one reference in vout (subpicture_t), one in input (bluray_overlay_t)
};
+/*
+ * cut the connection between vout and overlay.
+ * - called when vout is closed or overlay is closed.
+ * - frees subpicture_updater_sys_t when both sides have been closed.
+ */
+static void unref_subpicture_updater(subpicture_updater_sys_t *p_sys)
+{
+ vlc_mutex_lock(&p_sys->lock);
+ int refs = p_sys->ref_cnt--;
+ p_sys->p_overlay = NULL;
+ vlc_mutex_unlock(&p_sys->lock);
+
+ if (refs < 1) {
+ vlc_mutex_destroy(&p_sys->lock);
+ free(p_sys);
+ }
+}
+
/* Get a 3 char code
* FIXME: partiallyy duplicated from src/input/es_out.c
*/
@@ -280,6 +306,26 @@ static void blurayReleaseVout(demux_t *p_demux)
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);
+
+ for (int i = 0; i < MAX_OVERLAY; i++) {
+ bluray_overlay_t *p_ov = p_sys->p_overlays[i];
+ if (p_ov) {
+ vlc_mutex_lock(&p_ov->lock);
+ if (p_ov->i_channel != -1) {
+ msg_Err(p_demux, "blurayReleaseVout: subpicture channel exists\n");
+ vout_FlushSubpictureChannel(p_sys->p_vout, p_ov->i_channel);
+ }
+ p_ov->i_channel = -1;
+ p_ov->status = ToDisplay;
+ vlc_mutex_unlock(&p_ov->lock);
+
+ if (p_ov->p_updater) {
+ unref_subpicture_updater(p_ov->p_updater);
+ p_ov->p_updater = NULL;
+ }
+ }
+ }
+
vlc_object_release(p_sys->p_vout);
p_sys->p_vout = NULL;
}
@@ -668,6 +714,32 @@ static es_out_t *esOutNew(demux_t *p_demux)
/*****************************************************************************
* subpicture_updater_t functions:
*****************************************************************************/
+
+static bluray_overlay_t *updater_lock_overlay(subpicture_updater_sys_t *p_upd_sys)
+{
+ /* this lock is held while vout accesses overlay. => overlay can't be closed. */
+ vlc_mutex_lock(&p_upd_sys->lock);
+
+ bluray_overlay_t *ov = p_upd_sys->p_overlay;
+ if (ov) {
+ /* this lock is held while vout accesses overlay. => overlay can't be modified. */
+ vlc_mutex_lock(&ov->lock);
+ return ov;
+ }
+
+ /* overlay has been closed */
+ vlc_mutex_unlock(&p_upd_sys->lock);
+ return NULL;
+}
+
+static void updater_unlock_overlay(subpicture_updater_sys_t *p_upd_sys)
+{
+ assert (p_upd_sys->p_overlay);
+
+ vlc_mutex_unlock(&p_upd_sys->p_overlay->lock);
+ vlc_mutex_unlock(&p_upd_sys->lock);
+}
+
static int subpictureUpdaterValidate(subpicture_t *p_subpic,
bool b_fmt_src, const video_format_t *p_fmt_src,
bool b_fmt_dst, const video_format_t *p_fmt_dst,
@@ -680,11 +752,16 @@ static int subpictureUpdaterValidate(subpicture_t *p_subpic,
VLC_UNUSED(i_ts);
subpicture_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
- bluray_overlay_t *p_overlay = p_upd_sys->p_overlay;
+ bluray_overlay_t *p_overlay = updater_lock_overlay(p_upd_sys);
+
+ if (!p_overlay) {
+ return 1;
+ }
- vlc_mutex_lock(&p_overlay->lock);
int res = p_overlay->status == Outdated;
- vlc_mutex_unlock(&p_overlay->lock);
+
+ updater_unlock_overlay(p_upd_sys);
+
return res;
}
@@ -697,17 +774,19 @@ static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
VLC_UNUSED(p_fmt_dst);
VLC_UNUSED(i_ts);
subpicture_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
- bluray_overlay_t *p_overlay = p_upd_sys->p_overlay;
+ bluray_overlay_t *p_overlay = updater_lock_overlay(p_upd_sys);
+
+ if (!p_overlay) {
+ return;
+ }
/*
* When this function is called, all p_subpic regions are gone.
* We need to duplicate our regions (stored internaly) to this subpic.
*/
- vlc_mutex_lock(&p_overlay->lock);
-
subpicture_region_t *p_src = p_overlay->p_regions;
if (!p_src) {
- vlc_mutex_unlock(&p_overlay->lock);
+ updater_unlock_overlay(p_upd_sys);
return;
}
@@ -722,16 +801,24 @@ static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
if (*p_dst != NULL)
(*p_dst)->p_next = NULL;
p_overlay->status = Displayed;
- vlc_mutex_unlock(&p_overlay->lock);
-}
-static void blurayCleanOverlayStruct(bluray_overlay_t *);
+ updater_unlock_overlay(p_upd_sys);
+}
static void subpictureUpdaterDestroy(subpicture_t *p_subpic)
{
- blurayCleanOverlayStruct(p_subpic->updater.p_sys->p_overlay);
- free(p_subpic->updater.p_sys);
- }
+ subpicture_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
+ bluray_overlay_t *p_overlay = updater_lock_overlay(p_upd_sys);
+
+ if (p_overlay) {
+ /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
+ p_overlay->status = ToDisplay;
+ p_overlay->i_channel = -1;
+ updater_unlock_overlay(p_upd_sys);
+ }
+
+ unref_subpicture_updater(p_upd_sys);
+}
static subpicture_t *bluraySubpictureCreate(bluray_overlay_t *p_ov)
{
@@ -760,6 +847,11 @@ static subpicture_t *bluraySubpictureCreate(bluray_overlay_t *p_ov)
p_pic->b_ephemer = true;
p_pic->b_absolute = true;
+ vlc_mutex_init(&p_upd_sys->lock);
+ p_upd_sys->ref_cnt = 2;
+
+ p_ov->p_updater = p_upd_sys;
+
return p_pic;
}
@@ -799,30 +891,26 @@ static int sendKeyEvent(demux_sys_t *p_sys, unsigned int key)
* libbluray overlay handling:
*****************************************************************************/
-static void blurayCleanOverlayStruct(bluray_overlay_t *p_overlay)
-{
- if (!atomic_flag_test_and_set(&p_overlay->released_once))
- return;
- /*
- * This will be called when destroying the picture.
- * Don't delete it again from here!
- */
- vlc_mutex_destroy(&p_overlay->lock);
- subpicture_region_ChainDelete(p_overlay->p_regions);
- free(p_overlay);
-}
-
static void blurayCloseOverlay(demux_t *p_demux, int plane)
{
demux_sys_t *p_sys = p_demux->p_sys;
bluray_overlay_t *ov = p_sys->p_overlays[plane];
if (ov != NULL) {
+
+ /* drop overlay from vout */
+ if (ov->p_updater) {
+ unref_subpicture_updater(ov->p_updater);
+ }
+ /* no references to this overlay exist in vo anymore */
if (p_sys->p_vout && ov->i_channel != -1) {
vout_FlushSubpictureChannel(p_sys->p_vout, ov->i_channel);
}
- blurayCleanOverlayStruct(ov);
+ vlc_mutex_destroy(&ov->lock);
+ subpicture_region_ChainDelete(ov->p_regions);
+ free(ov);
+
p_sys->p_overlays[plane] = NULL;
}
@@ -1105,9 +1193,12 @@ static void bluraySendOverlayToVout(demux_t *p_demux, bluray_overlay_t *p_ov)
demux_sys_t *p_sys = p_demux->p_sys;
assert(p_ov != NULL);
-
+ assert(p_ov->i_channel == -1);
+ assert(p_ov->p_updater == NULL);
+
subpicture_t *p_pic = bluraySubpictureCreate(p_ov);
if (!p_pic) {
+ msg_Err(p_demux, "bluraySubpictureCreate() failed");
return;
}
@@ -1685,6 +1776,18 @@ static int blurayDemux(demux_t *p_demux)
if (display) {
if (p_sys->p_vout == NULL)
p_sys->p_vout = input_GetVout(p_demux->p_input);
+ else {
+ /* track vout changes */
+ vout_thread_t *p_vout = input_GetVout(p_demux->p_input);
+ if (p_vout != p_sys->p_vout) {
+ msg_Info(p_demux, "vout changed %p -> %p\n", p_sys->p_vout, p_vout);
+ blurayReleaseVout(p_demux);
+ p_sys->p_vout = p_vout;
+ } else {
+ vlc_object_release(p_vout);
+ }
+ }
+ ;// also, should always release as soon as possible ? --> old one can be released ...
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);
More information about the vlc-commits
mailing list