]> git.sesse.net Git - vlc/commitdiff
Added API to simplify/clean up vout controls.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 25 Apr 2010 17:18:02 +0000 (19:18 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Mon, 26 Apr 2010 15:53:56 +0000 (17:53 +0200)
src/Makefile.am
src/video_output/control.c [new file with mode: 0644]
src/video_output/control.h [new file with mode: 0644]
src/video_output/video_output.c
src/video_output/vout_internal.h
src/video_output/vout_pictures.c

index bc93824facd5c2ce5946c798209595ff07a67bf3..e8ed0d5e91c5b0bddf11b0322a06391f0c41e172 100644 (file)
@@ -356,6 +356,8 @@ SOURCES_libvlc_common = \
        input/subtitles.c \
        input/var.c \
        video_output/chrono.h \
+       video_output/control.c \
+       video_output/control.h \
        video_output/display.c \
        video_output/display.h \
        video_output/event.h \
diff --git a/src/video_output/control.c b/src/video_output/control.c
new file mode 100644 (file)
index 0000000..6e4e3ab
--- /dev/null
@@ -0,0 +1,205 @@
+/*****************************************************************************
+ * control.c : vout internal control
+ *****************************************************************************
+ * Copyright (C) 2009 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include "control.h"
+
+/* */
+void vout_control_cmd_Init(vout_control_cmd_t *cmd, int type)
+{
+    memset(cmd, 0, sizeof(*cmd));
+    cmd->type = type;
+}
+
+void vout_control_cmd_Clean(vout_control_cmd_t *cmd)
+{
+    switch (cmd->type) {
+    //case VOUT_CONTROL_OSD_MESSAGE:
+    case VOUT_CONTROL_OSD_TITLE:
+        free(cmd->u.message.string);
+        break;
+#if 0
+    case VOUT_CONTROL_OSD_TEXT:
+        free(cmd->text.string);
+        if (cmd->text.style)
+            text_style_Delete(cmd->text.style);
+        break;
+    case VOUT_CONTROL_OSD_SUBPICTURE:
+        if (cmd->subpicture)
+            subpicture_Delete(cmd->subpicture);
+        break;
+#endif
+    default:
+        break;
+    }
+}
+
+/* */
+void vout_control_Init(vout_control_t *ctrl)
+{
+    vlc_mutex_init(&ctrl->lock);
+    vlc_cond_init(&ctrl->wait_request);
+    vlc_cond_init(&ctrl->wait_acknowledge);
+
+    ctrl->is_dead = false;
+    ctrl->is_sleeping = false;
+    ctrl->can_sleep = true;
+    ctrl->is_processing = false;
+    ARRAY_INIT(ctrl->cmd);
+}
+
+void vout_control_Clean(vout_control_t *ctrl)
+{
+    /* */
+    for (int i = 0; i < ctrl->cmd.i_size; i++) {
+        vout_control_cmd_t cmd = ARRAY_VAL(ctrl->cmd, i);
+        vout_control_cmd_Clean(&cmd);
+    }
+    ARRAY_RESET(ctrl->cmd);
+
+    vlc_mutex_destroy(&ctrl->lock);
+    vlc_cond_destroy(&ctrl->wait_request);
+    vlc_cond_destroy(&ctrl->wait_acknowledge);
+}
+
+void vout_control_Dead(vout_control_t *ctrl)
+{
+    vlc_mutex_lock(&ctrl->lock);
+    ctrl->is_dead = true;
+    vlc_cond_broadcast(&ctrl->wait_acknowledge);
+    vlc_mutex_unlock(&ctrl->lock);
+
+}
+
+void vout_control_WaitEmpty(vout_control_t *ctrl)
+{
+    vlc_mutex_lock(&ctrl->lock);
+    while ((ctrl->cmd.i_size > 0 || ctrl->is_processing) && !ctrl->is_dead)
+        vlc_cond_wait(&ctrl->wait_acknowledge, &ctrl->lock);
+    vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_Push(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);
+    }
+    vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_Wake(vout_control_t *ctrl)
+{
+    vlc_mutex_lock(&ctrl->lock);
+    ctrl->can_sleep = false;
+    if (ctrl->is_sleeping)
+        vlc_cond_signal(&ctrl->wait_request);
+    vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_PushVoid(vout_control_t *ctrl, int type)
+{
+    vout_control_cmd_t cmd;
+
+    vout_control_cmd_Init(&cmd, type);
+    vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushBool(vout_control_t *ctrl, int type, bool boolean)
+{
+    vout_control_cmd_t cmd;
+
+    vout_control_cmd_Init(&cmd, type);
+    cmd.u.boolean = boolean;
+    vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushTime(vout_control_t *ctrl, int type, mtime_t time)
+{
+    vout_control_cmd_t cmd;
+
+    vout_control_cmd_Init(&cmd, type);
+    cmd.u.time = time;
+    vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushMessage(vout_control_t *ctrl, int type, int channel, const char *string)
+{
+    vout_control_cmd_t cmd;
+
+    vout_control_cmd_Init(&cmd, type);
+    cmd.u.message.channel = channel;
+    cmd.u.message.string = strdup(string);
+    vout_control_Push(ctrl, &cmd);
+}
+void vout_control_PushPair(vout_control_t *ctrl, int type, int a, int b)
+{
+    vout_control_cmd_t cmd;
+
+    vout_control_cmd_Init(&cmd, type);
+    cmd.u.pair.a = a;
+    cmd.u.pair.b = b;
+    vout_control_Push(ctrl, &cmd);
+}
+
+int vout_control_Pop(vout_control_t *ctrl, vout_control_cmd_t *cmd,
+                     mtime_t deadline, mtime_t timeout)
+{
+    vlc_mutex_lock(&ctrl->lock);
+    if (ctrl->cmd.i_size <= 0) {
+        ctrl->is_processing = false;
+        vlc_cond_broadcast(&ctrl->wait_acknowledge);
+
+        const mtime_t max_deadline = mdate() + timeout;
+
+        /* Supurious wake up are perfectly fine */
+        if (deadline <= VLC_TS_INVALID) {
+            ctrl->is_sleeping = true;
+            if (ctrl->can_sleep)
+                vlc_cond_timedwait(&ctrl->wait_request, &ctrl->lock, max_deadline);
+            ctrl->is_sleeping = false;
+        } else {
+            vlc_cond_timedwait(&ctrl->wait_request, &ctrl->lock, __MIN(deadline, max_deadline));
+        }
+    }
+
+    bool has_cmd;
+    if (ctrl->cmd.i_size > 0) {
+        has_cmd = true;
+        *cmd = ARRAY_VAL(ctrl->cmd, 0);
+        ARRAY_REMOVE(ctrl->cmd, 0);
+
+        ctrl->is_processing = true;
+    } else {
+        has_cmd = false;
+        ctrl->can_sleep = true;
+    }
+    vlc_mutex_unlock(&ctrl->lock);
+
+    return has_cmd ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
diff --git a/src/video_output/control.h b/src/video_output/control.h
new file mode 100644 (file)
index 0000000..4949f4e
--- /dev/null
@@ -0,0 +1,159 @@
+/*****************************************************************************
+ * control.h : vout internal control
+ *****************************************************************************
+ * Copyright (C) 2009-2010 Laurent Aimar
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__)
+# error This header file can only be included from LibVLC.
+#endif
+
+#ifndef _VOUT_INTERNAL_CONTROL_H
+#define _VOUT_INTERNAL_CONTROL_H
+
+/* */
+enum {
+#if 0
+    VOUT_CONTROL_INIT,
+    VOUT_CONTROL_EXIT,
+
+    /* */
+    VOUT_CONTROL_START,
+    VOUT_CONTROL_STOP,
+
+    /* */
+    VOUT_CONTROL_RESET,
+    VOUT_CONTROL_FLUSH,
+    VOUT_CONTROL_PAUSE,
+    VOUT_CONTROL_STEP,
+
+    /* Controls */
+    VOUT_CONTROL_FULLSCREEN,
+    VOUT_CONTROL_DISPLAY_FILLED,
+    VOUT_CONTROL_ZOOM,
+    VOUT_CONTROL_ON_TOP,
+
+    VOUT_CONTROL_SOURCE_ASPECT,
+    VOUT_CONTROL_SOURCE_CROP_BORDER,
+    VOUT_CONTROL_SOURCE_CROP_RATIO,
+    VOUT_CONTROL_SOURCE_CROP_WINDOW,
+
+    /* OSD */
+    VOUT_CONTROL_OSD_MESSAGE,
+    VOUT_CONTROL_OSD_TEXT,
+    VOUT_CONTROL_OSD_SLIDER,
+    VOUT_CONTROL_OSD_ICON,
+    VOUT_CONTROL_OSD_SUBPICTURE,
+#endif
+    VOUT_CONTROL_OSD_TITLE,
+};
+
+typedef struct {
+    int type;
+
+    union {
+        bool    boolean;
+        mtime_t time;
+        struct {
+            int a;
+            int b;
+        } pair;
+        struct {
+            bool is_on;
+            mtime_t date;
+        } pause;
+        struct {
+            int channel;
+            char *string;
+        } message;
+#if 0
+        struct {
+            int channel;
+            char *string;
+            text_style_t *style;
+            int flags;
+            int hmargin;
+            int vmargin;
+            mtime_t start;
+            mtime_t stop;
+        } text;
+        struct {
+            unsigned left;
+            unsigned top;
+            unsigned right;
+            unsigned bottom;
+        } border;
+        struct {
+            unsigned x;
+            unsigned y;
+            unsigned width;
+            unsigned height;
+        } window;
+        struct {
+            int   channel;
+            int   type;
+            float position;
+        } slider;
+        struct {
+            int channel;
+            int icon;
+        } icon;
+        subpicture_t *subpicture;
+#endif
+    } u;
+} vout_control_cmd_t;
+
+void vout_control_cmd_Init(vout_control_cmd_t *, int type);
+void vout_control_cmd_Clean(vout_control_cmd_t *);
+
+typedef struct {
+    vlc_mutex_t lock;
+    vlc_cond_t  wait_request;
+    vlc_cond_t  wait_acknowledge;
+
+    /* */
+    bool is_dead;
+    bool is_sleeping;
+    bool can_sleep;
+    bool is_processing;
+    DECL_ARRAY(vout_control_cmd_t) cmd;
+} vout_control_t;
+
+/* */
+void vout_control_Init(vout_control_t *);
+void vout_control_Clean(vout_control_t *);
+
+/* controls outside of the vout thread */
+void vout_control_WaitEmpty(vout_control_t *);
+
+void vout_control_Push(vout_control_t *, vout_control_cmd_t *);
+void vout_control_PushVoid(vout_control_t *, int type);
+void vout_control_PushBool(vout_control_t *, int type, bool boolean);
+void vout_control_PushTime(vout_control_t *, int type, mtime_t time);
+void vout_control_PushMessage(vout_control_t *, int type, int channel, const char *string);
+void vout_control_PushPair(vout_control_t *, int type, int a, int b);
+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, mtime_t timeout);
+void vout_control_Dead(vout_control_t *);
+
+#endif
+
index 39f4257b1ee601fef41727b7e7d161869df636a1..06533f544f010dc7034696b164196aae646b36bc 100644 (file)
@@ -281,6 +281,7 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt )
     video_format_FixRgb( &p_vout->fmt_in );
 
     /* Initialize misc stuff */
+    vout_control_Init( &p_vout->p->control );
     p_vout->p->i_changes    = 0;
     p_vout->p->b_fullscreen = 0;
     vout_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */
@@ -468,6 +469,7 @@ static void vout_Destructor( vlc_object_t * p_this )
     vlc_mutex_destroy( &p_vout->p->picture_lock );
     vlc_mutex_destroy( &p_vout->p->change_lock );
     vlc_mutex_destroy( &p_vout->p->vfilter_lock );
+    vout_control_Clean( &p_vout->p->control );
 
     /* */
     vout_statistic_Clean( &p_vout->p->statistic );
@@ -506,9 +508,10 @@ void vout_ChangePause( vout_thread_t *p_vout, bool b_paused, mtime_t i_date )
         if (p_vout->p->displayed.decoded)
             p_vout->p->displayed.decoded->date += i_duration;
 
-        vlc_cond_signal( &p_vout->p->picture_wait );
         vlc_mutex_unlock( &p_vout->p->picture_lock );
 
+        vout_control_Wake( &p_vout->p->control );
+
         spu_OffsetSubtitleDate( p_vout->p->p_spu, i_duration );
     }
     else
@@ -554,8 +557,8 @@ void vout_Flush(vout_thread_t *vout, mtime_t date)
 
     Flush(vout, date, false, false);
 
-    vlc_cond_signal(&vout->p->picture_wait);
     vlc_mutex_unlock(&vout->p->picture_lock);
+    vout_control_Wake(&vout->p->control);
 }
 
 void vout_Reset(vout_thread_t *vout)
@@ -568,8 +571,8 @@ void vout_Reset(vout_thread_t *vout)
     vout->p->pause.is_on = false;
     vout->p->pause.date  = mdate();
 
-    vlc_cond_signal( &vout->p->picture_wait );
     vlc_mutex_unlock(&vout->p->picture_lock);
+    vout_control_Wake(&vout->p->control);
 }
 
 void vout_FixLeaks( vout_thread_t *vout )
@@ -596,8 +599,8 @@ void vout_FixLeaks( vout_thread_t *vout )
     /* */
     picture_pool_NonEmpty(vout->p->decoder_pool, false);
 
-    vlc_cond_signal(&vout->p->picture_wait);
     vlc_mutex_unlock(&vout->p->picture_lock);
+    vout_control_Wake(&vout->p->control);
 }
 void vout_NextPicture(vout_thread_t *vout, mtime_t *duration)
 {
@@ -606,9 +609,11 @@ void vout_NextPicture(vout_thread_t *vout, mtime_t *duration)
     vout->p->b_picture_empty = false;
     vout->p->step.is_requested = true;
 
-    /* FIXME I highly doubt that it can works with only one cond_t FIXME */
-    vlc_cond_signal(&vout->p->picture_wait);
+    vlc_mutex_unlock(&vout->p->picture_lock);
+
+    vout_control_Wake(&vout->p->control);
 
+    vlc_mutex_lock(&vout->p->picture_lock);
     while (vout->p->step.is_requested && !vout->p->b_picture_empty)
         vlc_cond_wait(&vout->p->picture_wait, &vout->p->picture_lock);
 
@@ -1017,9 +1022,23 @@ static void *Thread(void *object)
      * Main loop - it is not executed if an error occurred during
      * initialization
      */
+    mtime_t deadline = VLC_TS_INVALID;
     while (!vout->p->b_done && !vout->p->b_error) {
+        vout_control_cmd_t cmd;
+
+        vlc_mutex_unlock(&vout->p->change_lock);
+        /* FIXME remove thoses ugly timeouts
+         */
+        while (!vout_control_Pop(&vout->p->control, &cmd, deadline, 100000)) {
+            switch(cmd.type) {
+            default:
+                break;
+            }
+            vout_control_cmd_Clean(&cmd);
+        }
+        vlc_mutex_lock(&vout->p->change_lock);
+
         /* */
-        mtime_t deadline;
         if (ThreadManage(vout, &deadline,
                          &interlacing, &postprocessing)) {
             vout->p->b_error = true;
@@ -1028,16 +1047,6 @@ static void *Thread(void *object)
 
         ThreadDisplayOsdTitle(vout);
         ThreadChangeFilter(vout);
-
-        vlc_mutex_unlock(&vout->p->change_lock);
-
-        if (deadline > VLC_TS_INVALID) {
-            vlc_mutex_lock(&vout->p->picture_lock);
-            vlc_cond_timedwait(&vout->p->picture_wait, &vout->p->picture_lock, deadline);
-            vlc_mutex_unlock(&vout->p->picture_lock);
-        }
-
-        vlc_mutex_lock(&vout->p->change_lock);
     }
 
     /*
@@ -1064,6 +1073,7 @@ exit_thread:
 
     if (has_wrapper)
         vout_CloseWrapper(vout);
+    vout_control_Dead(&vout->p->control);
 
     return NULL;
 }
index 21b358eaedb99c1bec9e60c43919562ddd6d5728..ee08763bc66088961880977ad1f6677d6c3886b7 100644 (file)
@@ -34,6 +34,7 @@
 #include <vlc_picture_pool.h>
 #include <vlc_vout_display.h>
 #include "vout_control.h"
+#include "control.h"
 #include "snapshot.h"
 #include "statistic.h"
 #include "chrono.h"
@@ -56,6 +57,7 @@ struct vout_thread_sys_t
     bool            b_ready;
     bool            b_done;
     bool            b_error;
+    vout_control_t  control;
 
     /* */
     struct {
index 5376a3faf85c6ca6eb6c43e0f779bdbb1d7275c3..3519caa70d3924202a54c1ee867a6429f8628e18 100644 (file)
@@ -82,8 +82,9 @@ void vout_PutPicture( vout_thread_t *p_vout, picture_t *p_pic )
     p_pic->p_next = NULL;
     picture_fifo_Push(p_vout->p->decoder_fifo, p_pic);
 
-    vlc_cond_signal( &p_vout->p->picture_wait );
     vlc_mutex_unlock( &p_vout->p->picture_lock );
+
+    vout_control_Wake( &p_vout->p->control);
 }
 
 /**
@@ -95,8 +96,9 @@ void vout_ReleasePicture( vout_thread_t *p_vout, picture_t *p_pic  )
 
     picture_Release( p_pic );
 
-    vlc_cond_signal( &p_vout->p->picture_wait );
     vlc_mutex_unlock( &p_vout->p->picture_lock );
+
+    vout_control_Wake( &p_vout->p->control);
 }
 
 /**