1 /*
2 * Copyright (C) 2000-2019 the xine project
3 *
4 * This file is part of xine, a free video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * Was originally part of toxine frontend.
21 * ...but has now been adapted to xine coding style standards ;)
22 * ......what changes, impressive!
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <pthread.h>
34
35 #include "xine.h"
36
37 #include <xine/video_out.h>
38 #include <xine/xine_internal.h>
39 #include <xine/xineutils.h>
40 #include <xine/vo_scale.h>
41
42 typedef struct {
43 vo_frame_t vo_frame;
44 unsigned int width;
45 unsigned int height;
46 double ratio;
47 int format;
48 } vo_none_frame_t;
49
50 typedef struct {
51 vo_driver_t vo_driver;
52 int ratio;
53 xine_t *xine;
54 } vo_none_driver_t;
55
56 typedef struct {
57 video_driver_class_t driver_class;
58 xine_t *xine;
59 } vo_none_class_t;
60
61
vo_none_free_framedata(vo_none_frame_t * frame)62 static void vo_none_free_framedata(vo_none_frame_t* frame) {
63 if(frame->vo_frame.base[0]) {
64 xine_free_aligned(frame->vo_frame.base[0]);
65 frame->vo_frame.base[0] = NULL;
66 frame->vo_frame.base[1] = NULL;
67 frame->vo_frame.base[2] = NULL;
68 }
69 }
70
vo_none_frame_dispose(vo_frame_t * vo_frame)71 static void vo_none_frame_dispose(vo_frame_t *vo_frame) {
72 vo_none_frame_t *frame = (vo_none_frame_t *)vo_frame;
73 vo_none_free_framedata(frame);
74 pthread_mutex_destroy (&frame->vo_frame.mutex);
75 free (frame);
76 }
77
vo_none_frame_field(vo_frame_t * vo_frame,int which_field)78 static void vo_none_frame_field(vo_frame_t *vo_frame, int which_field) {
79 /* do nothing */
80 (void)vo_frame;
81 (void)which_field;
82 }
83
vo_none_get_capabilities(vo_driver_t * vo_driver)84 static uint32_t vo_none_get_capabilities(vo_driver_t *vo_driver) {
85 /* No, we dont crop. Neither do we interpret color matrix or range. */
86 /* But we also dont ask decoders to convert data just for the trash ;-) */
87 (void)vo_driver;
88 return VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_COLOR_MATRIX | VO_CAP_FULLRANGE;
89 }
90
vo_none_alloc_frame(vo_driver_t * vo_driver)91 static vo_frame_t *vo_none_alloc_frame(vo_driver_t *vo_driver) {
92 /* none_driver_t *this = (none_driver_t *) vo_driver; */
93 vo_none_frame_t *frame;
94
95 frame = calloc(1, sizeof(vo_none_frame_t));
96 if(!frame)
97 return NULL;
98
99 pthread_mutex_init(&frame->vo_frame.mutex, NULL);
100
101 frame->vo_frame.base[0] = NULL;
102 frame->vo_frame.base[1] = NULL;
103 frame->vo_frame.base[2] = NULL;
104
105 frame->vo_frame.proc_slice = NULL;
106 frame->vo_frame.proc_frame = NULL;
107 frame->vo_frame.field = vo_none_frame_field;
108 frame->vo_frame.dispose = vo_none_frame_dispose;
109 frame->vo_frame.driver = vo_driver;
110
111 return (vo_frame_t *)frame;
112 }
113
vo_none_update_frame_format(vo_driver_t * vo_driver,vo_frame_t * vo_frame,uint32_t width,uint32_t height,double ratio,int format,int flags)114 static void vo_none_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_frame,
115 uint32_t width, uint32_t height,
116 double ratio, int format, int flags) {
117 vo_none_driver_t *this = (vo_none_driver_t *) vo_driver;
118 vo_none_frame_t *frame = (vo_none_frame_t *) vo_frame;
119
120 (void)flags;
121 if((frame->width != width) || (frame->height != height) || (frame->format != format)) {
122
123 vo_none_free_framedata(frame);
124
125 frame->width = width;
126 frame->height = height;
127 frame->format = format;
128
129 switch(format) {
130
131 case XINE_IMGFMT_YV12:
132 {
133 int y_size, uv_size;
134
135 frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
136 frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
137 frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
138
139 y_size = frame->vo_frame.pitches[0] * height;
140 uv_size = frame->vo_frame.pitches[1] * ((height+1)/2);
141
142 frame->vo_frame.base[0] = xine_malloc_aligned (y_size + 2*uv_size);
143 if (frame->vo_frame.base[0]) {
144 frame->vo_frame.base[1] = frame->vo_frame.base[0] + y_size;
145 frame->vo_frame.base[2] = frame->vo_frame.base[0] + y_size + uv_size;
146 } else {
147 frame->vo_frame.base[1] = NULL;
148 frame->vo_frame.base[2] = NULL;
149 xprintf (this->xine, XINE_VERBOSITY_DEBUG,
150 "video_out_none: error. (framedata allocation failed: out of memory)\n");
151 frame->width = 0;
152 frame->vo_frame.width = 0;
153 }
154 }
155 break;
156
157 case XINE_IMGFMT_YUY2:
158 frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
159 frame->vo_frame.base[0] = xine_malloc_aligned(frame->vo_frame.pitches[0] * height);
160 frame->vo_frame.base[1] = NULL;
161 frame->vo_frame.base[2] = NULL;
162 if (!frame->vo_frame.base[0]) {
163 xprintf (this->xine, XINE_VERBOSITY_DEBUG,
164 "video_out_none: error. (framedata allocation failed: out of memory)\n");
165 frame->width = 0;
166 frame->vo_frame.width = 0;
167 }
168 break;
169
170 default:
171 xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_none: unknown frame format %04x)\n", format);
172 frame->width = 0;
173 frame->vo_frame.width = 0;
174 break;
175 }
176 }
177
178 frame->ratio = ratio;
179 }
180
vo_none_display_frame(vo_driver_t * vo_driver,vo_frame_t * vo_frame)181 static void vo_none_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) {
182 /* vo_none_driver_t *driver = (vo_none_driver_t *)vo_driver; */
183
184 (void)vo_driver;
185 vo_frame->free(vo_frame);
186 }
187
vo_none_get_property(vo_driver_t * vo_driver,int property)188 static int vo_none_get_property(vo_driver_t *vo_driver, int property) {
189 vo_none_driver_t *driver = (vo_none_driver_t *)vo_driver;
190
191 switch(property) {
192
193 case VO_PROP_ASPECT_RATIO:
194 return driver->ratio;
195 break;
196
197 default:
198 break;
199 }
200
201 return 0;
202 }
203
vo_none_set_property(vo_driver_t * vo_driver,int property,int value)204 static int vo_none_set_property(vo_driver_t *vo_driver, int property, int value) {
205 vo_none_driver_t *driver = (vo_none_driver_t *)vo_driver;
206
207 switch(property) {
208
209 case VO_PROP_ASPECT_RATIO:
210 if(value >= XINE_VO_ASPECT_NUM_RATIOS)
211 value = XINE_VO_ASPECT_AUTO;
212
213 driver->ratio = value;
214 break;
215
216 default:
217 break;
218 }
219 return value;
220 }
221
vo_none_get_property_min_max(vo_driver_t * vo_driver,int property,int * min,int * max)222 static void vo_none_get_property_min_max(vo_driver_t *vo_driver,
223 int property, int *min, int *max) {
224 (void)vo_driver;
225 (void)property;
226 *min = 0;
227 *max = 0;
228 }
229
vo_none_gui_data_exchange(vo_driver_t * vo_driver,int data_type,void * data)230 static int vo_none_gui_data_exchange(vo_driver_t *vo_driver, int data_type, void *data) {
231 /* vo_none_driver_t *this = (vo_none_driver_t *) vo_driver; */
232
233 (void)vo_driver;
234 (void)data;
235 switch (data_type) {
236 case XINE_GUI_SEND_COMPLETION_EVENT:
237 case XINE_GUI_SEND_DRAWABLE_CHANGED:
238 case XINE_GUI_SEND_EXPOSE_EVENT:
239 case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO:
240 case XINE_GUI_SEND_VIDEOWIN_VISIBLE:
241 case XINE_GUI_SEND_SELECT_VISUAL:
242 break;
243 }
244
245 return 0;
246 }
vo_none_dispose(vo_driver_t * vo_driver)247 static void vo_none_dispose(vo_driver_t *vo_driver) {
248 vo_none_driver_t *this = (vo_none_driver_t *) vo_driver;
249
250 free(this);
251 }
252
vo_none_redraw_needed(vo_driver_t * vo_driver)253 static int vo_none_redraw_needed(vo_driver_t *vo_driver) {
254 (void)vo_driver;
255 return 0;
256 }
257
vo_none_open_plugin(video_driver_class_t * driver_class,const void * visual)258 static vo_driver_t *vo_none_open_plugin(video_driver_class_t *driver_class, const void *visual) {
259 vo_none_class_t *class = (vo_none_class_t *) driver_class;
260 vo_none_driver_t *driver;
261
262 (void)visual;
263 driver = calloc(1, sizeof(vo_none_driver_t));
264 if (!driver)
265 return NULL;
266
267 driver->xine = class->xine;
268 driver->ratio = XINE_VO_ASPECT_AUTO;
269
270 driver->vo_driver.get_capabilities = vo_none_get_capabilities;
271 driver->vo_driver.alloc_frame = vo_none_alloc_frame ;
272 driver->vo_driver.update_frame_format = vo_none_update_frame_format;
273 driver->vo_driver.overlay_begin = NULL;
274 driver->vo_driver.overlay_blend = NULL;
275 driver->vo_driver.overlay_end = NULL;
276 driver->vo_driver.display_frame = vo_none_display_frame;
277 driver->vo_driver.get_property = vo_none_get_property;
278 driver->vo_driver.set_property = vo_none_set_property;
279 driver->vo_driver.get_property_min_max = vo_none_get_property_min_max;
280 driver->vo_driver.gui_data_exchange = vo_none_gui_data_exchange;
281 driver->vo_driver.dispose = vo_none_dispose;
282 driver->vo_driver.redraw_needed = vo_none_redraw_needed;
283
284 return &driver->vo_driver;
285 }
286
287 /*
288 * Class related functions.
289 */
vo_none_init_class(xine_t * xine,const void * visual)290 static void *vo_none_init_class (xine_t *xine, const void *visual) {
291 vo_none_class_t *this;
292
293 (void)visual;
294 this = calloc(1, sizeof(vo_none_class_t));
295 if (!this)
296 return NULL;
297
298 this->driver_class.open_plugin = vo_none_open_plugin;
299 this->driver_class.identifier = "none";
300 this->driver_class.description = N_("xine video output plugin which displays nothing");
301 this->driver_class.dispose = default_video_driver_class_dispose;
302
303 this->xine = xine;
304
305 return this;
306 }
307
308 static const vo_info_t vo_info_none = {
309 .priority = 5,
310 .visual_type = XINE_VISUAL_TYPE_NONE,
311 };
312
313 #define VO_NONE_CATALOG { PLUGIN_VIDEO_OUT, 22, "none", XINE_VERSION_CODE, &vo_info_none, vo_none_init_class }
314
315 #ifndef XINE_MAKE_BUILTINS
316 const plugin_info_t xine_plugin_info[] EXPORTED = {
317 /* type, API, "name", version, special_info, init_function */
318 VO_NONE_CATALOG,
319 { PLUGIN_NONE, 0, NULL, 0, NULL, NULL }
320 };
321 #endif
322
323
324