summaryrefslogtreecommitdiff
path: root/src/modules/emotion/libvlc
diff options
context:
space:
mode:
authorThomas Guillem <thomas@gllm.fr>2016-03-25 09:05:38 +0100
committerJean-Philippe Andre <jp.andre@samsung.com>2016-03-28 16:40:02 +0900
commita6bd5dda420520a509fc1cee26e131a13401348f (patch)
tree1886264b09074ee64d417e94621c6c5ff9627fa8 /src/modules/emotion/libvlc
parent50d9f63c2e8e3773f3e433168c3b8020ac192ee4 (diff)
emotion/libvlc: use vlc vout display module
The vlc vout display module adds key and mouse event support. It improves performances since a video filter is not needed anymore to scale the image, and direct rendering with vlc avcodec module is now possible (less memcpy).
Diffstat (limited to 'src/modules/emotion/libvlc')
-rw-r--r--src/modules/emotion/libvlc/emotion_libvlc.c417
1 files changed, 70 insertions, 347 deletions
diff --git a/src/modules/emotion/libvlc/emotion_libvlc.c b/src/modules/emotion/libvlc/emotion_libvlc.c
index e256a56ec3..98f6fdfe67 100644
--- a/src/modules/emotion/libvlc/emotion_libvlc.c
+++ b/src/modules/emotion/libvlc/emotion_libvlc.c
@@ -39,8 +39,6 @@
39#endif 39#endif
40#define CRI(...) EINA_LOG_DOM_CRIT(_emotion_libvlc_log_domain, __VA_ARGS__) 40#define CRI(...) EINA_LOG_DOM_CRIT(_emotion_libvlc_log_domain, __VA_ARGS__)
41 41
42#define SINK_MAX_PLANES 3
43
44static int _emotion_libvlc_log_domain = -1; 42static int _emotion_libvlc_log_domain = -1;
45static Eina_Bool debug_fps = EINA_FALSE; 43static Eina_Bool debug_fps = EINA_FALSE;
46static libvlc_instance_t *libvlc = NULL; 44static libvlc_instance_t *libvlc = NULL;
@@ -68,6 +66,7 @@ struct _Emotion_LibVLC
68 66
69 /* options */ 67 /* options */
70 int video_mute; 68 int video_mute;
69 int video_mute_force;
71 int audio_mute; 70 int audio_mute;
72 int spu_mute; 71 int spu_mute;
73 int audio_vol; 72 int audio_vol;
@@ -90,24 +89,12 @@ struct _Emotion_LibVLC
90 Eina_Bool seeking; 89 Eina_Bool seeking;
91 Eina_Bool started; 90 Eina_Bool started;
92 Eina_Bool invalidate_tracks; 91 Eina_Bool invalidate_tracks;
92};
93 93
94 /* sink, must be locked by ev->lock */ 94struct close_data
95 struct 95{
96 { 96 libvlc_media_player_t *mp;
97 int width; 97 Evas_Object *evas_obj;
98 int height;
99 Evas_Colorspace colorspace;
100 void *data;
101 Eina_Bool waiting;
102 Eina_Bool is_yuv;
103
104 unsigned int nb_planes;
105 unsigned int lines[SINK_MAX_PLANES];
106 unsigned int pitches[SINK_MAX_PLANES];
107 unsigned int yuv_height[SINK_MAX_PLANES];
108 unsigned char *yuv_data[SINK_MAX_PLANES];
109 unsigned int yuv_planes_order[SINK_MAX_PLANES];
110 } sink;
111}; 98};
112 99
113static const libvlc_event_type_t mp_events[] = { 100static const libvlc_event_type_t mp_events[] = {
@@ -178,119 +165,6 @@ emotion_mainloop_call_locked(Emotion_LibVLC *ev, Ecore_Cb callback)
178 ecore_main_loop_thread_safe_call_async(callback, ev); 165 ecore_main_loop_thread_safe_call_async(callback, ev);
179} 166}
180 167
181/* Take the ev->lock from a sink mainloop callback.
182 * Returns false if the ev object is destroyed or is there is no evas object. */
183static Eina_Bool
184emotion_mainloop_sink_lock(Emotion_LibVLC *ev)
185{
186 if (emotion_mainloop_lock(ev))
187 {
188 if (!ev->evas_obj)
189 {
190 eina_lock_release(&ev->lock);
191 return EINA_FALSE;
192 }
193 else
194 return EINA_TRUE;
195 }
196 else
197 return EINA_FALSE;
198}
199
200/* Release the ev->lock from a sink mainloop callback and signal that the
201 * callback is processed. */
202static void
203emotion_mainloop_sink_signal_unlock(Emotion_LibVLC *ev)
204{
205 ev->sink.waiting = EINA_FALSE;
206 eina_condition_signal(&ev->wait);
207 eina_lock_release(&ev->lock);
208}
209
210/* Send a sink mainloop callback and wait. */
211static void
212emotion_mainloop_sink_call_wait_locked(Emotion_LibVLC *ev, Ecore_Cb callback)
213{
214 ev->sink.waiting = EINA_TRUE;
215
216 emotion_mainloop_call_locked(ev, callback);
217
218 while (ev->evas_obj && ev->sink.waiting)
219 eina_condition_wait(&ev->wait);
220}
221
222/* Sink mainloop callback, sent by libvlc_video_on_lock. */
223static void
224emotion_mainloop_sink_pic_lock(void *data)
225{
226 Emotion_LibVLC *ev = data;
227 if (!emotion_mainloop_sink_lock(ev)) return;
228
229 ev->sink.data = evas_object_image_data_get(ev->evas_obj, 1);
230
231 emotion_mainloop_sink_signal_unlock(ev);
232}
233
234/* Sink mainloop callback, sent by libvlc_video_on_unlock. */
235static void
236emotion_mainloop_sink_pic_unlock(void *data)
237{
238 Emotion_LibVLC *ev = data;
239
240 if (!emotion_mainloop_sink_lock(ev)) return;
241
242 if (!ev->sink.data)
243 goto end;
244
245 if (ev->sink.is_yuv)
246 {
247 unsigned int i, j;
248 const unsigned char **rows = (const unsigned char **)ev->sink.data;
249
250 for (i = 0; i < ev->sink.nb_planes; ++i)
251 for (j = 0; j < ev->sink.yuv_height[i]; ++j)
252 *(rows++) = &ev->sink.yuv_data[i][j * ev->sink.pitches[i]];
253 }
254 evas_object_image_data_set(ev->evas_obj, ev->sink.data);
255 ev->sink.data = NULL;
256
257end:
258 emotion_mainloop_sink_signal_unlock(ev);
259}
260
261/* Sink mainloop callback, sent by libvlc_video_on_display. */
262static void
263emotion_mainloop_sink_display(void *data)
264{
265 Emotion_LibVLC *ev = data;
266
267 if (!emotion_mainloop_sink_lock(ev)) return;
268
269 evas_object_image_data_update_add(ev->evas_obj, 0, 0, ev->sink.width,
270 ev->sink.height);
271 _emotion_frame_new(ev->obj);
272
273 emotion_mainloop_sink_signal_unlock(ev);
274}
275
276/* Sink mainloop callback, sent by libvlc_video_on_format. */
277static void
278emotion_mainloop_sink_format(void *data)
279{
280 Emotion_LibVLC *ev = data;
281
282 if (!emotion_mainloop_sink_lock(ev)) return;
283
284 evas_object_image_pixels_get_callback_set(ev->evas_obj, NULL, NULL);
285 evas_object_image_alpha_set(ev->evas_obj, 0);
286 evas_object_image_colorspace_set(ev->evas_obj, ev->sink.colorspace);
287 evas_object_image_size_set(ev->evas_obj, ev->sink.width, ev->sink.height);
288 _emotion_frame_resize(ev->obj, ev->sink.width, ev->sink.height,
289 ev->sink.width / (double)ev->sink.height);
290
291 emotion_mainloop_sink_signal_unlock(ev);
292}
293
294/* Process one libvlc event from the mainloop. */ 168/* Process one libvlc event from the mainloop. */
295static void 169static void
296emotion_mainloop_event(Emotion_LibVLC *ev, const libvlc_event_t *event) 170emotion_mainloop_event(Emotion_LibVLC *ev, const libvlc_event_t *event)
@@ -369,190 +243,6 @@ emotion_mainloop_event_list(void *data)
369 } 243 }
370} 244}
371 245
372/* Libvlc callback, see libvlc_video_set_callbacks and libvlc_video_lock_cb. */
373static void *
374libvlc_video_on_lock(void *opaque, void **pixels)
375{
376 Emotion_LibVLC *ev = opaque;
377
378 eina_lock_take(&ev->lock);
379 if (!ev->evas_obj) goto end;
380
381 emotion_mainloop_sink_call_wait_locked(ev, emotion_mainloop_sink_pic_lock);
382end:
383 if (ev->sink.data)
384 {
385 if (ev->sink.is_yuv)
386 {
387 unsigned int i;
388
389 for (i = 0; i < ev->sink.nb_planes; ++i)
390 pixels[i] = ev->sink.yuv_data[ev->sink.yuv_planes_order[i]];
391 }
392 else
393 pixels[0] = ev->sink.data;
394 }
395 eina_lock_release(&ev->lock);
396
397 return NULL;
398}
399
400/* Libvlc callback, see libvlc_video_set_callbacks and libvlc_video_unlock_cb.
401 * */
402static void
403libvlc_video_on_unlock(void *opaque, void *picture EINA_UNUSED,
404 void *const *pixels EINA_UNUSED)
405{
406 Emotion_LibVLC *ev = opaque;
407
408 eina_lock_take(&ev->lock);
409 if (!ev->evas_obj) goto end;
410
411 emotion_mainloop_sink_call_wait_locked(ev, emotion_mainloop_sink_pic_unlock);
412end:
413 eina_lock_release(&ev->lock);
414}
415
416/* Libvlc callback, see libvlc_video_set_callbacks and libvlc_video_display_cb.
417 * */
418static void
419libvlc_video_on_display(void *opaque, void *picture EINA_UNUSED)
420{
421 Emotion_LibVLC *ev = opaque;
422
423 eina_lock_take(&ev->lock);
424 if (!ev->evas_obj) goto end;
425
426 emotion_mainloop_sink_call_wait_locked(ev, emotion_mainloop_sink_display);
427end:
428 eina_lock_release(&ev->lock);
429}
430
431#define ALIGN32(x) (((x) + 31) & ~(31))
432
433/* Libvlc callback, see libvlc_video_set_format_callbacks and
434 * libvlc_video_format_cb. */
435static unsigned int
436libvlc_video_on_format(void **opaque, char *chroma,
437 unsigned int *width, unsigned int *height,
438 unsigned int *pitches,
439 unsigned int *lines)
440{
441 Emotion_LibVLC *ev = *opaque;
442
443 eina_lock_take(&ev->lock);
444 if (!ev->evas_obj) goto end;
445
446 INF("request video format: %s, size: %dx%d", chroma, *width, *height);
447
448 ev->sink.width = *width;
449 ev->sink.height = *height;
450
451 if (!strcmp(chroma, "RV32"))
452 {
453 ev->sink.colorspace = EVAS_COLORSPACE_ARGB8888;
454 ev->sink.nb_planes = 1;
455 ev->sink.lines[0] = ev->sink.height;
456 ev->sink.pitches[0] = ev->sink.width * 4;
457 }
458 /* Not implemented yet */
459#if 0
460 else if (!strcmp(chroma, "RV16"))
461 {
462 ev->sink.colorspace = EVAS_COLORSPACE_RGB565_A5P;
463 ev->sink.nb_planes = 1;
464 ev->sink.lines[0] = ev->sink.height;
465 ev->sink.pitches[0] = ev->sink.width * 2;
466 }
467#endif
468 else
469 {
470 /* YUV */
471
472 unsigned int i;
473
474 /* default planes order */
475 for (i = 0; i < ev->sink.nb_planes; ++i)
476 ev->sink.yuv_planes_order[i] = i;
477
478 if (!strcmp(chroma, "YUY2"))
479 {
480 ev->sink.colorspace = EVAS_COLORSPACE_YCBCR422601_PL;
481 ev->sink.nb_planes = 1;
482 ev->sink.yuv_height[0] = ev->sink.height;
483 ev->sink.pitches[0] = ev->sink.width * 2;
484 }
485 /* FIXME: SIGSEGV in evas_gl_common_texture_nv12_update */
486#if 0
487 else if (!strcmp(chroma, "NV12"))
488 {
489 ev->sink.colorspace = EVAS_COLORSPACE_YCBCR420NV12601_PL;
490 ev->sink.nb_planes = 2;
491 ev->sink.yuv_height[0] = ev->sink.height;
492 ev->sink.pitches[0] = ev->sink.width;
493 ev->sink.yuv_height[1] = ev->sink.height / 2;
494 ev->sink.pitches[1] = ev->sink.width;
495 }
496#endif
497 else
498 {
499 /* YV12 or I420 */
500 if (strcmp(chroma, "YV12") && strcmp(chroma, "I420"))
501 {
502 strcpy(chroma, "I420");
503 INF("native format not available, using: %s", chroma);
504 }
505 ev->sink.colorspace = EVAS_COLORSPACE_YCBCR422P601_PL;
506 ev->sink.nb_planes = 3;
507 ev->sink.yuv_height[0] = ev->sink.height;
508 ev->sink.pitches[0] = ev->sink.width;
509 ev->sink.yuv_height[1] = ev->sink.yuv_height[2] = ev->sink.height / 2;
510 ev->sink.pitches[1] = ev->sink.pitches[2] = ev->sink.width / 2;
511
512 if (!strcmp(chroma, "YV12"))
513 {
514 /* Cb and Cr inverted for YV12 */
515 ev->sink.yuv_planes_order[0] = 0;
516 ev->sink.yuv_planes_order[1] = 2;
517 ev->sink.yuv_planes_order[2] = 1;
518 }
519 }
520
521 assert(ev->sink.nb_planes <= SINK_MAX_PLANES);
522
523 /* Align pitches/lines and alloc planes */
524 for (i = 0; i < ev->sink.nb_planes; ++i)
525 {
526 ev->sink.lines[i] = ALIGN32(ev->sink.yuv_height[i]);
527 ev->sink.pitches[i] = ALIGN32(ev->sink.pitches[i]);
528 ev->sink.yuv_data[i] = malloc(ev->sink.lines[i]
529 * ev->sink.pitches[i]);
530 if (!ev->sink.yuv_data[i])
531 {
532 for (i = 0; i < ev->sink.nb_planes; ++i)
533 {
534 free(ev->sink.yuv_data[i]);
535 ev->sink.lines[i] = 0;
536 ev->sink.pitches[i] = 0;
537 }
538 ev->sink.nb_planes = 0;
539 goto end;
540 }
541 }
542 ev->sink.is_yuv = EINA_TRUE;
543 }
544
545 assert(ev->sink.nb_planes > 0);
546
547 memcpy(lines, ev->sink.lines, ev->sink.nb_planes * sizeof(unsigned int));
548 memcpy(pitches, ev->sink.pitches, ev->sink.nb_planes * sizeof(unsigned int));
549
550 emotion_mainloop_sink_call_wait_locked(ev, emotion_mainloop_sink_format);
551end:
552 eina_lock_release(&ev->lock);
553 return ev->sink.nb_planes;
554}
555
556/* Libvlc callback, see libvlc_event_manager_t. */ 246/* Libvlc callback, see libvlc_event_manager_t. */
557static void 247static void
558libvlc_on_mp_event(const libvlc_event_t *event, void *opaque) 248libvlc_on_mp_event(const libvlc_event_t *event, void *opaque)
@@ -581,6 +271,18 @@ libvlc_on_mp_event(const libvlc_event_t *event, void *opaque)
581 } 271 }
582} 272}
583 273
274static void
275evas_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
276 void *event EINA_UNUSED)
277{
278 Emotion_LibVLC *ev = data;
279 int w, h;
280
281 evas_object_image_size_get(ev->evas_obj, &w, &h);
282 _emotion_frame_resize(ev->obj, w, h, w / (double) h);
283 eo_event_callback_call(ev->obj, EMOTION_OBJECT_EVENT_FRAME_DECODE, NULL);
284}
285
584/* Returns true if libvlc mediaplayer is ready to process commands. */ 286/* Returns true if libvlc mediaplayer is ready to process commands. */
585static Eina_Bool 287static Eina_Bool
586libvlc_mp_is_ready(Emotion_LibVLC *ev) 288libvlc_mp_is_ready(Emotion_LibVLC *ev)
@@ -746,6 +448,8 @@ em_file_open(void *video,
746 ev->opt.no_video = EINA_TRUE; 448 ev->opt.no_video = EINA_TRUE;
747 } 449 }
748 450
451 evas_object_image_pixels_get_callback_set(ev->evas_obj, NULL, NULL);
452
749 ev->invalidate_tracks = true; 453 ev->invalidate_tracks = true;
750 454
751 /* Create libvlc_media */ 455 /* Create libvlc_media */
@@ -772,11 +476,16 @@ em_file_open(void *video,
772 libvlc_media_player_set_video_title_display(ev->mp, 476 libvlc_media_player_set_video_title_display(ev->mp,
773 libvlc_position_disable, 0); 477 libvlc_position_disable, 0);
774 478
775 /* Set sink callbacks */ 479 evas_object_ref(ev->evas_obj);
776 libvlc_video_set_format_callbacks(ev->mp, libvlc_video_on_format, NULL); 480 if (libvlc_media_player_set_evas_object(ev->mp, ev->evas_obj) == -1)
777 libvlc_video_set_callbacks(ev->mp, libvlc_video_on_lock, 481 {
778 libvlc_video_on_unlock, 482 CRI("libvlc_media_player_set_evas_object failed");
779 libvlc_video_on_display, ev); 483 libvlc_media_add_option(ev->m, ":no-video");
484 ev->video_mute = ev->video_mute_force = 1;
485 }
486
487 evas_object_event_callback_add(ev->evas_obj, EVAS_CALLBACK_IMAGE_RESIZE,
488 evas_resize_cb, ev);
780 489
781 if (ev->audio_vol != -1) 490 if (ev->audio_vol != -1)
782 libvlc_audio_set_volume(ev->mp, ev->audio_vol); 491 libvlc_audio_set_volume(ev->mp, ev->audio_vol);
@@ -791,6 +500,25 @@ error:
791} 500}
792 501
793static void 502static void
503emotion_close_cb(void *data, Ecore_Thread *thread EINA_UNUSED)
504{
505 struct close_data *close_data = data;
506
507 libvlc_media_player_release(close_data->mp);
508}
509
510static void
511emotion_close_mainloop_cb(void *data,
512 Ecore_Thread *thread EINA_UNUSED)
513{
514 struct close_data *close_data = data;
515
516 evas_object_unref(close_data->evas_obj);
517 free(close_data);
518 _emotion_pending_ecore_end();
519}
520
521static void
794em_file_close(void *video) 522em_file_close(void *video)
795{ 523{
796 Emotion_LibVLC *ev = video; 524 Emotion_LibVLC *ev = video;
@@ -798,19 +526,30 @@ em_file_close(void *video)
798 526
799 if (ev->mp) 527 if (ev->mp)
800 { 528 {
529 struct close_data *close_data;
801 libvlc_event_manager_t *event_m; 530 libvlc_event_manager_t *event_m;
802 531
532 evas_object_event_callback_del(ev->evas_obj, EVAS_CALLBACK_IMAGE_RESIZE,
533 evas_resize_cb);
534
803 event_m = libvlc_media_player_event_manager(ev->mp); 535 event_m = libvlc_media_player_event_manager(ev->mp);
804 for (i = 0; mp_events[i] != -1; ++i) 536 for (i = 0; mp_events[i] != -1; ++i)
805 libvlc_event_detach(event_m, mp_events[i], libvlc_on_mp_event, ev); 537 libvlc_event_detach(event_m, mp_events[i], libvlc_on_mp_event, ev);
806 538
807 /* Abort libvlc callbacks */ 539 libvlc_media_player_set_evas_object(ev->mp, NULL);
808 eina_lock_take(&ev->lock); 540
809 ev->evas_obj = NULL; 541 close_data = malloc(sizeof(struct close_data));
810 eina_condition_signal(&ev->wait); 542 if (close_data)
811 eina_lock_release(&ev->lock); 543 {
544 close_data->evas_obj = ev->evas_obj;
545 close_data->mp = ev->mp;
546 _emotion_pending_ecore_begin();
547 ecore_thread_run(emotion_close_cb,
548 emotion_close_mainloop_cb,
549 NULL, close_data);
550 }
812 551
813 libvlc_media_player_release(ev->mp); 552 ev->evas_obj = NULL;
814 ev->mp = NULL; 553 ev->mp = NULL;
815 554
816 if (ev->seeking) 555 if (ev->seeking)
@@ -818,23 +557,6 @@ em_file_close(void *video)
818 ev->seeking = EINA_FALSE; 557 ev->seeking = EINA_FALSE;
819 _emotion_seek_done(ev->obj); 558 _emotion_seek_done(ev->obj);
820 } 559 }
821 if (ev->sink.data)
822 {
823 /* unlock already locked buffer */
824 evas_object_image_data_set(ev->evas_obj, ev->sink.data);
825 ev->sink.data = NULL;
826 }
827
828 /* free image data */
829 evas_object_image_size_set(ev->evas_obj, 1, 1);
830 evas_object_image_data_set(ev->evas_obj, NULL);
831
832 /* free yuv data */
833 if (ev->sink.is_yuv)
834 {
835 for (i = 0; i < ev->sink.nb_planes; ++i)
836 free(ev->sink.yuv_data[i]);
837 }
838 } 560 }
839 if (ev->m) 561 if (ev->m)
840 { 562 {
@@ -866,7 +588,6 @@ em_file_close(void *video)
866 ev->vis = EMOTION_VIS_NONE; 588 ev->vis = EMOTION_VIS_NONE;
867 ev->started = ev->seeking = ev->invalidate_tracks = EINA_FALSE; 589 ev->started = ev->seeking = ev->invalidate_tracks = EINA_FALSE;
868 ev->pos = ev->len = ev->buffer_cache = 0.0; 590 ev->pos = ev->len = ev->buffer_cache = 0.0;
869 memset(&ev->sink, 0, sizeof(ev->sink));
870} 591}
871 592
872static void 593static void
@@ -1171,13 +892,13 @@ em_event_feed(void *video, int event)
1171static void 892static void
1172em_event_mouse_button_feed(void *video EINA_UNUSED, int button EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED) 893em_event_mouse_button_feed(void *video EINA_UNUSED, int button EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED)
1173{ 894{
1174 /* FIXME */ 895 /* Handled directly by VLC evas vout module */
1175} 896}
1176 897
1177static void 898static void
1178em_event_mouse_move_feed(void *video EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED) 899em_event_mouse_move_feed(void *video EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED)
1179{ 900{
1180 /* FIXME */ 901 /* Handled directly by VLC evas vout module */
1181} 902}
1182 903
1183static int 904static int
@@ -1265,6 +986,8 @@ em_video_channel_mute_set(void *video,
1265{ 986{
1266 Emotion_LibVLC *ev = video; 987 Emotion_LibVLC *ev = video;
1267 988
989 if (ev->video_mute_force)
990 return;
1268 ev->video_mute = mute; 991 ev->video_mute = mute;
1269 992
1270 if (libvlc_mp_is_ready(ev)) 993 if (libvlc_mp_is_ready(ev))