"Fossies" - the Fresh Open Source Software Archive

Member "vlc-3.0.16/modules/stream_out/chromaprint.c" (13 Jun 2021, 8436 Bytes) of package /linux/misc/vlc-3.0.16.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "chromaprint.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0.15_vs_3.0.16.

    1 /*****************************************************************************
    2  * chromaprint.c: Chromaprint Fingerprinter Module
    3  *****************************************************************************
    4  * Copyright (C) 2012 VLC authors and VideoLAN
    5  *
    6  * This program is free software; you can redistribute it and/or modify it
    7  * under the terms of the GNU Lesser General Public License as published by
    8  * the Free Software Foundation; either version 2.1 of the License, or
    9  * (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   14  * GNU Lesser General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU Lesser General Public License
   17  * along with this program; if not, write to the Free Software Foundation,
   18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
   19  *****************************************************************************/
   20 
   21 /*****************************************************************************
   22  * Preamble
   23  *****************************************************************************/
   24 
   25 #ifdef HAVE_CONFIG_H
   26 # include "config.h"
   27 #endif
   28 
   29 #include <vlc_common.h>
   30 #include <vlc_plugin.h>
   31 #include <vlc_input.h>
   32 #include <vlc_block.h>
   33 #include <vlc_sout.h>
   34 
   35 #include <assert.h>
   36 
   37 #ifdef _WIN32
   38 # define CHROMAPRINT_NODLL
   39 #endif
   40 
   41 #include <chromaprint.h> /* chromaprint lib */
   42 #include "chromaprint_data.h"
   43 
   44 /*****************************************************************************
   45  * Exported prototypes
   46  *****************************************************************************/
   47 static int      Open    ( vlc_object_t * );
   48 static void     Close   ( vlc_object_t * );
   49 
   50 static sout_stream_id_sys_t *Add( sout_stream_t *, const es_format_t * );
   51 static void              Del ( sout_stream_t *, sout_stream_id_sys_t * );
   52 static int               Send( sout_stream_t *, sout_stream_id_sys_t *, block_t* );
   53 
   54 /*****************************************************************************
   55  * Module descriptor
   56  *****************************************************************************/
   57 #define DURATION_TEXT N_("Duration of the fingerprinting" )
   58 #define DURATION_LONGTEXT N_("Default: 90sec")
   59 
   60 vlc_module_begin ()
   61     set_description( N_("Chromaprint stream output") )
   62     set_capability( "sout stream", 0 )
   63     add_shortcut( "chromaprint" )
   64     set_category( CAT_SOUT )
   65     set_subcategory( SUBCAT_SOUT_STREAM )
   66     add_integer( "duration", 90, DURATION_TEXT, DURATION_LONGTEXT, true )
   67     set_callbacks( Open, Close )
   68 vlc_module_end ()
   69 
   70 struct sout_stream_sys_t
   71 {
   72     unsigned int i_duration;
   73     unsigned int i_total_samples;
   74     int i_samples;
   75     bool b_finished;
   76     bool b_done;
   77     ChromaprintContext *p_chromaprint_ctx;
   78     sout_stream_id_sys_t *id;
   79     chromaprint_fingerprint_t *p_data;
   80 };
   81 
   82 struct sout_stream_id_sys_t
   83 {
   84     int i_samples;
   85     unsigned int i_channels;
   86     unsigned int i_samplerate;
   87 };
   88 
   89 #define BYTESPERSAMPLE 2
   90 
   91 /*****************************************************************************
   92  * Open:
   93  *****************************************************************************/
   94 static int Open( vlc_object_t *p_this )
   95 {
   96     sout_stream_t *p_stream = (sout_stream_t*)p_this;
   97     sout_stream_sys_t *p_sys;
   98 
   99     p_stream->p_sys = p_sys = malloc(sizeof(sout_stream_sys_t));
  100     if ( unlikely( ! p_sys ) ) return VLC_ENOMEM;
  101     p_sys->id = NULL;
  102     p_sys->b_finished = false;
  103     p_sys->b_done = false;
  104     p_sys->i_total_samples = 0;
  105     p_sys->i_duration = var_InheritInteger( p_stream, "duration" );
  106     p_sys->p_data = var_InheritAddress( p_stream, "fingerprint-data" );
  107     if ( !p_sys->p_data )
  108     {
  109         msg_Err( p_stream, "Fingerprint data holder not set" );
  110         free( p_sys );
  111         return VLC_ENOVAR;
  112     }
  113     msg_Dbg( p_stream, "chromaprint version %s", chromaprint_get_version() );
  114     p_sys->p_chromaprint_ctx = chromaprint_new( CHROMAPRINT_ALGORITHM_DEFAULT );
  115     if ( ! p_sys->p_chromaprint_ctx )
  116     {
  117         msg_Err( p_stream, "Can't create chromaprint context" );
  118         free( p_sys );
  119         return VLC_EGENERIC;
  120     }
  121     p_stream->pf_add  = Add;
  122     p_stream->pf_del  = Del;
  123     p_stream->pf_send = Send;
  124     return VLC_SUCCESS;
  125 }
  126 
  127 static void Finish( sout_stream_t *p_stream )
  128 {
  129     sout_stream_sys_t *p_sys = p_stream->p_sys;
  130     char *psz_fingerprint = NULL;
  131     if ( p_sys->b_finished && chromaprint_finish( p_sys->p_chromaprint_ctx ) )
  132     {
  133         chromaprint_get_fingerprint( p_sys->p_chromaprint_ctx,
  134                                      &psz_fingerprint );
  135         if ( psz_fingerprint )
  136         {
  137             p_sys->p_data->i_duration = p_sys->i_total_samples / p_sys->id->i_samplerate;
  138             p_sys->p_data->psz_fingerprint = strdup( psz_fingerprint );
  139             chromaprint_dealloc( psz_fingerprint );
  140             msg_Dbg( p_stream, "DURATION=%u;FINGERPRINT=%s",
  141                     p_sys->p_data->i_duration,
  142                     p_sys->p_data->psz_fingerprint );
  143         }
  144     } else {
  145         msg_Dbg( p_stream, "Cannot create %us fingerprint (not enough samples?)",
  146                  p_sys->i_duration );
  147     }
  148     p_sys->b_done = true;
  149     msg_Dbg( p_stream, "Fingerprinting finished" );
  150 }
  151 
  152 /*****************************************************************************
  153  * Close:
  154  *****************************************************************************/
  155 static void Close( vlc_object_t * p_this )
  156 {
  157     sout_stream_t *p_stream = (sout_stream_t *)p_this;
  158     sout_stream_sys_t *p_sys = p_stream->p_sys;
  159 
  160     if ( !p_sys->b_done ) Finish( p_stream );
  161     chromaprint_free( p_sys->p_chromaprint_ctx );
  162     free( p_sys );
  163 }
  164 
  165 static sout_stream_id_sys_t *Add( sout_stream_t *p_stream, const es_format_t *p_fmt )
  166 {
  167     sout_stream_sys_t *p_sys = p_stream->p_sys;
  168     sout_stream_id_sys_t *id = NULL;
  169 
  170     if ( p_fmt->i_cat == AUDIO_ES && !p_sys->id )
  171     {
  172         if( p_fmt->i_codec != VLC_CODEC_S16N || p_fmt->audio.i_channels > 2 )
  173         {
  174             msg_Warn( p_stream, "bad input format: need s16l, 1 or 2 channels" );
  175             goto error;
  176         }
  177 
  178         id = malloc( sizeof( sout_stream_id_sys_t ) );
  179         if ( !id ) goto error;
  180 
  181         id->i_channels = p_fmt->audio.i_channels;
  182         id->i_samplerate = p_fmt->audio.i_rate;
  183         id->i_samples = p_sys->i_duration * id->i_samplerate;
  184 
  185         if ( !chromaprint_start( p_sys->p_chromaprint_ctx, p_fmt->audio.i_rate, id->i_channels ) )
  186         {
  187             msg_Err( p_stream, "Failed starting chromaprint on %uHz %uch samples",
  188                      p_fmt->audio.i_rate, id->i_channels );
  189             goto error;
  190         }
  191         else
  192         {
  193             p_sys->id = id;
  194             msg_Dbg( p_stream, "Starting chromaprint on %uHz %uch samples",
  195                      p_fmt->audio.i_rate, id->i_channels );
  196         }
  197         return id;
  198     }
  199 
  200 error:
  201     free( id );
  202     return NULL;
  203 }
  204 
  205 static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
  206 {
  207     sout_stream_sys_t *p_sys = p_stream->p_sys;
  208     Finish( p_stream );
  209     if ( p_sys->id == id ) /* not assuming only 1 id is in use.. */
  210         p_sys->id = NULL;
  211     free( id );
  212 }
  213 
  214 static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
  215                  block_t *p_buf )
  216 {
  217     sout_stream_sys_t *p_sys = p_stream->p_sys;
  218 
  219     if ( p_sys->id != id )
  220     {
  221         /* drop the whole buffer at once */
  222         block_ChainRelease( p_buf );
  223         return VLC_SUCCESS;
  224     }
  225 
  226     while( p_buf )
  227     {
  228         block_t *p_next;
  229         int i_samples = p_buf->i_buffer / (BYTESPERSAMPLE * id->i_channels);
  230         p_sys->i_total_samples += i_samples;
  231         if ( !p_sys->b_finished && id->i_samples > 0 && p_buf->i_buffer )
  232         {
  233             if(! chromaprint_feed( p_sys->p_chromaprint_ctx,
  234                                    p_buf->p_buffer,
  235                                    p_buf->i_buffer / BYTESPERSAMPLE ) )
  236                 msg_Warn( p_stream, "feed error" );
  237             id->i_samples -= i_samples;
  238             if ( id->i_samples < 1 && !p_sys->b_finished )
  239             {
  240                 p_sys->b_finished = true;
  241                 msg_Dbg( p_stream, "Fingerprint collection finished" );
  242             }
  243         }
  244         p_next = p_buf->p_next;
  245         block_Release( p_buf );
  246         p_buf = p_next;
  247     }
  248 
  249     return VLC_SUCCESS;
  250 }