[vlc-devel] [PATCH 1/4] chromaprint: add stream out chromaprint module
Rémi Denis-Courmont
remi at remlab.net
Mon Feb 11 17:40:15 CET 2013
Le lundi 11 février 2013 15:52:33, Francois Cartegnie a écrit :
> diff --git a/modules/stream_out/Modules.am b/modules/stream_out/Modules.am
> index 26ad06b..6a2ca71 100644
> --- a/modules/stream_out/Modules.am
> +++ b/modules/stream_out/Modules.am
> @@ -14,6 +14,7 @@ SOURCES_stream_out_record = record.c
> SOURCES_stream_out_smem = smem.c
> SOURCES_stream_out_setid = setid.c
> SOURCES_stream_out_langfromtelx = langfromtelx.c
> +SOURCES_stream_out_chromaprint = chromaprint.c chromaprint_data.h
>
> libstream_out_transcode_plugin_la_SOURCES = \
> transcode/transcode.c transcode/transcode.h \
> @@ -61,3 +62,7 @@ libstream_out_raop_plugin_la_LIBADD = $(AM_LIBADD)
> $(GCRYPT_LIBS) -lgpg-error $( if HAVE_GCRYPT
> libvlc_LTLIBRARIES += libstream_out_raop_plugin.la
> endif
> +
> +if HAVE_CHROMAPRINT
> +libvlc_LTLIBRARIES += libstream_out_chromaprint_plugin.la
> +endif
> diff --git a/modules/stream_out/chromaprint.c
> b/modules/stream_out/chromaprint.c new file mode 100644
> index 0000000..9938e0d
> --- /dev/null
> +++ b/modules/stream_out/chromaprint.c
> @@ -0,0 +1,234 @@
> +/*************************************************************************
> **** + * chromaprint.c: Chromaprint Fingerprinter Module
> +
> **************************************************************************
> *** + * Copyright (C) 2012 VLC authors and VideoLAN
Seems off.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published
> by + * the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> License + * along with this program; if not, write to the Free Software
> Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA
> 02110-1301, USA. +
> **************************************************************************
> ***/ +
> +/*************************************************************************
> **** + * Preamble
> +
> **************************************************************************
> ***/ +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +
> +#include <vlc_common.h>
> +#include <vlc_plugin.h>
> +#include <vlc_input.h>
> +#include <vlc_block.h>
> +#include <vlc_sout.h>
> +
> +#include <assert.h>
> +
> +#include <chromaprint.h> /* chromaprint lib */
> +#include "chromaprint_data.h"
> +
> +/*************************************************************************
> **** + * Exported prototypes
> +
> **************************************************************************
> ***/ +static int Open ( vlc_object_t * );
> +static void Close ( vlc_object_t * );
> +
> +static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
> +static int Del ( sout_stream_t *, sout_stream_id_t * );
> +static int Send( sout_stream_t *, sout_stream_id_t *,
> block_t* ); +
> +/*************************************************************************
> **** + * Module descriptor
> +
> **************************************************************************
> ***/ +#define DURATION_TEXT N_("Duration of the fingerprinting" )
> +#define DURATION_LONGTEXT N_("Default: 90sec")
> +
> +vlc_module_begin ()
> + set_description( N_("Chromaprint stream output") )
> + set_capability( "sout stream", 0 )
> + add_shortcut( "chromaprint" )
> + add_integer( "duration", 90, DURATION_TEXT, DURATION_LONGTEXT, true )
> + set_callbacks( Open, Close )
> +vlc_module_end ()
> +
> +struct sout_stream_sys_t
> +{
> + unsigned int i_duration;
> + unsigned int i_total_samples;
> + int i_samples;
> + bool b_finished;
> + bool b_done;
> + ChromaprintContext *p_chromaprint_ctx;
> + sout_stream_id_t *id;
> + chromaprint_fingerprint_t *p_data;
> +};
> +
> +struct sout_stream_id_t
> +{
> + int i_samples;
> + unsigned int i_channels;
> + unsigned int i_samplesize;
> + unsigned int i_samplerate;
> +};
> +
> +/*************************************************************************
> **** + * 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->pf_add = Add;
> + p_stream->pf_del = Del;
> + p_stream->pf_send = Send;
We have been through this many times. Avoid initialization before error cases.
> + p_stream->p_sys = p_sys = malloc(sizeof(sout_stream_sys_t));
> + if ( ! 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_CreateGetInteger( p_stream->p_parent,
> "duration" );
Why parent? Why not var_Inherit...() ?
> + 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;
> + }
> + return VLC_SUCCESS;
> +}
> +
> +static void Finish( sout_stream_t *p_stream )
> +{
> + sout_stream_sys_t *p_sys = p_stream->p_sys;
> + char *psz_fingerprint = NULL;
> + if ( p_sys->b_finished && chromaprint_finish( p_sys->p_chromaprint_ctx
> ) )
> + {
> + chromaprint_get_fingerprint( p_sys->p_chromaprint_ctx,
> + &psz_fingerprint );
> + if ( psz_fingerprint )
> + {
> + p_sys->p_data->i_duration = p_sys->i_total_samples /
> p_sys->id->i_samplerate;
> + p_sys->p_data->psz_fingerprint = strdup( psz_fingerprint );
That's rather brittle. What if the same structure is reused?
> + chromaprint_dealloc( psz_fingerprint );
> + msg_Dbg( p_stream, "DURATION=%d;FINGERPRINT=%s",
> + p_sys->p_data->i_duration,
> + p_sys->p_data->psz_fingerprint );
> + }
> + } else {
> + msg_Dbg( p_stream, "Cannot create %ds fingerprint (not enough
> samples?)", + p_sys->i_duration );
> + }
> + p_sys->b_done = true;
> + msg_Dbg( p_stream, "Fingerprinting finished" );
> +}
> +
> +/*************************************************************************
> ****
> + * Close:
> +
> **************************************************************************
> ***/ +static void Close( 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;
> +
> + if ( !p_sys->b_done ) Finish( p_stream );
> +
> + if ( !p_sys->p_chromaprint_ctx ) goto end;
> + chromaprint_free( p_sys->p_chromaprint_ctx );
> +end:
> + free( p_sys );
> +}
> +
> +static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt
> ) +{
> + sout_stream_sys_t *p_sys = p_stream->p_sys;
> + sout_stream_id_t *id = malloc( sizeof( sout_stream_id_t ) );
Can't you simply return NULL for unsupported ESes?
> +
> + if ( id && p_fmt->i_cat == AUDIO_ES && !p_sys->id )
> + {
> + if( p_fmt->i_codec != VLC_CODEC_S16L )
> + {
> + msg_Warn( p_stream, "bad input format: need s16l" );
> + goto end;
> + }
> +
> + id->i_samplesize = p_fmt->audio.i_bitspersample >> 3;
> + id->i_channels = p_fmt->audio.i_channels;
> + id->i_samplerate = p_fmt->audio.i_rate;
> + id->i_samples = p_sys->i_duration * id->i_samplerate;
> +
> + if ( id->i_channels > 2 || !p_sys->p_chromaprint_ctx )
> + goto end;
> +
> + if ( !chromaprint_start( p_sys->p_chromaprint_ctx,
> p_fmt->audio.i_rate, id->i_channels ) ) + {
> + msg_Err( p_stream, "Failed starting chromaprint on %dHz %dch
> samples",
> + p_fmt->audio.i_rate, id->i_channels );
> + goto end;
> + }
> + else
> + {
> + p_sys->id = id;
> + msg_Dbg( p_stream, "Starting chromaprint on %dHz %dch
> samples", + p_fmt->audio.i_rate, id->i_channels );
> + }
> + }
> +end:
> + return id;
> +}
> +
> +static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
> +{
> + Finish( p_stream );
> + free( id );
p_sys->id is left stale.
> + return VLC_SUCCESS;
> +}
> +
> +static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
> + block_t *p_buf )
> +{
> + sout_stream_sys_t *p_sys = p_stream->p_sys;
> + if ( p_sys->id == id )
This could yield a false positive because of stale p_sys->id.
> + {
> + while( p_buf )
> + {
> + int i_samples = p_buf->i_buffer / (id->i_samplesize *
> id->i_channels); + p_sys->i_total_samples += i_samples;
> + if ( !p_sys->b_finished && id->i_samples > 0 &&
> p_buf->i_buffer ) + {
> + if(! chromaprint_feed( p_sys->p_chromaprint_ctx,
> + p_buf->p_buffer,
> + p_buf->i_buffer / id->i_samplesize
> ) ) + msg_Warn( p_stream, "feed error" );
> + id->i_samples -= i_samples;
> + if ( id->i_samples < 1 && !p_sys->b_finished )
> + {
> + p_sys->b_finished = true;
> + msg_Dbg( p_stream, "Fingerprint collection finished"
> ); + }
> + }
> + p_buf = p_buf->p_next;
> + }
> + }
> + block_ChainRelease( p_buf );
Huge memory leak.
> + return VLC_SUCCESS;
> +}
> diff --git a/modules/stream_out/chromaprint_data.h
> b/modules/stream_out/chromaprint_data.h new file mode 100644
> index 0000000..6fc3077
> --- /dev/null
> +++ b/modules/stream_out/chromaprint_data.h
> @@ -0,0 +1,27 @@
> +/*************************************************************************
> **** + * chromaprint_data.h: Chromaprint's sout fingerprint data header +
> **************************************************************************
> *** + * Copyright (C) 2012 VLC authors and VideoLAN
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License as published
> by + * the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> License + * along with this program; if not, write to the Free Software
> Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA
> 02110-1301, USA. +
> **************************************************************************
> ***/ +
> +struct chromaprint_fingerprint_t
> +{
> + char *psz_fingerprint;
> + unsigned int i_duration;
> +};
> +
> +typedef struct chromaprint_fingerprint_t chromaprint_fingerprint_t;
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list