From 317f07804c2ce93be7ccb7af188a0c07476efea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?= Date: Tue, 14 Jun 2011 23:25:25 -0400 Subject: [PATCH] vlc-thumb: use pthread conditions Also use a static boolean if the condition has been signaled before we start waiting on it: libvlc_MediaPlayerSnapshotTaken event is serialized with libvlc_video_take_snapshot() so when the function returns the event already happened. --- doc/libvlc/vlc-thumb.c | 83 ++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/doc/libvlc/vlc-thumb.c b/doc/libvlc/vlc-thumb.c index c373f99d21..1a0365ef34 100644 --- a/doc/libvlc/vlc-thumb.c +++ b/doc/libvlc/vlc-thumb.c @@ -3,7 +3,7 @@ /* Copyright © 2007-2011 Rafaël Carré */ /* Works with : libvlc 1.2.0 - gcc -pedantic -Wall -Werror -Wextra `pkg-config --cflags --libs libvlc` + gcc -pedantic -Wall -Werror -Wextra `pkg-config --cflags --libs libvlc` -lpthread # to register the thumbnailer: list=`grep ^Mime vlc.desktop|cut -d= -f2-|sed -e s/";"/\\\n/g -e s,/,@,g` @@ -22,6 +22,17 @@ #include #include #include +#include +#include +#include + +#if !defined (_POSIX_CLOCK_SELECTION) +# define _POSIX_CLOCK_SELECTION (-1) +#endif + +#if (_POSIX_CLOCK_SELECTION < 0) +# error Clock selection is not available! +#endif #include @@ -96,67 +107,75 @@ static libvlc_instance_t *create_libvlc(void) return libvlc_new(sizeof args / sizeof *args, args); } +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t wait; +static bool done; + static void callback(const libvlc_event_t *ev, void *param) { - float new_position = ev->u.media_player_position_changed.new_position; + float new_position; + (void)param; + pthread_mutex_lock(&lock); switch (ev->type) { - case libvlc_MediaPlayerPositionChanged: - if (new_position >= VLC_THUMBNAIL_POSITION * .9) { /* 90% margin */ - *(int*)param = 1; - } - break; + new_position = ev->u.media_player_position_changed.new_position; + if (new_position < VLC_THUMBNAIL_POSITION * .9 /* 90% margin */) + break; case libvlc_MediaPlayerSnapshotTaken: - *(int*)param = 1; + done = true; + pthread_cond_signal(&wait); break; default: assert(0); } + pthread_mutex_unlock(&lock); } -/* FIXME: should use pthread notification */ -static void event_wait(const char *error, int *f) +static void event_wait(const char *error) { + int ret; + struct timespec ts; #define VLC_THUMBNAIL_TIMEOUT 5.0 /* 5 secs */ -#define VLC_THUMBNAIL_LOOP_STEP 0.2 /* 200 ms */ - float max = VLC_THUMBNAIL_TIMEOUT; - while ((max -= VLC_THUMBNAIL_LOOP_STEP) > 0.) { - if (*f) - return; + clock_gettime(CLOCK_MONOTONIC, &ts); + ts.tv_sec += VLC_THUMBNAIL_TIMEOUT; + pthread_mutex_lock(&lock); + ret = done ? 0 : pthread_cond_timedwait(&wait, &lock, &ts); + pthread_mutex_unlock(&lock); - usleep(VLC_THUMBNAIL_LOOP_STEP * 1000000); - } + assert(!ret || ret == ETIMEDOUT); - fprintf(stderr, - "%s (timeout after %.2f secs!\n", error, VLC_THUMBNAIL_TIMEOUT); - exit(1); + if (ret) { + fprintf(stderr, + "%s (timeout after %.2f secs!\n", error, VLC_THUMBNAIL_TIMEOUT); + exit(1); + } } static void set_position(libvlc_media_player_t *mp) { - int f = 0; libvlc_event_manager_t *em = libvlc_media_player_event_manager(mp); assert(em); - libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, callback, &f); + libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, callback, NULL); + done = false; libvlc_media_player_set_position(mp, VLC_THUMBNAIL_POSITION); - event_wait("Couldn't set position", &f); - libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, callback, &f); + event_wait("Couldn't set position"); + libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, callback, NULL); } static void snapshot(libvlc_media_player_t *mp, int width, char *out_with_ext) { - int f = 0; libvlc_event_manager_t *em = libvlc_media_player_event_manager(mp); assert(em); - libvlc_event_attach(em, libvlc_MediaPlayerSnapshotTaken, callback, &f); + libvlc_event_attach(em, libvlc_MediaPlayerSnapshotTaken, callback, NULL); + done = false; libvlc_video_take_snapshot(mp, 0, out_with_ext, width, 0); - event_wait("Snapshot has not been written", &f); - libvlc_event_detach(em, libvlc_MediaPlayerSnapshotTaken, callback, &f); + event_wait("Snapshot has not been written"); + libvlc_event_detach(em, libvlc_MediaPlayerSnapshotTaken, callback, NULL); } int main(int argc, const char **argv) @@ -164,6 +183,7 @@ int main(int argc, const char **argv) const char *in; char *out, *out_with_ext; int width; + pthread_condattr_t attr; libvlc_instance_t *libvlc; libvlc_media_player_t *mp; libvlc_media_t *m; @@ -173,6 +193,11 @@ int main(int argc, const char **argv) cmdline(argc, argv, &in, &out, &out_with_ext, &width); + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&wait, &attr); + pthread_condattr_destroy(&attr); + /* starts vlc */ libvlc = create_libvlc(); assert(libvlc); @@ -202,5 +227,7 @@ int main(int argc, const char **argv) libvlc_media_release(m); libvlc_release(libvlc); + pthread_cond_destroy(&wait); + return 0; }