[vlc-commits] access: bluray: simplify overlays

Francois Cartegnie git at videolan.org
Fri Nov 9 13:30:54 CET 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Nov  7 20:50:43 2018 +0100| [08851a1ff2e3c1b67af48e461041372b872ad924] | committer: Francois Cartegnie

access: bluray: simplify overlays

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=08851a1ff2e3c1b67af48e461041372b872ad924
---

 modules/access/bluray.c | 313 ++++++++++++++++++++----------------------------
 1 file changed, 129 insertions(+), 184 deletions(-)

diff --git a/modules/access/bluray.c b/modules/access/bluray.c
index de0fbc320e..014179e7d1 100644
--- a/modules/access/bluray.c
+++ b/modules/access/bluray.c
@@ -209,7 +209,7 @@ typedef struct bluray_spu_updater_sys_t bluray_spu_updater_sys_t;
 typedef struct bluray_overlay_t
 {
     vlc_mutex_t         lock;
-    int                 i_channel;
+    bool                b_on_vout;
     OverlayStatus       status;
     subpicture_region_t *p_regions;
     int                 width, height;
@@ -267,8 +267,6 @@ typedef struct
     {
         bluray_overlay_t *p_overlays[MAX_OVERLAY];
         vlc_mutex_t  lock; /* used to lock BD-J overlay open/close while overlays are being sent to vout */
-        es_out_id_t *p_dummy_video;
-        es_out_id_t *p_video_es;
     } bdj;
 
     /* */
@@ -452,6 +450,7 @@ static int   bluraySetTitle(demux_t *p_demux, int i_title);
 
 static void  blurayOverlayProc(void *ptr, const BD_OVERLAY * const overlay);
 static void  blurayArgbOverlayProc(void *ptr, const BD_ARGB_OVERLAY * const overlay);
+static void  blurayCloseOverlay(demux_t *p_demux, int plane);
 
 static void  onMouseEvent(const vlc_mouse_t *mouse, void *user_data);
 static void  blurayRestartParser(demux_t *p_demux, bool);
@@ -514,111 +513,37 @@ static void FindMountPoint(char **file)
 #endif
 }
 
-static void blurayReleaseVideoES(demux_t *p_demux)
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-
-    if (p_sys->bdj.p_video_es != NULL) {
-        for (int i = 0; i < MAX_OVERLAY; i++) {
-            bluray_overlay_t *p_ov = p_sys->bdj.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");
-                    es_out_Control( p_demux->out, ES_OUT_VOUT_FLUSH_OVERLAY,
-                                    p_sys->bdj.p_video_es, 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;
-                }
-            }
-        }
-        p_sys->bdj.p_video_es = NULL;
-    }
-}
-
 /*****************************************************************************
  * BD-J background video
  *****************************************************************************/
 
-static es_out_id_t * blurayCreateBackgroundUnlocked(demux_t *p_demux)
+static void bluraySendBackgroundImage(vlc_object_t *p_obj,
+                                      es_out_t *p_dst_out,
+                                      es_out_id_t *p_es,
+                                      const es_format_t *p_fmt)
 {
-    demux_sys_t *p_sys = p_demux->p_sys;
-
-    if (p_sys->bdj.p_dummy_video)
-        return p_sys->bdj.p_dummy_video;
+    msg_Info(p_obj, "Start background");
 
-    msg_Info(p_demux, "Start background");
-
-    /* */
-    es_format_t fmt;
-    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_I420 );
-    video_format_Setup( &fmt.video, VLC_CODEC_I420,
-                        1920, 1080, 1920, 1080, 1, 1);
-    fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
-    fmt.i_id = 4115; /* 4113 = main video. 4114 = MVC. 4115 = unused. */
-    fmt.i_group = 1;
-    fmt.psz_description = strdup("Background video");
-
-    p_sys->bdj.p_dummy_video = es_out_Add(p_demux->out, &fmt);
-
-    if (!p_sys->bdj.p_dummy_video) {
-        msg_Err(p_demux, "Error adding background ES");
-        goto out;
-    }
-
-    block_t *p_block = block_Alloc(fmt.video.i_width * fmt.video.i_height *
-                                   fmt.video.i_bits_per_pixel / 8);
+    block_t *p_block = block_Alloc(p_fmt->video.i_width * p_fmt->video.i_height *
+                                   p_fmt->video.i_bits_per_pixel / 8);
     if (!p_block) {
-        msg_Err(p_demux, "Error allocating block for background video");
-        goto out;
+        msg_Err(p_obj, "Error allocating block for background video");
+        return;
     }
 
     // XXX TODO: what would be correct timestamp ???
     p_block->i_dts = p_block->i_pts = vlc_tick_now() + VLC_TICK_FROM_MS(40);
 
     uint8_t *p = p_block->p_buffer;
-    memset(p, 0, fmt.video.i_width * fmt.video.i_height);
-    p += fmt.video.i_width * fmt.video.i_height;
-    memset(p, 0x80, fmt.video.i_width * fmt.video.i_height / 2);
-
-    es_out_Control(p_demux->out, ES_OUT_SET_ES, p_sys->bdj.p_dummy_video);
-    es_out_Send(p_demux->out, p_sys->bdj.p_dummy_video, p_block);
-
-    es_out_Control( p_demux->out, ES_OUT_VOUT_SET_MOUSE_EVENT,
-                    p_sys->bdj.p_dummy_video, onMouseEvent, p_demux );
+    memset(p, 0, p_fmt->video.i_width * p_fmt->video.i_height);
+    p += p_fmt->video.i_width * p_fmt->video.i_height;
+    memset(p, 0x80, p_fmt->video.i_width * p_fmt->video.i_height / 2);
 
- out:
-    es_format_Clean(&fmt);
-    return p_sys->bdj.p_dummy_video;
-}
-
-static void stopBackground(demux_t *p_demux)
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-
-    vlc_mutex_lock(&p_sys->bdj.lock);
-
-    if (!p_sys->bdj.p_dummy_video)
-    {
-        vlc_mutex_unlock(&p_sys->bdj.lock);
-        return;
-    }
-
-    msg_Info(p_demux, "Stop background");
-
-    if (p_sys->bdj.p_video_es == p_sys->bdj.p_dummy_video)
-        blurayReleaseVideoES(p_demux);
-
-    es_out_Del(p_demux->out, p_sys->bdj.p_dummy_video);
-    p_sys->bdj.p_dummy_video = NULL;
-
-    vlc_mutex_unlock(&p_sys->bdj.lock);
+    es_out_SetPCR(p_dst_out, p_block->i_dts - VLC_TICK_FROM_MS(40));
+    es_out_Control(p_dst_out, ES_OUT_SET_ES, p_es);
+    es_out_Send(p_dst_out, p_es, p_block);
+    es_out_Control( p_dst_out, ES_OUT_VOUT_SET_MOUSE_EVENT, p_es, onMouseEvent, p_obj );
+    es_out_SetPCR(p_dst_out, p_block->i_dts);
 }
 
 /*****************************************************************************
@@ -1087,7 +1012,8 @@ static void blurayClose(vlc_object_t *object)
     }
 
     vlc_mutex_lock(&p_sys->bdj.lock);
-    blurayReleaseVideoES(p_demux);
+    for(int i = 0; i < MAX_OVERLAY; i++)
+        blurayCloseOverlay(p_demux, i);
     vlc_mutex_unlock(&p_sys->bdj.lock);
 
     if (p_sys->p_parser)
@@ -1194,25 +1120,6 @@ static int blurayGetStreamPID(demux_sys_t *p_sys, int i_stream_type, uint8_t i_s
 }
 
 /*****************************************************************************
- * internal overlay
- *****************************************************************************/
-static void bluraySetActiveVideoES(demux_t *p_demux, es_out_id_t *p_es)
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-
-    vlc_mutex_lock(&p_sys->bdj.lock);
-    if(p_sys->bdj.p_video_es == p_es)
-    {
-        vlc_mutex_unlock(&p_sys->bdj.lock);
-        return;
-    }
-    p_sys->bdj.p_video_es = p_es;
-    vlc_mutex_unlock(&p_sys->bdj.lock);
-    es_out_Control( p_demux->out, ES_OUT_VOUT_SET_MOUSE_EVENT, p_es,
-                    onMouseEvent, p_demux );
-}
-
-/*****************************************************************************
  * bluray fake es_out
  *****************************************************************************/
 typedef struct
@@ -1232,6 +1139,11 @@ typedef struct
         int i_video_pid;
         int i_spu_pid;   /* Selected spu stream. -1 if default */
     } selected;
+    struct
+    {
+        es_out_id_t *p_video_es;
+        int channels[MAX_OVERLAY];
+    } overlay;
     es_out_t es_out;
 } bluray_esout_priv_t;
 
@@ -1244,11 +1156,13 @@ enum
     BLURAY_ES_OUT_CONTROL_DISABLE_OUTPUT,
     BLURAY_ES_OUT_CONTROL_ENABLE_LOW_DELAY,
     BLURAY_ES_OUT_CONTROL_DISABLE_LOW_DELAY,
+    BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY,
+    BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY,
 };
 
-static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
+static es_out_id_t *bluray_esOutAddUnlocked(bluray_esout_priv_t *esout_priv,
+                                            const es_format_t *p_fmt)
 {
-    bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
     demux_t *p_demux = esout_priv->priv;
     demux_sys_t *p_sys = p_demux->p_sys;
     es_format_t fmt;
@@ -1256,8 +1170,6 @@ static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
 
     es_format_Copy(&fmt, p_fmt);
 
-    vlc_mutex_lock(&esout_priv->lock);
-
     switch (fmt.i_cat) {
     case VIDEO_ES:
         if(esout_priv->b_lowdelay)
@@ -1309,14 +1221,27 @@ static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
             es_format_Copy(&p_pair->fmt, &fmt);
         }
         if (b_select)
-            es_out_Control(p_demux->out, ES_OUT_SET_ES, p_es);
+            es_out_Control(esout_priv->p_dst_out, ES_OUT_SET_ES, p_es);
     }
 
     if (p_es && fmt.i_cat == VIDEO_ES && b_select)
-        bluraySetActiveVideoES(p_demux, p_es);
+    {
+        es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_SET_MOUSE_EVENT, p_es,
+                       onMouseEvent, p_demux);
+        esout_priv->overlay.p_video_es = p_es;
+    }
 
     es_format_Clean(&fmt);
 
+    return p_es;
+}
+
+static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
+{
+    bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
+
+    vlc_mutex_lock(&esout_priv->lock);
+    es_out_id_t *p_es = bluray_esOutAddUnlocked(esout_priv, p_fmt);
     vlc_mutex_unlock(&esout_priv->lock);
 
     return p_es;
@@ -1325,8 +1250,6 @@ static es_out_id_t *bluray_esOutAdd(es_out_t *p_out, const es_format_t *p_fmt)
 static void bluray_esOutDeleteNonReusedESUnlocked(es_out_t *p_out)
 {
     bluray_esout_priv_t *esout_priv = container_of(p_out, bluray_esout_priv_t, es_out);
-    demux_t *p_demux = esout_priv->priv;
-    demux_sys_t *p_sys = p_demux->p_sys;
 
     if(!esout_priv->b_entered_recycling)
         return;
@@ -1336,11 +1259,11 @@ static void bluray_esOutDeleteNonReusedESUnlocked(es_out_t *p_out)
     while((p_pair = getUnusedEsPair(&esout_priv->es)))
     {
         msg_Info(esout_priv->p_obj, "Trashing unused ES %d", p_pair->fmt.i_id);
-        vlc_mutex_lock(&p_sys->bdj.lock);
-        if (p_pair->p_es == p_sys->bdj.p_video_es)
-            p_sys->bdj.p_video_es = NULL;
+
+        if(esout_priv->overlay.p_video_es == p_pair->p_es)
+            esout_priv->overlay.p_video_es = NULL;
+
         es_out_Del(esout_priv->p_dst_out, p_pair->p_es);
-        vlc_mutex_unlock(&p_sys->bdj.lock);
 
         es_pair_Remove(&esout_priv->es, p_pair);
     }
@@ -1457,6 +1380,65 @@ static int bluray_esOutControl(es_out_t *p_out, int i_query, va_list args)
             i_ret = VLC_SUCCESS;
         } break;
 
+        case BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY:
+        {
+            int i_plane = va_arg(args, int);
+            subpicture_t *p_pic = va_arg(args, subpicture_t *);
+            if(!esout_priv->overlay.p_video_es)
+            {
+                es_format_t fmt;
+                es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_I420);
+                video_format_Setup(&fmt.video, VLC_CODEC_I420,
+                                   1920, 1080, 1920, 1080, 1, 1);
+                fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE;
+                fmt.i_id = 0x1011;
+                fmt.i_group = 1;
+                fmt.video.i_frame_rate = 1; fmt.video.i_frame_rate_base = 1;
+                fmt.b_packetized = true;
+                esout_priv->overlay.p_video_es = bluray_esOutAddUnlocked(esout_priv, &fmt);
+                if(esout_priv->overlay.p_video_es)
+                {
+                    bluraySendBackgroundImage(esout_priv->p_obj,
+                                              esout_priv->p_dst_out,
+                                              esout_priv->overlay.p_video_es,
+                                              &fmt);
+                }
+                es_format_Clean(&fmt);
+            }
+
+            if(esout_priv->overlay.p_video_es && i_plane < MAX_OVERLAY)
+            {
+                i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_ADD_OVERLAY,
+                                       esout_priv->overlay.p_video_es, p_pic,
+                                       &esout_priv->overlay.channels[i_plane]);
+            }
+            else
+            {
+                i_ret = VLC_EGENERIC;
+            }
+            break;
+        }
+
+        case BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY:
+        {
+            int i_plane = va_arg(args, int);
+            if(esout_priv->overlay.p_video_es &&
+               i_plane < MAX_OVERLAY &&
+               esout_priv->overlay.channels[i_plane] != VOUT_SPU_CHANNEL_INVALID)
+            {
+                i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_FLUSH_OVERLAY,
+                                       esout_priv->overlay.p_video_es,
+                                       esout_priv->overlay.channels[i_plane]);
+                esout_priv->overlay.channels[i_plane] = VOUT_SPU_CHANNEL_INVALID;
+            }
+            else
+            {
+                assert(esout_priv->overlay.channels[i_plane] == VOUT_SPU_CHANNEL_INVALID);
+                i_ret = VLC_EGENERIC;
+            }
+            break;
+        }
+
         case ES_OUT_SET_ES_DEFAULT:
         case ES_OUT_SET_ES:
         case ES_OUT_UNSET_ES:
@@ -1515,6 +1497,9 @@ static es_out_t *esOutNew(vlc_object_t *p_obj, es_out_t *p_dst_out, void *priv)
     esout_priv->selected.i_audio_pid = -1;
     esout_priv->selected.i_video_pid = -1;
     esout_priv->selected.i_spu_pid = -1;
+    esout_priv->overlay.p_video_es = NULL;
+    for(size_t i=0; i<MAX_OVERLAY; i++)
+        esout_priv->overlay.channels[i] = VOUT_SPU_CHANNEL_INVALID;
     vlc_mutex_init(&esout_priv->lock);
     return &esout_priv->es_out;
 }
@@ -1621,7 +1606,7 @@ static void subpictureUpdaterDestroy(subpicture_t *p_subpic)
     if (p_overlay) {
         /* vout is closed (seek, new clip, ?). Overlay must be redrawn. */
         p_overlay->status = ToDisplay;
-        p_overlay->i_channel = -1;
+        p_overlay->b_on_vout = false;
         updater_unlock_overlay(p_upd_sys);
     }
 
@@ -1706,11 +1691,9 @@ static void blurayCloseOverlay(demux_t *p_demux, int plane)
         if (ov->p_updater) {
             unref_subpicture_updater(ov->p_updater);
         }
+
         /* no references to this overlay exist in vo anymore */
-        if (p_sys->bdj.p_video_es && ov->i_channel != -1) {
-            es_out_Control( p_demux->out, ES_OUT_VOUT_FLUSH_OVERLAY,
-                            p_sys->bdj.p_video_es, ov->i_channel );
-        }
+        es_out_Control(p_sys->p_out, BLURAY_ES_OUT_CONTROL_DELETE_OVERLAY, plane);
 
         vlc_mutex_destroy(&ov->lock);
         subpicture_region_ChainDelete(ov->p_regions);
@@ -1718,13 +1701,6 @@ static void blurayCloseOverlay(demux_t *p_demux, int plane)
 
         p_sys->bdj.p_overlays[plane] = NULL;
     }
-
-    for (int i = 0; i < MAX_OVERLAY; i++)
-        if (p_sys->bdj.p_overlays[i])
-            return;
-
-    /* All overlays have been closed */
-    blurayReleaseVideoES(p_demux);
 }
 
 /*
@@ -1744,9 +1720,7 @@ static void blurayActivateOverlay(demux_t *p_demux, int plane)
      * We must NOT use vout_PutSubpicture if a picture is already displayed.
      */
     vlc_mutex_lock(&ov->lock);
-    if (ov->status >= Displayed && ov->i_channel != -1 &&
-        p_sys->bdj.p_video_es)
-    {
+    if (ov->status >= Displayed && ov->b_on_vout) {
         ov->status = Outdated;
         vlc_mutex_unlock(&ov->lock);
         return;
@@ -1773,7 +1747,7 @@ static void blurayInitOverlay(demux_t *p_demux, int plane, int width, int height
 
     ov->width = width;
     ov->height = height;
-    ov->i_channel = -1;
+    ov->b_on_vout = false;
 
     vlc_mutex_init(&ov->lock);
 
@@ -1890,9 +1864,8 @@ static void blurayOverlayProc(void *ptr, const BD_OVERLAY *const overlay)
 
     if (!overlay) {
         msg_Info(p_demux, "Closing overlays.");
-        if (p_sys->bdj.p_video_es)
-            for (int i = 0; i < MAX_OVERLAY; i++)
-                blurayCloseOverlay(p_demux, i);
+        for (int i = 0; i < MAX_OVERLAY; i++)
+            blurayCloseOverlay(p_demux, i);
         vlc_mutex_unlock(&p_sys->bdj.lock);
         return;
     }
@@ -2010,12 +1983,12 @@ static void blurayArgbOverlayProc(void *ptr, const BD_ARGB_OVERLAY *const overla
     }
 }
 
-static void bluraySendOverlayToVout(demux_t *p_demux, bluray_overlay_t *p_ov)
+static void bluraySendOverlayToVout(demux_t *p_demux, int plane, 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->b_on_vout);
 
     if (p_ov->p_updater) {
         unref_subpicture_updater(p_ov->p_updater);
@@ -2034,16 +2007,17 @@ static void bluraySendOverlayToVout(demux_t *p_demux, bluray_overlay_t *p_ov)
      * This must be done only once per subpicture, ie. only once between each
      * blurayInitOverlay & blurayCloseOverlay call.
      */
-    int ret = es_out_Control( p_demux->out, ES_OUT_VOUT_ADD_OVERLAY,
-                              p_sys->bdj.p_video_es, p_pic, &p_ov->i_channel);
+    int ret = es_out_Control(p_sys->p_out, BLURAY_ES_OUT_CONTROL_CREATE_OVERLAY,
+                             plane, p_pic);
     if (ret != VLC_SUCCESS)
     {
         unref_subpicture_updater(p_ov->p_updater);
         p_ov->p_updater = NULL;
-        p_ov->i_channel = -1;
+        p_ov->b_on_vout = false;
         subpicture_Delete(p_pic);
         return;
     }
+    p_ov->b_on_vout = true;
 
     /*
      * Mark the picture as Outdated, as it contains no region for now.
@@ -2893,26 +2867,9 @@ static void blurayHandleEvent(demux_t *p_demux, const BD_EVENT *e)
     }
 }
 
-static bool blurayIsBdjTitle(demux_t *p_demux)
-{
-    demux_sys_t *p_sys = p_demux->p_sys;
-    unsigned int i_title = p_sys->cur_title;
-    const BLURAY_DISC_INFO *di = bd_get_disc_info(p_sys->bluray);
-
-    if (di && di->titles) {
-        if ((i_title <= di->num_titles && di->titles[i_title] && di->titles[i_title]->bdj) ||
-            (i_title == p_sys->i_title - 1 && di->first_play && di->first_play->bdj)) {
-          return true;
-        }
-    }
-
-    return false;
-}
-
-static void blurayHandleOverlays(demux_t *p_demux, int nread)
+static void blurayHandleOverlays(demux_t *p_demux)
 {
     demux_sys_t *p_sys = p_demux->p_sys;
-
     vlc_mutex_lock(&p_sys->bdj.lock);
 
     for (int i = 0; i < MAX_OVERLAY; i++) {
@@ -2923,24 +2880,14 @@ static void blurayHandleOverlays(demux_t *p_demux, int nread)
         vlc_mutex_lock(&ov->lock);
         bool display = ov->status == ToDisplay;
         vlc_mutex_unlock(&ov->lock);
-        if (display && ov->i_channel == -1) {
+        if (display && !ov->b_on_vout)
+        {
             /* NOTE: we might want to enable background video always when there's no video stream playing.
                Now, with some discs, there are perioids (even seconds) during which the video window
                disappears and just playlist is shown.
                (sometimes BD-J runs slowly ...)
             */
-            if (!p_sys->bdj.p_video_es && p_sys->b_menu &&
-                !p_sys->p_pl_info && nread == 0 &&
-                blurayIsBdjTitle(p_demux)) {
-
-                /* Looks like there's no video stream playing.
-                   Emit blank frame so that BD-J overlay can be drawn. */
-                p_sys->bdj.p_video_es = blurayCreateBackgroundUnlocked(p_demux);
-            }
-
-            if (p_sys->bdj.p_video_es != NULL) {
-                bluraySendOverlayToVout(p_demux, ov);
-            }
+            bluraySendOverlayToVout(p_demux, i, ov);
         }
     }
 
@@ -2986,7 +2933,7 @@ static int blurayDemux(demux_t *p_demux)
         }
     }
 
-    blurayHandleOverlays(p_demux, nread);
+    blurayHandleOverlays(p_demux);
 
     if (nread <= 0) {
         block_Release(p_block);
@@ -3002,8 +2949,6 @@ static int blurayDemux(demux_t *p_demux)
 
     p_block->i_buffer = nread;
 
-    stopBackground(p_demux);
-
     vlc_demux_chained_Send(p_sys->p_parser, p_block);
 
     p_sys->b_flushed = false;



More information about the vlc-commits mailing list