00001
00002 #include <cstdio>
00003 #include <cstdlib>
00004 #include <cmath>
00005
00006
00007 #include <pthread.h>
00008 #include <unistd.h>
00009 #include <sys/time.h>
00010
00011
00012 #include <qdatetime.h>
00013 #include <qstring.h>
00014 #include <qdeepcopy.h>
00015
00016
00017 #include "compat.h"
00018 #include "audiooutputbase.h"
00019 #include "audiooutputdigitalencoder.h"
00020 #include "SoundTouch.h"
00021 #include "freesurround.h"
00022
00023 #define LOC QString("AO: ")
00024 #define LOC_ERR QString("AO, ERROR: ")
00025
00026 AudioOutputBase::AudioOutputBase(
00027 QString laudio_main_device, QString laudio_passthru_device,
00028 int , int ,
00029 int , AudioOutputSource lsource,
00030 bool lset_initial_vol, bool ) :
00031
00032 effdsp(0), effdspstretched(0),
00033 audio_channels(-1), audio_bytes_per_sample(0),
00034 audio_bits(-1), audio_samplerate(-1),
00035 audio_buffer_unused(0),
00036 fragment_size(0), soundcard_buffer_size(0),
00037
00038 audio_main_device(QDeepCopy<QString>(laudio_main_device)),
00039 audio_passthru_device(QDeepCopy<QString>(laudio_passthru_device)),
00040 audio_passthru(false), audio_stretchfactor(1.0f),
00041
00042 audio_codec(NULL),
00043 source(lsource), killaudio(false),
00044
00045 pauseaudio(false), audio_actually_paused(false),
00046 was_paused(false),
00047
00048 set_initial_vol(lset_initial_vol),
00049 buffer_output_data_for_use(false),
00050 need_resampler(false),
00051
00052 src_ctx(NULL),
00053
00054 pSoundStretch(NULL),
00055 encoder(NULL),
00056 upmixer(NULL),
00057 source_audio_channels(-1),
00058 source_audio_bytes_per_sample(0),
00059 needs_upmix(false),
00060 surround_mode(FreeSurround::SurroundModePassive),
00061
00062 blocking(false),
00063
00064 lastaudiolen(0), samples_buffered(0),
00065
00066 audio_thread_exists(false),
00067
00068 audiotime(0),
00069 raud(0), waud(0),
00070 audbuf_timecode(0),
00071
00072 numlowbuffer(0), killAudioLock(false),
00073 current_seconds(-1), source_bitrate(-1)
00074 {
00075 pthread_mutex_init(&audio_buflock, NULL);
00076 pthread_mutex_init(&avsync_lock, NULL);
00077 pthread_cond_init(&audio_bufsig, NULL);
00078
00079
00080 memset(&src_data, 0, sizeof(SRC_DATA));
00081 memset(src_in, 0, sizeof(float) * AUDIO_SRC_IN_SIZE);
00082 memset(src_out, 0, sizeof(float) * AUDIO_SRC_OUT_SIZE);
00083 memset(tmp_buff, 0, sizeof(short) * AUDIO_TMP_BUF_SIZE);
00084 memset(&audiotime_updated, 0, sizeof(audiotime_updated));
00085 memset(audiobuffer, 0, sizeof(char) * AUDBUFSIZE);
00086 configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2);
00087
00088
00089
00090
00091 }
00092
00093 AudioOutputBase::~AudioOutputBase()
00094 {
00095
00096
00097
00098
00099 pthread_mutex_destroy(&audio_buflock);
00100 pthread_mutex_destroy(&avsync_lock);
00101 pthread_cond_destroy(&audio_bufsig);
00102 }
00103
00104 void AudioOutputBase::SetSourceBitrate(int rate)
00105 {
00106 if (rate > 0)
00107 source_bitrate = rate;
00108 }
00109
00110 void AudioOutputBase::SetStretchFactorLocked(float laudio_stretchfactor)
00111 {
00112 effdspstretched = (int)((float)effdsp / laudio_stretchfactor);
00113 if (audio_stretchfactor != laudio_stretchfactor)
00114 {
00115 audio_stretchfactor = laudio_stretchfactor;
00116 if (pSoundStretch)
00117 {
00118 VERBOSE(VB_GENERAL, LOC + QString("Changing time stretch to %1")
00119 .arg(audio_stretchfactor));
00120 pSoundStretch->setTempo(audio_stretchfactor);
00121 }
00122 else if (audio_stretchfactor != 1.0)
00123 {
00124 VERBOSE(VB_GENERAL, LOC + QString("Using time stretch %1")
00125 .arg(audio_stretchfactor));
00126 pSoundStretch = new soundtouch::SoundTouch();
00127 if (audio_codec)
00128 {
00129 if (!encoder)
00130 {
00131 VERBOSE(VB_AUDIO, LOC +
00132 QString("Creating Encoder for codec %1 origfs %2")
00133 .arg(audio_codec->codec_id)
00134 .arg(audio_codec->frame_size));
00135
00136 encoder = new AudioOutputDigitalEncoder();
00137 if (!encoder->Init(audio_codec->codec_id,
00138 audio_codec->bit_rate,
00139 audio_codec->sample_rate,
00140 audio_codec->channels
00141 ))
00142 {
00143
00144 delete encoder;
00145 encoder = NULL;
00146 VERBOSE(VB_AUDIO, LOC +
00147 QString("Failed to Create Encoder"));
00148 }
00149 }
00150 }
00151 if (audio_codec && encoder)
00152 {
00153 pSoundStretch->setSampleRate(audio_codec->sample_rate);
00154 pSoundStretch->setChannels(audio_codec->channels);
00155 }
00156 else
00157 {
00158 pSoundStretch->setSampleRate(audio_samplerate);
00159 pSoundStretch->setChannels(audio_channels);
00160 }
00161
00162 pSoundStretch->setTempo(audio_stretchfactor);
00163 pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
00164
00165
00166
00167
00168
00169
00170
00171 }
00172 }
00173 }
00174
00175 void AudioOutputBase::SetStretchFactor(float laudio_stretchfactor)
00176 {
00177 pthread_mutex_lock(&audio_buflock);
00178 SetStretchFactorLocked(laudio_stretchfactor);
00179 pthread_mutex_unlock(&audio_buflock);
00180 }
00181
00182 float AudioOutputBase::GetStretchFactor(void)
00183 {
00184 return audio_stretchfactor;
00185 }
00186
00187 void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels,
00188 int laudio_samplerate, bool laudio_passthru,
00189 void *laudio_codec)
00190 {
00191 int codec_id = CODEC_ID_NONE;
00192 int lcodec_id = CODEC_ID_NONE;
00193 int lcchannels = 0;
00194 int cchannels = 0;
00195 int lsource_audio_channels = laudio_channels;
00196 bool lneeds_upmix = false;
00197
00198 if (laudio_codec)
00199 {
00200 lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id;
00201 laudio_bits = 16;
00202 laudio_channels = 2;
00203 lsource_audio_channels = laudio_channels;
00204 laudio_samplerate = 48000;
00205 lcchannels = ((AVCodecContext*)laudio_codec)->channels;
00206 }
00207
00208 if (audio_codec)
00209 {
00210 codec_id = audio_codec->codec_id;
00211 cchannels = ((AVCodecContext*)audio_codec)->channels;
00212 }
00213
00214 if ((configured_audio_channels == 6) &&
00215 !(laudio_codec || audio_codec))
00216 {
00217 laudio_channels = configured_audio_channels;
00218 lneeds_upmix = true;
00219 VERBOSE(VB_AUDIO,LOC + "Needs upmix");
00220 }
00221
00222 ClearError();
00223 bool general_deps = (laudio_bits == audio_bits &&
00224 laudio_channels == audio_channels &&
00225 laudio_samplerate == audio_samplerate && !need_resampler &&
00226 laudio_passthru == audio_passthru &&
00227 lneeds_upmix == needs_upmix &&
00228 lcodec_id == codec_id && lcchannels == cchannels);
00229 bool upmix_deps =
00230 (lsource_audio_channels == source_audio_channels);
00231 if (general_deps && upmix_deps)
00232 {
00233 VERBOSE(VB_AUDIO,LOC + "no change exiting");
00234 return;
00235 }
00236
00237 if (general_deps && !upmix_deps && lneeds_upmix && upmixer)
00238 {
00239 upmixer->flush();
00240 source_audio_channels = lsource_audio_channels;
00241 VERBOSE(VB_AUDIO,LOC + QString("source channels changed to %1")
00242 .arg(source_audio_channels));
00243 return;
00244 }
00245
00246 KillAudio();
00247
00248 pthread_mutex_lock(&audio_buflock);
00249 pthread_mutex_lock(&avsync_lock);
00250
00251 lastaudiolen = 0;
00252 waud = raud = 0;
00253 audio_actually_paused = false;
00254
00255 bool redo_stretch = (pSoundStretch && audio_channels != laudio_channels);
00256 audio_channels = laudio_channels;
00257 source_audio_channels = lsource_audio_channels;
00258 audio_bits = laudio_bits;
00259 audio_samplerate = laudio_samplerate;
00260 audio_codec = (AVCodecContext*)laudio_codec;
00261 audio_passthru = laudio_passthru;
00262 needs_upmix = lneeds_upmix;
00263
00264 if (audio_bits != 8 && audio_bits != 16)
00265 {
00266 pthread_mutex_unlock(&avsync_lock);
00267 pthread_mutex_unlock(&audio_buflock);
00268 Error("AudioOutput only supports 8 or 16bit audio.");
00269 return;
00270 }
00271 audio_bytes_per_sample = audio_channels * audio_bits / 8;
00272 source_audio_bytes_per_sample = source_audio_channels * audio_bits / 8;
00273
00274 need_resampler = false;
00275 killaudio = false;
00276 pauseaudio = false;
00277 was_paused = true;
00278 internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
00279
00280 numlowbuffer = 0;
00281
00282 VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2(%3) sr %4")
00283 .arg(audio_main_device).arg(audio_channels)
00284 .arg(source_audio_channels).arg(audio_samplerate));
00285
00286
00287 if (!OpenDevice())
00288 {
00289 VERBOSE(VB_AUDIO, LOC_ERR + "Aborting reconfigure");
00290 pthread_mutex_unlock(&avsync_lock);
00291 pthread_mutex_unlock(&audio_buflock);
00292 if (GetError().isEmpty())
00293 Error("Aborting reconfigure");
00294 VERBOSE(VB_AUDIO, "Aborting reconfigure");
00295 return;
00296 }
00297
00298 SyncVolume();
00299
00300 VERBOSE(VB_AUDIO, LOC + QString("Audio fragment size: %1")
00301 .arg(fragment_size));
00302
00303 if (audio_buffer_unused < 0)
00304 audio_buffer_unused = 0;
00305
00306 if (!gContext->GetNumSetting("AggressiveSoundcardBuffer", 0))
00307 audio_buffer_unused = 0;
00308
00309 audbuf_timecode = 0;
00310 audiotime = 0;
00311 samples_buffered = 0;
00312 effdsp = audio_samplerate * 100;
00313 gettimeofday(&audiotime_updated, NULL);
00314 current_seconds = -1;
00315 source_bitrate = -1;
00316
00317
00318
00319 if (audio_samplerate != laudio_samplerate)
00320 {
00321 int error;
00322 VERBOSE(VB_GENERAL, LOC + QString("Using resampler. From: %1 to %2")
00323 .arg(laudio_samplerate).arg(audio_samplerate));
00324 src_ctx = src_new (SRC_SINC_BEST_QUALITY, audio_channels, &error);
00325 if (error)
00326 {
00327 Error(QString("Error creating resampler, the error was: %1")
00328 .arg(src_strerror(error)) );
00329 pthread_mutex_unlock(&avsync_lock);
00330 pthread_mutex_unlock(&audio_buflock);
00331 return;
00332 }
00333 src_data.src_ratio = (double) audio_samplerate / laudio_samplerate;
00334 src_data.data_in = src_in;
00335 src_data.data_out = src_out;
00336 src_data.output_frames = 16384*6;
00337 need_resampler = true;
00338 }
00339
00340 if (needs_upmix)
00341 {
00342 VERBOSE(VB_AUDIO, LOC + QString("create upmixer"));
00343 if (configured_audio_channels == 6)
00344 {
00345 surround_mode = gContext->GetNumSetting("AudioUpmixType", 2);
00346 }
00347
00348 upmixer = new FreeSurround(
00349 audio_samplerate,
00350 source == AUDIOOUTPUT_VIDEO,
00351 (FreeSurround::SurroundMode)surround_mode);
00352
00353 VERBOSE(VB_AUDIO, LOC +
00354 QString("create upmixer done with surround mode %1")
00355 .arg(surround_mode));
00356 }
00357
00358 VERBOSE(VB_AUDIO, LOC + QString("Audio Stretch Factor: %1")
00359 .arg(audio_stretchfactor));
00360 VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1")
00361 .arg((audio_codec) ?
00362 codec_id_string(audio_codec->codec_id) : "not set"));
00363
00364 if (redo_stretch)
00365 {
00366 float laudio_stretchfactor = audio_stretchfactor;
00367 delete pSoundStretch;
00368 pSoundStretch = NULL;
00369 audio_stretchfactor = 0.0f;
00370 SetStretchFactorLocked(laudio_stretchfactor);
00371 }
00372 else
00373 {
00374 SetStretchFactorLocked(audio_stretchfactor);
00375 if (pSoundStretch)
00376 {
00377
00378 if (audio_codec)
00379 {
00380 if (!encoder)
00381 {
00382 VERBOSE(VB_AUDIO, LOC +
00383 QString("Creating Encoder for codec %1")
00384 .arg(audio_codec->codec_id));
00385
00386 encoder = new AudioOutputDigitalEncoder();
00387 if (!encoder->Init(audio_codec->codec_id,
00388 audio_codec->bit_rate,
00389 audio_codec->sample_rate,
00390 audio_codec->channels
00391 ))
00392 {
00393
00394 delete encoder;
00395 encoder = NULL;
00396 VERBOSE(VB_AUDIO, LOC + "Failed to Create Encoder");
00397 }
00398 }
00399 }
00400 if (audio_codec && encoder)
00401 {
00402 pSoundStretch->setSampleRate(audio_codec->sample_rate);
00403 pSoundStretch->setChannels(audio_codec->channels);
00404 }
00405 else
00406 {
00407 pSoundStretch->setSampleRate(audio_samplerate);
00408 pSoundStretch->setChannels(audio_channels);
00409 }
00410 }
00411 }
00412
00413
00414 prepareVisuals();
00415
00416 StartOutputThread();
00417 pthread_mutex_unlock(&avsync_lock);
00418 pthread_mutex_unlock(&audio_buflock);
00419 VERBOSE(VB_AUDIO, LOC + "Ending reconfigure");
00420 }
00421
00422 bool AudioOutputBase::StartOutputThread(void)
00423 {
00424 if (audio_thread_exists)
00425 return true;
00426
00427 int status = pthread_create(
00428 &audio_thread, NULL, kickoffOutputAudioLoop, this);
00429
00430 if (status)
00431 {
00432 Error("Failed to create audio thread" + ENO);
00433 return false;
00434 }
00435
00436 audio_thread_exists = true;
00437
00438 return true;
00439 }
00440
00441
00442 void AudioOutputBase::StopOutputThread(void)
00443 {
00444 if (audio_thread_exists)
00445 {
00446 pthread_join(audio_thread, NULL);
00447 audio_thread_exists = false;
00448 }
00449 }
00450
00451 void AudioOutputBase::KillAudio()
00452 {
00453 killAudioLock.lock();
00454
00455 VERBOSE(VB_AUDIO, LOC + "Killing AudioOutputDSP");
00456 killaudio = true;
00457 StopOutputThread();
00458
00459
00460 if (src_ctx)
00461 src_delete(src_ctx);
00462 need_resampler = false;
00463
00464
00465 if (pSoundStretch)
00466 {
00467 delete pSoundStretch;
00468 pSoundStretch = NULL;
00469 }
00470
00471 if (encoder)
00472 {
00473 delete encoder;
00474 encoder = NULL;
00475 }
00476
00477 if (upmixer)
00478 {
00479 delete upmixer;
00480 upmixer = NULL;
00481 }
00482 needs_upmix = false;
00483
00484 CloseDevice();
00485
00486 killAudioLock.unlock();
00487 }
00488
00489
00490 bool AudioOutputBase::GetPause(void)
00491 {
00492 return audio_actually_paused;
00493 }
00494
00495 void AudioOutputBase::Pause(bool paused)
00496 {
00497 VERBOSE(VB_AUDIO, LOC + QString("Pause %0").arg(paused));
00498 pauseaudio = paused;
00499 audio_actually_paused = false;
00500 }
00501
00502 void AudioOutputBase::Reset()
00503 {
00504 pthread_mutex_lock(&audio_buflock);
00505 pthread_mutex_lock(&avsync_lock);
00506
00507 raud = waud = 0;
00508 audbuf_timecode = 0;
00509 audiotime = 0;
00510 samples_buffered = 0;
00511 current_seconds = -1;
00512 was_paused = !pauseaudio;
00513
00514
00515 prepareVisuals();
00516
00517 gettimeofday(&audiotime_updated, NULL);
00518
00519 pthread_mutex_unlock(&avsync_lock);
00520 pthread_mutex_unlock(&audio_buflock);
00521 }
00522
00523 void AudioOutputBase::SetTimecode(long long timecode)
00524 {
00525 pthread_mutex_lock(&audio_buflock);
00526 audbuf_timecode = timecode;
00527 samples_buffered = (long long)((timecode * effdsp) / 100000.0);
00528 pthread_mutex_unlock(&audio_buflock);
00529 }
00530
00531 void AudioOutputBase::SetEffDsp(int dsprate)
00532 {
00533 VERBOSE(VB_AUDIO, LOC + QString("SetEffDsp: %1").arg(dsprate));
00534 effdsp = dsprate;
00535 effdspstretched = (int)((float)effdsp / audio_stretchfactor);
00536 }
00537
00538 void AudioOutputBase::SetBlocking(bool blocking)
00539 {
00540 this->blocking = blocking;
00541 }
00542
00543 int AudioOutputBase::audiolen(bool use_lock)
00544 {
00545
00546 int ret;
00547
00548 if (use_lock)
00549 pthread_mutex_lock(&audio_buflock);
00550
00551 if (waud >= raud)
00552 ret = waud - raud;
00553 else
00554 ret = AUDBUFSIZE - (raud - waud);
00555
00556 if (use_lock)
00557 pthread_mutex_unlock(&audio_buflock);
00558
00559 return ret;
00560 }
00561
00562 int AudioOutputBase::audiofree(bool use_lock)
00563 {
00564 return AUDBUFSIZE - audiolen(use_lock) - 1;
00565
00566
00567
00568 }
00569
00570 int AudioOutputBase::GetAudiotime(void)
00571 {
00572
00573
00574
00575
00576
00577
00578
00579
00580 long long ret;
00581 struct timeval now;
00582
00583 if (audiotime == 0)
00584 return 0;
00585
00586 pthread_mutex_lock(&avsync_lock);
00587
00588 gettimeofday(&now, NULL);
00589
00590 ret = (now.tv_sec - audiotime_updated.tv_sec) * 1000;
00591 ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000;
00592 ret = (long long)(ret * audio_stretchfactor);
00593
00594 #if 1
00595 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
00596 QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7")
00597 .arg(now.tv_sec).arg(now.tv_usec)
00598 .arg(audiotime_updated.tv_sec).arg(audiotime_updated.tv_usec)
00599 .arg(ret)
00600 .arg(audiotime)
00601 .arg(audio_stretchfactor)
00602 );
00603 #endif
00604
00605 ret += audiotime;
00606
00607 pthread_mutex_unlock(&avsync_lock);
00608 return (int)ret;
00609 }
00610
00611 void AudioOutputBase::SetAudiotime(void)
00612 {
00613 if (audbuf_timecode == 0)
00614 return;
00615
00616 int soundcard_buffer = 0;
00617 int totalbuffer;
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 pthread_mutex_lock(&audio_buflock);
00637 pthread_mutex_lock(&avsync_lock);
00638
00639 soundcard_buffer = getBufferedOnSoundcard();
00640 totalbuffer = audiolen(false) + soundcard_buffer;
00641
00642
00643 if (pSoundStretch)
00644 {
00645
00646
00647 totalbuffer += (int)(pSoundStretch->numSamples() *
00648 audio_bytes_per_sample);
00649
00650 totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() *
00651 audio_bytes_per_sample) / audio_stretchfactor);
00652 }
00653
00654 if (upmixer && needs_upmix)
00655 {
00656 totalbuffer += upmixer->sampleLatency() * audio_bytes_per_sample;
00657 }
00658
00659 audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 /
00660 (audio_bytes_per_sample * effdspstretched));
00661
00662 gettimeofday(&audiotime_updated, NULL);
00663 #if 1
00664 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
00665 QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 "
00666 "tb=%5 sb=%6 eds=%7 abps=%8 sf=%9")
00667 .arg(audiotime_updated.tv_sec).arg(audiotime_updated.tv_usec)
00668 .arg(audiotime)
00669 .arg(audbuf_timecode)
00670 .arg(totalbuffer)
00671 .arg(soundcard_buffer)
00672 .arg(effdspstretched)
00673 .arg(audio_bytes_per_sample)
00674 .arg(audio_stretchfactor));
00675 #endif
00676
00677 pthread_mutex_unlock(&avsync_lock);
00678 pthread_mutex_unlock(&audio_buflock);
00679 }
00680
00681 bool AudioOutputBase::AddSamples(char *buffers[], int samples,
00682 long long timecode)
00683 {
00684
00685 int afree = audiofree(true);
00686 int abps = (encoder) ?
00687 encoder->audio_bytes_per_sample : audio_bytes_per_sample;
00688 int len = samples * abps;
00689
00690
00691 if (need_resampler && src_ctx)
00692 len = (int)ceilf(float(len) * src_data.src_ratio);
00693
00694
00695 if (needs_upmix && upmixer)
00696 len += upmixer->numUnprocessedSamples() * abps;
00697
00698 if (pSoundStretch)
00699 len += (pSoundStretch->numUnprocessedSamples() +
00700 (int)(pSoundStretch->numSamples()/audio_stretchfactor))*abps;
00701
00702 if (((len > afree) || ((audbuf_timecode - GetAudiotime()) > 2000)) && !blocking)
00703 {
00704 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC + QString(
00705 "AddSamples FAILED bytes=%1, used=%2, free=%3, timecode=%4")
00706 .arg(len).arg(AUDBUFSIZE-afree).arg(afree)
00707 .arg(timecode));
00708
00709 return false;
00710 }
00711
00712
00713 if (need_resampler && src_ctx)
00714 {
00715
00716
00717 short **buf_ptr = (short**)buffers;
00718 for (int sample = 0; sample < samples; sample++)
00719 {
00720 for (int channel = 0; channel < audio_channels; channel++)
00721 {
00722 src_in[sample] = buf_ptr[channel][sample] / (1.0 * 0x8000);
00723 }
00724 }
00725
00726 src_data.input_frames = samples;
00727 src_data.end_of_input = 0;
00728 int error = src_process(src_ctx, &src_data);
00729 if (error)
00730 VERBOSE(VB_IMPORTANT, LOC_ERR +
00731 QString("Error occured while resampling audio: %1")
00732 .arg(src_strerror(error)));
00733
00734 src_float_to_short_array(src_data.data_out, (short int*)tmp_buff,
00735 src_data.output_frames_gen*audio_channels);
00736
00737 _AddSamples(tmp_buff, true, src_data.output_frames_gen, timecode);
00738 }
00739 else
00740 {
00741
00742 _AddSamples(buffers, false, samples, timecode);
00743 }
00744
00745 return true;
00746 }
00747
00748 bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode)
00749 {
00750
00751
00752 int afree = audiofree(true);
00753 int abps = (encoder) ?
00754 encoder->audio_bytes_per_sample : audio_bytes_per_sample;
00755 int len = samples * abps;
00756
00757
00758 if (need_resampler && src_ctx)
00759 len = (int)ceilf(float(len) * src_data.src_ratio);
00760
00761
00762 if (needs_upmix && upmixer)
00763 len += upmixer->numUnprocessedSamples() * abps;
00764
00765 if (pSoundStretch)
00766 {
00767 len += (pSoundStretch->numUnprocessedSamples() +
00768 (int)(pSoundStretch->numSamples()/audio_stretchfactor))*abps;
00769 }
00770
00771 if (((len > afree) || (audiotime && ((audbuf_timecode - GetAudiotime()) > 2000))) && !blocking)
00772 {
00773 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC + QString(
00774 "AddSamples FAILED bytes=%1, used=%2, free=%3, timecode=%4")
00775 .arg(len).arg(AUDBUFSIZE-afree).arg(afree)
00776 .arg(timecode));
00777 return false;
00778 }
00779
00780
00781 if (need_resampler && src_ctx)
00782 {
00783
00784 short *buf_ptr = (short*)buffer;
00785 for (int sample = 0; sample < samples * audio_channels; sample++)
00786 {
00787 src_in[sample] = (float)buf_ptr[sample] / (1.0 * 0x8000);
00788 }
00789
00790 src_data.input_frames = samples;
00791 src_data.end_of_input = 0;
00792 int error = src_process(src_ctx, &src_data);
00793 if (error)
00794 VERBOSE(VB_IMPORTANT, LOC_ERR +
00795 QString("Error occured while resampling audio: %1")
00796 .arg(src_strerror(error)));
00797 src_float_to_short_array(src_data.data_out, (short int*)tmp_buff,
00798 src_data.output_frames_gen*audio_channels);
00799
00800 _AddSamples(tmp_buff, true, src_data.output_frames_gen, timecode);
00801 }
00802 else
00803 {
00804
00805 _AddSamples(buffer, true, samples, timecode);
00806 }
00807
00808 return true;
00809 }
00810
00811 int AudioOutputBase::WaitForFreeSpace(int samples)
00812 {
00813 int abps = (encoder) ?
00814 encoder->audio_bytes_per_sample : audio_bytes_per_sample;
00815 int len = samples * abps;
00816 int afree = audiofree(false);
00817
00818 while (len > afree)
00819 {
00820 if (blocking)
00821 {
00822 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC + "Waiting for free space " +
00823 QString("(need %1, available %2)").arg(len).arg(afree));
00824
00825
00826 pthread_cond_wait(&audio_bufsig, &audio_buflock);
00827 afree = audiofree(false);
00828 }
00829 else
00830 {
00831 VERBOSE(VB_IMPORTANT, LOC_ERR +
00832 QString("Audio buffer overflow, %1 audio samples lost!")
00833 .arg(samples - (afree / abps)));
00834 samples = afree / abps;
00835 len = samples * abps;
00836 if (src_ctx)
00837 {
00838 int error = src_reset(src_ctx);
00839 if (error)
00840 VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
00841 "Error occured while resetting resampler: %1")
00842 .arg(src_strerror(error)));
00843 }
00844 }
00845 }
00846 return len;
00847 }
00848
00849 void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
00850 long long timecode)
00851 {
00852 pthread_mutex_lock(&audio_buflock);
00853
00854 int len;
00855 int audio_bytes = audio_bits / 8;
00856 int org_waud = waud;
00857
00858 int afree = audiofree(false);
00859
00860 int abps = (encoder) ?
00861 encoder->audio_bytes_per_sample : audio_bytes_per_sample;
00862
00863 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
00864 LOC + QString("_AddSamples samples=%1 bytes=%2, used=%3, "
00865 "free=%4, timecode=%5 needsupmix %6")
00866 .arg(samples)
00867 .arg(samples * abps)
00868 .arg(AUDBUFSIZE-afree).arg(afree).arg(timecode)
00869 .arg(needs_upmix));
00870
00871 if (upmixer && needs_upmix)
00872 {
00873 int out_samples = 0;
00874 int step = (interleaved)?source_audio_channels:1;
00875 len = WaitForFreeSpace(samples);
00876 for (int itemp = 0; itemp < samples; )
00877 {
00878
00879
00880 pthread_mutex_unlock(&audio_buflock);
00881 if (audio_bytes == 2)
00882 {
00883 itemp += upmixer->putSamples(
00884 (short*)buffer + itemp * step,
00885 samples - itemp,
00886 source_audio_channels,
00887 (interleaved) ? 0 : samples);
00888 }
00889 else
00890 {
00891 itemp += upmixer->putSamples(
00892 (char*)buffer + itemp * step,
00893 samples - itemp,
00894 source_audio_channels,
00895 (interleaved) ? 0 : samples);
00896 }
00897 pthread_mutex_lock(&audio_buflock);
00898
00899 int copy_samples = upmixer->numSamples();
00900 if (copy_samples)
00901 {
00902 int copy_len = copy_samples * abps;
00903 out_samples += copy_samples;
00904 if (out_samples > samples)
00905 len = WaitForFreeSpace(out_samples);
00906 int bdiff = AUDBUFSIZE - org_waud;
00907 if (bdiff < copy_len)
00908 {
00909 int bdiff_samples = bdiff/abps;
00910 upmixer->receiveSamples(
00911 (short*)(audiobuffer + org_waud), bdiff_samples);
00912 upmixer->receiveSamples(
00913 (short*)(audiobuffer), (copy_samples - bdiff_samples));
00914 }
00915 else
00916 {
00917 upmixer->receiveSamples(
00918 (short*)(audiobuffer + org_waud), copy_samples);
00919 }
00920 org_waud = (org_waud + copy_len) % AUDBUFSIZE;
00921 }
00922 }
00923
00924 if (samples > 0)
00925 len = WaitForFreeSpace(out_samples);
00926
00927 samples = out_samples;
00928 }
00929 else
00930 {
00931 len = WaitForFreeSpace(samples);
00932
00933 if (interleaved)
00934 {
00935 char *mybuf = (char*)buffer;
00936 int bdiff = AUDBUFSIZE - org_waud;
00937 if (bdiff < len)
00938 {
00939 memcpy(audiobuffer + org_waud, mybuf, bdiff);
00940 memcpy(audiobuffer, mybuf + bdiff, len - bdiff);
00941 }
00942 else
00943 {
00944 memcpy(audiobuffer + org_waud, mybuf, len);
00945 }
00946
00947 org_waud = (org_waud + len) % AUDBUFSIZE;
00948 }
00949 else
00950 {
00951 char **mybuf = (char**)buffer;
00952 for (int itemp = 0; itemp < samples * audio_bytes;
00953 itemp += audio_bytes)
00954 {
00955 for (int chan = 0; chan < audio_channels; chan++)
00956 {
00957 audiobuffer[org_waud++] = mybuf[chan][itemp];
00958 if (audio_bits == 16)
00959 audiobuffer[org_waud++] = mybuf[chan][itemp+1];
00960
00961 if (org_waud >= AUDBUFSIZE)
00962 org_waud -= AUDBUFSIZE;
00963 }
00964 }
00965 }
00966 }
00967
00968 if (samples > 0)
00969 {
00970 if (pSoundStretch)
00971 {
00972
00973
00974
00975 org_waud = waud;
00976 int bdiff = AUDBUFSIZE - org_waud;
00977 int nSamplesToEnd = bdiff/abps;
00978 if (bdiff < len)
00979 {
00980 pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)
00981 (audiobuffer +
00982 org_waud), nSamplesToEnd);
00983 pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer,
00984 (len - bdiff) / abps);
00985 }
00986 else
00987 {
00988 pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)
00989 (audiobuffer + org_waud),
00990 len / abps);
00991 }
00992
00993 if (encoder)
00994 {
00995
00996
00997 soundtouch::SAMPLETYPE *temp_buff =
00998 (soundtouch::SAMPLETYPE*)encoder->GetFrameBuffer();
00999 size_t frameSize = encoder->FrameSize()/abps;
01000
01001 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
01002 QString("_AddSamples Enc sfs=%1 bfs=%2 sss=%3")
01003 .arg(frameSize)
01004 .arg(encoder->FrameSize())
01005 .arg(pSoundStretch->numSamples()));
01006
01007
01008
01009 while (pSoundStretch->numSamples() >= frameSize)
01010 {
01011 int got = pSoundStretch->receiveSamples(
01012 temp_buff, frameSize);
01013 int amount = encoder->Encode(temp_buff);
01014
01015 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
01016 QString("_AddSamples Enc bytes=%1 got=%2 left=%3")
01017 .arg(amount)
01018 .arg(got)
01019 .arg(pSoundStretch->numSamples()));
01020
01021 if (!amount)
01022 continue;
01023
01024
01025 char *ob = encoder->GetOutBuff();
01026 if (amount >= bdiff)
01027 {
01028 memcpy(audiobuffer + org_waud, ob, bdiff);
01029 ob += bdiff;
01030 amount -= bdiff;
01031 org_waud = 0;
01032 }
01033 if (amount > 0)
01034 memcpy(audiobuffer + org_waud, ob, amount);
01035
01036 bdiff = AUDBUFSIZE - amount;
01037 org_waud += amount;
01038 }
01039 }
01040 else
01041 {
01042 int newLen = 0;
01043 int nSamples;
01044 len = WaitForFreeSpace(pSoundStretch->numSamples() *
01045 audio_bytes_per_sample);
01046 do
01047 {
01048 int samplesToGet = len/audio_bytes_per_sample;
01049 if (samplesToGet > nSamplesToEnd)
01050 {
01051 samplesToGet = nSamplesToEnd;
01052 }
01053
01054 nSamples = pSoundStretch->receiveSamples(
01055 (soundtouch::SAMPLETYPE*)
01056 (audiobuffer + org_waud), samplesToGet);
01057 if (nSamples == nSamplesToEnd)
01058 {
01059 org_waud = 0;
01060 nSamplesToEnd = AUDBUFSIZE/audio_bytes_per_sample;
01061 }
01062 else
01063 {
01064 org_waud += nSamples * audio_bytes_per_sample;
01065 nSamplesToEnd -= nSamples;
01066 }
01067
01068 newLen += nSamples * audio_bytes_per_sample;
01069 len -= nSamples * audio_bytes_per_sample;
01070 } while (nSamples > 0);
01071 }
01072 }
01073
01074 waud = org_waud;
01075 lastaudiolen = audiolen(false);
01076
01077 if (timecode < 0)
01078 {
01079
01080 timecode = (int)((samples_buffered * 100000.0) / effdsp);
01081 }
01082
01083 samples_buffered += samples;
01084
01085
01086
01087
01088
01089 audbuf_timecode = timecode + (int)((samples * 100000.0) / effdsp);
01090
01091 if (interleaved)
01092 {
01093 dispatchVisual((unsigned char *)buffer, len, timecode,
01094 source_audio_channels, audio_bits);
01095 }
01096 }
01097
01098 pthread_mutex_unlock(&audio_buflock);
01099 }
01100
01101 void AudioOutputBase::Status()
01102 {
01103 long ct = GetAudiotime();
01104
01105 if (ct < 0)
01106 ct = 0;
01107
01108 if (source_bitrate == -1)
01109 {
01110 source_bitrate = audio_samplerate * source_audio_channels * audio_bits;
01111 }
01112
01113 if (ct / 1000 != current_seconds)
01114 {
01115 current_seconds = ct / 1000;
01116 OutputEvent e(current_seconds, ct,
01117 source_bitrate, audio_samplerate, audio_bits,
01118 source_audio_channels);
01119 dispatch(e);
01120 }
01121 }
01122
01123 void AudioOutputBase::GetBufferStatus(uint &fill, uint &total)
01124 {
01125 fill = AUDBUFSIZE - audiofree(true);
01126 total = AUDBUFSIZE;
01127 }
01128
01129 void AudioOutputBase::OutputAudioLoop(void)
01130 {
01131 int space_on_soundcard, last_space_on_soundcard;
01132 unsigned char zeros[fragment_size];
01133 unsigned char fragment[fragment_size];
01134
01135 bzero(zeros, fragment_size);
01136 last_space_on_soundcard = 0;
01137
01138 while (!killaudio)
01139 {
01140 if (pauseaudio)
01141 {
01142 if (!audio_actually_paused)
01143 {
01144 VERBOSE(VB_AUDIO, LOC + "OutputAudioLoop: audio paused");
01145 OutputEvent e(OutputEvent::Paused);
01146 dispatch(e);
01147 was_paused = true;
01148 }
01149
01150 audio_actually_paused = true;
01151
01152 audiotime = 0;
01153
01154 space_on_soundcard = getSpaceOnSoundcard();
01155
01156 if (space_on_soundcard != last_space_on_soundcard)
01157 {
01158 VERBOSE(VB_AUDIO|VB_TIMESTAMP,
01159 LOC + QString("%1 bytes free on soundcard")
01160 .arg(space_on_soundcard));
01161
01162 last_space_on_soundcard = space_on_soundcard;
01163 }
01164
01165
01166
01167 if (fragment_size >= soundcard_buffer_size - space_on_soundcard)
01168 {
01169 if (fragment_size <= space_on_soundcard) {
01170 WriteAudio(zeros, fragment_size);
01171 } else {
01172
01173 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC +
01174 QString("waiting for space on soundcard "
01175 "to write zeros: have %1 need %2")
01176 .arg(space_on_soundcard).arg(fragment_size));
01177 usleep(5000);
01178 }
01179 }
01180
01181 usleep(2000);
01182 continue;
01183 }
01184 else
01185 {
01186 if (was_paused)
01187 {
01188 VERBOSE(VB_AUDIO, LOC + "OutputAudioLoop: Play Event");
01189 OutputEvent e(OutputEvent::Playing);
01190 dispatch(e);
01191 was_paused = false;
01192 }
01193 }
01194
01195 space_on_soundcard = getSpaceOnSoundcard();
01196
01197
01198
01199
01200 if (space_on_soundcard != last_space_on_soundcard)
01201 SetAudiotime();
01202
01203
01204
01205
01206 if (fragment_size > audiolen(true))
01207 {
01208 if (audiolen(true) > 0)
01209 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC +
01210 QString("audio waiting for buffer to fill: "
01211 "have %1 want %2")
01212 .arg(audiolen(true)).arg(fragment_size));
01213
01214
01215
01216 pthread_mutex_lock(&audio_buflock);
01217 pthread_cond_broadcast(&audio_bufsig);
01218 pthread_mutex_unlock(&audio_buflock);
01219
01220 usleep(2000);
01221 continue;
01222 }
01223
01224
01225
01226 if (fragment_size > space_on_soundcard)
01227 {
01228 if (space_on_soundcard != last_space_on_soundcard) {
01229 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC +
01230 QString("audio waiting for space on soundcard: "
01231 "have %1 need %2")
01232 .arg(space_on_soundcard).arg(fragment_size));
01233 last_space_on_soundcard = space_on_soundcard;
01234 }
01235
01236 numlowbuffer++;
01237 if (numlowbuffer > 5 && audio_buffer_unused)
01238 {
01239 VERBOSE(VB_IMPORTANT, LOC + "dropping back audio_buffer_unused");
01240 audio_buffer_unused /= 2;
01241 }
01242
01243 usleep(5000);
01244 continue;
01245 }
01246 else
01247 numlowbuffer = 0;
01248
01249 Status();
01250
01251 if (GetAudioData(fragment, fragment_size, true))
01252 WriteAudio(fragment, fragment_size);
01253 }
01254
01255 VERBOSE(VB_AUDIO, LOC + "OutputAudioLoop: Stop Event");
01256 OutputEvent e(OutputEvent::Stopped);
01257 dispatch(e);
01258 }
01259
01260 int AudioOutputBase::GetAudioData(unsigned char *buffer, int buf_size, bool full_buffer)
01261 {
01262 pthread_mutex_lock(&audio_buflock);
01263
01264
01265
01266 int avail_size = audiolen(false);
01267 int fragment_size = buf_size;
01268 int written_size = 0;
01269 if (!full_buffer && (buf_size > avail_size))
01270 {
01271
01272 fragment_size = avail_size;
01273 }
01274
01275 if (avail_size && (fragment_size <= avail_size))
01276 {
01277 int bdiff = AUDBUFSIZE - raud;
01278 if (fragment_size > bdiff)
01279 {
01280
01281 memcpy(buffer, audiobuffer + raud, bdiff);
01282 memcpy(buffer + bdiff, audiobuffer, fragment_size - bdiff);
01283 }
01284 else
01285 {
01286 memcpy(buffer, audiobuffer + raud, fragment_size);
01287 }
01288
01289
01290 raud = (raud + fragment_size) % AUDBUFSIZE;
01291 VERBOSE(VB_AUDIO|VB_TIMESTAMP, LOC + "Broadcasting free space avail");
01292 pthread_cond_broadcast(&audio_bufsig);
01293
01294 written_size = fragment_size;
01295 }
01296 pthread_mutex_unlock(&audio_buflock);
01297
01298
01299 kMuteState mute_state = GetMute();
01300 if (written_size &&
01301 audio_channels > 1 &&
01302 (mute_state == MUTE_LEFT || mute_state == MUTE_RIGHT))
01303 {
01304 int offset_src = 0;
01305 int offset_dst = 0;
01306
01307 if (mute_state == MUTE_LEFT)
01308 offset_src = audio_bits / 8;
01309 else if (mute_state == MUTE_RIGHT)
01310 offset_dst = audio_bits / 8;
01311
01312 for (int i = 0; i < written_size; i += audio_bytes_per_sample)
01313 {
01314 buffer[i + offset_dst] = buffer[i + offset_src];
01315 if (audio_bits == 16)
01316 buffer[i + offset_dst + 1] = buffer[i + offset_src + 1];
01317 }
01318 }
01319
01320 return written_size;
01321 }
01322
01323
01324 void AudioOutputBase::Drain()
01325 {
01326 while (audiolen(true) > fragment_size)
01327 {
01328 usleep(1000);
01329 }
01330 }
01331
01332 void *AudioOutputBase::kickoffOutputAudioLoop(void *player)
01333 {
01334 VERBOSE(VB_AUDIO, LOC + QString("kickoffOutputAudioLoop: pid = %1")
01335 .arg(getpid()));
01336 ((AudioOutputBase *)player)->OutputAudioLoop();
01337 VERBOSE(VB_AUDIO, LOC + "kickoffOutputAudioLoop exiting");
01338 return NULL;
01339 }
01340
01341 int AudioOutputBase::readOutputData(unsigned char*, int)
01342 {
01343 VERBOSE(VB_IMPORTANT, LOC_ERR + "base AudioOutputBase should not be "
01344 "getting asked to readOutputData()");
01345 return 0;
01346 }
01347
01348
01349