demux: ts: only seek on pcr for current program
[vlc.git] / modules / video_output / evas.c
blob36afcfd3e34c9ecc3eda2ea7b3a1c82bcc0db4bb
1 /*****************************************************************************
2 * evas.c: EFL Evas video output
3 *****************************************************************************
4 * Copyright (C) 2015 VLC authors, VideoLAN, and VideoLabs
6 * Authors: Thomas Guillem <thomas@gllm.fr>
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.
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.
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 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <assert.h>
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_vout_display.h>
32 #include <vlc_picture_pool.h>
33 #include <vlc_filter.h>
35 #include <Evas.h>
36 #include <Ecore.h>
38 /* Deactivate TBM surface for now: it's impossible to specify a crop (visible
39 * lines/pitch) and to avoid green borders. */
40 #undef HAVE_TIZEN_SDK
42 #ifdef HAVE_TIZEN_SDK
43 # include <tbm_surface.h>
44 #endif
46 #if defined(EVAS_VERSION_MAJOR) && defined(EVAS_VERSION_MINOR)
47 # if EVAS_VERSION_MAJOR > 1 || ( EVAS_VERSION_MAJOR == 1 && EVAS_VERSION_MINOR >= 10 )
48 # define HAVE_EVAS_CALLBACK_KEY_UP
49 # endif
50 #endif
52 /*****************************************************************************
53 * Module descriptor
54 *****************************************************************************/
55 #define CHROMA_TEXT "Chroma used"
56 #define CHROMA_LONGTEXT "Force use of a specific chroma for evas image"
58 static int Open ( vlc_object_t * );
59 static void Close( vlc_object_t * );
61 vlc_module_begin()
62 set_category( CAT_VIDEO )
63 set_subcategory( SUBCAT_VIDEO_VOUT )
64 set_shortname( "evas" )
65 set_description( "evas video output" )
66 set_capability( "vout display", 220 )
67 add_shortcut( "evas" )
68 add_string( "evas-image-chroma", NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true )
69 set_callbacks( Open, Close )
70 vlc_module_end()
72 /*****************************************************************************
73 * Local prototypes
74 *****************************************************************************/
76 static int EvasImageSetup( vout_display_t * );
77 #ifdef HAVE_TIZEN_SDK
78 static bool EvasIsOpenGLSupported( vout_display_t * );
79 static int TbmSurfaceSetup( vout_display_t * );
80 #endif
82 /* Buffer and Event Fifo */
84 struct fifo_item
86 struct fifo_item *p_next;
89 struct fifo
91 vlc_mutex_t lock;
92 struct fifo_item *p_first;
93 struct fifo_item *p_last;
96 struct buffer
98 struct fifo_item fifo_item;
99 uint8_t *p[PICTURE_PLANE_MAX];
100 bool b_locked;
101 #ifdef HAVE_TIZEN_SDK
102 tbm_surface_h p_tbm_surface;
103 #endif
106 struct event
108 struct fifo_item fifo_item;
109 int i_type;
110 union {
111 int i_key;
112 int i_button;
113 struct {
114 int i_x, i_y;
115 } point;
116 } u;
119 struct vout_display_sys_t
121 picture_pool_t *p_pool;
123 int i_width, i_height;
125 /* Planes */
126 plane_t p_planes[PICTURE_PLANE_MAX];
127 int i_planes_order[PICTURE_PLANE_MAX];
128 unsigned int i_nb_planes;
130 /* Array of video buffers */
131 struct buffer *p_buffers;
132 unsigned int i_nb_buffers;
134 /* FIFO of unlocked video buffers */
135 struct fifo buffer_fifo;
137 /* New buffer to display */
138 struct buffer *p_new_buffer;
139 /* Buffer being displayed */
140 struct buffer *p_current_buffer;
142 /* Evas */
143 Evas_Object *p_evas;
144 Ecore_Animator *p_anim;
146 /* If true: this module doesn't own the Evas_Object anymore */
147 bool b_evas_changed;
148 /* If true: apply rotation to vd->fmt */
149 bool b_apply_rotation;
151 /* FIFO of events */
152 struct fifo event_fifo;
154 /* lock and cond used by EcoreMainLoopCallSync */
155 vlc_mutex_t cb_lock;
156 vlc_cond_t cb_wait;
158 union {
159 struct evas
161 Evas_Colorspace i_colorspace;
162 bool b_yuv;
163 } evas;
164 #ifdef HAVE_TIZEN_SDK
165 struct {
166 tbm_format i_format;
167 int i_angle;
168 } tbm;
169 #endif
170 } u;
172 /* Specific callbacks for EvasImage or TBMSurface */
173 int (*pf_set_data)( vout_display_t * );
174 int (*pf_buffers_alloc)( vout_display_t *, video_format_t * );
175 void (*pf_buffers_free)( vout_display_t * );
178 struct picture_sys_t
180 vout_display_sys_t *p_vd_sys;
181 struct buffer *p_buffer;
184 static void
185 fifo_push( struct fifo *p_fifo, struct fifo_item *p_new )
187 struct fifo_item *p_last;
189 vlc_mutex_lock( &p_fifo->lock );
191 p_new->p_next = NULL;
192 p_last = p_fifo->p_last;
194 if( p_last )
195 p_last->p_next = p_new;
196 else
197 p_fifo->p_first = p_new;
198 p_fifo->p_last = p_new;
200 vlc_mutex_unlock( &p_fifo->lock );
203 static struct fifo_item *
204 fifo_pop( struct fifo *p_fifo )
206 struct fifo_item *p_new;
208 vlc_mutex_lock( &p_fifo->lock );
210 p_new = p_fifo->p_first;
212 if( p_new )
214 if( p_fifo->p_last == p_fifo->p_first )
215 p_fifo->p_first = p_fifo->p_last = NULL;
216 else
217 p_fifo->p_first = p_new->p_next;
220 vlc_mutex_unlock( &p_fifo->lock );
221 return p_new;
224 static void
225 fifo_init( struct fifo *p_fifo )
227 vlc_mutex_init( &p_fifo->lock );
228 p_fifo->p_first = p_fifo->p_last = NULL;
231 static void
232 fifo_deinit( struct fifo *p_fifo )
234 vlc_mutex_destroy( &p_fifo->lock );
237 #define BUFFER_FIFO_PUSH( buffer ) fifo_push( &sys->buffer_fifo, (struct fifo_item *)(buffer) )
238 #define BUFFER_FIFO_POP() (struct buffer *) fifo_pop( &sys->buffer_fifo )
239 #define EVENT_FIFO_PUSH( event ) fifo_push( &sys->event_fifo, (struct fifo_item *)(event) )
240 #define EVENT_FIFO_POP() (struct event *) fifo_pop( &sys->event_fifo )
242 typedef int (*mainloop_cb)( vout_display_t *vd );
244 struct mainloop_cb_args
246 vout_display_t *vd;
247 mainloop_cb p_cb;
248 int i_ret;
249 bool b_signal;
252 static void
253 EcoreMainLoopCb( void *p_opaque )
255 struct mainloop_cb_args *p_args = p_opaque;
256 vout_display_sys_t *sys = p_args->vd->sys;
258 p_args->i_ret = p_args->p_cb( p_args->vd );
260 vlc_mutex_lock( &sys->cb_lock );
261 p_args->b_signal = true;
262 vlc_cond_signal( &sys->cb_wait );
263 vlc_mutex_unlock( &sys->cb_lock );
266 static int
267 EcoreMainLoopCallSync( vout_display_t *vd, mainloop_cb p_cb )
269 vout_display_sys_t *sys = vd->sys;
270 struct mainloop_cb_args args = { .vd = vd, .p_cb = p_cb, .b_signal = false };
271 ecore_main_loop_thread_safe_call_async( EcoreMainLoopCb, &args );
273 vlc_mutex_lock( &sys->cb_lock );
274 while( !args.b_signal )
275 vlc_cond_wait( &sys->cb_wait, &sys->cb_lock );
276 vlc_mutex_unlock( &sys->cb_lock );
278 return args.i_ret;
281 #ifdef HAVE_EVAS_CALLBACK_KEY_UP
282 static void
283 EventSendKey( vout_display_t *vd, int i_key )
285 vout_display_sys_t *sys = vd->sys;
286 struct event *p_event = malloc( sizeof(struct event) );
288 if( !p_event )
289 return;
290 p_event->i_type = VOUT_DISPLAY_EVENT_KEY;
291 p_event->u.i_key = i_key;
292 EVENT_FIFO_PUSH( p_event );
295 static void
296 EvasKeyUpCb( void *data, Evas *e, Evas_Object *obj, void *event )
298 (void) e; (void) obj;
299 Evas_Event_Key_Up *p_key_up = (Evas_Event_Key_Up *) event;
301 EventSendKey( data, p_key_up->keycode );
303 #endif
305 static void
306 EventSendMouseMoved( vout_display_t *vd, int i_x, int i_y )
308 vout_display_sys_t *sys = vd->sys;
309 Evas_Coord i_ox, i_oy, i_ow, i_oh;
310 struct event *p_event = malloc( sizeof(struct event) );
312 if( !p_event )
313 return;
314 evas_object_geometry_get( sys->p_evas, &i_ox, &i_oy, &i_ow, &i_oh );
315 p_event->i_type = VOUT_DISPLAY_EVENT_MOUSE_MOVED;
316 p_event->u.point.i_x = ( ( i_x - i_ox ) * sys->i_width ) / i_ow;
317 p_event->u.point.i_y = ( ( i_y - i_oy ) * sys->i_height ) / i_oh;
318 EVENT_FIFO_PUSH( p_event );
321 static void
322 EventSendMouseButton( vout_display_t *vd, int i_type, int i_button )
324 vout_display_sys_t *sys = vd->sys;
325 struct event *p_event = malloc( sizeof(struct event) );
327 if( !p_event )
328 return;
329 p_event->i_type = i_type;
330 p_event->u.i_button = i_button;
331 EVENT_FIFO_PUSH( p_event );
334 static void
335 EventMouseDownCb( void *data, Evas *e, Evas_Object *obj, void *event )
337 (void) e; (void) obj;
338 Evas_Event_Mouse_Down *p_mouse_down = (Evas_Event_Mouse_Down *) event;
340 EventSendMouseButton( data, VOUT_DISPLAY_EVENT_MOUSE_PRESSED,
341 p_mouse_down->button - 1 );
344 static void
345 EvasMouseUpCb( void *data, Evas *e, Evas_Object *obj, void *event )
347 (void) e; (void) obj;
348 Evas_Event_Mouse_Up *p_mouse_up = (Evas_Event_Mouse_Up *) event;
350 EventSendMouseButton( data, VOUT_DISPLAY_EVENT_MOUSE_RELEASED,
351 p_mouse_up->button - 1 );
354 static void
355 EvasMouseMoveCb( void *data, Evas *e, Evas_Object *obj, void *event )
357 (void) e; (void) obj;
358 Evas_Event_Mouse_Move *p_mouse_move = (Evas_Event_Mouse_Move *) event;
359 EventSendMouseMoved( data, p_mouse_move->cur.canvas.x,
360 p_mouse_move->cur.canvas.y );
363 static void
364 EvasMultiDownCb( void *data, Evas *e, Evas_Object *obj, void *event )
366 (void) e; (void) obj; (void) event;
367 EventSendMouseButton( data, VOUT_DISPLAY_EVENT_MOUSE_PRESSED, 1 );
370 static void
371 EvasMultiUpCb( void *data, Evas *e, Evas_Object *obj, void *event )
373 (void) e; (void) obj; (void) event;
374 EventSendMouseButton( data, VOUT_DISPLAY_EVENT_MOUSE_RELEASED, 1 );
377 static void
378 EvasMultiMoveCb( void *data, Evas *e, Evas_Object *obj, void *event )
380 (void) e; (void) obj;
381 Evas_Event_Multi_Move *p_multi_move = (Evas_Event_Multi_Move *) event;
383 EventSendMouseMoved( data, p_multi_move->cur.canvas.x,
384 p_multi_move->cur.canvas.y );
387 static void
388 FmtUpdate( vout_display_t *vd )
390 vout_display_sys_t *sys = vd->sys;
391 vout_display_place_t place;
392 video_format_t src;
394 vout_display_PlacePicture( &place, &vd->source, vd->cfg, false );
396 if( sys->b_apply_rotation )
398 video_format_ApplyRotation( &src, &vd->source );
399 vd->fmt.orientation = 0;
401 else
402 src = vd->source;
404 vd->fmt.i_width = src.i_width * place.width / src.i_visible_width;
405 vd->fmt.i_height = src.i_height * place.height / src.i_visible_height;
407 vd->fmt.i_visible_width = place.width;
408 vd->fmt.i_visible_height = place.height;
409 vd->fmt.i_x_offset = src.i_x_offset * place.width / src.i_visible_width;
410 vd->fmt.i_y_offset = src.i_y_offset * place.height / src.i_visible_height;
412 sys->i_width = vd->fmt.i_visible_width;
413 sys->i_height = vd->fmt.i_visible_height;
416 static Eina_Bool
417 mainloop_evas_anim_cb( void *p_opaque )
419 vout_display_t *vd = p_opaque;
420 vout_display_sys_t *sys = vd->sys;
421 evas_object_image_pixels_dirty_set( sys->p_evas, 1 );
423 sys->p_anim = NULL;
424 return false;
427 static void
428 EvasResizeCb( void *data, Evas *e, Evas_Object *obj, void *event )
430 (void) e; (void) obj; (void) event;
431 vout_display_t *vd = data;
432 vout_display_sys_t *sys = vd->sys;
434 sys->b_evas_changed = true;
437 static int
438 EvasDisplayMainloopCb( vout_display_t *vd )
440 vout_display_sys_t *sys = vd->sys;
442 if( sys->b_evas_changed || sys->pf_set_data( vd ) )
443 return -1;
445 evas_object_image_data_update_add( sys->p_evas, 0, 0,
446 sys->i_width, sys->i_height );
447 evas_object_image_pixels_dirty_set( sys->p_evas, 0 );
449 if( !sys->p_anim )
450 sys->p_anim = ecore_animator_add( mainloop_evas_anim_cb, vd );
452 if( sys->p_current_buffer )
453 BUFFER_FIFO_PUSH( sys->p_current_buffer );
455 sys->p_current_buffer = sys->p_new_buffer;
456 sys->p_new_buffer = NULL;
457 return 0;
460 static int
461 EvasInitMainloopCb( vout_display_t *vd )
463 vout_display_sys_t *sys = vd->sys;
465 #ifdef HAVE_TIZEN_SDK
466 if( !EvasIsOpenGLSupported( vd ) || TbmSurfaceSetup( vd ) )
467 #endif
468 if( EvasImageSetup( vd ) )
469 return -1;
471 evas_object_image_alpha_set( sys->p_evas, 0 );
472 evas_object_image_size_set( sys->p_evas, sys->i_width, sys->i_height );
474 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MOUSE_DOWN,
475 EventMouseDownCb, vd );
476 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MOUSE_UP,
477 EvasMouseUpCb, vd );
478 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MOUSE_MOVE,
479 EvasMouseMoveCb, vd );
480 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MULTI_DOWN,
481 EvasMultiDownCb, vd );
482 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MULTI_UP,
483 EvasMultiUpCb, vd );
484 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_MULTI_MOVE,
485 EvasMultiMoveCb, vd );
486 #ifdef HAVE_EVAS_CALLBACK_KEY_UP
487 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_KEY_UP,
488 EvasKeyUpCb, sys );
489 #endif
491 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_IMAGE_RESIZE,
492 EvasResizeCb, vd );
494 return 0;
497 static int
498 EvasDeinitMainloopCb( vout_display_t *vd )
500 vout_display_sys_t *sys = vd->sys;
502 if( sys->p_anim )
504 ecore_animator_del( sys->p_anim );
505 sys->p_anim = NULL;
508 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_IMAGE_RESIZE,
509 EvasResizeCb, vd );
511 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MOUSE_DOWN,
512 EventMouseDownCb, vd );
513 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MOUSE_UP,
514 EvasMouseUpCb, vd );
515 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MOUSE_MOVE,
516 EvasMouseMoveCb, vd );
517 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MULTI_DOWN,
518 EvasMultiDownCb, vd );
519 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MULTI_UP,
520 EvasMultiUpCb, vd );
521 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_MULTI_MOVE,
522 EvasMultiMoveCb, vd );
523 #ifdef HAVE_EVAS_CALLBACK_KEY_UP
524 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_KEY_UP,
525 EvasKeyUpCb, vd );
526 #endif
528 if( !sys->b_evas_changed )
530 evas_object_image_data_set( sys->p_evas, NULL );
531 evas_object_image_pixels_dirty_set( sys->p_evas, 0 );
534 return 0;
537 static int
538 EvasResetMainloopCb( vout_display_t *vd )
540 vout_display_sys_t *sys = vd->sys;
542 if( sys->b_evas_changed )
543 return -1;
545 if( sys->p_anim )
547 ecore_animator_del( sys->p_anim );
548 sys->p_anim = NULL;
551 evas_object_event_callback_del_full( sys->p_evas, EVAS_CALLBACK_IMAGE_RESIZE,
552 EvasResizeCb, vd );
554 FmtUpdate( vd );
556 evas_object_image_data_set( sys->p_evas, NULL );
557 evas_object_image_size_set( sys->p_evas, sys->i_width, sys->i_height );
559 evas_object_event_callback_add( sys->p_evas, EVAS_CALLBACK_IMAGE_RESIZE,
560 EvasResizeCb, vd );
561 return 0;
564 static int
565 BuffersSetup( vout_display_t *vd, video_format_t *p_fmt,
566 unsigned int *p_requested_count )
568 vout_display_sys_t *sys = vd->sys;
570 sys->i_nb_buffers = *p_requested_count;
571 if( sys->pf_buffers_alloc( vd, p_fmt ) )
573 sys->i_nb_planes = 0;
574 return VLC_EGENERIC;
576 *p_requested_count = sys->i_nb_buffers;
578 for( unsigned int i = 0; i < sys->i_nb_buffers; ++i )
579 BUFFER_FIFO_PUSH( &sys->p_buffers[i] );
580 return VLC_SUCCESS;
583 static void
584 BuffersClean( vout_display_t *vd )
586 vout_display_sys_t *sys = vd->sys;
588 if( sys->p_buffers )
589 sys->pf_buffers_free( vd );
590 sys->buffer_fifo.p_first = sys->buffer_fifo.p_last = NULL;
593 static picture_t *
594 PictureAlloc( vout_display_t *vd )
596 vout_display_sys_t *sys = vd->sys;
597 picture_resource_t rsc;
598 picture_t *p_pic = NULL;
599 picture_sys_t *p_picsys = calloc(1, sizeof(*p_picsys));
601 if( !p_picsys )
602 return NULL;
604 p_picsys->p_vd_sys = vd->sys;
605 memset(&rsc, 0, sizeof(picture_resource_t));
606 rsc.p_sys = p_picsys;
607 for( unsigned int i = 0; i < sys->i_nb_planes; ++i )
609 rsc.p[i].i_lines = sys->p_planes[i].i_lines;
610 rsc.p[i].i_pitch = sys->p_planes[i].i_pitch;
613 p_pic = picture_NewFromResource( &vd->fmt, &rsc );
614 if( !p_pic )
616 free( p_picsys );
617 return NULL;
620 return p_pic;
623 static int
624 PoolLockPicture(picture_t *p_pic)
626 picture_sys_t *p_picsys = p_pic->p_sys;
627 vout_display_sys_t *sys = p_picsys->p_vd_sys;
629 struct buffer *p_buffer = BUFFER_FIFO_POP();
630 if( !p_buffer || !p_buffer->p[0] )
631 return -1;
633 p_picsys->p_buffer = p_buffer;
634 for( unsigned int i = 0; i < sys->i_nb_planes; ++i )
635 p_pic->p[i].p_pixels = p_buffer->p[i];
636 return 0;
639 static void
640 PoolUnlockPicture(picture_t *p_pic)
642 picture_sys_t *p_picsys = p_pic->p_sys;
643 vout_display_sys_t *sys = p_picsys->p_vd_sys;
645 if( p_picsys->p_buffer )
647 BUFFER_FIFO_PUSH( p_picsys->p_buffer );
648 p_picsys->p_buffer = NULL;
652 static picture_pool_t *
653 PoolAlloc( vout_display_t *vd, unsigned i_requested_count )
655 picture_t **pp_pics = NULL;
656 picture_pool_t *p_pool;
657 picture_pool_configuration_t pool_cfg;
659 msg_Dbg(vd, "PoolAlloc, requested_count: %d", i_requested_count);
661 i_requested_count++; /* picture owned by evas */
663 if( BuffersSetup( vd, &vd->fmt, &i_requested_count) )
665 msg_Err( vd, "BuffersSetup failed" );
666 return NULL;
668 if( i_requested_count <= 1 )
670 msg_Err( vd, "not enough buffers allocated" );
671 goto error;
673 i_requested_count--;
675 msg_Dbg( vd, "PoolAlloc, got: %d", i_requested_count );
677 if( !( pp_pics = calloc( i_requested_count, sizeof(picture_t) ) ) )
678 goto error;
680 for( unsigned int i = 0; i < i_requested_count; ++i )
682 if( !( pp_pics[i] = PictureAlloc( vd ) ) )
684 i_requested_count = i;
685 msg_Err( vd, "PictureAlloc failed" );
686 goto error;
690 memset( &pool_cfg, 0, sizeof(pool_cfg) );
691 pool_cfg.picture_count = i_requested_count;
692 pool_cfg.picture = pp_pics;
693 pool_cfg.lock = PoolLockPicture;
694 pool_cfg.unlock = PoolUnlockPicture;
696 p_pool = picture_pool_NewExtended( &pool_cfg );
697 if( p_pool )
698 return p_pool;
700 error:
701 if( pp_pics )
703 for( unsigned int i = 0; i < i_requested_count; ++i )
704 picture_Release( pp_pics[i] );
705 free( pp_pics );
707 BuffersClean( vd );
708 return NULL;
711 static picture_pool_t *
712 Pool( vout_display_t *vd, unsigned i_requested_count )
714 vout_display_sys_t *sys = vd->sys;
716 if( sys->p_pool == NULL )
717 sys->p_pool = PoolAlloc( vd, i_requested_count );
718 return sys->p_pool;
721 static void
722 Display( vout_display_t *vd, picture_t *p_pic, subpicture_t *p_subpic )
724 (void) p_subpic;
725 vout_display_sys_t *sys = vd->sys;
726 picture_sys_t *p_picsys = p_pic->p_sys;
728 if( p_picsys->p_buffer )
730 sys->p_new_buffer = p_picsys->p_buffer;
731 p_picsys->p_buffer = NULL;
733 EcoreMainLoopCallSync( vd, EvasDisplayMainloopCb );
735 picture_Release( p_pic );
738 static int
739 Control( vout_display_t *vd, int i_query, va_list ap )
741 vout_display_sys_t *sys = vd->sys;
743 switch( i_query )
745 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
747 vout_display_place_t place;
748 video_format_t fmt;
750 msg_Dbg( vd, "VOUT_DISPLAY_CHANGE_SOURCE_ASPECT" );
752 video_format_ApplyRotation( &fmt, &vd->source );
753 vout_display_PlacePicture( &place, &fmt, vd->cfg, false );
755 if( place.width != (unsigned) sys->i_width
756 && place.height != (unsigned) sys->i_height )
758 if( vd->info.has_pictures_invalid )
760 msg_Warn( vd, "ratio changed: invalidate pictures" );
761 vout_display_SendEventPicturesInvalid( vd );
763 else
764 return VLC_EGENERIC;
766 return VLC_SUCCESS;
768 case VOUT_DISPLAY_RESET_PICTURES:
769 msg_Dbg( vd, "VOUT_DISPLAY_RESET_PICTURES" );
771 EcoreMainLoopCallSync( vd, EvasResetMainloopCb );
773 BuffersClean( vd );
775 if( sys->p_pool )
777 picture_pool_Release( sys->p_pool );
778 sys->p_pool = NULL;
780 return VLC_SUCCESS;
781 case VOUT_DISPLAY_CHANGE_ZOOM:
782 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
783 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
784 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
785 return VLC_EGENERIC;
786 default:
787 msg_Warn( vd, "Unknown request in evas_output" );
788 return VLC_EGENERIC;
792 static void
793 Manage( vout_display_t *vd )
795 vout_display_sys_t *sys = vd->sys;
796 struct event *p_event;
798 while( ( p_event = EVENT_FIFO_POP() ) )
800 switch( p_event->i_type )
802 case VOUT_DISPLAY_EVENT_MOUSE_MOVED:
803 vout_display_SendEventMouseMoved( vd, p_event->u.point.i_x,
804 p_event->u.point.i_y );
805 break;
806 case VOUT_DISPLAY_EVENT_MOUSE_PRESSED:
807 case VOUT_DISPLAY_EVENT_MOUSE_RELEASED:
808 vout_display_SendEvent( vd, p_event->i_type,
809 p_event->u.i_button );
810 break;
811 case VOUT_DISPLAY_EVENT_KEY:
812 vout_display_SendEventKey( vd, p_event->u.i_key );
813 break;
815 free( p_event );
819 static void
820 Close( vlc_object_t *p_this )
822 vout_display_t *vd = (vout_display_t *)p_this;
823 vout_display_sys_t *sys = vd->sys;
824 struct event *p_event;
826 if (!sys)
827 return;
829 EcoreMainLoopCallSync( vd, EvasDeinitMainloopCb );
831 BuffersClean( vd );
832 fifo_deinit( &sys->buffer_fifo );
834 if( sys->p_pool )
835 picture_pool_Release(sys->p_pool);
837 while( ( p_event = EVENT_FIFO_POP() ) )
838 free( p_event );
840 vlc_mutex_destroy( &sys->cb_lock );
841 vlc_cond_destroy( &sys->cb_wait );
843 free( sys );
846 static int
847 Open( vlc_object_t *p_this )
849 vout_display_t *vd = (vout_display_t*)p_this;
850 vout_display_sys_t *sys;
851 Evas_Object *p_evas;
853 if( vout_display_IsWindowed( vd ) )
854 return VLC_EGENERIC;
856 p_evas = var_InheritAddress( p_this, "drawable-evasobject" );
857 if( !p_evas )
858 return VLC_EGENERIC;
860 vd->sys = sys = (struct vout_display_sys_t *) calloc( 1, sizeof(*sys) );
861 if( !sys )
862 return VLC_ENOMEM;
864 vlc_mutex_init( &sys->cb_lock );
865 vlc_cond_init( &sys->cb_wait );
866 fifo_init( &sys->buffer_fifo );
867 fifo_init( &sys->event_fifo );
869 sys->p_evas = p_evas;
871 msg_Dbg( vd, "request video format: %4.4s",
872 (const char *)&vd->fmt.i_chroma );
874 /* Evas Initialisation must be done from the Mainloop */
875 if( EcoreMainLoopCallSync( vd, EvasInitMainloopCb ) )
877 msg_Err( vd, "EvasInitMainloopCb failed" );
878 Close( p_this );
879 return VLC_EGENERIC;
882 for( unsigned int i = 0; i < PICTURE_PLANE_MAX; ++i )
883 sys->i_planes_order[i] = i;
885 switch( vd->fmt.i_chroma )
887 case VLC_CODEC_RGB32:
888 case VLC_CODEC_RGB16:
889 video_format_FixRgb(&vd->fmt);
890 break;
891 case VLC_CODEC_YV12:
892 sys->i_planes_order[1] = 2;
893 sys->i_planes_order[2] = 1;
894 default:
895 break;
898 msg_Dbg( vd, "got video format: %4.4s, size: %dx%d",
899 (const char *)&vd->fmt.i_chroma,
900 sys->i_width, sys->i_height );
902 /* Setup vout_display */
903 vd->pool = Pool;
904 vd->prepare = NULL;
905 vd->display = Display;
906 vd->control = Control;
907 vd->manage = Manage;
909 return VLC_SUCCESS;
912 static int
913 EvasImageSetData( vout_display_t *vd )
915 vout_display_sys_t *sys = vd->sys;
916 struct buffer *p_buffer = sys->p_new_buffer;
918 if( sys->u.evas.b_yuv )
920 void *p_data = evas_object_image_data_get( sys->p_evas, 1 );
921 const uint8_t **pp_rows = (const uint8_t **) p_data;
923 if( !p_data )
924 return -1;
926 for( unsigned int i = 0; i < sys->i_nb_planes; ++i )
928 plane_t *p_plane = &sys->p_planes[sys->i_planes_order[i]];
930 for( int j = 0; j < p_plane->i_visible_lines; ++j )
931 *(pp_rows++) = &p_buffer->p[i][j * p_plane->i_pitch];
934 evas_object_image_data_set( sys->p_evas, p_data );
936 else
937 evas_object_image_data_set( sys->p_evas, p_buffer->p[0] );
939 return 0;
942 static void
943 EvasImageBuffersFree( vout_display_t *vd )
945 vout_display_sys_t *sys = vd->sys;
947 for( unsigned int i = 0; i < sys->i_nb_buffers; i++ )
948 aligned_free( sys->p_buffers[i].p[0] );
949 free( sys->p_buffers );
950 sys->p_buffers = NULL;
951 sys->i_nb_buffers = 0;
952 sys->i_nb_planes = 0;
955 static int
956 EvasImageBuffersAlloc( vout_display_t *vd, video_format_t *p_fmt )
958 vout_display_sys_t *sys = vd->sys;
959 picture_t *p_pic = NULL;
960 picture_resource_t rsc;
961 size_t i_bytes = 0;
963 memset(&rsc, 0, sizeof(picture_resource_t));
964 if( !( p_pic = picture_NewFromResource( p_fmt, &rsc ) ) )
965 return -1;
967 if( picture_Setup( p_pic, p_fmt ) )
969 picture_Release( p_pic );
970 return -1;
973 for( int i = 0; i < p_pic->i_planes; ++i )
974 memcpy( &sys->p_planes[i], &p_pic->p[i], sizeof(plane_t));
975 sys->i_nb_planes = p_pic->i_planes;
976 picture_Release( p_pic );
978 if( !( sys->p_buffers = calloc( sys->i_nb_buffers, sizeof(struct buffer) ) ) )
979 goto error;
981 /* Calculate how big the new image should be */
982 for( unsigned int i = 0; i < sys->i_nb_planes; i++ )
984 const plane_t *p = &sys->p_planes[i];
986 if( p->i_pitch < 0 || p->i_lines <= 0 ||
987 (size_t)p->i_pitch > (SIZE_MAX - i_bytes)/p->i_lines )
988 goto error;
989 i_bytes += p->i_pitch * p->i_lines;
992 if( !i_bytes )
993 goto error;
995 for( unsigned int i = 0; i < sys->i_nb_buffers; ++i )
997 struct buffer *p_buffer = &sys->p_buffers[i];
999 p_buffer->p[0] = aligned_alloc( 16, i_bytes );
1001 if( !p_buffer->p[0] )
1003 sys->i_nb_buffers = i;
1004 break;
1007 for( unsigned int j = 1; j < sys->i_nb_planes; j++ )
1008 p_buffer->p[j] = &p_buffer->p[j-1][ sys->p_planes[j-1].i_lines *
1009 sys->p_planes[j-1].i_pitch ];
1012 return 0;
1014 error:
1015 if( sys->p_buffers )
1016 EvasImageBuffersFree( vd );
1017 return -1;
1020 static int
1021 EvasImageSetup( vout_display_t *vd )
1023 vout_display_sys_t *sys = vd->sys;
1024 char *psz_fcc = var_InheritString( vd, "evas-image-chroma" );
1026 if( psz_fcc )
1028 vd->fmt.i_chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, psz_fcc );
1029 free( psz_fcc );
1032 switch( vd->fmt.i_chroma )
1034 case VLC_CODEC_RGB32:
1035 sys->u.evas.i_colorspace = EVAS_COLORSPACE_ARGB8888;
1036 break;
1037 /* Not implemented yet */
1038 #if 0
1039 case VLC_CODEC_RGB16:
1040 sys->u.evas.i_colorspace = EVAS_COLORSPACE_RGB565_A5P;
1041 break;
1042 #endif
1043 case VLC_CODEC_YUYV:
1044 sys->u.evas.i_colorspace = EVAS_COLORSPACE_YCBCR422601_PL;
1045 sys->u.evas.b_yuv = true;
1046 break;
1047 /* FIXME: SIGSEGV in evas_gl_common_texture_nv12_update */
1048 #if 0
1049 case VLC_CODEC_NV12:
1050 sys->u.evas.i_colorspace = EVAS_COLORSPACE_YCBCR420NV12601_PL;
1051 sys->u.evas.b_yuv = true;
1052 break;
1053 #endif
1054 case VLC_CODEC_YV12:
1055 sys->u.evas.i_colorspace = EVAS_COLORSPACE_YCBCR422P601_PL;
1056 sys->u.evas.b_yuv = true;
1057 break;
1058 default:
1059 case VLC_CODEC_I420:
1060 sys->u.evas.i_colorspace = EVAS_COLORSPACE_YCBCR422P601_PL;
1061 vd->fmt.i_chroma = VLC_CODEC_I420;
1062 sys->u.evas.b_yuv = true;
1063 break;
1066 evas_object_image_colorspace_set( sys->p_evas, sys->u.evas.i_colorspace );
1067 evas_object_image_data_set( sys->p_evas, NULL );
1069 /* No rotation support with EvasImage */
1070 sys->b_apply_rotation = true;
1071 FmtUpdate( vd );
1073 /* No aspect ratio support with EvasImage */
1074 vd->info.has_pictures_invalid = true;
1076 sys->pf_set_data = EvasImageSetData;
1077 sys->pf_buffers_alloc = EvasImageBuffersAlloc;
1078 sys->pf_buffers_free = EvasImageBuffersFree;
1080 msg_Dbg( vd, "using evas_image" );
1081 return 0;
1084 #ifdef HAVE_TIZEN_SDK
1086 struct tbm_format_to_vlc
1088 tbm_format i_tbm_format;
1089 vlc_fourcc_t i_vlc_chroma;
1092 struct tbm_format_to_vlc tbm_format_to_vlc_list[] = {
1093 { TBM_FORMAT_NV12, VLC_CODEC_NV12 },
1094 { TBM_FORMAT_YUV420, VLC_CODEC_I420 },
1095 { TBM_FORMAT_BGRA8888, VLC_CODEC_RGB32 },
1097 #define TBM_FORMAT_TO_VLC_LIST_COUNT \
1098 ( sizeof(tbm_format_to_vlc_list) / sizeof(struct tbm_format_to_vlc) )
1100 static bool
1101 EvasIsOpenGLSupported( vout_display_t *vd )
1103 vout_display_sys_t *sys = vd->sys;
1104 Evas *p_canvas = evas_object_evas_get(sys->p_evas);
1105 Eina_List *p_engine_list, *p_l;
1106 int i_render_id;
1107 char *psz_render_name;
1108 bool b_is_gl = false;
1110 if( !p_canvas )
1111 return false;
1112 i_render_id = evas_output_method_get( p_canvas );
1114 p_engine_list = evas_render_method_list();
1115 if( !p_engine_list )
1116 return false;
1118 EINA_LIST_FOREACH( p_engine_list, p_l, psz_render_name )
1120 if( evas_render_method_lookup( psz_render_name ) == i_render_id )
1122 b_is_gl = strncmp( psz_render_name, "gl", 2 ) == 0;
1123 break;
1127 evas_render_method_list_free( p_engine_list );
1128 return b_is_gl;
1131 static int
1132 TbmSurfaceBufferLock( struct buffer *p_buffer )
1134 tbm_surface_info_s tbm_surface_info;
1135 if( tbm_surface_map( p_buffer->p_tbm_surface, TBM_SURF_OPTION_WRITE,
1136 &tbm_surface_info ) )
1137 return -1;
1139 for( unsigned i = 0; i < tbm_surface_info.num_planes; ++i )
1140 p_buffer->p[i] = tbm_surface_info.planes[i].ptr;
1141 return 0;
1144 static int
1145 TbmSurfaceBufferUnlock( struct buffer *p_buffer )
1147 tbm_surface_unmap( p_buffer->p_tbm_surface );
1148 p_buffer->p[0] = NULL;
1149 return 0;
1152 static int
1153 TbmSurfaceSetData( vout_display_t *vd )
1155 vout_display_sys_t *sys = vd->sys;
1156 Evas_Native_Surface surf;
1158 TbmSurfaceBufferUnlock( sys->p_new_buffer );
1160 surf.version = EVAS_NATIVE_SURFACE_VERSION;
1161 surf.type = EVAS_NATIVE_SURFACE_TBM;
1162 surf.data.tizen.buffer = sys->p_new_buffer->p_tbm_surface;
1163 surf.data.tizen.rot = sys->u.tbm.i_angle;
1164 surf.data.tizen.ratio = 0;
1165 surf.data.tizen.flip = 0;
1166 evas_object_image_native_surface_set( sys->p_evas, &surf );
1168 if( sys->p_current_buffer )
1169 TbmSurfaceBufferLock( sys->p_current_buffer );
1170 return 0;
1173 static void
1174 TbmSurfaceBuffersFree( vout_display_t *vd )
1176 vout_display_sys_t *sys = vd->sys;
1178 for( unsigned int i = 0; i < sys->i_nb_buffers; i++ )
1180 if( sys->p_buffers[i].p[0] )
1181 tbm_surface_unmap( sys->p_buffers[i].p_tbm_surface );
1182 tbm_surface_destroy( sys->p_buffers[i].p_tbm_surface );
1184 free( sys->p_buffers );
1185 sys->p_buffers = NULL;
1186 sys->i_nb_buffers = 0;
1187 sys->i_nb_planes = 0;
1190 static int
1191 TbmSurfaceBuffersAllocMainloopCb( vout_display_t *vd )
1193 vout_display_sys_t *sys = vd->sys;
1194 tbm_surface_info_s tbm_surface_info;
1196 sys->i_nb_buffers = 2;
1198 if( !( sys->p_buffers = calloc( sys->i_nb_buffers, sizeof(struct buffer) ) ) )
1199 return -1;
1201 for( unsigned i = 0; i < sys->i_nb_buffers; ++i )
1203 struct buffer *p_buffer = &sys->p_buffers[i];
1204 tbm_surface_h p_tbm_surface = tbm_surface_create( sys->i_width,
1205 sys->i_height,
1206 sys->u.tbm.i_format );
1207 if( !p_tbm_surface
1208 || tbm_surface_get_info( p_tbm_surface, &tbm_surface_info ) )
1210 tbm_surface_destroy( p_tbm_surface );
1211 p_tbm_surface = NULL;
1214 if( !p_tbm_surface )
1216 sys->i_nb_buffers = i;
1217 break;
1219 p_buffer->p_tbm_surface = p_tbm_surface;
1220 TbmSurfaceBufferLock( p_buffer );
1223 sys->i_nb_planes = tbm_surface_info.num_planes;
1224 for( unsigned i = 0; i < tbm_surface_info.num_planes; ++i )
1226 sys->p_planes[i].i_lines = tbm_surface_info.planes[i].size
1227 / tbm_surface_info.planes[i].stride;
1228 sys->p_planes[i].i_visible_lines = sys->p_planes[i].i_lines;
1229 sys->p_planes[i].i_pitch = tbm_surface_info.planes[i].stride;
1230 sys->p_planes[i].i_visible_pitch = sys->p_planes[i].i_pitch;
1233 return 0;
1236 static int
1237 TbmSurfaceBuffersAlloc( vout_display_t *vd, video_format_t *p_fmt )
1239 (void) p_fmt;
1240 return EcoreMainLoopCallSync( vd, TbmSurfaceBuffersAllocMainloopCb );
1243 static int
1244 TbmSurfaceSetup( vout_display_t *vd )
1246 vout_display_sys_t *sys = vd->sys;
1247 tbm_format i_tbm_format = 0;
1248 bool b_found = false;
1249 uint32_t *p_formats;
1250 uint32_t i_format_num;
1252 for( unsigned int i = 0; i < TBM_FORMAT_TO_VLC_LIST_COUNT; ++i )
1254 if( tbm_format_to_vlc_list[i].i_vlc_chroma == vd->fmt.i_chroma )
1256 i_tbm_format = tbm_format_to_vlc_list[i].i_tbm_format;
1257 break;
1260 if( !i_tbm_format )
1262 msg_Err( vd, "no tbm format found" );
1263 return -1;
1266 if( tbm_surface_query_formats( &p_formats, &i_format_num ) )
1268 msg_Warn( vd, "tbm_surface_query_formats failed" );
1269 return -1;
1272 for( unsigned int i = 0; i < i_format_num; i++ )
1274 if( p_formats[i] == i_tbm_format )
1276 b_found = true;
1277 break;
1280 if( !b_found )
1282 if( i_tbm_format != TBM_FORMAT_YUV420 )
1284 msg_Warn( vd, "vlc format not matching any tbm format: trying with I420");
1285 i_tbm_format = TBM_FORMAT_YUV420;
1286 for( uint32_t i = 0; i < i_format_num; i++ )
1288 if( p_formats[i] == i_tbm_format )
1290 vd->fmt.i_chroma = VLC_CODEC_I420;
1291 b_found = true;
1292 break;
1297 free( p_formats );
1299 if( !b_found )
1301 msg_Warn( vd, "can't find any compatible tbm format" );
1302 return -1;
1304 sys->u.tbm.i_format = i_tbm_format;
1306 switch( vd->fmt.orientation )
1308 case ORIENT_ROTATED_90:
1309 sys->u.tbm.i_angle = 270;
1310 break;
1311 case ORIENT_ROTATED_180:
1312 sys->u.tbm.i_angle = 180;
1313 break;
1314 case ORIENT_ROTATED_270:
1315 sys->u.tbm.i_angle = 90;
1316 break;
1317 default:
1318 sys->u.tbm.i_angle = 0;
1321 sys->b_apply_rotation = false;
1323 FmtUpdate( vd );
1325 vd->info.has_pictures_invalid = true;
1327 sys->pf_set_data = TbmSurfaceSetData;
1328 sys->pf_buffers_alloc = TbmSurfaceBuffersAlloc;
1329 sys->pf_buffers_free = TbmSurfaceBuffersFree;
1331 msg_Dbg( vd, "using tbm_surface" );
1333 return 0;
1335 #endif