1 /*****************************************************************************
2 * common.c : audio output management of common data structures
3 *****************************************************************************
4 * Copyright (C) 2002-2007 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
33 #include "aout_internal.h"
36 * Instances management (internal and external)
40 static void aout_Destructor( vlc_object_t
* p_this
);
42 /*****************************************************************************
43 * aout_New: initialize aout structure
44 *****************************************************************************/
45 aout_instance_t
* __aout_New( vlc_object_t
* p_parent
)
47 aout_instance_t
* p_aout
;
50 /* Allocate descriptor. */
51 p_aout
= vlc_object_create( p_parent
, VLC_OBJECT_AOUT
);
57 /* Initialize members. */
58 vlc_mutex_init( &p_aout
->input_fifos_lock
);
59 vlc_mutex_init( &p_aout
->mixer_lock
);
60 vlc_mutex_init( &p_aout
->output_fifo_lock
);
61 p_aout
->i_nb_inputs
= 0;
62 p_aout
->mixer
.f_multiplier
= 1.0;
63 p_aout
->mixer
.b_error
= 1;
64 p_aout
->output
.b_error
= 1;
65 p_aout
->output
.b_starving
= 1;
67 var_Create( p_aout
, "intf-change", VLC_VAR_BOOL
);
69 var_Set( p_aout
, "intf-change", val
);
71 vlc_object_set_destructor( p_aout
, aout_Destructor
);
76 /*****************************************************************************
77 * aout_Destructor: destroy aout structure
78 *****************************************************************************/
79 static void aout_Destructor( vlc_object_t
* p_this
)
81 aout_instance_t
* p_aout
= (aout_instance_t
*)p_this
;
82 vlc_mutex_destroy( &p_aout
->input_fifos_lock
);
83 vlc_mutex_destroy( &p_aout
->mixer_lock
);
84 vlc_mutex_destroy( &p_aout
->output_fifo_lock
);
89 * Formats management (internal and external)
92 /*****************************************************************************
93 * aout_FormatNbChannels : return the number of channels
94 *****************************************************************************/
95 unsigned int aout_FormatNbChannels( const audio_sample_format_t
* p_format
)
97 static const uint32_t pi_channels
[] =
98 { AOUT_CHAN_CENTER
, AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
,
99 AOUT_CHAN_REARCENTER
, AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
,
100 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
, AOUT_CHAN_LFE
};
101 unsigned int i_nb
= 0, i
;
103 for ( i
= 0; i
< sizeof(pi_channels
)/sizeof(uint32_t); i
++ )
105 if ( p_format
->i_physical_channels
& pi_channels
[i
] ) i_nb
++;
111 /*****************************************************************************
112 * aout_BitsPerSample : get the number of bits per sample
113 *****************************************************************************/
114 unsigned int aout_BitsPerSample( vlc_fourcc_t i_format
)
118 case VLC_FOURCC('u','8',' ',' '):
119 case VLC_FOURCC('s','8',' ',' '):
122 case VLC_FOURCC('u','1','6','l'):
123 case VLC_FOURCC('s','1','6','l'):
124 case VLC_FOURCC('u','1','6','b'):
125 case VLC_FOURCC('s','1','6','b'):
128 case VLC_FOURCC('u','2','4','l'):
129 case VLC_FOURCC('s','2','4','l'):
130 case VLC_FOURCC('u','2','4','b'):
131 case VLC_FOURCC('s','2','4','b'):
134 case VLC_FOURCC('f','l','3','2'):
135 case VLC_FOURCC('f','i','3','2'):
138 case VLC_FOURCC('f','l','6','4'):
142 /* For these formats the caller has to indicate the parameters
148 /*****************************************************************************
149 * aout_FormatPrepare : compute the number of bytes per frame & frame length
150 *****************************************************************************/
151 void aout_FormatPrepare( audio_sample_format_t
* p_format
)
153 p_format
->i_bitspersample
= aout_BitsPerSample( p_format
->i_format
);
154 if( p_format
->i_bitspersample
> 0 )
156 p_format
->i_bytes_per_frame
= ( p_format
->i_bitspersample
/ 8 )
157 * aout_FormatNbChannels( p_format
);
158 p_format
->i_frame_length
= 1;
162 /*****************************************************************************
163 * aout_FormatPrintChannels : print a channel in a human-readable form
164 *****************************************************************************/
165 const char * aout_FormatPrintChannels( const audio_sample_format_t
* p_format
)
167 switch ( p_format
->i_physical_channels
& AOUT_CHAN_PHYSMASK
)
169 case AOUT_CHAN_CENTER
:
170 if ( (p_format
->i_original_channels
& AOUT_CHAN_CENTER
)
171 || (p_format
->i_original_channels
172 & (AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
)) )
174 else if ( p_format
->i_original_channels
& AOUT_CHAN_LEFT
)
177 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
:
178 if ( p_format
->i_original_channels
& AOUT_CHAN_REVERSESTEREO
)
180 if ( p_format
->i_original_channels
& AOUT_CHAN_DOLBYSTEREO
)
181 return "Dolby/Reverse";
182 return "Stereo/Reverse";
186 if ( p_format
->i_original_channels
& AOUT_CHAN_DOLBYSTEREO
)
188 else if ( p_format
->i_original_channels
& AOUT_CHAN_DUALMONO
)
190 else if ( p_format
->i_original_channels
== AOUT_CHAN_CENTER
)
191 return "Stereo/Mono";
192 else if ( !(p_format
->i_original_channels
& AOUT_CHAN_RIGHT
) )
193 return "Stereo/Left";
194 else if ( !(p_format
->i_original_channels
& AOUT_CHAN_LEFT
) )
195 return "Stereo/Right";
198 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
:
200 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARCENTER
:
202 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
203 | AOUT_CHAN_REARCENTER
:
205 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
206 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
:
208 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
209 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
:
212 case AOUT_CHAN_CENTER
| AOUT_CHAN_LFE
:
213 if ( (p_format
->i_original_channels
& AOUT_CHAN_CENTER
)
214 || (p_format
->i_original_channels
215 & (AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
)) )
217 else if ( p_format
->i_original_channels
& AOUT_CHAN_LEFT
)
220 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_LFE
:
221 if ( p_format
->i_original_channels
& AOUT_CHAN_DOLBYSTEREO
)
223 else if ( p_format
->i_original_channels
& AOUT_CHAN_DUALMONO
)
224 return "Dual-mono/LFE";
225 else if ( p_format
->i_original_channels
== AOUT_CHAN_CENTER
)
227 else if ( !(p_format
->i_original_channels
& AOUT_CHAN_RIGHT
) )
228 return "Stereo/Left/LFE";
229 else if ( !(p_format
->i_original_channels
& AOUT_CHAN_LEFT
) )
230 return "Stereo/Right/LFE";
232 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
| AOUT_CHAN_LFE
:
234 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARCENTER
237 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
238 | AOUT_CHAN_REARCENTER
| AOUT_CHAN_LFE
:
240 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
241 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
:
243 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
244 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
:
246 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
247 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
248 | AOUT_CHAN_MIDDLERIGHT
:
250 case AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
251 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
252 | AOUT_CHAN_MIDDLERIGHT
| AOUT_CHAN_LFE
:
259 /*****************************************************************************
260 * aout_FormatPrint : print a format in a human-readable form
261 *****************************************************************************/
262 void aout_FormatPrint( aout_instance_t
* p_aout
, const char * psz_text
,
263 const audio_sample_format_t
* p_format
)
265 msg_Dbg( p_aout
, "%s '%4.4s' %d Hz %s frame=%d samples/%d bytes", psz_text
,
266 (char *)&p_format
->i_format
, p_format
->i_rate
,
267 aout_FormatPrintChannels( p_format
),
268 p_format
->i_frame_length
, p_format
->i_bytes_per_frame
);
271 /*****************************************************************************
272 * aout_FormatsPrint : print two formats in a human-readable form
273 *****************************************************************************/
274 void aout_FormatsPrint( aout_instance_t
* p_aout
, const char * psz_text
,
275 const audio_sample_format_t
* p_format1
,
276 const audio_sample_format_t
* p_format2
)
278 msg_Dbg( p_aout
, "%s '%4.4s'->'%4.4s' %d Hz->%d Hz %s->%s",
280 (char *)&p_format1
->i_format
, (char *)&p_format2
->i_format
,
281 p_format1
->i_rate
, p_format2
->i_rate
,
282 aout_FormatPrintChannels( p_format1
),
283 aout_FormatPrintChannels( p_format2
) );
288 * FIFO management (internal) - please understand that solving race conditions
289 * is _your_ job, ie. in the audio output you should own the mixer lock
290 * before calling any of these functions.
293 /*****************************************************************************
294 * aout_FifoInit : initialize the members of a FIFO
295 *****************************************************************************/
296 void aout_FifoInit( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
,
301 msg_Err( p_aout
, "initialising fifo with zero divider" );
304 p_fifo
->p_first
= NULL
;
305 p_fifo
->pp_last
= &p_fifo
->p_first
;
306 aout_DateInit( &p_fifo
->end_date
, i_rate
);
309 /*****************************************************************************
310 * aout_FifoPush : push a packet into the FIFO
311 *****************************************************************************/
312 void aout_FifoPush( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
,
313 aout_buffer_t
* p_buffer
)
316 *p_fifo
->pp_last
= p_buffer
;
317 p_fifo
->pp_last
= &p_buffer
->p_next
;
318 *p_fifo
->pp_last
= NULL
;
319 /* Enforce the continuity of the stream. */
320 if ( aout_DateGet( &p_fifo
->end_date
) )
322 p_buffer
->start_date
= aout_DateGet( &p_fifo
->end_date
);
323 p_buffer
->end_date
= aout_DateIncrement( &p_fifo
->end_date
,
324 p_buffer
->i_nb_samples
);
328 aout_DateSet( &p_fifo
->end_date
, p_buffer
->end_date
);
332 /*****************************************************************************
333 * aout_FifoSet : set end_date and trash all buffers (because they aren't
335 *****************************************************************************/
336 void aout_FifoSet( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
,
339 aout_buffer_t
* p_buffer
;
342 aout_DateSet( &p_fifo
->end_date
, date
);
343 p_buffer
= p_fifo
->p_first
;
344 while ( p_buffer
!= NULL
)
346 aout_buffer_t
* p_next
= p_buffer
->p_next
;
347 aout_BufferFree( p_buffer
);
350 p_fifo
->p_first
= NULL
;
351 p_fifo
->pp_last
= &p_fifo
->p_first
;
354 /*****************************************************************************
355 * aout_FifoMoveDates : Move forwards or backwards all dates in the FIFO
356 *****************************************************************************/
357 void aout_FifoMoveDates( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
,
360 aout_buffer_t
* p_buffer
;
363 aout_DateMove( &p_fifo
->end_date
, difference
);
364 p_buffer
= p_fifo
->p_first
;
365 while ( p_buffer
!= NULL
)
367 p_buffer
->start_date
+= difference
;
368 p_buffer
->end_date
+= difference
;
369 p_buffer
= p_buffer
->p_next
;
373 /*****************************************************************************
374 * aout_FifoNextStart : return the current end_date
375 *****************************************************************************/
376 mtime_t
aout_FifoNextStart( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
)
379 return aout_DateGet( &p_fifo
->end_date
);
382 /*****************************************************************************
383 * aout_FifoFirstDate : return the playing date of the first buffer in the
385 *****************************************************************************/
386 mtime_t
aout_FifoFirstDate( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
)
389 return p_fifo
->p_first
? p_fifo
->p_first
->start_date
: 0;
392 /*****************************************************************************
393 * aout_FifoPop : get the next buffer out of the FIFO
394 *****************************************************************************/
395 aout_buffer_t
* aout_FifoPop( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
)
397 aout_buffer_t
* p_buffer
;
400 p_buffer
= p_fifo
->p_first
;
401 if ( p_buffer
== NULL
) return NULL
;
402 p_fifo
->p_first
= p_buffer
->p_next
;
403 if ( p_fifo
->p_first
== NULL
)
405 p_fifo
->pp_last
= &p_fifo
->p_first
;
411 /*****************************************************************************
412 * aout_FifoDestroy : destroy a FIFO and its buffers
413 *****************************************************************************/
414 void aout_FifoDestroy( aout_instance_t
* p_aout
, aout_fifo_t
* p_fifo
)
416 aout_buffer_t
* p_buffer
;
419 p_buffer
= p_fifo
->p_first
;
420 while ( p_buffer
!= NULL
)
422 aout_buffer_t
* p_next
= p_buffer
->p_next
;
423 aout_BufferFree( p_buffer
);
427 p_fifo
->p_first
= NULL
;
428 p_fifo
->pp_last
= &p_fifo
->p_first
;
433 * Date management (internal and external)
436 /*****************************************************************************
437 * aout_DateInit : set the divider of an audio_date_t
438 *****************************************************************************/
439 void aout_DateInit( audio_date_t
* p_date
, uint32_t i_divider
)
442 p_date
->i_divider
= i_divider
;
443 p_date
->i_remainder
= 0;
446 /*****************************************************************************
447 * aout_DateSet : set the date of an audio_date_t
448 *****************************************************************************/
449 void aout_DateSet( audio_date_t
* p_date
, mtime_t new_date
)
451 p_date
->date
= new_date
;
452 p_date
->i_remainder
= 0;
455 /*****************************************************************************
456 * aout_DateMove : move forwards or backwards the date of an audio_date_t
457 *****************************************************************************/
458 void aout_DateMove( audio_date_t
* p_date
, mtime_t difference
)
460 p_date
->date
+= difference
;
463 /*****************************************************************************
464 * aout_DateGet : get the date of an audio_date_t
465 *****************************************************************************/
466 mtime_t
aout_DateGet( const audio_date_t
* p_date
)
471 /*****************************************************************************
472 * aout_DateIncrement : increment the date and return the result, taking
473 * into account rounding errors
474 *****************************************************************************/
475 mtime_t
aout_DateIncrement( audio_date_t
* p_date
, uint32_t i_nb_samples
)
477 mtime_t i_dividend
= (mtime_t
)i_nb_samples
* 1000000;
478 p_date
->date
+= i_dividend
/ p_date
->i_divider
;
479 p_date
->i_remainder
+= (int)(i_dividend
% p_date
->i_divider
);
480 if ( p_date
->i_remainder
>= p_date
->i_divider
)
482 /* This is Bresenham algorithm. */
484 p_date
->i_remainder
-= p_date
->i_divider
;
489 /*****************************************************************************
490 * aout_CheckChannelReorder : Check if we need to do some channel re-ordering
491 *****************************************************************************/
492 int aout_CheckChannelReorder( const uint32_t *pi_chan_order_in
,
493 const uint32_t *pi_chan_order_out
,
494 uint32_t i_channel_mask
,
495 int i_channels
, int *pi_chan_table
)
497 bool b_chan_reorder
= false;
500 if( i_channels
> AOUT_CHAN_MAX
) return false;
502 for( i
= 0, j
= 0; pi_chan_order_in
[i
]; i
++ )
504 if( !(i_channel_mask
& pi_chan_order_in
[i
]) ) continue;
506 for( k
= 0, l
= 0; pi_chan_order_in
[i
] != pi_chan_order_out
[k
]; k
++ )
508 if( i_channel_mask
& pi_chan_order_out
[k
] ) l
++;
511 pi_chan_table
[j
++] = l
;
514 for( i
= 0; i
< i_channels
; i
++ )
516 if( pi_chan_table
[i
] != i
) b_chan_reorder
= true;
519 return b_chan_reorder
;
522 /*****************************************************************************
523 * aout_ChannelReorder :
524 *****************************************************************************/
525 void aout_ChannelReorder( uint8_t *p_buf
, int i_buffer
,
526 int i_channels
, const int *pi_chan_table
,
527 int i_bits_per_sample
)
529 uint8_t p_tmp
[AOUT_CHAN_MAX
* 4];
532 if( i_bits_per_sample
== 8 )
534 for( i
= 0; i
< i_buffer
/ i_channels
; i
++ )
536 for( j
= 0; j
< i_channels
; j
++ )
538 p_tmp
[pi_chan_table
[j
]] = p_buf
[j
];
541 memcpy( p_buf
, p_tmp
, i_channels
);
545 else if( i_bits_per_sample
== 16 )
547 for( i
= 0; i
< i_buffer
/ i_channels
/ 2; i
++ )
549 for( j
= 0; j
< i_channels
; j
++ )
551 p_tmp
[2 * pi_chan_table
[j
]] = p_buf
[2 * j
];
552 p_tmp
[2 * pi_chan_table
[j
] + 1] = p_buf
[2 * j
+ 1];
555 memcpy( p_buf
, p_tmp
, 2 * i_channels
);
556 p_buf
+= 2 * i_channels
;
559 else if( i_bits_per_sample
== 24 )
561 for( i
= 0; i
< i_buffer
/ i_channels
/ 3; i
++ )
563 for( j
= 0; j
< i_channels
; j
++ )
565 p_tmp
[3 * pi_chan_table
[j
]] = p_buf
[3 * j
];
566 p_tmp
[3 * pi_chan_table
[j
] + 1] = p_buf
[3 * j
+ 1];
567 p_tmp
[3 * pi_chan_table
[j
] + 2] = p_buf
[3 * j
+ 2];
570 memcpy( p_buf
, p_tmp
, 3 * i_channels
);
571 p_buf
+= 3 * i_channels
;
574 else if( i_bits_per_sample
== 32 )
576 for( i
= 0; i
< i_buffer
/ i_channels
/ 4; i
++ )
578 for( j
= 0; j
< i_channels
; j
++ )
580 p_tmp
[4 * pi_chan_table
[j
]] = p_buf
[4 * j
];
581 p_tmp
[4 * pi_chan_table
[j
] + 1] = p_buf
[4 * j
+ 1];
582 p_tmp
[4 * pi_chan_table
[j
] + 2] = p_buf
[4 * j
+ 2];
583 p_tmp
[4 * pi_chan_table
[j
] + 3] = p_buf
[4 * j
+ 3];
586 memcpy( p_buf
, p_tmp
, 4 * i_channels
);
587 p_buf
+= 4 * i_channels
;