videotoolbox: rework >= 10bit output handling
[vlc.git] / doc / libvlc / vlc-thumb.c
bloba63307379ce718de23274e5fbc0399afdd6b16e5
1 /* Copyright Rafaël Carré (licence WTFPL) */
2 /* A video thumbnailer compatible with nautilus */
3 /* Copyright © 2007-2011 Rafaël Carré <funman@videolanorg> */
5 /* Works with : libvlc 2.0.0
6 gcc -pedantic -Wall -Werror -Wextra `pkg-config --cflags --libs libvlc` -lpthread
8 # to register the thumbnailer on gnome 3.x:
9 cp vlc-thumb.thumbnailer /usr/share/thumbnailers
11 # to register the thumbnailer on gnome 2.x:
12 list=`grep ^Mime vlc.desktop|cut -d= -f2-|sed -e s/";"/\\\n/g -e s,/,@,g`
13 vid=`echo $mimes|grep ^vid`
14 for i in $vid
15 do
16 key=/desktop/gnome/thumbnailers/$i/enable
17 gconftool-2 -t boolean -s $key true
18 gconftool-2 -t string -s $key "vlc-thumb -s %s %u %o"
19 done
22 #include <assert.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <locale.h>
28 #include <pthread.h>
29 #include <errno.h>
30 #include <time.h>
32 #if !defined (_POSIX_CLOCK_SELECTION)
33 # define _POSIX_CLOCK_SELECTION (-1)
34 #endif
36 #if (_POSIX_CLOCK_SELECTION < 0)
37 # error Clock selection is not available!
38 #endif
40 #include <vlc/vlc.h>
42 /* position at which the snapshot is taken */
43 #define VLC_THUMBNAIL_POSITION (30./100.)
45 static void usage(const char *name, int ret)
47 fprintf(stderr, "Usage: %s [-s width] <video> <output.png>\n", name);
48 exit(ret);
51 /* extracts options from command line */
52 static void cmdline(int argc, const char **argv, const char **in,
53 char **out, char **out_with_ext, int *w)
55 int idx = 1;
56 size_t len;
58 if (argc != 3 && argc != 5)
59 usage(argv[0], argc != 2 || strcmp(argv[1], "-h"));
61 *w = 0;
63 if (argc == 5) {
64 if (strcmp(argv[1], "-s"))
65 usage(argv[0], 1);
67 idx += 2; /* skip "-s width" */
68 *w = atoi(argv[2]);
71 *in = argv[idx++];
72 *out = strdup(argv[idx++]);
73 if (!*out)
74 abort();
76 len = strlen(*out);
77 if (len >= 4 && !strcmp(*out + len - 4, ".png")) {
78 *out_with_ext = *out;
79 return;
82 /* We need to add .png extension to filename,
83 * VLC relies on it to detect output format,
84 * and nautilus doesn't give filenames ending in .png */
86 *out_with_ext = malloc(len + sizeof ".png");
87 if (!*out_with_ext)
88 abort();
89 strcpy(*out_with_ext, *out);
90 strcat(*out_with_ext, ".png");
93 static libvlc_instance_t *create_libvlc(void)
95 static const char* const args[] = {
96 "--intf", "dummy", /* no interface */
97 "--vout", "dummy", /* we don't want video (output) */
98 "--no-audio", /* we don't want audio (decoding) */
99 "--no-video-title-show", /* nor the filename displayed */
100 "--no-stats", /* no stats */
101 "--no-sub-autodetect-file", /* we don't want subtitles */
102 "--no-inhibit", /* we don't want interfaces */
103 "--no-disable-screensaver", /* we don't want interfaces */
104 "--no-snapshot-preview", /* no blending in dummy vout */
105 #ifndef NDEBUG
106 "--verbose=2", /* full log */
107 #endif
110 return libvlc_new(sizeof args / sizeof *args, args);
113 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
114 static pthread_cond_t wait;
115 static bool done;
117 static void callback(const libvlc_event_t *ev, void *param)
119 float new_position;
120 (void)param;
122 pthread_mutex_lock(&lock);
123 switch (ev->type) {
124 case libvlc_MediaPlayerPositionChanged:
125 new_position = ev->u.media_player_position_changed.new_position;
126 if (new_position < VLC_THUMBNAIL_POSITION * .9 /* 90% margin */)
127 break;
128 case libvlc_MediaPlayerSnapshotTaken:
129 done = true;
130 pthread_cond_signal(&wait);
131 break;
133 default:
134 assert(0);
136 pthread_mutex_unlock(&lock);
139 static void event_wait(const char *error)
141 int ret;
142 struct timespec ts;
143 #define VLC_THUMBNAIL_TIMEOUT 5 /* 5 secs */
145 clock_gettime(CLOCK_MONOTONIC, &ts);
146 ts.tv_sec += VLC_THUMBNAIL_TIMEOUT;
147 pthread_mutex_lock(&lock);
148 ret = done ? 0 : pthread_cond_timedwait(&wait, &lock, &ts);
149 pthread_mutex_unlock(&lock);
151 assert(!ret || ret == ETIMEDOUT);
153 if (ret) {
154 fprintf(stderr,
155 "%s (timeout after %d secs!\n", error, VLC_THUMBNAIL_TIMEOUT);
156 exit(1);
160 static void set_position(libvlc_media_player_t *mp)
162 libvlc_event_manager_t *em = libvlc_media_player_event_manager(mp);
163 assert(em);
165 libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, callback, NULL);
166 done = false;
167 libvlc_media_player_set_position(mp, VLC_THUMBNAIL_POSITION);
168 event_wait("Couldn't set position");
169 libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, callback, NULL);
172 static void snapshot(libvlc_media_player_t *mp, int width, char *out_with_ext)
174 libvlc_event_manager_t *em = libvlc_media_player_event_manager(mp);
175 assert(em);
177 libvlc_event_attach(em, libvlc_MediaPlayerSnapshotTaken, callback, NULL);
178 done = false;
179 libvlc_video_take_snapshot(mp, 0, out_with_ext, width, 0);
180 event_wait("Snapshot has not been written");
181 libvlc_event_detach(em, libvlc_MediaPlayerSnapshotTaken, callback, NULL);
184 int main(int argc, const char **argv)
186 const char *in;
187 char *out, *out_with_ext;
188 int width;
189 pthread_condattr_t attr;
190 libvlc_instance_t *libvlc;
191 libvlc_media_player_t *mp;
192 libvlc_media_t *m;
194 /* mandatory to support UTF-8 filenames (provided the locale is well set)*/
195 setlocale(LC_ALL, "");
197 cmdline(argc, argv, &in, &out, &out_with_ext, &width);
199 pthread_condattr_init(&attr);
200 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
201 pthread_cond_init(&wait, &attr);
202 pthread_condattr_destroy(&attr);
204 /* starts vlc */
205 libvlc = create_libvlc();
206 assert(libvlc);
208 m = libvlc_media_new_path(libvlc, in);
209 assert(m);
211 mp = libvlc_media_player_new_from_media(m);
212 assert(mp);
214 libvlc_media_player_play(mp);
216 /* takes snapshot */
217 set_position(mp);
218 snapshot(mp, width, out_with_ext);
220 libvlc_media_player_stop_async(mp);
222 /* clean up */
223 if (out != out_with_ext) {
224 rename(out_with_ext, out);
225 free(out_with_ext);
227 free(out);
229 libvlc_media_player_release(mp);
230 libvlc_media_release(m);
231 libvlc_release(libvlc);
233 pthread_cond_destroy(&wait);
235 return 0;