]> git.sesse.net Git - vlc/blob - modules/video_output/drawable.c
decoder: fix data race in input_DecoderFrameNext()
[vlc] / modules / video_output / drawable.c
1 /**
2  * @file drawable.c
3  * @brief Legacy monolithic LibVLC video window provider
4  */
5 /*****************************************************************************
6  * Copyright © 2009 Rémi Denis-Courmont
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <stdarg.h>
28 #include <assert.h>
29
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_vout_window.h>
33
34 #define HWND_TEXT N_("Window handle (HWND)")
35 #define HWND_LONGTEXT N_( \
36     "Video will be embedded in this pre-existing window. " \
37     "If zero, a new window will be created.")
38
39 static int  Open (vout_window_t *, const vout_window_cfg_t *);
40 static void Close(vout_window_t *);
41
42 /*
43  * Module descriptor
44  */
45 vlc_module_begin ()
46     set_shortname (N_("Drawable"))
47     set_description (N_("Embedded window video"))
48     set_category (CAT_VIDEO)
49     set_subcategory (SUBCAT_VIDEO_VOUT)
50     set_capability ("vout window", 70)
51     set_callbacks (Open, Close)
52     add_shortcut ("embed-hwnd")
53
54     add_integer ("drawable-hwnd", 0, HWND_TEXT, HWND_LONGTEXT, true)
55         change_volatile ()
56 vlc_module_end ()
57
58 static int Control (vout_window_t *, int, va_list);
59
60 /* Keep a list of busy drawables, so we don't overlap videos if there are
61  * more than one video track in the stream. */
62 static vlc_mutex_t serializer = VLC_STATIC_MUTEX;
63 static uintptr_t *used = NULL;
64
65 /**
66  * Find the drawable set by libvlc application.
67  */
68 static int Open (vout_window_t *wnd, const vout_window_cfg_t *cfg)
69 {
70     if (cfg->type != VOUT_WINDOW_TYPE_INVALID
71      && cfg->type != VOUT_WINDOW_TYPE_HWND)
72         return VLC_EGENERIC;
73
74     uintptr_t val = var_InheritInteger (wnd, "drawable-hwnd");
75     if (val == 0)
76         return VLC_EGENERIC;
77
78     uintptr_t *tab;
79     size_t n = 0;
80
81     vlc_mutex_lock (&serializer);
82     if (used != NULL)
83         for (/*n = 0*/; used[n]; n++)
84             if (used[n] == val)
85             {
86                 msg_Warn (wnd, "HWND 0x%zX is busy", val);
87                 val = 0;
88                 goto skip;
89             }
90
91     tab = realloc (used, sizeof (*used) * (n + 2));
92     if (likely(tab != NULL))
93     {
94         used = tab;
95         used[n] = val;
96         used[n + 1] = 0;
97     }
98     else
99         val = 0;
100 skip:
101     vlc_mutex_unlock (&serializer);
102
103     if (val == 0)
104         return VLC_EGENERIC;
105
106     wnd->type = VOUT_WINDOW_TYPE_HWND;
107     wnd->handle.hwnd = (void *)val;
108     wnd->control = Control;
109     wnd->sys = (void *)val;
110     return VLC_SUCCESS;
111 }
112
113 /**
114  * Release the drawable.
115  */
116 static void Close (vout_window_t *wnd)
117 {
118     uintptr_t val = (uintptr_t)wnd->sys;
119     size_t n = 0;
120
121     /* Remove this drawable from the list of busy ones */
122     vlc_mutex_lock (&serializer);
123     assert (used != NULL);
124     while (used[n] != val)
125     {
126         assert (used[n]);
127         n++;
128     }
129     do
130         used[n] = used[n + 1];
131     while (used[++n] != 0);
132
133     if (n == 0)
134     {
135          free (used);
136          used = NULL;
137     }
138     vlc_mutex_unlock (&serializer);
139 }
140
141
142 static int Control (vout_window_t *wnd, int query, va_list ap)
143 {
144     VLC_UNUSED( ap );
145
146     switch (query)
147     {
148         case VOUT_WINDOW_SET_SIZE:   /* not allowed */
149         case VOUT_WINDOW_SET_STATE: /* not allowed either, would be ugly */
150             return VLC_EGENERIC;
151         default:
152             msg_Warn (wnd, "unsupported control query %d", query);
153             return VLC_EGENERIC;
154     }
155 }