1 /*
2  * Copyright (c) 2013 Andrew Kelley
3  *
4  * This file is part of libgroove, which is MIT licensed.
5  * See http://opensource.org/licenses/MIT
6  */
7 
8 #include "fingerprinter.h"
9 #include <groove/queue.h>
10 
11 #include <chromaprint.h>
12 
13 #include <libavutil/mem.h>
14 #include <libavutil/log.h>
15 
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <pthread.h>
20 
21 struct GrooveFingerprinterPrivate {
22     struct GrooveFingerprinter externals;
23 
24     int state_history_count;
25 
26     // index into all_track_states
27     struct GrooveSink *sink;
28     struct GrooveQueue *info_queue;
29     pthread_t thread_id;
30 
31     // info_head_mutex applies to variables inside this block.
32     pthread_mutex_t info_head_mutex;
33     char info_head_mutex_inited;
34     // current playlist item pointer
35     struct GroovePlaylistItem *info_head;
36     double info_pos;
37     // analyze_thread waits on this when the info queue is full
38     pthread_cond_t drain_cond;
39     char drain_cond_inited;
40     // how many items are in the queue
41     int info_queue_count;
42     double track_duration;
43     double album_duration;
44 
45     ChromaprintContext *chroma_ctx;
46 
47     // set temporarily
48     struct GroovePlaylistItem *purge_item;
49 
50     int abort_request;
51 };
52 
emit_track_info(struct GrooveFingerprinterPrivate * p)53 static int emit_track_info(struct GrooveFingerprinterPrivate *p) {
54     struct GrooveFingerprinterInfo *info = av_mallocz(sizeof(struct GrooveFingerprinterInfo));
55     if (!info) {
56         av_log(NULL, AV_LOG_ERROR, "unable to allocate fingerprinter info\n");
57         return -1;
58     }
59     info->item = p->info_head;
60     info->duration = p->track_duration;
61 
62     if (!chromaprint_finish(p->chroma_ctx)) {
63         av_log(NULL, AV_LOG_ERROR, "unable to finish chromaprint\n");
64         return -1;
65     }
66     if (!chromaprint_get_raw_fingerprint(p->chroma_ctx,
67 #if CHROMAPRINT_VERSION_MAJOR > 1 || CHROMAPRINT_VERSION_MINOR >= 4
68                 (uint32_t**)&info->fingerprint, &info->fingerprint_size))
69 #else
70                 (void**)&info->fingerprint, &info->fingerprint_size))
71 #endif
72     {
73         av_log(NULL, AV_LOG_ERROR, "unable to get fingerprint\n");
74         return -1;
75     }
76 
77     groove_queue_put(p->info_queue, info);
78 
79     return 0;
80 }
81 
print_thread(void * arg)82 static void *print_thread(void *arg) {
83     struct GrooveFingerprinterPrivate *p = arg;
84     struct GrooveFingerprinter *printer = &p->externals;
85 
86     struct GrooveBuffer *buffer;
87     while (!p->abort_request) {
88         pthread_mutex_lock(&p->info_head_mutex);
89 
90         if (p->info_queue_count >= printer->info_queue_size) {
91             pthread_cond_wait(&p->drain_cond, &p->info_head_mutex);
92             pthread_mutex_unlock(&p->info_head_mutex);
93             continue;
94         }
95 
96         // we definitely want to unlock the mutex while we wait for the
97         // next buffer. Otherwise there will be a deadlock when sink_flush or
98         // sink_purge is called.
99         pthread_mutex_unlock(&p->info_head_mutex);
100 
101         int result = groove_sink_buffer_get(p->sink, &buffer, 1);
102 
103         pthread_mutex_lock(&p->info_head_mutex);
104 
105         if (result == GROOVE_BUFFER_END) {
106             // last file info
107             emit_track_info(p);
108 
109             // send album info
110             struct GrooveFingerprinterInfo *info = av_mallocz(
111                     sizeof(struct GrooveFingerprinterInfo));
112             if (info) {
113                 info->duration = p->album_duration;
114                 groove_queue_put(p->info_queue, info);
115             } else {
116                 av_log(NULL, AV_LOG_ERROR, "unable to allocate album fingerprint info\n");
117             }
118 
119             p->album_duration = 0.0;
120 
121             p->info_head = NULL;
122             p->info_pos = -1.0;
123 
124             pthread_mutex_unlock(&p->info_head_mutex);
125             continue;
126         }
127 
128         if (result != GROOVE_BUFFER_YES) {
129             pthread_mutex_unlock(&p->info_head_mutex);
130             break;
131         }
132 
133         if (buffer->item != p->info_head) {
134             if (p->info_head) {
135                 emit_track_info(p);
136             }
137             if (!chromaprint_start(p->chroma_ctx, 44100, 2)) {
138                 av_log(NULL, AV_LOG_ERROR, "unable to start fingerprint\n");
139             }
140             p->track_duration = 0.0;
141             p->info_head = buffer->item;
142             p->info_pos = buffer->pos;
143         }
144 
145         double buffer_duration = buffer->frame_count / (double)buffer->format.sample_rate;
146         p->track_duration += buffer_duration;
147         p->album_duration += buffer_duration;
148 #if CHROMAPRINT_VERSION_MAJOR > 1 || CHROMAPRINT_VERSION_MINOR >= 4
149         if (!chromaprint_feed(p->chroma_ctx, (const int16_t*)buffer->data[0], buffer->frame_count * 2)) {
150 #else
151         if (!chromaprint_feed(p->chroma_ctx, buffer->data[0], buffer->frame_count * 2)) {
152 #endif
153             av_log(NULL, AV_LOG_ERROR, "unable to feed fingerprint\n");
154         }
155 
156         pthread_mutex_unlock(&p->info_head_mutex);
157         groove_buffer_unref(buffer);
158     }
159 
160     return NULL;
161 }
162 
163 static void info_queue_cleanup(struct GrooveQueue* queue, void *obj) {
164     struct GrooveFingerprinterInfo *info = obj;
165     struct GrooveFingerprinterPrivate *p = queue->context;
166     p->info_queue_count -= 1;
167     av_free(info);
168 }
169 
170 static void info_queue_put(struct GrooveQueue *queue, void *obj) {
171     struct GrooveFingerprinterPrivate *p = queue->context;
172     p->info_queue_count += 1;
173 }
174 
175 static void info_queue_get(struct GrooveQueue *queue, void *obj) {
176     struct GrooveFingerprinterPrivate *p = queue->context;
177     struct GrooveFingerprinter *printer = &p->externals;
178 
179     p->info_queue_count -= 1;
180 
181     if (p->info_queue_count < printer->info_queue_size)
182         pthread_cond_signal(&p->drain_cond);
183 }
184 
185 static int info_queue_purge(struct GrooveQueue* queue, void *obj) {
186     struct GrooveFingerprinterInfo *info = obj;
187     struct GrooveFingerprinterPrivate *p = queue->context;
188 
189     return info->item == p->purge_item;
190 }
191 
192 static void sink_purge(struct GrooveSink *sink, struct GroovePlaylistItem *item) {
193     struct GrooveFingerprinterPrivate *p = sink->userdata;
194 
195     pthread_mutex_lock(&p->info_head_mutex);
196     p->purge_item = item;
197     groove_queue_purge(p->info_queue);
198     p->purge_item = NULL;
199 
200     if (p->info_head == item) {
201         p->info_head = NULL;
202         p->info_pos = -1.0;
203     }
204     pthread_cond_signal(&p->drain_cond);
205     pthread_mutex_unlock(&p->info_head_mutex);
206 }
207 
208 static void sink_flush(struct GrooveSink *sink) {
209     struct GrooveFingerprinterPrivate *p = sink->userdata;
210 
211     pthread_mutex_lock(&p->info_head_mutex);
212     groove_queue_flush(p->info_queue);
213     p->track_duration = 0.0;
214     p->info_head = NULL;
215     p->info_pos = -1.0;
216 
217     pthread_cond_signal(&p->drain_cond);
218     pthread_mutex_unlock(&p->info_head_mutex);
219 }
220 
221 struct GrooveFingerprinter *groove_fingerprinter_create(void) {
222     struct GrooveFingerprinterPrivate *p = av_mallocz(sizeof(struct GrooveFingerprinterPrivate));
223     if (!p) {
224         av_log(NULL, AV_LOG_ERROR, "unable to allocate fingerprinter\n");
225         return NULL;
226     }
227 
228     struct GrooveFingerprinter *printer = &p->externals;
229 
230     if (pthread_mutex_init(&p->info_head_mutex, NULL) != 0) {
231         groove_fingerprinter_destroy(printer);
232         av_log(NULL, AV_LOG_ERROR, "unable to create mutex\n");
233         return NULL;
234     }
235     p->info_head_mutex_inited = 1;
236 
237     if (pthread_cond_init(&p->drain_cond, NULL) != 0) {
238         groove_fingerprinter_destroy(printer);
239         av_log(NULL, AV_LOG_ERROR, "unable to create mutex condition\n");
240         return NULL;
241     }
242     p->drain_cond_inited = 1;
243 
244     p->info_queue = groove_queue_create();
245     if (!p->info_queue) {
246         groove_fingerprinter_destroy(printer);
247         av_log(NULL, AV_LOG_ERROR, "unable to allocate queue\n");
248         return NULL;
249     }
250     p->info_queue->context = printer;
251     p->info_queue->cleanup = info_queue_cleanup;
252     p->info_queue->put = info_queue_put;
253     p->info_queue->get = info_queue_get;
254     p->info_queue->purge = info_queue_purge;
255 
256     p->sink = groove_sink_create();
257     if (!p->sink) {
258         groove_fingerprinter_destroy(printer);
259         av_log(NULL, AV_LOG_ERROR, "unable to allocate sink\n");
260         return NULL;
261     }
262     p->sink->audio_format.sample_rate = 44100;
263     p->sink->audio_format.channel_layout = GROOVE_CH_LAYOUT_STEREO;
264     p->sink->audio_format.sample_fmt = GROOVE_SAMPLE_FMT_S16;
265     p->sink->userdata = printer;
266     p->sink->purge = sink_purge;
267     p->sink->flush = sink_flush;
268 
269     // set some defaults
270     printer->info_queue_size = INT_MAX;
271     printer->sink_buffer_size = p->sink->buffer_size;
272 
273     return printer;
274 }
275 
276 void groove_fingerprinter_destroy(struct GrooveFingerprinter *printer) {
277     if (!printer)
278         return;
279 
280     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
281 
282     if (p->sink)
283         groove_sink_destroy(p->sink);
284 
285     if (p->info_queue)
286         groove_queue_destroy(p->info_queue);
287 
288     if (p->info_head_mutex_inited)
289         pthread_mutex_destroy(&p->info_head_mutex);
290 
291     if (p->drain_cond_inited)
292         pthread_cond_destroy(&p->drain_cond);
293 
294     av_free(p);
295 }
296 
297 int groove_fingerprinter_attach(struct GrooveFingerprinter *printer,
298         struct GroovePlaylist *playlist)
299 {
300     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
301 
302     printer->playlist = playlist;
303     groove_queue_reset(p->info_queue);
304 
305     p->chroma_ctx = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT);
306     if (!p->chroma_ctx) {
307         groove_fingerprinter_detach(printer);
308         av_log(NULL, AV_LOG_ERROR, "unable to allocate chromaprint\n");
309         return -1;
310     }
311 
312     if (groove_sink_attach(p->sink, playlist) < 0) {
313         groove_fingerprinter_detach(printer);
314         av_log(NULL, AV_LOG_ERROR, "unable to attach sink\n");
315         return -1;
316     }
317 
318     if (pthread_create(&p->thread_id, NULL, print_thread, printer) != 0) {
319         groove_fingerprinter_detach(printer);
320         av_log(NULL, AV_LOG_ERROR, "unable to create printer thread\n");
321         return -1;
322     }
323 
324     return 0;
325 }
326 
327 int groove_fingerprinter_detach(struct GrooveFingerprinter *printer) {
328     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
329 
330     p->abort_request = 1;
331     groove_sink_detach(p->sink);
332     groove_queue_flush(p->info_queue);
333     groove_queue_abort(p->info_queue);
334     pthread_cond_signal(&p->drain_cond);
335     pthread_join(p->thread_id, NULL);
336 
337     printer->playlist = NULL;
338 
339     if (p->chroma_ctx) {
340         chromaprint_free(p->chroma_ctx);
341         p->chroma_ctx = NULL;
342     }
343 
344     p->abort_request = 0;
345     p->info_head = NULL;
346     p->info_pos = 0;
347     p->track_duration = 0.0;
348 
349     return 0;
350 }
351 
352 int groove_fingerprinter_info_get(struct GrooveFingerprinter *printer,
353         struct GrooveFingerprinterInfo *info, int block)
354 {
355     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
356 
357     struct GrooveFingerprinterInfo *info_ptr;
358     if (groove_queue_get(p->info_queue, (void**)&info_ptr, block) == 1) {
359         *info = *info_ptr;
360         av_free(info_ptr);
361         return 1;
362     }
363 
364     return 0;
365 }
366 
367 int groove_fingerprinter_info_peek(struct GrooveFingerprinter *printer,
368         int block)
369 {
370     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
371     return groove_queue_peek(p->info_queue, block);
372 }
373 
374 void groove_fingerprinter_position(struct GrooveFingerprinter *printer,
375         struct GroovePlaylistItem **item, double *seconds)
376 {
377     struct GrooveFingerprinterPrivate *p = (struct GrooveFingerprinterPrivate *) printer;
378 
379     pthread_mutex_lock(&p->info_head_mutex);
380 
381     if (item)
382         *item = p->info_head;
383 
384     if (seconds)
385         *seconds = p->info_pos;
386 
387     pthread_mutex_unlock(&p->info_head_mutex);
388 }
389 
390 void groove_fingerprinter_free_info(struct GrooveFingerprinterInfo *info) {
391     if (!info->fingerprint) return;
392     chromaprint_dealloc((void*)info->fingerprint);
393     info->fingerprint = NULL;
394 }
395 
396 int groove_fingerprinter_encode(int32_t *fp, int size, char **encoded_fp) {
397     int encoded_size;
398 #if CHROMAPRINT_VERSION_MAJOR > 1 || CHROMAPRINT_VERSION_MINOR >= 4
399     int err = chromaprint_encode_fingerprint((const uint32_t*)fp, size,
400 #else
401     int err = chromaprint_encode_fingerprint(fp, size,
402 #endif
403             CHROMAPRINT_ALGORITHM_DEFAULT, (void*)encoded_fp, &encoded_size, 1);
404     return err == 1 ? 0 : -1;
405 }
406 
407 int groove_fingerprinter_decode(char *encoded_fp, int32_t **fp, int *size) {
408     int algorithm;
409     int encoded_size = strlen(encoded_fp);
410 #if CHROMAPRINT_VERSION_MAJOR > 1 || CHROMAPRINT_VERSION_MINOR >= 4
411     int err = chromaprint_decode_fingerprint(encoded_fp, encoded_size, (uint32_t**)fp, size,
412 #else
413     int err = chromaprint_decode_fingerprint(encoded_fp, encoded_size, (void**)fp, size,
414 #endif
415             &algorithm, 1);
416     return err == 1 ? 0 : -1;
417 }
418 
419 void groove_fingerprinter_dealloc(void *ptr) {
420     if (!ptr) return;
421     chromaprint_dealloc(ptr);
422 }
423