]> git.sesse.net Git - vlc/blob - src/audio_output/common.c
Fix support of .00x splitted files on Win32
[vlc] / src / audio_output / common.c
1 /*****************************************************************************
2  * common.c : audio output management of common data structures
3  *****************************************************************************
4  * Copyright (C) 2002-2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@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 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <limits.h>
29 #include <assert.h>
30
31 #include <vlc_common.h>
32 #include <vlc_aout.h>
33 #include "aout_internal.h"
34
35 /*
36  * Formats management (internal and external)
37  */
38
39 /*****************************************************************************
40  * aout_BitsPerSample : get the number of bits per sample
41  *****************************************************************************/
42 unsigned int aout_BitsPerSample( vlc_fourcc_t i_format )
43 {
44     switch( vlc_fourcc_GetCodec( AUDIO_ES, i_format ) )
45     {
46     case VLC_CODEC_U8:
47     case VLC_CODEC_S8:
48     case VLC_CODEC_ALAW:
49     case VLC_CODEC_MULAW:
50         return 8;
51
52     case VLC_CODEC_U16L:
53     case VLC_CODEC_S16L:
54     case VLC_CODEC_U16B:
55     case VLC_CODEC_S16B:
56         return 16;
57
58     case VLC_CODEC_U24L:
59     case VLC_CODEC_S24L:
60     case VLC_CODEC_U24B:
61     case VLC_CODEC_S24B:
62         return 24;
63
64     case VLC_CODEC_S32L:
65     case VLC_CODEC_S32B:
66     case VLC_CODEC_F32L:
67     case VLC_CODEC_F32B:
68     case VLC_CODEC_FI32:
69         return 32;
70
71     case VLC_CODEC_F64L:
72     case VLC_CODEC_F64B:
73         return 64;
74
75     default:
76         /* For these formats the caller has to indicate the parameters
77          * by hand. */
78         return 0;
79     }
80 }
81
82 vlc_fourcc_t aout_NativeEndian( vlc_fourcc_t i_format )
83 {
84     switch( i_format )
85     {
86         case VLC_CODEC_F64B:
87         case VLC_CODEC_F64L:
88             return VLC_CODEC_FL64;
89
90         case VLC_CODEC_F32B:
91         case VLC_CODEC_F32L:
92             return VLC_CODEC_FL32;
93
94         case VLC_CODEC_S32B:
95         case VLC_CODEC_S32L:
96             return VLC_CODEC_S32N;
97
98         case VLC_CODEC_U32B:
99         case VLC_CODEC_U32L:
100             return VLC_CODEC_U32N;
101
102         case VLC_CODEC_S24B:
103         case VLC_CODEC_S24L:
104             return VLC_CODEC_S24N;
105
106         case VLC_CODEC_U24B:
107         case VLC_CODEC_U24L:
108             return VLC_CODEC_U24N;
109
110         case VLC_CODEC_S16B:
111         case VLC_CODEC_S16L:
112             return VLC_CODEC_S16N;
113
114         case VLC_CODEC_U16B:
115         case VLC_CODEC_U16L:
116             return VLC_CODEC_U16N;
117     }
118     return 0;
119 }
120
121
122 /*****************************************************************************
123  * aout_FormatPrepare : compute the number of bytes per frame & frame length
124  *****************************************************************************/
125 void aout_FormatPrepare( audio_sample_format_t * p_format )
126 {
127     p_format->i_channels = aout_FormatNbChannels( p_format );
128     p_format->i_bitspersample = aout_BitsPerSample( p_format->i_format );
129     if( p_format->i_bitspersample > 0 )
130     {
131         p_format->i_bytes_per_frame = ( p_format->i_bitspersample / 8 )
132                                     * aout_FormatNbChannels( p_format );
133         p_format->i_frame_length = 1;
134     }
135 }
136
137 /*****************************************************************************
138  * aout_FormatPrintChannels : print a channel in a human-readable form
139  *****************************************************************************/
140 const char * aout_FormatPrintChannels( const audio_sample_format_t * p_format )
141 {
142     switch ( p_format->i_physical_channels )
143     {
144     case AOUT_CHAN_LEFT:
145     case AOUT_CHAN_RIGHT:
146     case AOUT_CHAN_CENTER:
147         if ( (p_format->i_original_channels & AOUT_CHAN_CENTER)
148               || (p_format->i_original_channels
149                    & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
150             return "Mono";
151         else if ( p_format->i_original_channels & AOUT_CHAN_LEFT )
152             return "Left";
153         return "Right";
154     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT:
155         if ( p_format->i_original_channels & AOUT_CHAN_REVERSESTEREO )
156         {
157             if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
158                 return "Dolby/Reverse";
159             return "Stereo/Reverse";
160         }
161         else
162         {
163             if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
164                 return "Dolby";
165             else if ( p_format->i_original_channels & AOUT_CHAN_DUALMONO )
166                 return "Dual-mono";
167             else if ( p_format->i_original_channels == AOUT_CHAN_CENTER )
168                 return "Stereo/Mono";
169             else if ( !(p_format->i_original_channels & AOUT_CHAN_RIGHT) )
170                 return "Stereo/Left";
171             else if ( !(p_format->i_original_channels & AOUT_CHAN_LEFT) )
172                 return "Stereo/Right";
173             return "Stereo";
174         }
175     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER:
176         return "3F";
177     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER:
178         return "2F1R";
179     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
180           | AOUT_CHAN_REARCENTER:
181         return "3F1R";
182     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
183           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
184         return "2F2R";
185     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
186           | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT:
187         return "2F2M";
188     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
189           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
190         return "3F2R";
191     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
192           | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT:
193         return "3F2M";
194
195     case AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
196         if ( (p_format->i_original_channels & AOUT_CHAN_CENTER)
197               || (p_format->i_original_channels
198                    & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
199             return "Mono/LFE";
200         else if ( p_format->i_original_channels & AOUT_CHAN_LEFT )
201             return "Left/LFE";
202         return "Right/LFE";
203     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE:
204         if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
205             return "Dolby/LFE";
206         else if ( p_format->i_original_channels & AOUT_CHAN_DUALMONO )
207             return "Dual-mono/LFE";
208         else if ( p_format->i_original_channels == AOUT_CHAN_CENTER )
209             return "Mono/LFE";
210         else if ( !(p_format->i_original_channels & AOUT_CHAN_RIGHT) )
211             return "Stereo/Left/LFE";
212         else if ( !(p_format->i_original_channels & AOUT_CHAN_LEFT) )
213             return "Stereo/Right/LFE";
214          return "Stereo/LFE";
215     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
216         return "3F/LFE";
217     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER
218           | AOUT_CHAN_LFE:
219         return "2F1R/LFE";
220     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
221           | AOUT_CHAN_REARCENTER | AOUT_CHAN_LFE:
222         return "3F1R/LFE";
223     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
224           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
225         return "2F2R/LFE";
226     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
227           | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
228         return "2F2M/LFE";
229     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
230           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
231         return "3F2R/LFE";
232     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
233           | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
234         return "3F2M/LFE";
235     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
236           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
237           | AOUT_CHAN_MIDDLERIGHT:
238         return "3F2M2R";
239     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
240           | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
241           | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
242         return "3F2M2R/LFE";
243     case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
244           | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
245           | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
246         return "3F2M1R/LFE";
247     }
248
249     return "ERROR";
250 }
251
252 #undef aout_FormatPrint
253 /**
254  * Prints an audio sample format in a human-readable form.
255  */
256 void aout_FormatPrint( vlc_object_t *obj, const char *psz_text,
257                        const audio_sample_format_t *p_format )
258 {
259     msg_Dbg( obj, "%s '%4.4s' %d Hz %s frame=%d samples/%d bytes", psz_text,
260              (char *)&p_format->i_format, p_format->i_rate,
261              aout_FormatPrintChannels( p_format ),
262              p_format->i_frame_length, p_format->i_bytes_per_frame );
263 }
264
265 #undef aout_FormatsPrint
266 /**
267  * Prints two formats in a human-readable form
268  */
269 void aout_FormatsPrint( vlc_object_t *obj, const char * psz_text,
270                         const audio_sample_format_t * p_format1,
271                         const audio_sample_format_t * p_format2 )
272 {
273     msg_Dbg( obj, "%s '%4.4s'->'%4.4s' %d Hz->%d Hz %s->%s",
274              psz_text,
275              (char *)&p_format1->i_format, (char *)&p_format2->i_format,
276              p_format1->i_rate, p_format2->i_rate,
277              aout_FormatPrintChannels( p_format1 ),
278              aout_FormatPrintChannels( p_format2 ) );
279 }
280
281 /*****************************************************************************
282  * aout_CheckChannelReorder : Check if we need to do some channel re-ordering
283  *****************************************************************************/
284 unsigned aout_CheckChannelReorder( const uint32_t *chans_in,
285                                    const uint32_t *chans_out,
286                                    uint32_t mask, uint8_t *restrict table )
287 {
288     unsigned channels = 0;
289
290     if( chans_in == NULL )
291         chans_in = pi_vlc_chan_order_wg4;
292     if( chans_out == NULL )
293         chans_out = pi_vlc_chan_order_wg4;
294
295     for( unsigned i = 0; chans_in[i]; i++ )
296     {
297         const uint32_t chan = chans_in[i];
298         if( !(mask & chan) )
299             continue;
300
301         unsigned index = 0;
302         for( unsigned j = 0; chan != chans_out[j]; j++ )
303             if( mask & chans_out[j] )
304                 index++;
305
306         table[channels++] = index;
307     }
308
309     for( unsigned i = 0; i < channels; i++ )
310         if( table[i] != i )
311             return channels;
312     return 0;
313 }
314
315 /*****************************************************************************
316  * aout_ChannelReorder :
317  *****************************************************************************/
318 void aout_ChannelReorder( void *ptr, size_t bytes, unsigned channels,
319                           const uint8_t *chans_table, unsigned bits_per_sample )
320 {
321     size_t samples = bytes / (channels * (bits_per_sample >> 3));
322
323     assert( channels <= AOUT_CHAN_MAX );
324
325     switch( bits_per_sample )
326     {
327         case 32:
328         {
329             uint32_t *buf = ptr;
330
331             for( size_t i = 0; i < samples; i++ )
332             {
333                 uint32_t tmp[AOUT_CHAN_MAX];
334
335                 for( size_t j = 0; j < channels; j++ )
336                     tmp[chans_table[j]] = buf[j];
337
338                 memcpy( buf, tmp, 4 * channels );
339                 buf += channels;
340             }
341             break;
342         }
343
344         case 16:
345         {
346             uint16_t *buf = ptr;
347
348             for( size_t i = 0; i < samples; i++ )
349             {
350                 uint16_t tmp[AOUT_CHAN_MAX];
351
352                 for( size_t j = 0; j < channels; j++ )
353                     tmp[chans_table[j]] = buf[j];
354
355                 memcpy( buf, tmp, 2 * channels );
356                 buf += channels;
357             }
358             break;
359         }
360
361         case 8:
362         {
363             uint8_t *buf = ptr;
364
365             for( size_t i = 0; i < samples; i++ )
366             {
367                 uint8_t tmp[AOUT_CHAN_MAX];
368
369                 for( size_t j = 0; j < channels; j++ )
370                     tmp[chans_table[j]] = buf[j];
371
372                 memcpy( buf, tmp, channels );
373                 buf += channels;
374             }
375             break;
376         }
377
378         case 24:
379         {
380             uint8_t *buf = ptr;
381
382             for( size_t i = 0; i < samples; i++ )
383             {
384                 uint8_t tmp[3 * AOUT_CHAN_MAX];
385
386                 for( size_t j = 0; j < channels; j++ )
387                     memcpy( tmp + (3 * chans_table[j]), buf + (3 * j), 3 );
388
389                 memcpy( buf, tmp, 3 * channels );
390                 buf += 3 * channels;
391             }
392         }
393     }
394 }
395
396 /*****************************************************************************
397  * aout_ChannelExtract:
398  *****************************************************************************/
399 static inline void ExtractChannel( uint8_t *pi_dst, int i_dst_channels,
400                                    const uint8_t *pi_src, int i_src_channels,
401                                    int i_sample_count,
402                                    const int *pi_selection, int i_bytes )
403 {
404     for( int i = 0; i < i_sample_count; i++ )
405     {
406         for( int j = 0; j < i_dst_channels; j++ )
407             memcpy( &pi_dst[j * i_bytes], &pi_src[pi_selection[j] * i_bytes], i_bytes );
408         pi_dst += i_dst_channels * i_bytes;
409         pi_src += i_src_channels * i_bytes;
410     }
411 }
412
413 void aout_ChannelExtract( void *p_dst, int i_dst_channels,
414                           const void *p_src, int i_src_channels,
415                           int i_sample_count, const int *pi_selection, int i_bits_per_sample )
416 {
417     /* It does not work in place */
418     assert( p_dst != p_src );
419
420     /* Force the compiler to inline for the specific cases so it can optimize */
421     if( i_bits_per_sample == 8 )
422         ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 1 );
423     else  if( i_bits_per_sample == 16 )
424         ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 2 );
425     else  if( i_bits_per_sample == 24 )
426         ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 3 );
427     else  if( i_bits_per_sample == 32 )
428         ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 4 );
429     else  if( i_bits_per_sample == 64 )
430         ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 8 );
431 }
432
433 bool aout_CheckChannelExtraction( int *pi_selection,
434                                   uint32_t *pi_layout, int *pi_channels,
435                                   const uint32_t pi_order_dst[AOUT_CHAN_MAX],
436                                   const uint32_t *pi_order_src, int i_channels )
437 {
438     const uint32_t pi_order_dual_mono[] = { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT };
439     uint32_t i_layout = 0;
440     int i_out = 0;
441     int pi_index[AOUT_CHAN_MAX];
442
443     /* */
444     if( !pi_order_dst )
445         pi_order_dst = pi_vlc_chan_order_wg4;
446
447     /* Detect special dual mono case */
448     if( i_channels == 2 &&
449         pi_order_src[0] == AOUT_CHAN_CENTER && pi_order_src[1] == AOUT_CHAN_CENTER )
450     {
451         i_layout |= AOUT_CHAN_DUALMONO;
452         pi_order_src = pi_order_dual_mono;
453     }
454
455     /* */
456     for( int i = 0; i < i_channels; i++ )
457     {
458         /* Ignore unknown or duplicated channels or not present in output */
459         if( !pi_order_src[i] || (i_layout & pi_order_src[i]) )
460             continue;
461
462         for( int j = 0; j < AOUT_CHAN_MAX; j++ )
463         {
464             if( pi_order_dst[j] == pi_order_src[i] )
465             {
466                 assert( i_out < AOUT_CHAN_MAX );
467                 pi_index[i_out++] = i;
468                 i_layout |= pi_order_src[i];
469                 break;
470             }
471         }
472     }
473
474     /* */
475     for( int i = 0, j = 0; i < AOUT_CHAN_MAX; i++ )
476     {
477         for( int k = 0; k < i_out; k++ )
478         {
479             if( pi_order_dst[i] == pi_order_src[pi_index[k]] )
480             {
481                 pi_selection[j++] = pi_index[k];
482                 break;
483             }
484         }
485     }
486
487     *pi_layout = i_layout;
488     *pi_channels = i_out;
489
490     for( int i = 0; i < i_out; i++ )
491     {
492         if( pi_selection[i] != i )
493             return true;
494     }
495     return i_out == i_channels;
496 }
497
498 /* Return the order in which filters should be inserted */
499 static int FilterOrder( const char *psz_name )
500 {
501     static const struct {
502         const char psz_name[10];
503         int        i_order;
504     } filter[] = {
505         { "equalizer",  0 },
506     };
507     for( unsigned i = 0; i < ARRAY_SIZE(filter); i++ )
508     {
509         if( !strcmp( filter[i].psz_name, psz_name ) )
510             return filter[i].i_order;
511     }
512     return INT_MAX;
513 }
514
515 /* This function will add or remove a a module from a string list (colon
516  * separated). It will return true if there is a modification
517  * In case p_aout is NULL, we will use configuration instead of variable */
518 bool aout_ChangeFilterString( vlc_object_t *p_obj, vlc_object_t *p_aout,
519                               const char *psz_variable,
520                               const char *psz_name, bool b_add )
521 {
522     if( *psz_name == '\0' )
523         return false;
524
525     char *psz_list;
526     if( p_aout )
527     {
528         psz_list = var_GetString( p_aout, psz_variable );
529     }
530     else
531     {
532         psz_list = var_CreateGetString( p_obj->p_libvlc, psz_variable );
533         var_Destroy( p_obj->p_libvlc, psz_variable );
534     }
535
536     /* Split the string into an array of filters */
537     int i_count = 1;
538     for( char *p = psz_list; p && *p; p++ )
539         i_count += *p == ':';
540     i_count += b_add;
541
542     const char **ppsz_filter = calloc( i_count, sizeof(*ppsz_filter) );
543     if( !ppsz_filter )
544     {
545         free( psz_list );
546         return false;
547     }
548     bool b_present = false;
549     i_count = 0;
550     for( char *p = psz_list; p && *p; )
551     {
552         char *psz_end = strchr(p, ':');
553         if( psz_end )
554             *psz_end++ = '\0';
555         else
556             psz_end = p + strlen(p);
557         if( *p )
558         {
559             b_present |= !strcmp( p, psz_name );
560             ppsz_filter[i_count++] = p;
561         }
562         p = psz_end;
563     }
564     if( b_present == b_add )
565     {
566         free( ppsz_filter );
567         free( psz_list );
568         return false;
569     }
570
571     if( b_add )
572     {
573         int i_order = FilterOrder( psz_name );
574         int i;
575         for( i = 0; i < i_count; i++ )
576         {
577             if( FilterOrder( ppsz_filter[i] ) > i_order )
578                 break;
579         }
580         if( i < i_count )
581             memmove( &ppsz_filter[i+1], &ppsz_filter[i], (i_count - i) * sizeof(*ppsz_filter) );
582         ppsz_filter[i] = psz_name;
583         i_count++;
584     }
585     else
586     {
587         for( int i = 0; i < i_count; i++ )
588         {
589             if( !strcmp( ppsz_filter[i], psz_name ) )
590                 ppsz_filter[i] = "";
591         }
592     }
593     size_t i_length = 0;
594     for( int i = 0; i < i_count; i++ )
595         i_length += 1 + strlen( ppsz_filter[i] );
596
597     char *psz_new = malloc( i_length + 1 );
598     *psz_new = '\0';
599     for( int i = 0; i < i_count; i++ )
600     {
601         if( *ppsz_filter[i] == '\0' )
602             continue;
603         if( *psz_new )
604             strcat( psz_new, ":" );
605         strcat( psz_new, ppsz_filter[i] );
606     }
607     free( ppsz_filter );
608     free( psz_list );
609
610     if( p_aout )
611         var_SetString( p_aout, psz_variable, psz_new );
612     else
613         config_PutPsz( p_obj, psz_variable, psz_new );
614     free( psz_new );
615
616     return true;
617 }