]> git.sesse.net Git - vlc/blob - modules/audio_filter/equalizer.c
skins2: avoid layout resize if size is unchanged
[vlc] / modules / audio_filter / equalizer.c
1 /*****************************************************************************
2  * equalizer.c:
3  *****************************************************************************
4  * Copyright (C) 2004-2012 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <math.h>
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_charset.h>
37
38 #include <vlc_aout.h>
39 #include <vlc_filter.h>
40
41 #include "equalizer_presets.h"
42
43 /* TODO:
44  *  - optimize a bit (you can hardly do slower ;)
45  *  - add tables for more bands (15 and 32 would be cool), maybe with auto coeffs
46  *    computation (not too hard once the Q is found).
47  *  - support for external preset
48  *  - callback to handle preset changes on the fly
49  *  - ...
50  */
51
52 /*****************************************************************************
53  * Module descriptor
54  *****************************************************************************/
55 static int  Open ( vlc_object_t * );
56 static void Close( vlc_object_t * );
57
58 #define PRESET_TEXT N_( "Equalizer preset" )
59 #define PRESET_LONGTEXT N_("Preset to use for the equalizer." )
60
61 #define BANDS_TEXT N_( "Bands gain")
62 #define BANDS_LONGTEXT N_( \
63          "Don't use presets, but manually specified bands. You need to " \
64          "provide 10 values between -20dB and 20dB, separated by spaces, " \
65          "e.g. \"0 2 4 2 0 -2 -4 -2 0 2\"." )
66
67 #define VLC_BANDS_TEXT N_( "Use VLC frequency bands" )
68 #define VLC_BANDS_LONGTEXT N_( \
69          "Use the VLC frequency bands. Otherwise, use the ISO Standard " \
70          "frequency bands." )
71
72 #define TWOPASS_TEXT N_( "Two pass" )
73 #define TWOPASS_LONGTEXT N_( "Filter the audio twice. This provides a more "  \
74          "intense effect.")
75
76 #define PREAMP_TEXT N_("Global gain" )
77 #define PREAMP_LONGTEXT N_("Set the global gain in dB (-20 ... 20)." )
78
79 vlc_module_begin ()
80     set_description( N_("Equalizer with 10 bands") )
81     set_shortname( N_("Equalizer" ) )
82     set_capability( "audio filter", 0 )
83     set_category( CAT_AUDIO )
84     set_subcategory( SUBCAT_AUDIO_AFILTER )
85
86     add_string( "equalizer-preset", "flat", PRESET_TEXT,
87                 PRESET_LONGTEXT, false )
88         change_string_list( preset_list, preset_list_text )
89     add_string( "equalizer-bands", NULL, BANDS_TEXT,
90                 BANDS_LONGTEXT, true )
91     add_bool( "equalizer-2pass", false, TWOPASS_TEXT,
92               TWOPASS_LONGTEXT, true )
93     add_bool( "equalizer-vlcfreqs", true, VLC_BANDS_TEXT,
94               VLC_BANDS_LONGTEXT, true )
95     add_float( "equalizer-preamp", 12.0, PREAMP_TEXT,
96                PREAMP_LONGTEXT, true )
97     set_callbacks( Open, Close )
98     add_shortcut( "equalizer" )
99 vlc_module_end ()
100
101 /*****************************************************************************
102  * Local prototypes
103  *****************************************************************************/
104 struct filter_sys_t
105 {
106     /* Filter static config */
107     int i_band;
108     float *f_alpha;
109     float *f_beta;
110     float *f_gamma;
111
112     float f_newpreamp;
113     char *psz_newbands;
114     bool b_first;
115
116     /* Filter dyn config */
117     float *f_amp;   /* Per band amp */
118     float f_gamp;   /* Global preamp */
119     bool b_2eqz;
120
121     /* Filter state */
122     float x[32][2];
123     float y[32][128][2];
124
125     /* Second filter state */
126     float x2[32][2];
127     float y2[32][128][2];
128
129     vlc_mutex_t lock;
130 };
131
132 static block_t *DoWork( filter_t *, block_t * );
133
134 #define EQZ_IN_FACTOR (0.25)
135 static int  EqzInit( filter_t *, int );
136 static void EqzFilter( filter_t *, float *, float *, int, int );
137 static void EqzClean( filter_t * );
138
139 static int PresetCallback ( vlc_object_t *, char const *, vlc_value_t,
140                             vlc_value_t, void * );
141 static int PreampCallback ( vlc_object_t *, char const *, vlc_value_t,
142                             vlc_value_t, void * );
143 static int BandsCallback  ( vlc_object_t *, char const *, vlc_value_t,
144                             vlc_value_t, void * );
145 static int TwoPassCallback( vlc_object_t *, char const *, vlc_value_t,
146                             vlc_value_t, void * );
147
148
149
150 /*****************************************************************************
151  * Open:
152  *****************************************************************************/
153 static int Open( vlc_object_t *p_this )
154 {
155     filter_t     *p_filter = (filter_t *)p_this;
156
157     /* Allocate structure */
158     filter_sys_t *p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) );
159     if( !p_sys )
160         return VLC_ENOMEM;
161
162     vlc_mutex_init( &p_sys->lock );
163     if( EqzInit( p_filter, p_filter->fmt_in.audio.i_rate ) != VLC_SUCCESS )
164     {
165         vlc_mutex_destroy( &p_sys->lock );
166         free( p_sys );
167         return VLC_EGENERIC;
168     }
169
170     p_filter->fmt_in.audio.i_format = VLC_CODEC_FL32;
171     p_filter->fmt_out.audio = p_filter->fmt_in.audio;
172     p_filter->pf_audio_filter = DoWork;
173
174     return VLC_SUCCESS;
175 }
176
177 /*****************************************************************************
178  * Close: close the plugin
179  *****************************************************************************/
180 static void Close( vlc_object_t *p_this )
181 {
182     filter_t     *p_filter = (filter_t *)p_this;
183     filter_sys_t *p_sys = p_filter->p_sys;
184
185     EqzClean( p_filter );
186     vlc_mutex_destroy( &p_sys->lock );
187     free( p_sys );
188 }
189
190 /*****************************************************************************
191  * DoWork: process samples buffer
192  *****************************************************************************
193  *
194  *****************************************************************************/
195 static block_t * DoWork( filter_t * p_filter, block_t * p_in_buf )
196 {
197     EqzFilter( p_filter, (float*)p_in_buf->p_buffer,
198                (float*)p_in_buf->p_buffer, p_in_buf->i_nb_samples,
199                aout_FormatNbChannels( &p_filter->fmt_in.audio ) );
200     return p_in_buf;
201 }
202
203 /*****************************************************************************
204  * Equalizer stuff
205  *****************************************************************************/
206 typedef struct
207 {
208     int   i_band;
209
210     struct
211     {
212         float f_frequency;
213         float f_alpha;
214         float f_beta;
215         float f_gamma;
216     } band[EQZ_BANDS_MAX];
217
218 } eqz_config_t;
219
220 /* The frequency tables */
221 static const float f_vlc_frequency_table_10b[EQZ_BANDS_MAX] =
222 {
223     60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000,
224 };
225
226 static const float f_iso_frequency_table_10b[EQZ_BANDS_MAX] =
227 {
228     31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000,
229 };
230
231 /* Equalizer coefficient calculation function based on equ-xmms */
232 static void EqzCoeffs( int i_rate, float f_octave_percent,
233                        bool b_use_vlc_freqs,
234                        eqz_config_t *p_eqz_config )
235 {
236     const float *f_freq_table_10b = b_use_vlc_freqs
237                                   ? f_vlc_frequency_table_10b
238                                   : f_iso_frequency_table_10b;
239     float f_rate = (float) i_rate;
240     float f_nyquist_freq = 0.5 * f_rate;
241     float f_octave_factor = pow( 2.0, 0.5 * f_octave_percent );
242     float f_octave_factor_1 = 0.5 * ( f_octave_factor + 1.0 );
243     float f_octave_factor_2 = 0.5 * ( f_octave_factor - 1.0 );
244
245     p_eqz_config->i_band = EQZ_BANDS_MAX;
246
247     for( int i = 0; i < EQZ_BANDS_MAX; i++ )
248     {
249         float f_freq = f_freq_table_10b[i];
250
251         p_eqz_config->band[i].f_frequency = f_freq;
252
253         if( f_freq <= f_nyquist_freq )
254         {
255             float f_theta_1 = ( 2.0 * M_PI * f_freq ) / f_rate;
256             float f_theta_2 = f_theta_1 / f_octave_factor;
257             float f_sin     = sin( f_theta_2 ) * 0.5;
258             float f_sin_prd = sin( f_theta_2 * f_octave_factor_1 )
259                             * sin( f_theta_2 * f_octave_factor_2 );
260             /* The equation from equ-xmms simplifies to something similar to
261              * this when you restrict the domain to all valid frequencies at or
262              * below the Nyquist frequency (the interval 0 <= f_theta_1 <= Pi).
263              * (This result for the root is twice that returned by equ-xmms,
264              * but the more efficient calculations for alpha, beta, and gamma
265              * below compensate for this.) */
266             float f_root    = ( f_sin - f_sin_prd ) / ( f_sin + f_sin_prd );
267
268             p_eqz_config->band[i].f_alpha = ( 1.0 - f_root ) * 0.5;
269             p_eqz_config->band[i].f_beta  = f_root;
270             p_eqz_config->band[i].f_gamma = ( 1.0 + f_root ) * cos( f_theta_1 );
271         }
272         else
273         {
274             /* Any frequency beyond the Nyquist frequency is no good... */
275             p_eqz_config->band[i].f_alpha =
276             p_eqz_config->band[i].f_beta  =
277             p_eqz_config->band[i].f_gamma = 0.0;
278         }
279     }
280 }
281
282 static inline float EqzConvertdB( float db )
283 {
284     /* Map it to gain,
285      * (we do as if the input of iir is /EQZ_IN_FACTOR, but in fact it's the non iir data that is *EQZ_IN_FACTOR)
286      * db = 20*log( out / in ) with out = in + amp*iir(i/EQZ_IN_FACTOR)
287      * or iir(i) == i for the center freq so
288      * db = 20*log( 1 + amp/EQZ_IN_FACTOR )
289      * -> amp = EQZ_IN_FACTOR*(10^(db/20) - 1)
290      **/
291
292     if( db < -20.0 )
293         db = -20.0;
294     else if(  db > 20.0 )
295         db = 20.0;
296     return EQZ_IN_FACTOR * ( pow( 10, db / 20.0 ) - 1.0 );
297 }
298
299 static int EqzInit( filter_t *p_filter, int i_rate )
300 {
301     filter_sys_t *p_sys = p_filter->p_sys;
302     eqz_config_t cfg;
303     int i, ch;
304     vlc_value_t val1, val2, val3;
305     vlc_object_t *p_aout = p_filter->p_parent;
306     int i_ret = VLC_ENOMEM;
307
308     bool b_vlcFreqs = var_InheritBool( p_aout, "equalizer-vlcfreqs" );
309     EqzCoeffs( i_rate, 1.0, b_vlcFreqs, &cfg );
310
311     /* Create the static filter config */
312     p_sys->i_band = cfg.i_band;
313     p_sys->f_alpha = malloc( p_sys->i_band * sizeof(float) );
314     p_sys->f_beta  = malloc( p_sys->i_band * sizeof(float) );
315     p_sys->f_gamma = malloc( p_sys->i_band * sizeof(float) );
316     if( !p_sys->f_alpha || !p_sys->f_beta || !p_sys->f_gamma )
317         goto error;
318
319     for( i = 0; i < p_sys->i_band; i++ )
320     {
321         p_sys->f_alpha[i] = cfg.band[i].f_alpha;
322         p_sys->f_beta[i]  = cfg.band[i].f_beta;
323         p_sys->f_gamma[i] = cfg.band[i].f_gamma;
324     }
325
326     /* Filter dyn config */
327     p_sys->b_2eqz = false;
328     p_sys->f_gamp = 1.0;
329     p_sys->f_amp  = malloc( p_sys->i_band * sizeof(float) );
330     if( !p_sys->f_amp )
331         goto error;
332
333     for( i = 0; i < p_sys->i_band; i++ )
334     {
335         p_sys->f_amp[i] = 0.0;
336     }
337
338     /* Filter state */
339     for( ch = 0; ch < 32; ch++ )
340     {
341         p_sys->x[ch][0]  =
342         p_sys->x[ch][1]  =
343         p_sys->x2[ch][0] =
344         p_sys->x2[ch][1] = 0.0;
345
346         for( i = 0; i < p_sys->i_band; i++ )
347         {
348             p_sys->y[ch][i][0]  =
349             p_sys->y[ch][i][1]  =
350             p_sys->y2[ch][i][0] =
351             p_sys->y2[ch][i][1] = 0.0;
352         }
353     }
354
355     var_Create( p_aout, "equalizer-bands", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
356     var_Create( p_aout, "equalizer-preset", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
357
358     p_sys->b_2eqz = var_CreateGetBool( p_aout, "equalizer-2pass" );
359
360     var_Create( p_aout, "equalizer-preamp", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
361
362     /* Get initial values */
363     var_Get( p_aout, "equalizer-preset", &val1 );
364     var_Get( p_aout, "equalizer-bands", &val2 );
365     var_Get( p_aout, "equalizer-preamp", &val3 );
366
367     p_sys->b_first = true;
368     PresetCallback( VLC_OBJECT( p_aout ), NULL, val1, val1, p_sys );
369     BandsCallback(  VLC_OBJECT( p_aout ), NULL, val2, val2, p_sys );
370     PreampCallback( VLC_OBJECT( p_aout ), NULL, val3, val3, p_sys );
371     p_sys->b_first = false;
372
373     free( val1.psz_string );
374
375     /* Register preset bands (for intf) if : */
376     /* We have no bands info --> the preset info must be given to the intf */
377     /* or The bands info matches the preset */
378     if (p_sys->psz_newbands == NULL)
379     {
380         msg_Err(p_filter, "No preset selected");
381         free( val2.psz_string );
382         free( p_sys->f_amp );
383         i_ret = VLC_EGENERIC;
384         goto error;
385     }
386     if( ( *(val2.psz_string) &&
387         strstr( p_sys->psz_newbands, val2.psz_string ) ) || !*val2.psz_string )
388     {
389         var_SetString( p_aout, "equalizer-bands", p_sys->psz_newbands );
390         if( p_sys->f_newpreamp == p_sys->f_gamp )
391             var_SetFloat( p_aout, "equalizer-preamp", p_sys->f_newpreamp );
392     }
393     free( val2.psz_string );
394
395     /* Add our own callbacks */
396     var_AddCallback( p_aout, "equalizer-preset", PresetCallback, p_sys );
397     var_AddCallback( p_aout, "equalizer-bands", BandsCallback, p_sys );
398     var_AddCallback( p_aout, "equalizer-preamp", PreampCallback, p_sys );
399     var_AddCallback( p_aout, "equalizer-2pass", TwoPassCallback, p_sys );
400
401     msg_Dbg( p_filter, "equalizer loaded for %d Hz with %d bands %d pass",
402                         i_rate, p_sys->i_band, p_sys->b_2eqz ? 2 : 1 );
403     for( i = 0; i < p_sys->i_band; i++ )
404     {
405         msg_Dbg( p_filter, "   %.2f Hz -> factor:%f alpha:%f beta:%f gamma:%f",
406                  cfg.band[i].f_frequency, p_sys->f_amp[i],
407                  p_sys->f_alpha[i], p_sys->f_beta[i], p_sys->f_gamma[i]);
408     }
409     return VLC_SUCCESS;
410
411 error:
412     free( p_sys->f_alpha );
413     free( p_sys->f_beta );
414     free( p_sys->f_gamma );
415     return i_ret;
416 }
417
418 static void EqzFilter( filter_t *p_filter, float *out, float *in,
419                        int i_samples, int i_channels )
420 {
421     filter_sys_t *p_sys = p_filter->p_sys;
422     int i, ch, j;
423
424     vlc_mutex_lock( &p_sys->lock );
425     for( i = 0; i < i_samples; i++ )
426     {
427         for( ch = 0; ch < i_channels; ch++ )
428         {
429             const float x = in[ch];
430             float o = 0.0;
431
432             for( j = 0; j < p_sys->i_band; j++ )
433             {
434                 float y = p_sys->f_alpha[j] * ( x - p_sys->x[ch][1] ) +
435                           p_sys->f_gamma[j] * p_sys->y[ch][j][0] -
436                           p_sys->f_beta[j]  * p_sys->y[ch][j][1];
437
438                 p_sys->y[ch][j][1] = p_sys->y[ch][j][0];
439                 p_sys->y[ch][j][0] = y;
440
441                 o += y * p_sys->f_amp[j];
442             }
443             p_sys->x[ch][1] = p_sys->x[ch][0];
444             p_sys->x[ch][0] = x;
445
446             /* Second filter */
447             if( p_sys->b_2eqz )
448             {
449                 const float x2 = EQZ_IN_FACTOR * x + o;
450                 o = 0.0;
451                 for( j = 0; j < p_sys->i_band; j++ )
452                 {
453                     float y = p_sys->f_alpha[j] * ( x2 - p_sys->x2[ch][1] ) +
454                               p_sys->f_gamma[j] * p_sys->y2[ch][j][0] -
455                               p_sys->f_beta[j]  * p_sys->y2[ch][j][1];
456
457                     p_sys->y2[ch][j][1] = p_sys->y2[ch][j][0];
458                     p_sys->y2[ch][j][0] = y;
459
460                     o += y * p_sys->f_amp[j];
461                 }
462                 p_sys->x2[ch][1] = p_sys->x2[ch][0];
463                 p_sys->x2[ch][0] = x2;
464
465                 /* We add source PCM + filtered PCM */
466                 out[ch] = p_sys->f_gamp *( EQZ_IN_FACTOR * x2 + o );
467             }
468             else
469             {
470                 /* We add source PCM + filtered PCM */
471                 out[ch] = p_sys->f_gamp *( EQZ_IN_FACTOR * x + o );
472             }
473         }
474
475         in  += i_channels;
476         out += i_channels;
477     }
478     vlc_mutex_unlock( &p_sys->lock );
479 }
480
481 static void EqzClean( filter_t *p_filter )
482 {
483     filter_sys_t *p_sys = p_filter->p_sys;
484     vlc_object_t *p_aout = p_filter->p_parent;
485
486     var_DelCallback( p_aout, "equalizer-bands", BandsCallback, p_sys );
487     var_DelCallback( p_aout, "equalizer-preset", PresetCallback, p_sys );
488     var_DelCallback( p_aout, "equalizer-preamp", PreampCallback, p_sys );
489     var_DelCallback( p_aout, "equalizer-2pass", TwoPassCallback, p_sys );
490
491     free( p_sys->f_alpha );
492     free( p_sys->f_beta );
493     free( p_sys->f_gamma );
494
495     free( p_sys->f_amp );
496     free( p_sys->psz_newbands );
497 }
498
499
500 static int PresetCallback( vlc_object_t *p_aout, char const *psz_cmd,
501                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
502 {
503     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
504     filter_sys_t *p_sys = p_data;
505
506     const char *psz_preset = newval.psz_string;
507
508     vlc_mutex_lock( &p_sys->lock );
509     if( !*psz_preset || p_sys->i_band != 10 )
510     {
511         vlc_mutex_unlock( &p_sys->lock );
512         return VLC_SUCCESS;
513     }
514
515     for( unsigned i = 0; i < NB_PRESETS; i++ )
516     {
517         if( !strcasecmp( eqz_preset_10b[i].psz_name, psz_preset ) )
518         {
519             char *psz_newbands = NULL;
520
521             p_sys->f_gamp *= pow( 10, eqz_preset_10b[i].f_preamp / 20.0 );
522             for( int j = 0; j < p_sys->i_band; j++ )
523             {
524                 lldiv_t d;
525                 char *psz;
526
527                 p_sys->f_amp[j] = EqzConvertdB( eqz_preset_10b[i].f_amp[j] );
528                 d = lldiv( eqz_preset_10b[i].f_amp[j] * 10000000, 10000000 );
529                 if( asprintf( &psz, "%s %lld.%07llu",
530                               psz_newbands ? psz_newbands : "",
531                               d.quot, d.rem ) == -1 )
532                 {
533                     free( psz_newbands );
534                     vlc_mutex_unlock( &p_sys->lock );
535                     return VLC_ENOMEM;
536                 }
537                 free( psz_newbands );
538                 psz_newbands = psz;
539             }
540             if( !p_sys->b_first )
541             {
542                 vlc_mutex_unlock( &p_sys->lock );
543                 var_SetString( p_aout, "equalizer-bands", psz_newbands );
544                 var_SetFloat( p_aout, "equalizer-preamp",
545                               eqz_preset_10b[i].f_preamp );
546                 free( psz_newbands );
547             }
548             else
549             {
550                 p_sys->psz_newbands = psz_newbands;
551                 p_sys->f_newpreamp = eqz_preset_10b[i].f_preamp;
552                 vlc_mutex_unlock( &p_sys->lock );
553             }
554             return VLC_SUCCESS;
555         }
556     }
557     vlc_mutex_unlock( &p_sys->lock );
558     msg_Err( p_aout, "equalizer preset '%s' not found", psz_preset );
559     msg_Info( p_aout, "full list:" );
560     for( unsigned i = 0; i < NB_PRESETS; i++ )
561          msg_Info( p_aout, "  - '%s'", eqz_preset_10b[i].psz_name );
562     return VLC_SUCCESS;
563 }
564
565 static int PreampCallback( vlc_object_t *p_this, char const *psz_cmd,
566                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
567 {
568     VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
569     filter_sys_t *p_sys = p_data;
570
571     if( newval.f_float < -20.0 )
572         newval.f_float = -20.0;
573     else if( newval.f_float > 20.0 )
574         newval.f_float = 20.0;
575
576     vlc_mutex_lock( &p_sys->lock );
577     p_sys->f_gamp = pow( 10, newval.f_float /20.0);
578     vlc_mutex_unlock( &p_sys->lock );
579
580     return VLC_SUCCESS;
581 }
582
583 static int BandsCallback( vlc_object_t *p_this, char const *psz_cmd,
584                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
585 {
586     VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
587     filter_sys_t *p_sys = p_data;
588     const char *psz_bands = newval.psz_string;
589     const char *p = psz_bands;
590     char *psz_next;
591
592     /* Same thing for bands */
593     vlc_mutex_lock( &p_sys->lock );
594     for( int i = 0; i < p_sys->i_band; i++ )
595     {
596         float f;
597
598         if( *psz_bands == '\0' )
599             break;
600
601         /* Read dB -20/20 */
602         f = us_strtof( p, &psz_next );
603
604         if( psz_next == p )
605             break; /* no conversion */
606
607         p_sys->f_amp[i] = EqzConvertdB( f );
608
609         if( *psz_next == '\0' )
610             break; /* end of line */
611         p = &psz_next[1];
612     }
613     vlc_mutex_unlock( &p_sys->lock );
614     return VLC_SUCCESS;
615 }
616 static int TwoPassCallback( vlc_object_t *p_this, char const *psz_cmd,
617                             vlc_value_t oldval, vlc_value_t newval, void *p_data )
618 {
619     VLC_UNUSED(p_this); VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
620     filter_sys_t *p_sys = p_data;
621
622     vlc_mutex_lock( &p_sys->lock );
623     p_sys->b_2eqz = newval.b_bool;
624     vlc_mutex_unlock( &p_sys->lock );
625     return VLC_SUCCESS;
626 }
627