[vlc-devel] [PATCH 1/2] vout: add vout_Drain()

Rémi Denis-Courmont remi at remlab.net
Wed Mar 15 15:44:20 CET 2017


On March 15, 2017 4:33:30 PM GMT+02:00, Thomas Guillem <thomas at gllm.fr> wrote:
>vout_Drain() asks the vout thread to drain its queued pictures. This
>function
>will wait for the last picture to be displayed.
>
>Refs #18105
>---
>src/video_output/control.c       | 33 +++++++++++++++++++++++++++++++--
> src/video_output/control.h       |  4 ++++
> src/video_output/video_output.c  | 28 ++++++++++++++++++++++++++++
> src/video_output/vout_control.h  |  5 +++++
> src/video_output/vout_internal.h |  1 +
> 5 files changed, 69 insertions(+), 2 deletions(-)
>
>diff --git a/src/video_output/control.c b/src/video_output/control.c
>index bbdb8948eb..078c510450 100644
>--- a/src/video_output/control.c
>+++ b/src/video_output/control.c
>@@ -64,6 +64,7 @@ void vout_control_Init(vout_control_t *ctrl)
>     ctrl->is_dead = false;
>     ctrl->can_sleep = true;
>     ctrl->is_processing = false;
>+    ctrl->is_draining = false;
>     ARRAY_INIT(ctrl->cmd);
> }
> 
>@@ -98,15 +99,21 @@ void vout_control_WaitEmpty(vout_control_t *ctrl)
>     vlc_mutex_unlock(&ctrl->lock);
> }
> 
>-void vout_control_Push(vout_control_t *ctrl, vout_control_cmd_t *cmd)
>+static void vout_control_PushLocked(vout_control_t *ctrl,
>+                                    vout_control_cmd_t *cmd)
> {
>-    vlc_mutex_lock(&ctrl->lock);
>     if (!ctrl->is_dead) {
>         ARRAY_APPEND(ctrl->cmd, *cmd);
>         vlc_cond_signal(&ctrl->wait_request);
>     } else {
>         vout_control_cmd_Clean(cmd);
>     }
>+}
>+
>+void vout_control_Push(vout_control_t *ctrl, vout_control_cmd_t *cmd)
>+{
>+    vlc_mutex_lock(&ctrl->lock);
>+    vout_control_PushLocked(ctrl, cmd);
>     vlc_mutex_unlock(&ctrl->lock);
> }
> 
>@@ -176,6 +183,28 @@ void vout_control_PushString(vout_control_t *ctrl,
>int type, const char *string)
>     vout_control_Push(ctrl, &cmd);
> }
> 
>+void vout_control_Drained(vout_control_t *ctrl)
>+{
>+    vlc_mutex_lock(&ctrl->lock);
>+    ctrl->is_draining = false;
>+    vlc_cond_broadcast(&ctrl->wait_acknowledge);
>+    vlc_mutex_unlock(&ctrl->lock);
>+}
>+
>+void vout_control_Drain(vout_control_t *ctrl)
>+{
>+    vout_control_cmd_t cmd;
>+
>+    vout_control_cmd_Init(&cmd, VOUT_CONTROL_DRAIN);
>+
>+    vlc_mutex_lock(&ctrl->lock);
>+    ctrl->is_draining = true;
>+    vout_control_PushLocked(ctrl, &cmd);
>+    while (ctrl->is_draining && !ctrl->is_dead)
>+        vlc_cond_wait(&ctrl->wait_acknowledge, &ctrl->lock);
>+    vlc_mutex_unlock(&ctrl->lock);
>+}
>+
> int vout_control_Pop(vout_control_t *ctrl, vout_control_cmd_t *cmd,
>                      mtime_t deadline)
> {
>diff --git a/src/video_output/control.h b/src/video_output/control.h
>index 14eec3468d..c41a444aa6 100644
>--- a/src/video_output/control.h
>+++ b/src/video_output/control.h
>@@ -48,6 +48,7 @@ enum {
> 
>     VOUT_CONTROL_PAUSE,
>     VOUT_CONTROL_FLUSH,                 /* time */
>+    VOUT_CONTROL_DRAIN,                 /* void */
>     VOUT_CONTROL_STEP,                  /* time_ptr */
> 
>     VOUT_CONTROL_FULLSCREEN,            /* bool */
>@@ -115,6 +116,7 @@ typedef struct {
>     bool is_dead;
>     bool can_sleep;
>     bool is_processing;
>+    bool is_draining;
>     DECL_ARRAY(vout_control_cmd_t) cmd;
> } vout_control_t;
> 
>@@ -124,6 +126,7 @@ void vout_control_Clean(vout_control_t *);
> 
> /* controls outside of the vout thread */
> void vout_control_WaitEmpty(vout_control_t *);
>+void vout_control_Drain(vout_control_t *);
> 
> void vout_control_Push(vout_control_t *, vout_control_cmd_t *);
> void vout_control_PushVoid(vout_control_t *, int type);
>@@ -138,5 +141,6 @@ void vout_control_Wake(vout_control_t *);
> /* control inside of the vout thread */
>int vout_control_Pop(vout_control_t *, vout_control_cmd_t *, mtime_t
>deadline);
> void vout_control_Dead(vout_control_t *);
>+void vout_control_Drained(vout_control_t *);
> 
> #endif
>diff --git a/src/video_output/video_output.c
>b/src/video_output/video_output.c
>index 155d6a9e30..16e3704f7c 100644
>--- a/src/video_output/video_output.c
>+++ b/src/video_output/video_output.c
>@@ -332,6 +332,11 @@ void vout_Flush(vout_thread_t *vout, mtime_t date)
>     vout_control_WaitEmpty(&vout->p->control);
> }
> 
>+void vout_Drain(vout_thread_t *vout)
>+{
>+    vout_control_Drain(&vout->p->control);
>+}
>+
> bool vout_IsEmpty(vout_thread_t *vout)
> {
>     picture_t *picture = picture_fifo_Peek(vout->p->decoder_fifo);
>@@ -1067,6 +1072,25 @@ static int ThreadDisplayPicture(vout_thread_t
>*vout, mtime_t *deadline)
>     const mtime_t date = mdate();
>const mtime_t render_delay = vout_chrono_GetHigh(&vout->p->render) +
>VOUT_MWAIT_TOLERANCE;
> 
>+    if (vout->p->draining && vout->p->displayed.next == NULL)
>+    {
>+        /* We reached the last picture to display */
>+        if (vout->p->displayed.date <= VLC_TS_INVALID
>+         || vout->p->displayed.date + render_delay <= date)
>+        {
>+            /* Notify the input (the caller of vout_Drain()) that the
>vout is
>+             * drained */
>+            vout_control_Drained(&vout->p->control);
>+        }
>+        else
>+        {
>+            /* Wait a little more before notifying the input, this
>function
>+             * will be called again after the deadline. */
>+            *deadline = vout->p->displayed.date + render_delay;
>+        }
>+        return VLC_EGENERIC;
>+    }
>+
>     bool drop_next_frame = frame_by_frame;
>     mtime_t date_next = VLC_TS_INVALID;
>     if (!paused && vout->p->displayed.next) {
>@@ -1450,6 +1474,7 @@ static void ThreadInit(vout_thread_t *vout)
>  vout->p->is_late_dropped = var_InheritBool(vout, "drop-late-frames");
>     vout->p->pause.is_on     = false;
>     vout->p->pause.date      = VLC_TS_INVALID;
>+    vout->p->draining        = false;
> 
>vout_chrono_Init(&vout->p->render, 5, 10000); /* Arbitrary initial time
>*/
> }
>@@ -1571,6 +1596,9 @@ static int ThreadControl(vout_thread_t *vout,
>vout_control_cmd_t cmd)
>     case VOUT_CONTROL_FLUSH:
>         ThreadFlush(vout, false, cmd.u.time);
>         break;
>+    case VOUT_CONTROL_DRAIN:
>+        vout->p->draining = true;
>+        break;
>     case VOUT_CONTROL_STEP:
>         ThreadStep(vout, cmd.u.time_ptr);
>         break;
>diff --git a/src/video_output/vout_control.h
>b/src/video_output/vout_control.h
>index 25bae8e9aa..e12b8eb169 100644
>--- a/src/video_output/vout_control.h
>+++ b/src/video_output/vout_control.h
>@@ -50,6 +50,11 @@ void vout_GetResetStatistic( vout_thread_t *p_vout,
>unsigned *pi_displayed,
>  */
> void vout_Flush( vout_thread_t *p_vout, mtime_t i_date );
> 
>+/**
>+ * This function will wait for all queued pictures to be displayed.
>+ */
>+void vout_Drain( vout_thread_t *p_vout );
>+
> /*
>* Cancel the vout, if cancel is true, it won't return any pictures
>after this
>  * call.
>diff --git a/src/video_output/vout_internal.h
>b/src/video_output/vout_internal.h
>index fec54f38eb..b441786089 100644
>--- a/src/video_output/vout_internal.h
>+++ b/src/video_output/vout_internal.h
>@@ -74,6 +74,7 @@ struct vout_thread_sys_t
>     /* Thread & synchronization */
>     vlc_thread_t    thread;
>     bool            dead;
>+    bool            draining;
>     vout_control_t  control;
> 
>     /* */
>-- 
>2.11.0
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

Fine With me but I fear this sort of thing is not to the liking of the ES output buffering code.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list