Ticket #5501: audio_qthread.diff
File audio_qthread.diff, 22.6 KB (added by , 16 years ago) |
---|
-
libs/libmyth/audiooutputjack.h
1 1 #ifndef AUDIOOUTPUTJACK 2 2 #define AUDIOOUTPUTJACK 3 3 4 #include <vector>5 #include <qstring.h>6 #include <qmutex.h>7 8 4 #include "audiooutputbase.h" 9 5 10 6 using namespace std; -
libs/libmyth/audiosettings.cpp
89 89 90 90 QString AudioSettings::GetMainDevice(void) const 91 91 { 92 return Q3DeepCopy<QString>(main_device); 92 QString ret = main_device; 93 ret.detach(); 94 return ret; 93 95 } 94 96 95 97 QString AudioSettings::GetPassthruDevice(void) const 96 98 { 97 return Q3DeepCopy<QString>(passthru_device); 99 QString ret = passthru_device; 100 ret.detach(); 101 return ret; 98 102 } 99 103 -
libs/libmyth/audiooutputbase.h
2 2 #define AUDIOOUTPUTBASE 3 3 4 4 // POSIX headers 5 #include <pthread.h>6 5 #include <sys/time.h> // for struct timeval 7 6 8 7 // C++ headers … … 10 9 using namespace std; 11 10 12 11 // Qt headers 13 #include <qstring.h> 14 #include <qmutex.h> 12 #include <QString> 13 #include <QMutex> 14 #include <QWaitCondition> 15 #include <QThread> 15 16 16 17 // MythTV headers 17 18 #include "audiooutput.h" … … 24 25 class AudioOutputDigitalEncoder; 25 26 struct AVCodecContext; 26 27 27 class AudioOutputBase : public AudioOutput 28 class AudioOutputBase : public AudioOutput, public QThread 28 29 { 29 30 public: 30 31 AudioOutputBase(const AudioSettings &settings); … … 55 56 // Wait for all data to finish playing 56 57 virtual void Drain(void); 57 58 58 virtual int GetAudiotime(void) const;59 virtual int GetAudioBufferedTime(void) const;59 virtual int GetAudiotime(void); 60 virtual int GetAudioBufferedTime(void); 60 61 61 62 // Send output events showing current progress 62 63 virtual void Status(void); 63 64 64 65 virtual void SetSourceBitrate(int rate); 65 66 66 virtual void GetBufferStatus(uint &fill, uint &total) const;67 virtual void GetBufferStatus(uint &fill, uint &total); 67 68 68 69 // Only really used by the AudioOutputNULL object 69 70 … … 95 96 void _AddSamples(void *buffer, bool interleaved, int samples, long long timecode); 96 97 97 98 void OutputAudioLoop(void); 98 static void *kickoffOutputAudioLoop(void *player); 99 100 virtual void run(); 101 //static void *kickoffOutputAudioLoop(void *player); 102 99 103 void SetAudiotime(void); 100 104 int WaitForFreeSpace(int len); 101 105 102 int audiolen(bool use_lock) const; // number of valid bytes in audio buffer103 int audiofree(bool use_lock) const; // number of free bytes in audio buffer106 int audiolen(bool use_lock); // number of valid bytes in audio buffer 107 int audiofree(bool use_lock); // number of free bytes in audio buffer 104 108 105 109 void UpdateVolume(void); 106 110 … … 161 165 long long samples_buffered; 162 166 163 167 bool audio_thread_exists; 164 pthread_t audio_thread;165 168 166 169 /** adjustments to audiotimecode, waud, and raud can only be made 167 170 while holding this lock */ 168 mutable pthread_mutex_taudio_buflock;171 QMutex audio_buflock; 169 172 170 173 /** condition is signaled when the buffer gets more free space. 171 174 Must be holding audio_buflock to use. */ 172 pthread_cond_taudio_bufsig;175 QWaitCondition audio_bufsig; 173 176 174 177 /** must hold avsync_lock to read or write 'audiotime' and 175 178 'audiotime_updated' */ 176 mutable pthread_mutex_tavsync_lock;179 QMutex avsync_lock; 177 180 178 181 /// timecode of audio leaving the soundcard (same units as timecodes) 179 182 long long audiotime; -
libs/libmyth/audiooutputca.cpp
322 322 } 323 323 324 324 /** Reimplement the base class's version of GetAudiotime() 325 * so that we don't use gettimeofday or pthreadmutexes.325 * so that we don't use gettimeofday or Qt mutexes. 326 326 */ 327 int AudioOutputCA::GetAudiotime(void) const327 int AudioOutputCA::GetAudiotime(void) 328 328 { 329 329 int ret; 330 330 … … 340 340 } 341 341 342 342 /** Reimplement base's SetAudiotime() 343 * without gettimeofday() or pthreadmutexes.343 * without gettimeofday() or Qt mutexes. 344 344 */ 345 345 void AudioOutputCA::SetAudiotime(void) 346 346 { -
libs/libmyth/audiooutputwin.h
1 1 #ifndef AUDIOOUTPUTWIN 2 2 #define AUDIOOUTPUTWIN 3 3 4 // Qt headers5 #include <qstring.h>6 7 4 // MythTV headers 8 5 #include "audiooutputbase.h" 9 6 -
libs/libmyth/audiooutputjack.cpp
8 8 #include <cstring> 9 9 10 10 #include <iostream> 11 #include <qdatetime.h>12 11 13 12 using namespace std; 14 13 -
libs/libmyth/audiooutputoss.h
1 1 #ifndef AUDIOOUTPUTOSS 2 2 #define AUDIOOUTPUTOSS 3 3 4 #include <vector>5 #include <qstring.h>6 #include <qmutex.h>7 8 4 #include "audiooutputbase.h" 9 5 10 6 using namespace std; -
libs/libmyth/audiooutputbase.cpp
2 2 #include <cmath> 3 3 4 4 // POSIX headers 5 #include <pthread.h>6 5 #include <unistd.h> 7 6 #include <sys/time.h> 8 7 9 8 // Qt headers 10 #include <qdatetime.h> 11 #include <qstring.h> 12 #include <q3deepcopy.h> 9 #include <QMutexLocker> 13 10 14 11 // MythTV headers 15 12 #include "compat.h" … … 74 71 memory_corruption_test3(0xdeadbeef), 75 72 memory_corruption_test4(0xdeadbeef) 76 73 { 77 pthread_mutex_init(&audio_buflock, NULL);78 pthread_mutex_init(&avsync_lock, NULL);79 pthread_cond_init(&audio_bufsig, NULL);80 81 74 // The following are not bzero() because MS Windows doesn't like it. 82 75 memset(&src_data, 0, sizeof(SRC_DATA)); 83 76 memset(src_in, 0, sizeof(float) * kAudioSourceInputSize); … … 101 94 "~AudioOutputBase called, but KillAudio has not been called!"); 102 95 } 103 96 104 pthread_mutex_destroy(&audio_buflock);105 pthread_mutex_destroy(&avsync_lock);106 pthread_cond_destroy(&audio_bufsig);107 108 97 assert(memory_corruption_test0 == 0xdeadbeef); 109 98 assert(memory_corruption_test1 == 0xdeadbeef); 110 99 assert(memory_corruption_test2 == 0xdeadbeef); … … 185 174 186 175 void AudioOutputBase::SetStretchFactor(float laudio_stretchfactor) 187 176 { 188 pthread_mutex_lock(&audio_buflock);177 QMutexLocker lock(&audio_buflock); 189 178 SetStretchFactorLocked(laudio_stretchfactor); 190 pthread_mutex_unlock(&audio_buflock);191 179 } 192 180 193 181 float AudioOutputBase::GetStretchFactor(void) const … … 256 244 257 245 KillAudio(); 258 246 259 pthread_mutex_lock(&audio_buflock);260 pthread_mutex_lock(&avsync_lock);247 QMutexLocker lock1(&audio_buflock); 248 QMutexLocker lock2(&avsync_lock); 261 249 262 250 lastaudiolen = 0; 263 251 waud = raud = 0; … … 274 262 275 263 if (audio_bits != 8 && audio_bits != 16) 276 264 { 277 pthread_mutex_unlock(&avsync_lock);278 pthread_mutex_unlock(&audio_buflock);279 265 Error("AudioOutput only supports 8 or 16bit audio."); 280 266 return; 281 267 } … … 298 284 if (!OpenDevice()) 299 285 { 300 286 VERBOSE(VB_AUDIO, LOC_ERR + "Aborting reconfigure"); 301 pthread_mutex_unlock(&avsync_lock);302 pthread_mutex_unlock(&audio_buflock);303 287 if (GetError().isEmpty()) 304 288 Error("Aborting reconfigure"); 305 289 VERBOSE(VB_AUDIO, "Aborting reconfigure"); … … 337 321 { 338 322 Error(QString("Error creating resampler, the error was: %1") 339 323 .arg(src_strerror(error)) ); 340 pthread_mutex_unlock(&avsync_lock);341 pthread_mutex_unlock(&audio_buflock);342 324 return; 343 325 } 344 326 src_data.src_ratio = (double) audio_samplerate / settings.samplerate; … … 423 405 prepareVisuals(); 424 406 425 407 StartOutputThread(); 426 pthread_mutex_unlock(&avsync_lock);427 pthread_mutex_unlock(&audio_buflock);428 408 VERBOSE(VB_AUDIO, LOC + "Ending reconfigure"); 429 409 } 430 410 … … 433 413 if (audio_thread_exists) 434 414 return true; 435 415 436 int status = pthread_create( 437 &audio_thread, NULL, kickoffOutputAudioLoop, this); 438 439 if (status) 440 { 441 Error("Failed to create audio thread" + ENO); 442 return false; 443 } 444 416 start(); 445 417 audio_thread_exists = true; 446 418 447 419 return true; … … 452 424 { 453 425 if (audio_thread_exists) 454 426 { 455 pthread_join(audio_thread, NULL);427 wait(); 456 428 audio_thread_exists = false; 457 429 } 458 430 } … … 504 476 505 477 void AudioOutputBase::Reset() 506 478 { 507 pthread_mutex_lock(&audio_buflock);508 pthread_mutex_lock(&avsync_lock);479 QMutexLocker lock1(&audio_buflock); 480 QMutexLocker lock2(&avsync_lock); 509 481 510 482 raud = waud = 0; 511 483 audbuf_timecode = 0; … … 518 490 prepareVisuals(); 519 491 520 492 gettimeofday(&audiotime_updated, NULL); 521 522 pthread_mutex_unlock(&avsync_lock);523 pthread_mutex_unlock(&audio_buflock);524 493 } 525 494 526 495 void AudioOutputBase::SetTimecode(long long timecode) 527 496 { 528 pthread_mutex_lock(&audio_buflock);497 QMutexLocker locker(&audio_buflock); 529 498 audbuf_timecode = timecode; 530 499 samples_buffered = (long long)((timecode * effdsp) / 100000.0); 531 pthread_mutex_unlock(&audio_buflock);532 500 } 533 501 534 502 void AudioOutputBase::SetEffDsp(int dsprate) … … 543 511 this->blocking = blocking; 544 512 } 545 513 546 int AudioOutputBase::audiolen(bool use_lock) const514 int AudioOutputBase::audiolen(bool use_lock) 547 515 { 548 516 /* Thread safe, returns the number of valid bytes in the audio buffer */ 549 517 int ret; 550 518 551 519 if (use_lock) 552 pthread_mutex_lock(&audio_buflock);520 audio_buflock.lock(); 553 521 554 522 if (waud >= raud) 555 523 ret = waud - raud; … … 557 525 ret = kAudioRingBufferSize - (raud - waud); 558 526 559 527 if (use_lock) 560 pthread_mutex_unlock(&audio_buflock);528 audio_buflock.unlock(); 561 529 562 530 return ret; 563 531 } 564 532 565 int AudioOutputBase::audiofree(bool use_lock) const533 int AudioOutputBase::audiofree(bool use_lock) 566 534 { 567 535 return kAudioRingBufferSize - audiolen(use_lock) - 1; 568 536 /* There is one wasted byte in the buffer. The case where waud = raud is … … 570 538 be is kAudioRingBufferSize - 1. */ 571 539 } 572 540 573 int AudioOutputBase::GetAudiotime(void) const541 int AudioOutputBase::GetAudiotime(void) 574 542 { 575 543 /* Returns the current timecode of audio leaving the soundcard, based 576 544 on the 'audiotime' computed earlier, and the delay since it was computed. … … 586 554 if (audiotime == 0) 587 555 return 0; 588 556 589 pthread_mutex_lock(&avsync_lock);557 QMutexLocker lock(&avsync_lock); 590 558 591 559 gettimeofday(&now, NULL); 592 560 … … 607 575 608 576 ret += audiotime; 609 577 610 pthread_mutex_unlock(&avsync_lock);611 578 return (int)ret; 612 579 } 613 580 … … 636 603 'ms/byte' is given by '25000/effdsp'... 637 604 */ 638 605 639 pthread_mutex_lock(&audio_buflock);640 pthread_mutex_lock(&avsync_lock);606 QMutexLocker lock1(&audio_buflock); 607 QMutexLocker lock2(&avsync_lock); 641 608 642 609 soundcard_buffer = GetBufferedOnSoundcard(); // bytes 643 610 totalbuffer = audiolen(false) + soundcard_buffer; … … 676 643 .arg(audio_bytes_per_sample) 677 644 .arg(audio_stretchfactor)); 678 645 #endif 679 680 pthread_mutex_unlock(&avsync_lock);681 pthread_mutex_unlock(&audio_buflock);682 646 } 683 647 684 int AudioOutputBase::GetAudioBufferedTime(void) const648 int AudioOutputBase::GetAudioBufferedTime(void) 685 649 { 686 650 return audbuf_timecode - GetAudiotime(); 687 651 } … … 831 795 QString("(need %1, available %2)").arg(len).arg(afree)); 832 796 833 797 // wait for more space 834 pthread_cond_wait(&audio_bufsig,&audio_buflock);798 audio_bufsig.wait(&audio_buflock); 835 799 afree = audiofree(false); 836 800 } 837 801 else … … 857 821 void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples, 858 822 long long timecode) 859 823 { 860 pthread_mutex_lock(&audio_buflock);824 audio_buflock.lock(); 861 825 862 826 int len; // = samples * audio_bytes_per_sample; 863 827 int audio_bytes = audio_bits / 8; … … 885 849 { 886 850 // just in case it does a processing cycle, release the lock 887 851 // to allow the output loop to do output 888 pthread_mutex_unlock(&audio_buflock);852 audio_buflock.unlock(); 889 853 if (audio_bytes == 2) 890 854 { 891 855 itemp += upmixer->putSamples( … … 902 866 source_audio_channels, 903 867 (interleaved) ? 0 : samples); 904 868 } 905 pthread_mutex_lock(&audio_buflock);869 audio_buflock.lock(); 906 870 907 871 int copy_samples = upmixer->numSamples(); 908 872 if (copy_samples) … … 1103 1067 } 1104 1068 } 1105 1069 1106 pthread_mutex_unlock(&audio_buflock);1070 audio_buflock.unlock(); 1107 1071 } 1108 1072 1109 1073 void AudioOutputBase::Status() … … 1128 1092 } 1129 1093 } 1130 1094 1131 void AudioOutputBase::GetBufferStatus(uint &fill, uint &total) const1095 void AudioOutputBase::GetBufferStatus(uint &fill, uint &total) 1132 1096 { 1133 1097 fill = kAudioRingBufferSize - audiofree(true); 1134 1098 total = kAudioRingBufferSize; … … 1221 1185 1222 1186 //VERBOSE(VB_AUDIO+VB_TIMESTAMP, 1223 1187 //LOC + "Broadcasting free space avail"); 1224 pthread_mutex_lock(&audio_buflock);1225 pthread_cond_broadcast(&audio_bufsig);1226 pthread_mutex_unlock(&audio_buflock);1188 audio_buflock.lock(); 1189 audio_bufsig.wakeAll(); 1190 audio_buflock.unlock(); 1227 1191 1228 1192 usleep(2000); 1229 1193 continue; … … 1267 1231 1268 1232 int AudioOutputBase::GetAudioData(unsigned char *buffer, int buf_size, bool full_buffer) 1269 1233 { 1270 pthread_mutex_lock(&audio_buflock); // begin critical section1234 audio_buflock.lock(); // begin critical section 1271 1235 1272 1236 // re-check audiolen() in case things changed. 1273 1237 // for example, ClearAfterSeek() might have run … … 1297 1261 /* update raud */ 1298 1262 raud = (raud + fragment_size) % kAudioRingBufferSize; 1299 1263 VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + "Broadcasting free space avail"); 1300 pthread_cond_broadcast(&audio_bufsig);1264 audio_bufsig.wakeAll(); 1301 1265 1302 1266 written_size = fragment_size; 1303 1267 } 1304 pthread_mutex_unlock(&audio_buflock); // end critical section1268 audio_buflock.unlock(); 1305 1269 1306 1270 // Mute individual channels through mono->stereo duplication 1307 1271 kMuteState mute_state = GetMute(); … … 1337 1301 } 1338 1302 } 1339 1303 1340 void *AudioOutputBase::kickoffOutputAudioLoop(void *player)1304 void AudioOutputBase::run(void) 1341 1305 { 1342 1306 VERBOSE(VB_AUDIO, LOC + QString("kickoffOutputAudioLoop: pid = %1") 1343 1307 .arg(getpid())); 1344 ((AudioOutputBase *)player)->OutputAudioLoop();1308 OutputAudioLoop(); 1345 1309 VERBOSE(VB_AUDIO, LOC + "kickoffOutputAudioLoop exiting"); 1346 return NULL;1347 1310 } 1348 1311 1349 1312 int AudioOutputBase::readOutputData(unsigned char*, int) -
libs/libmyth/audiooutput.cpp
1 1 #include <cstdio> 2 2 #include <cstdlib> 3 3 4 #include <Q3DeepCopy>5 6 4 using namespace std; 7 5 8 6 #include "mythconfig.h" … … 124 122 125 123 void AudioOutput::Error(const QString &msg) 126 124 { 127 lastError = Q3DeepCopy<QString>(msg); 125 lastError = msg; 126 lastError.detach(); 128 127 VERBOSE(VB_IMPORTANT, "AudioOutput Error: " + lastError); 129 128 } 130 129 131 130 void AudioOutput::Warn(const QString &msg) 132 131 { 133 lastWarn = Q3DeepCopy<QString>(msg); 132 lastWarn = msg; 133 lastWarn.detach(); 134 134 VERBOSE(VB_IMPORTANT, "AudioOutput Warning: " + lastWarn); 135 135 } 136 136 -
libs/libmyth/mythdialogs.cpp
25 25 #endif 26 26 27 27 #include <iostream> 28 #include <pthread.h>29 28 using namespace std; 30 29 31 #ifdef USE_LIRC32 #include "lirc.h"33 #include "lircevent.h"34 #endif35 36 #ifdef USE_JOYSTICK_MENU37 #include "jsmenu.h"38 #include "jsmenuevent.h"39 #endif40 41 30 #include "uitypes.h" 42 31 #include "uilistbtntype.h" 43 32 #include "xmlparse.h" -
libs/libmyth/audiosettings.h
8 8 #ifndef _AUDIO_SETTINGS_H_ 9 9 #define _AUDIO_SETTINGS_H_ 10 10 11 #include < qstring.h>11 #include <QString> 12 12 13 13 #include "mythexp.h" 14 14 -
libs/libmyth/audiooutputca.h
1 1 #ifndef AUDIOOUTPUTCA 2 2 #define AUDIOOUTPUTCA 3 3 4 #include <vector>5 #include <qstring.h>6 7 4 #include "audiooutputbase.h" 8 5 9 6 using namespace std; … … 21 18 AudioOutputCA(const AudioSettings &settings); 22 19 virtual ~AudioOutputCA(); 23 20 24 virtual int GetAudiotime(void) const;21 virtual int GetAudiotime(void); 25 22 void SetAudiotime(void); 26 23 27 24 // callback for delivering audio to output device -
libs/libmyth/audiooutputoss.cpp
10 10 #include <cstring> 11 11 12 12 #include <iostream> 13 #include <qdatetime.h>14 13 #include "config.h" 15 14 16 15 #ifdef HAVE_SYS_SOUNDCARD_H -
libs/libmyth/audiooutputarts.cpp
1 1 #include <cstdio> 2 2 #include <cstdlib> 3 3 4 5 4 using namespace std; 6 5 7 6 #include "mythcontext.h" -
libs/libmyth/audiooutputdx.cpp
310 310 paused = pause; 311 311 } 312 312 313 int AudioOutputDX::GetAudiotime(void) const313 int AudioOutputDX::GetAudiotime(void) 314 314 { 315 315 DWORD play_pos; 316 316 HRESULT dsresult; -
libs/libmyth/audiooutputnull.h
1 1 #ifndef AUDIOOUTPUTNULL 2 2 #define AUDIOOUTPUTNULL 3 3 4 #include <qmutex.h>5 #include <pthread.h>6 7 4 #include "audiooutputbase.h" 8 5 9 6 #define NULLAUDIO_OUTPUT_BUFFER_SIZE 32768 -
libs/libmyth/audiooutput.h
1 1 #ifndef AUDIOOUTPUT 2 2 #define AUDIOOUTPUT 3 3 4 #include < qstring.h>4 #include <QString> 5 5 6 6 #include "audiosettings.h" 7 7 #include "mythcontext.h" … … 51 51 // Wait for all data to finish playing 52 52 virtual void Drain(void) = 0; 53 53 54 virtual int GetAudiotime(void) const= 0;54 virtual int GetAudiotime(void) = 0; 55 55 56 56 /// report amount of audio buffered in milliseconds. 57 virtual int GetAudioBufferedTime(void) const{ return 0; }57 virtual int GetAudioBufferedTime(void) { return 0; } 58 58 59 59 virtual void SetSourceBitrate(int ) { } 60 60 61 61 QString GetError(void) const { return lastError; } 62 62 QString GetWarning(void) const { return lastWarn; } 63 63 64 virtual void GetBufferStatus(uint &fill, uint &total) const64 virtual void GetBufferStatus(uint &fill, uint &total) 65 65 { fill = total = 0; } 66 66 67 67 // Only really used by the AudioOutputNULL object -
libs/libmyth/audiooutputnull.cpp
12 12 #include <cerrno> 13 13 #include <cstring> 14 14 #include <iostream> 15 #include <qdatetime.h> 15 16 16 #include "config.h" 17 17 18 18 using namespace std; -
libs/libmyth/audiooutputarts.h
1 1 #ifndef AUDIOOUTPUTARTS 2 2 #define AUDIOOUTPUTARTS 3 3 4 #include <qstring.h>5 6 4 #define ARTS_PCM_NEW_HW_PARAMS_API 7 5 #define ARTS_PCM_NEW_SW_PARAMS_API 8 6 #include <artsc.h> -
libs/libmyth/audiooutputdx.h
8 8 #include <windows.h> // HACK HACK HACK 9 9 #include <dsound.h> // HACK HACK HACK 10 10 11 // Qt headers12 #include <qstring.h>13 14 11 // MythTV headers 15 12 #include "audiooutputbase.h" 16 13 … … 43 40 44 41 virtual void Drain(void); 45 42 46 virtual int GetAudiotime(void) const;43 virtual int GetAudiotime(void); 47 44 48 45 // Volume control 49 46 virtual int GetVolumeChannel(int channel) const; // Returns 0-100 -
libs/libmyth/audiooutputalsa.h
1 1 #ifndef AUDIOOUTPUTALSA 2 2 #define AUDIOOUTPUTALSA 3 3 4 #include <vector>5 #include <qstring.h>6 #include <qmutex.h>7 8 4 #define ALSA_PCM_NEW_HW_PARAMS_API 9 5 #define ALSA_PCM_NEW_SW_PARAMS_API 10 6 #include <alsa/asoundlib.h> … … 90 86 QMutex killAudioLock; 91 87 snd_mixer_t *mixer_handle; 92 88 QString mixer_control; // e.g. "PCM" 93 snd_pcm_sframes_t (*pcm_write_func)( 94 snd_pcm_t*, const void*,snd_pcm_uframes_t);89 snd_pcm_sframes_t (*pcm_write_func)(snd_pcm_t*, const void*, 90 snd_pcm_uframes_t); 95 91 }; 96 92 97 93 #endif -
programs/mythtranscode/transcode.cpp
167 167 return; 168 168 } 169 169 170 virtual int GetAudiotime(void) const170 virtual int GetAudiotime(void) 171 171 { 172 172 return last_audiotime; 173 173 }