00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #include <vlc/vlc.h>
00031
00032 #include "audio_output.h"
00033 #include "aout_internal.h"
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 aout_instance_t * __aout_New( vlc_object_t * p_parent )
00044 {
00045 aout_instance_t * p_aout;
00046 vlc_value_t val;
00047
00048
00049 p_aout = vlc_object_create( p_parent, VLC_OBJECT_AOUT );
00050 if( p_aout == NULL )
00051 {
00052 return NULL;
00053 }
00054
00055
00056 vlc_mutex_init( p_parent, &p_aout->input_fifos_lock );
00057 vlc_mutex_init( p_parent, &p_aout->mixer_lock );
00058 vlc_mutex_init( p_parent, &p_aout->output_fifo_lock );
00059 p_aout->i_nb_inputs = 0;
00060 p_aout->mixer.f_multiplier = 1.0;
00061 p_aout->mixer.b_error = 1;
00062 p_aout->output.b_error = 1;
00063 p_aout->output.b_starving = 1;
00064
00065 var_Create( p_aout, "intf-change", VLC_VAR_BOOL );
00066 val.b_bool = VLC_TRUE;
00067 var_Set( p_aout, "intf-change", val );
00068
00069 return p_aout;
00070 }
00071
00072
00073
00074
00075 void aout_Delete( aout_instance_t * p_aout )
00076 {
00077 var_Destroy( p_aout, "intf-change" );
00078
00079 vlc_mutex_destroy( &p_aout->input_fifos_lock );
00080 vlc_mutex_destroy( &p_aout->mixer_lock );
00081 vlc_mutex_destroy( &p_aout->output_fifo_lock );
00082
00083
00084 vlc_object_destroy( p_aout );
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 unsigned int aout_FormatNbChannels( const audio_sample_format_t * p_format )
00096 {
00097 static const uint32_t pi_channels[] =
00098 { AOUT_CHAN_CENTER, AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
00099 AOUT_CHAN_REARCENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
00100 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_LFE };
00101 unsigned int i_nb = 0, i;
00102
00103 for ( i = 0; i < sizeof(pi_channels)/sizeof(uint32_t); i++ )
00104 {
00105 if ( p_format->i_physical_channels & pi_channels[i] ) i_nb++;
00106 }
00107
00108 return i_nb;
00109 }
00110
00111
00112
00113
00114 void aout_FormatPrepare( audio_sample_format_t * p_format )
00115 {
00116 int i_result;
00117
00118 switch ( p_format->i_format )
00119 {
00120 case VLC_FOURCC('u','8',' ',' '):
00121 case VLC_FOURCC('s','8',' ',' '):
00122 i_result = 1;
00123 break;
00124
00125 case VLC_FOURCC('u','1','6','l'):
00126 case VLC_FOURCC('s','1','6','l'):
00127 case VLC_FOURCC('u','1','6','b'):
00128 case VLC_FOURCC('s','1','6','b'):
00129 i_result = 2;
00130 break;
00131
00132 case VLC_FOURCC('u','2','4','l'):
00133 case VLC_FOURCC('s','2','4','l'):
00134 case VLC_FOURCC('u','2','4','b'):
00135 case VLC_FOURCC('s','2','4','b'):
00136 i_result = 3;
00137 break;
00138
00139 case VLC_FOURCC('f','l','3','2'):
00140 case VLC_FOURCC('f','i','3','2'):
00141 i_result = 4;
00142 break;
00143
00144 case VLC_FOURCC('s','p','d','i'):
00145 case VLC_FOURCC('s','p','d','b'):
00146 case VLC_FOURCC('a','5','2',' '):
00147 case VLC_FOURCC('d','t','s',' '):
00148 case VLC_FOURCC('m','p','g','a'):
00149 case VLC_FOURCC('m','p','g','3'):
00150 default:
00151
00152
00153 return;
00154 }
00155
00156 p_format->i_bytes_per_frame = i_result * aout_FormatNbChannels( p_format );
00157 p_format->i_frame_length = 1;
00158 }
00159
00160
00161
00162
00163 const char * aout_FormatPrintChannels( const audio_sample_format_t * p_format )
00164 {
00165 switch ( p_format->i_physical_channels & AOUT_CHAN_PHYSMASK )
00166 {
00167 case AOUT_CHAN_CENTER:
00168 if ( (p_format->i_original_channels & AOUT_CHAN_CENTER)
00169 || (p_format->i_original_channels
00170 & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
00171 return "Mono";
00172 else if ( p_format->i_original_channels & AOUT_CHAN_LEFT )
00173 return "Left";
00174 return "Right";
00175 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT:
00176 if ( p_format->i_original_channels & AOUT_CHAN_REVERSESTEREO )
00177 {
00178 if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
00179 return "Dolby/Reverse";
00180 return "Stereo/Reverse";
00181 }
00182 else
00183 {
00184 if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
00185 return "Dolby";
00186 else if ( p_format->i_original_channels & AOUT_CHAN_DUALMONO )
00187 return "Dual-mono";
00188 else if ( p_format->i_original_channels == AOUT_CHAN_CENTER )
00189 return "Stereo/Mono";
00190 else if ( !(p_format->i_original_channels & AOUT_CHAN_RIGHT) )
00191 return "Stereo/Left";
00192 else if ( !(p_format->i_original_channels & AOUT_CHAN_LEFT) )
00193 return "Stereo/Right";
00194 return "Stereo";
00195 }
00196 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER:
00197 return "3F";
00198 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER:
00199 return "2F1R";
00200 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00201 | AOUT_CHAN_REARCENTER:
00202 return "3F1R";
00203 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
00204 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
00205 return "2F2R";
00206 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00207 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
00208 return "3F2R";
00209
00210 case AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
00211 if ( (p_format->i_original_channels & AOUT_CHAN_CENTER)
00212 || (p_format->i_original_channels
00213 & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
00214 return "Mono/LFE";
00215 else if ( p_format->i_original_channels & AOUT_CHAN_LEFT )
00216 return "Left/LFE";
00217 return "Right/LFE";
00218 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE:
00219 if ( p_format->i_original_channels & AOUT_CHAN_DOLBYSTEREO )
00220 return "Dolby/LFE";
00221 else if ( p_format->i_original_channels & AOUT_CHAN_DUALMONO )
00222 return "Dual-mono/LFE";
00223 else if ( p_format->i_original_channels == AOUT_CHAN_CENTER )
00224 return "Mono/LFE";
00225 else if ( !(p_format->i_original_channels & AOUT_CHAN_RIGHT) )
00226 return "Stereo/Left/LFE";
00227 else if ( !(p_format->i_original_channels & AOUT_CHAN_LEFT) )
00228 return "Stereo/Right/LFE";
00229 return "Stereo/LFE";
00230 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
00231 return "3F/LFE";
00232 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER
00233 | AOUT_CHAN_LFE:
00234 return "2F1R/LFE";
00235 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00236 | AOUT_CHAN_REARCENTER | AOUT_CHAN_LFE:
00237 return "3F1R/LFE";
00238 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
00239 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
00240 return "2F2R/LFE";
00241 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00242 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
00243 return "3F2R/LFE";
00244 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00245 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
00246 | AOUT_CHAN_MIDDLERIGHT:
00247 return "3F2M2R";
00248 case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00249 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
00250 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
00251 return "3F2M2R/LFE";
00252 }
00253
00254 return "ERROR";
00255 }
00256
00257
00258
00259
00260 void aout_FormatPrint( aout_instance_t * p_aout, const char * psz_text,
00261 const audio_sample_format_t * p_format )
00262 {
00263 msg_Dbg( p_aout, "%s '%4.4s' %d Hz %s frame=%d samples/%d bytes", psz_text,
00264 (char *)&p_format->i_format, p_format->i_rate,
00265 aout_FormatPrintChannels( p_format ),
00266 p_format->i_frame_length, p_format->i_bytes_per_frame );
00267 }
00268
00269
00270
00271
00272 void aout_FormatsPrint( aout_instance_t * p_aout, const char * psz_text,
00273 const audio_sample_format_t * p_format1,
00274 const audio_sample_format_t * p_format2 )
00275 {
00276 msg_Dbg( p_aout, "%s '%4.4s'->'%4.4s' %d Hz->%d Hz %s->%s",
00277 psz_text,
00278 (char *)&p_format1->i_format, (char *)&p_format2->i_format,
00279 p_format1->i_rate, p_format2->i_rate,
00280 aout_FormatPrintChannels( p_format1 ),
00281 aout_FormatPrintChannels( p_format2 ) );
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 void aout_FifoInit( aout_instance_t * p_aout, aout_fifo_t * p_fifo,
00295 uint32_t i_rate )
00296 {
00297 p_fifo->p_first = NULL;
00298 p_fifo->pp_last = &p_fifo->p_first;
00299 aout_DateInit( &p_fifo->end_date, i_rate );
00300 }
00301
00302
00303
00304
00305 void aout_FifoPush( aout_instance_t * p_aout, aout_fifo_t * p_fifo,
00306 aout_buffer_t * p_buffer )
00307 {
00308 *p_fifo->pp_last = p_buffer;
00309 p_fifo->pp_last = &p_buffer->p_next;
00310 *p_fifo->pp_last = NULL;
00311
00312 if ( aout_DateGet( &p_fifo->end_date ) )
00313 {
00314 p_buffer->start_date = aout_DateGet( &p_fifo->end_date );
00315 p_buffer->end_date = aout_DateIncrement( &p_fifo->end_date,
00316 p_buffer->i_nb_samples );
00317 }
00318 else
00319 {
00320 aout_DateSet( &p_fifo->end_date, p_buffer->end_date );
00321 }
00322 }
00323
00324
00325
00326
00327
00328 void aout_FifoSet( aout_instance_t * p_aout, aout_fifo_t * p_fifo,
00329 mtime_t date )
00330 {
00331 aout_buffer_t * p_buffer;
00332
00333 aout_DateSet( &p_fifo->end_date, date );
00334 p_buffer = p_fifo->p_first;
00335 while ( p_buffer != NULL )
00336 {
00337 aout_buffer_t * p_next = p_buffer->p_next;
00338 aout_BufferFree( p_buffer );
00339 p_buffer = p_next;
00340 }
00341 p_fifo->p_first = NULL;
00342 p_fifo->pp_last = &p_fifo->p_first;
00343 }
00344
00345
00346
00347
00348 void aout_FifoMoveDates( aout_instance_t * p_aout, aout_fifo_t * p_fifo,
00349 mtime_t difference )
00350 {
00351 aout_buffer_t * p_buffer;
00352
00353 aout_DateMove( &p_fifo->end_date, difference );
00354 p_buffer = p_fifo->p_first;
00355 while ( p_buffer != NULL )
00356 {
00357 p_buffer->start_date += difference;
00358 p_buffer->end_date += difference;
00359 p_buffer = p_buffer->p_next;
00360 }
00361 }
00362
00363
00364
00365
00366 mtime_t aout_FifoNextStart( aout_instance_t * p_aout, aout_fifo_t * p_fifo )
00367 {
00368 return aout_DateGet( &p_fifo->end_date );
00369 }
00370
00371
00372
00373
00374
00375 mtime_t aout_FifoFirstDate( aout_instance_t * p_aout, aout_fifo_t * p_fifo )
00376 {
00377 return p_fifo->p_first ? p_fifo->p_first->start_date : 0;
00378 }
00379
00380
00381
00382
00383 aout_buffer_t * aout_FifoPop( aout_instance_t * p_aout, aout_fifo_t * p_fifo )
00384 {
00385 aout_buffer_t * p_buffer;
00386
00387 p_buffer = p_fifo->p_first;
00388 if ( p_buffer == NULL ) return NULL;
00389 p_fifo->p_first = p_buffer->p_next;
00390 if ( p_fifo->p_first == NULL )
00391 {
00392 p_fifo->pp_last = &p_fifo->p_first;
00393 }
00394
00395 return p_buffer;
00396 }
00397
00398
00399
00400
00401 void aout_FifoDestroy( aout_instance_t * p_aout, aout_fifo_t * p_fifo )
00402 {
00403 aout_buffer_t * p_buffer;
00404
00405 p_buffer = p_fifo->p_first;
00406 while ( p_buffer != NULL )
00407 {
00408 aout_buffer_t * p_next = p_buffer->p_next;
00409 aout_BufferFree( p_buffer );
00410 p_buffer = p_next;
00411 }
00412
00413 p_fifo->p_first = NULL;
00414 p_fifo->pp_last = &p_fifo->p_first;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 void aout_DateInit( audio_date_t * p_date, uint32_t i_divider )
00426 {
00427 p_date->date = 0;
00428 p_date->i_divider = i_divider;
00429 p_date->i_remainder = 0;
00430 }
00431
00432
00433
00434
00435 void aout_DateSet( audio_date_t * p_date, mtime_t new_date )
00436 {
00437 p_date->date = new_date;
00438 p_date->i_remainder = 0;
00439 }
00440
00441
00442
00443
00444 void aout_DateMove( audio_date_t * p_date, mtime_t difference )
00445 {
00446 p_date->date += difference;
00447 }
00448
00449
00450
00451
00452 mtime_t aout_DateGet( const audio_date_t * p_date )
00453 {
00454 return p_date->date;
00455 }
00456
00457
00458
00459
00460
00461 mtime_t aout_DateIncrement( audio_date_t * p_date, uint32_t i_nb_samples )
00462 {
00463 mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000;
00464 p_date->date += i_dividend / p_date->i_divider;
00465 p_date->i_remainder += (int)(i_dividend % p_date->i_divider);
00466 if ( p_date->i_remainder >= p_date->i_divider )
00467 {
00468
00469 p_date->date++;
00470 p_date->i_remainder -= p_date->i_divider;
00471 }
00472 return p_date->date;
00473 }
00474
00475
00476
00477
00478 int aout_CheckChannelReorder( const uint32_t *pi_chan_order_in,
00479 const uint32_t *pi_chan_order_out,
00480 uint32_t i_channel_mask,
00481 int i_channels, int *pi_chan_table )
00482 {
00483 vlc_bool_t b_chan_reorder = VLC_FALSE;
00484 int i, j, k, l;
00485
00486 if( i_channels > AOUT_CHAN_MAX ) return VLC_FALSE;
00487
00488 for( i = 0, j = 0; pi_chan_order_in[i]; i++ )
00489 {
00490 if( !(i_channel_mask & pi_chan_order_in[i]) ) continue;
00491
00492 for( k = 0, l = 0; pi_chan_order_in[i] != pi_chan_order_out[k]; k++ )
00493 {
00494 if( i_channel_mask & pi_chan_order_out[k] ) l++;
00495 }
00496
00497 pi_chan_table[j++] = l;
00498 }
00499
00500 for( i = 0; i < i_channels; i++ )
00501 {
00502 if( pi_chan_table[i] != i ) b_chan_reorder = VLC_TRUE;
00503 }
00504
00505 return b_chan_reorder;
00506 }
00507
00508
00509
00510
00511 void aout_ChannelReorder( uint8_t *p_buf, int i_buffer,
00512 int i_channels, const int *pi_chan_table,
00513 int i_bits_per_sample )
00514 {
00515 uint8_t p_tmp[AOUT_CHAN_MAX * 4];
00516 int i, j;
00517
00518 if( i_bits_per_sample == 8 )
00519 {
00520 for( i = 0; i < i_buffer / i_channels; i++ )
00521 {
00522 for( j = 0; j < i_channels; j++ )
00523 {
00524 p_tmp[pi_chan_table[j]] = p_buf[j];
00525 }
00526
00527 memcpy( p_buf, p_tmp, i_channels );
00528 p_buf += i_channels;
00529 }
00530 }
00531 else if( i_bits_per_sample == 16 )
00532 {
00533 for( i = 0; i < i_buffer / i_channels / 2; i++ )
00534 {
00535 for( j = 0; j < i_channels; j++ )
00536 {
00537 p_tmp[2 * pi_chan_table[j]] = p_buf[2 * j];
00538 p_tmp[2 * pi_chan_table[j] + 1] = p_buf[2 * j + 1];
00539 }
00540
00541 memcpy( p_buf, p_tmp, 2 * i_channels );
00542 p_buf += 2 * i_channels;
00543 }
00544 }
00545 else if( i_bits_per_sample == 24 )
00546 {
00547 for( i = 0; i < i_buffer / i_channels / 3; i++ )
00548 {
00549 for( j = 0; j < i_channels; j++ )
00550 {
00551 p_tmp[3 * pi_chan_table[j]] = p_buf[3 * j];
00552 p_tmp[3 * pi_chan_table[j] + 1] = p_buf[3 * j + 1];
00553 p_tmp[3 * pi_chan_table[j] + 2] = p_buf[3 * j + 2];
00554 }
00555
00556 memcpy( p_buf, p_tmp, 3 * i_channels );
00557 p_buf += 3 * i_channels;
00558 }
00559 }
00560 else if( i_bits_per_sample == 32 )
00561 {
00562 for( i = 0; i < i_buffer / i_channels / 4; i++ )
00563 {
00564 for( j = 0; j < i_channels; j++ )
00565 {
00566 p_tmp[4 * pi_chan_table[j]] = p_buf[4 * j];
00567 p_tmp[4 * pi_chan_table[j] + 1] = p_buf[4 * j + 1];
00568 p_tmp[4 * pi_chan_table[j] + 2] = p_buf[4 * j + 2];
00569 p_tmp[4 * pi_chan_table[j] + 3] = p_buf[4 * j + 3];
00570 }
00571
00572 memcpy( p_buf, p_tmp, 4 * i_channels );
00573 p_buf += 4 * i_channels;
00574 }
00575 }
00576 }