/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_sys_t *p_sys; p_stream->p_sys = p_sys = malloc(sizeof(sout_stream_sys_t)); if ( unlikely( ! p_sys ) ) return VLC_ENOMEM; p_sys->id = NULL; p_sys->b_finished = false; p_sys->b_done = false; p_sys->i_total_samples = 0; p_sys->i_duration = var_InheritInteger( p_stream, "duration" ); p_sys->p_data = var_InheritAddress( p_stream, "fingerprint-data" ); if ( !p_sys->p_data ) { msg_Err( p_stream, "Fingerprint data holder not set" ); free( p_sys ); return VLC_ENOVAR; } msg_Dbg( p_stream, "chromaprint version %s", chromaprint_get_version() ); p_sys->p_chromaprint_ctx = chromaprint_new( CHROMAPRINT_ALGORITHM_DEFAULT ); if ( ! p_sys->p_chromaprint_ctx ) { msg_Err( p_stream, "Can't create chromaprint context" ); free( p_sys ); return VLC_EGENERIC; } p_stream->pf_add = Add; p_stream->pf_del = Del; p_stream->pf_send = Send; return VLC_SUCCESS; }
static gboolean plugin_init (GstPlugin * plugin) { gboolean ret; GST_DEBUG_CATEGORY_INIT (gst_chromaprint_debug, "chromaprint", 0, "chromaprint element"); GST_INFO ("libchromaprint %s", chromaprint_get_version ()); ret = gst_element_register (plugin, "chromaprint", GST_RANK_NONE, GST_TYPE_CHROMAPRINT); if (ret) { gst_tag_register (GST_TAG_CHROMAPRINT_FINGERPRINT, GST_TAG_FLAG_META, G_TYPE_STRING, "chromaprint fingerprint", "Chromaprint fingerprint", NULL); } return ret; }
int decode_audio_file(ChromaprintContext *chromaprint_ctx, int16_t *buffer1, int16_t *buffer2, const char *file_name, int max_length, int *duration) { int i, ok = 0, remaining, length, consumed, buffer_size, codec_ctx_opened = 0; AVFormatContext *format_ctx = NULL; AVCodecContext *codec_ctx = NULL; AVCodec *codec = NULL; AVStream *stream = NULL; AVPacket packet, packet_temp; #ifdef HAVE_AV_AUDIO_CONVERT AVAudioConvert *convert_ctx = NULL; #endif int16_t *buffer; if (!strcmp(file_name, "-")) { file_name = "pipe:0"; } #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 2, 0) if (av_open_input_file(&format_ctx, file_name, NULL, 0, NULL) != 0) { #else if (avformat_open_input(&format_ctx, file_name, NULL, NULL) != 0) { #endif fprintf(stderr, "ERROR: couldn't open the file\n"); goto done; } if (av_find_stream_info(format_ctx) < 0) { fprintf(stderr, "ERROR: couldn't find stream information in the file\n"); goto done; } for (i = 0; i < format_ctx->nb_streams; i++) { codec_ctx = format_ctx->streams[i]->codec; if (codec_ctx && codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { stream = format_ctx->streams[i]; break; } } if (!stream) { fprintf(stderr, "ERROR: couldn't find any audio stream in the file\n"); goto done; } codec = avcodec_find_decoder(codec_ctx->codec_id); if (!codec) { fprintf(stderr, "ERROR: unknown codec\n"); goto done; } if (avcodec_open(codec_ctx, codec) < 0) { fprintf(stderr, "ERROR: couldn't open the codec\n"); goto done; } codec_ctx_opened = 1; if (codec_ctx->channels <= 0) { fprintf(stderr, "ERROR: no channels found in the audio stream\n"); goto done; } if (codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16) { #ifdef HAVE_AV_AUDIO_CONVERT convert_ctx = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, codec_ctx->channels, codec_ctx->sample_fmt, codec_ctx->channels, NULL, 0); if (!convert_ctx) { fprintf(stderr, "ERROR: couldn't create sample format converter\n"); goto done; } #else fprintf(stderr, "ERROR: unsupported sample format\n"); goto done; #endif } *duration = stream->time_base.num * stream->duration / stream->time_base.den; av_init_packet(&packet); av_init_packet(&packet_temp); remaining = max_length * codec_ctx->channels * codec_ctx->sample_rate; chromaprint_start(chromaprint_ctx, codec_ctx->sample_rate, codec_ctx->channels); while (1) { if (av_read_frame(format_ctx, &packet) < 0) { break; } packet_temp.data = packet.data; packet_temp.size = packet.size; while (packet_temp.size > 0) { buffer_size = BUFFER_SIZE; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52, 23, 0) consumed = avcodec_decode_audio2(codec_ctx, buffer1, &buffer_size, packet_temp.data, packet_temp.size); #else consumed = avcodec_decode_audio3(codec_ctx, buffer1, &buffer_size, &packet_temp); #endif if (consumed < 0) { break; } packet_temp.data += consumed; packet_temp.size -= consumed; if (buffer_size <= 0) { if (buffer_size < 0) { fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too small\n"); } continue; } if (buffer_size > BUFFER_SIZE) { fprintf(stderr, "WARNING: size returned from avcodec_decode_audioX is too large\n"); continue; } #ifdef HAVE_AV_AUDIO_CONVERT if (convert_ctx) { const void *ibuf[6] = { buffer1 }; void *obuf[6] = { buffer2 }; #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 8, 0) int istride[6] = { av_get_bits_per_sample_format(codec_ctx->sample_fmt) / 8 }; #else int istride[6] = { av_get_bytes_per_sample(codec_ctx->sample_fmt) }; #endif int ostride[6] = { 2 }; int len = buffer_size / istride[0]; if (av_audio_convert(convert_ctx, obuf, ostride, ibuf, istride, len) < 0) { break; } buffer = buffer2; buffer_size = len * ostride[0]; } else { buffer = buffer1; } #else buffer = buffer1; #endif length = MIN(remaining, buffer_size / 2); if (!chromaprint_feed(chromaprint_ctx, buffer, length)) { fprintf(stderr, "ERROR: fingerprint calculation failed\n"); goto done; } if (max_length) { remaining -= length; if (remaining <= 0) { goto finish; } } } if (packet.data) { av_free_packet(&packet); } } finish: if (!chromaprint_finish(chromaprint_ctx)) { fprintf(stderr, "ERROR: fingerprint calculation failed\n"); goto done; } ok = 1; done: if (codec_ctx_opened) { avcodec_close(codec_ctx); } if (format_ctx) { av_close_input_file(format_ctx); } #ifdef HAVE_AV_AUDIO_CONVERT if (convert_ctx) { av_audio_convert_free(convert_ctx); } #endif return ok; } int fpcalc_main(int argc, char **argv) { int i, j, max_length = 120, num_file_names = 0, raw = 0, raw_fingerprint_size, duration; int16_t *buffer1, *buffer2; int32_t *raw_fingerprint; char *file_name, *fingerprint, **file_names; ChromaprintContext *chromaprint_ctx; int algo = CHROMAPRINT_ALGORITHM_DEFAULT; file_names = malloc(argc * sizeof(char *)); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-length") && i + 1 < argc) { max_length = atoi(argv[++i]); } else if (!strcmp(arg, "-version") || !strcmp(arg, "-v")) { printf("fpcalc version %s\n", chromaprint_get_version()); return 0; } else if (!strcmp(arg, "-raw")) { raw = 1; } else if (!strcmp(arg, "-algo") && i + 1 < argc) { const char *v = argv[++i]; if (!strcmp(v, "test1")) { algo = CHROMAPRINT_ALGORITHM_TEST1; } else if (!strcmp(v, "test2")) { algo = CHROMAPRINT_ALGORITHM_TEST2; } else if (!strcmp(v, "test3")) { algo = CHROMAPRINT_ALGORITHM_TEST3; } else if (!strcmp(v, "test4")) { algo = CHROMAPRINT_ALGORITHM_TEST4; } else { fprintf(stderr, "WARNING: unknown algorithm, using the default\n"); } } else if (!strcmp(arg, "-set") && i + 1 < argc) { i += 1; } else { file_names[num_file_names++] = argv[i]; } } if (!num_file_names) { printf("usage: %s [OPTIONS] FILE...\n\n", argv[0]); printf("Options:\n"); printf(" -version print version information\n"); printf(" -length SECS length of the audio data used for fingerprint calculation (default 120)\n"); printf(" -raw output the raw uncompressed fingerprint\n"); printf(" -algo NAME version of the fingerprint algorithm\n"); return 2; } av_register_all(); av_log_set_level(AV_LOG_ERROR); buffer1 = av_malloc(BUFFER_SIZE + 16); buffer2 = av_malloc(BUFFER_SIZE + 16); chromaprint_ctx = chromaprint_new(algo); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-set") && i + 1 < argc) { char *name = argv[++i]; char *value = strchr(name, '='); if (value) { *value++ = '\0'; chromaprint_set_option(chromaprint_ctx, name, atoi(value)); } } } for (i = 0; i < num_file_names; i++) { file_name = file_names[i]; if (!decode_audio_file(chromaprint_ctx, buffer1, buffer2, file_name, max_length, &duration)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } if (i > 0) { printf("\n"); } printf("FILE=%s\n", file_name); printf("DURATION=%d\n", duration); if (raw) { if (!chromaprint_get_raw_fingerprint(chromaprint_ctx, (void **)&raw_fingerprint, &raw_fingerprint_size)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } printf("FINGERPRINT="); for (j = 0; j < raw_fingerprint_size; j++) { printf("%d%s", raw_fingerprint[j], j + 1 < raw_fingerprint_size ? "," : ""); } printf("\n"); chromaprint_dealloc(raw_fingerprint); } else { if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); continue; } printf("FINGERPRINT=%s\n", fingerprint); chromaprint_dealloc(fingerprint); } } chromaprint_free(chromaprint_ctx); av_free(buffer1); av_free(buffer2); free(file_names); return 0; }
int fpcalc_main(int argc, char **argv) { int i, j, max_length = 120, num_file_names = 0, raw = 0, raw_fingerprint_size, duration; int32_t *raw_fingerprint; char *file_name, *fingerprint, **file_names; ChromaprintContext *chromaprint_ctx; int algo = CHROMAPRINT_ALGORITHM_DEFAULT, num_failed = 0, do_hash = 0; file_names = malloc(argc * sizeof(char *)); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-length") && i + 1 < argc) { max_length = atoi(argv[++i]); } else if (!strcmp(arg, "-version") || !strcmp(arg, "-v")) { printf("fpcalc version %s\n", chromaprint_get_version()); return 0; } else if (!strcmp(arg, "-raw")) { raw = 1; } else if (!strcmp(arg, "-hash")) { do_hash = 1; } else if (!strcmp(arg, "-algo") && i + 1 < argc) { const char *v = argv[++i]; if (!strcmp(v, "test1")) { algo = CHROMAPRINT_ALGORITHM_TEST1; } else if (!strcmp(v, "test2")) { algo = CHROMAPRINT_ALGORITHM_TEST2; } else if (!strcmp(v, "test3")) { algo = CHROMAPRINT_ALGORITHM_TEST3; } else if (!strcmp(v, "test4")) { algo = CHROMAPRINT_ALGORITHM_TEST4; } else { fprintf(stderr, "WARNING: unknown algorithm, using the default\n"); } } else if (!strcmp(arg, "-set") && i + 1 < argc) { i += 1; } else { file_names[num_file_names++] = argv[i]; } } if (!num_file_names) { printf("usage: %s [OPTIONS] FILE...\n\n", argv[0]); printf("Options:\n"); printf(" -version print version information\n"); printf(" -length SECS length of the audio data used for fingerprint calculation (default 120)\n"); printf(" -raw output the raw uncompressed fingerprint\n"); printf(" -algo NAME version of the fingerprint algorithm\n"); printf(" -hash calculate also the fingerprint hash\n"); return 2; } av_register_all(); av_log_set_level(AV_LOG_ERROR); chromaprint_ctx = chromaprint_new(algo); for (i = 1; i < argc; i++) { char *arg = argv[i]; if (!strcmp(arg, "-set") && i + 1 < argc) { char *name = argv[++i]; char *value = strchr(name, '='); if (value) { *value++ = '\0'; chromaprint_set_option(chromaprint_ctx, name, atoi(value)); } } } for (i = 0; i < num_file_names; i++) { file_name = file_names[i]; if (!decode_audio_file(chromaprint_ctx, file_name, max_length, &duration)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); num_failed++; continue; } if (i > 0) { printf("\n"); } printf("FILE=%s\n", file_name); printf("DURATION=%d\n", duration); if (raw) { if (!chromaprint_get_raw_fingerprint(chromaprint_ctx, (void **)&raw_fingerprint, &raw_fingerprint_size)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); num_failed++; continue; } printf("FINGERPRINT="); for (j = 0; j < raw_fingerprint_size; j++) { printf("%d%s", raw_fingerprint[j], j + 1 < raw_fingerprint_size ? "," : ""); } printf("\n"); chromaprint_dealloc(raw_fingerprint); } else { if (!chromaprint_get_fingerprint(chromaprint_ctx, &fingerprint)) { fprintf(stderr, "ERROR: unable to calculate fingerprint for file %s, skipping\n", file_name); num_failed++; continue; } printf("FINGERPRINT=%s\n", fingerprint); chromaprint_dealloc(fingerprint); } if (do_hash) { int32_t hash = 0; chromaprint_get_fingerprint_hash(chromaprint_ctx, &hash); printf("HASH=%d\n", hash); } } chromaprint_free(chromaprint_ctx); free(file_names); return num_failed ? 1 : 0; }