Ticket #5501: audio_qthread.diff

File audio_qthread.diff, 22.6 KB (added by Isaac Richards, 16 years ago)
  • libs/libmyth/audiooutputjack.h

     
    11#ifndef AUDIOOUTPUTJACK
    22#define AUDIOOUTPUTJACK
    33
    4 #include <vector>
    5 #include <qstring.h>
    6 #include <qmutex.h>
    7 
    84#include "audiooutputbase.h"
    95
    106using namespace std;
  • libs/libmyth/audiosettings.cpp

     
    8989
    9090QString AudioSettings::GetMainDevice(void) const
    9191{
    92     return Q3DeepCopy<QString>(main_device);
     92    QString ret = main_device;
     93    ret.detach();
     94    return ret;
    9395}
    9496
    9597QString AudioSettings::GetPassthruDevice(void) const
    9698{
    97     return Q3DeepCopy<QString>(passthru_device);
     99    QString ret = passthru_device;
     100    ret.detach();
     101    return ret;
    98102}
    99103
  • libs/libmyth/audiooutputbase.h

     
    22#define AUDIOOUTPUTBASE
    33
    44// POSIX headers
    5 #include <pthread.h>
    65#include <sys/time.h> // for struct timeval
    76
    87// C++ headers
     
    109using namespace std;
    1110
    1211// Qt headers
    13 #include <qstring.h>
    14 #include <qmutex.h>
     12#include <QString>
     13#include <QMutex>
     14#include <QWaitCondition>
     15#include <QThread>
    1516
    1617// MythTV headers
    1718#include "audiooutput.h"
     
    2425class AudioOutputDigitalEncoder;
    2526struct AVCodecContext;
    2627
    27 class AudioOutputBase : public AudioOutput
     28class AudioOutputBase : public AudioOutput, public QThread
    2829{
    2930 public:
    3031    AudioOutputBase(const AudioSettings &settings);
     
    5556    // Wait for all data to finish playing
    5657    virtual void Drain(void);
    5758
    58     virtual int GetAudiotime(void) const;
    59     virtual int GetAudioBufferedTime(void) const;
     59    virtual int GetAudiotime(void);
     60    virtual int GetAudioBufferedTime(void);
    6061
    6162    // Send output events showing current progress
    6263    virtual void Status(void);
    6364
    6465    virtual void SetSourceBitrate(int rate);
    6566
    66     virtual void GetBufferStatus(uint &fill, uint &total) const;
     67    virtual void GetBufferStatus(uint &fill, uint &total);
    6768
    6869    //  Only really used by the AudioOutputNULL object
    6970
     
    9596    void _AddSamples(void *buffer, bool interleaved, int samples, long long timecode);
    9697
    9798    void OutputAudioLoop(void);
    98     static void *kickoffOutputAudioLoop(void *player);
     99
     100    virtual void run();
     101    //static void *kickoffOutputAudioLoop(void *player);
     102
    99103    void SetAudiotime(void);
    100104    int WaitForFreeSpace(int len);
    101105
    102     int audiolen(bool use_lock) const; // number of valid bytes in audio buffer
    103     int audiofree(bool use_lock) const; // number of free bytes in audio buffer
     106    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
    104108
    105109    void UpdateVolume(void);
    106110
     
    161165    long long samples_buffered;
    162166
    163167    bool audio_thread_exists;
    164     pthread_t audio_thread;
    165168
    166169    /** adjustments to audiotimecode, waud, and raud can only be made
    167170        while holding this lock */
    168     mutable pthread_mutex_t audio_buflock;
     171    QMutex audio_buflock;
    169172
    170173    /** condition is signaled when the buffer gets more free space.
    171174        Must be holding audio_buflock to use. */
    172     pthread_cond_t audio_bufsig;
     175    QWaitCondition audio_bufsig;
    173176
    174177    /** must hold avsync_lock to read or write 'audiotime' and
    175178        'audiotime_updated' */
    176     mutable pthread_mutex_t avsync_lock;
     179    QMutex avsync_lock;
    177180
    178181    /// timecode of audio leaving the soundcard (same units as timecodes)
    179182    long long audiotime;
  • libs/libmyth/audiooutputca.cpp

     
    322322}
    323323
    324324/** Reimplement the base class's version of GetAudiotime()
    325  *  so that we don't use gettimeofday or pthread mutexes.
     325 *  so that we don't use gettimeofday or Qt mutexes.
    326326 */
    327 int AudioOutputCA::GetAudiotime(void) const
     327int AudioOutputCA::GetAudiotime(void)
    328328{
    329329    int ret;
    330330
     
    340340}
    341341
    342342/** Reimplement base's SetAudiotime()
    343  *  without gettimeofday() or pthread mutexes.
     343 *  without gettimeofday() or Qt mutexes.
    344344 */
    345345void AudioOutputCA::SetAudiotime(void)
    346346{
  • libs/libmyth/audiooutputwin.h

     
    11#ifndef AUDIOOUTPUTWIN
    22#define AUDIOOUTPUTWIN
    33
    4 // Qt headers
    5 #include <qstring.h>
    6 
    74// MythTV headers
    85#include "audiooutputbase.h"
    96
  • libs/libmyth/audiooutputjack.cpp

     
    88#include <cstring>
    99
    1010#include <iostream>
    11 #include <qdatetime.h>
    1211
    1312using namespace std;
    1413
  • libs/libmyth/audiooutputoss.h

     
    11#ifndef AUDIOOUTPUTOSS
    22#define AUDIOOUTPUTOSS
    33
    4 #include <vector>
    5 #include <qstring.h>
    6 #include <qmutex.h>
    7 
    84#include "audiooutputbase.h"
    95
    106using namespace std;
  • libs/libmyth/audiooutputbase.cpp

     
    22#include <cmath>
    33
    44// POSIX headers
    5 #include <pthread.h>
    65#include <unistd.h>
    76#include <sys/time.h>
    87
    98// Qt headers
    10 #include <qdatetime.h>
    11 #include <qstring.h>
    12 #include <q3deepcopy.h>
     9#include <QMutexLocker>
    1310
    1411// MythTV headers
    1512#include "compat.h"
     
    7471    memory_corruption_test3(0xdeadbeef),
    7572    memory_corruption_test4(0xdeadbeef)
    7673{
    77     pthread_mutex_init(&audio_buflock, NULL);
    78     pthread_mutex_init(&avsync_lock, NULL);
    79     pthread_cond_init(&audio_bufsig, NULL);
    80 
    8174    // The following are not bzero() because MS Windows doesn't like it.
    8275    memset(&src_data,          0, sizeof(SRC_DATA));
    8376    memset(src_in,             0, sizeof(float) * kAudioSourceInputSize);
     
    10194                "~AudioOutputBase called, but KillAudio has not been called!");
    10295    }
    10396
    104     pthread_mutex_destroy(&audio_buflock);
    105     pthread_mutex_destroy(&avsync_lock);
    106     pthread_cond_destroy(&audio_bufsig);
    107 
    10897    assert(memory_corruption_test0 == 0xdeadbeef);
    10998    assert(memory_corruption_test1 == 0xdeadbeef);
    11099    assert(memory_corruption_test2 == 0xdeadbeef);
     
    185174
    186175void AudioOutputBase::SetStretchFactor(float laudio_stretchfactor)
    187176{
    188     pthread_mutex_lock(&audio_buflock);
     177    QMutexLocker lock(&audio_buflock);
    189178    SetStretchFactorLocked(laudio_stretchfactor);
    190     pthread_mutex_unlock(&audio_buflock);
    191179}
    192180
    193181float AudioOutputBase::GetStretchFactor(void) const
     
    256244
    257245    KillAudio();
    258246
    259     pthread_mutex_lock(&audio_buflock);
    260     pthread_mutex_lock(&avsync_lock);
     247    QMutexLocker lock1(&audio_buflock);
     248    QMutexLocker lock2(&avsync_lock);
    261249
    262250    lastaudiolen = 0;
    263251    waud = raud = 0;
     
    274262
    275263    if (audio_bits != 8 && audio_bits != 16)
    276264    {
    277         pthread_mutex_unlock(&avsync_lock);
    278         pthread_mutex_unlock(&audio_buflock);
    279265        Error("AudioOutput only supports 8 or 16bit audio.");
    280266        return;
    281267    }
     
    298284    if (!OpenDevice())
    299285    {
    300286        VERBOSE(VB_AUDIO, LOC_ERR + "Aborting reconfigure");
    301         pthread_mutex_unlock(&avsync_lock);
    302         pthread_mutex_unlock(&audio_buflock);
    303287        if (GetError().isEmpty())
    304288            Error("Aborting reconfigure");
    305289        VERBOSE(VB_AUDIO, "Aborting reconfigure");
     
    337321        {
    338322            Error(QString("Error creating resampler, the error was: %1")
    339323                  .arg(src_strerror(error)) );
    340             pthread_mutex_unlock(&avsync_lock);
    341             pthread_mutex_unlock(&audio_buflock);
    342324            return;
    343325        }
    344326        src_data.src_ratio = (double) audio_samplerate / settings.samplerate;
     
    423405    prepareVisuals();
    424406
    425407    StartOutputThread();
    426     pthread_mutex_unlock(&avsync_lock);
    427     pthread_mutex_unlock(&audio_buflock);
    428408    VERBOSE(VB_AUDIO, LOC + "Ending reconfigure");
    429409}
    430410
     
    433413    if (audio_thread_exists)
    434414        return true;
    435415
    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();
    445417    audio_thread_exists = true;
    446418
    447419    return true;
     
    452424{
    453425    if (audio_thread_exists)
    454426    {
    455         pthread_join(audio_thread, NULL);
     427        wait();
    456428        audio_thread_exists = false;
    457429    }
    458430}
     
    504476
    505477void AudioOutputBase::Reset()
    506478{
    507     pthread_mutex_lock(&audio_buflock);
    508     pthread_mutex_lock(&avsync_lock);
     479    QMutexLocker lock1(&audio_buflock);
     480    QMutexLocker lock2(&avsync_lock);
    509481
    510482    raud = waud = 0;
    511483    audbuf_timecode = 0;
     
    518490    prepareVisuals();
    519491
    520492    gettimeofday(&audiotime_updated, NULL);
    521 
    522     pthread_mutex_unlock(&avsync_lock);
    523     pthread_mutex_unlock(&audio_buflock);
    524493}
    525494
    526495void AudioOutputBase::SetTimecode(long long timecode)
    527496{
    528     pthread_mutex_lock(&audio_buflock);
     497    QMutexLocker locker(&audio_buflock);
    529498    audbuf_timecode = timecode;
    530499    samples_buffered = (long long)((timecode * effdsp) / 100000.0);
    531     pthread_mutex_unlock(&audio_buflock);
    532500}
    533501
    534502void AudioOutputBase::SetEffDsp(int dsprate)
     
    543511    this->blocking = blocking;
    544512}
    545513
    546 int AudioOutputBase::audiolen(bool use_lock) const
     514int AudioOutputBase::audiolen(bool use_lock)
    547515{
    548516    /* Thread safe, returns the number of valid bytes in the audio buffer */
    549517    int ret;
    550518
    551519    if (use_lock)
    552         pthread_mutex_lock(&audio_buflock);
     520        audio_buflock.lock();
    553521
    554522    if (waud >= raud)
    555523        ret = waud - raud;
     
    557525        ret = kAudioRingBufferSize - (raud - waud);
    558526
    559527    if (use_lock)
    560         pthread_mutex_unlock(&audio_buflock);
     528        audio_buflock.unlock();
    561529
    562530    return ret;
    563531}
    564532
    565 int AudioOutputBase::audiofree(bool use_lock) const
     533int AudioOutputBase::audiofree(bool use_lock)
    566534{
    567535    return kAudioRingBufferSize - audiolen(use_lock) - 1;
    568536    /* There is one wasted byte in the buffer. The case where waud = raud is
     
    570538       be is kAudioRingBufferSize - 1. */
    571539}
    572540
    573 int AudioOutputBase::GetAudiotime(void) const
     541int AudioOutputBase::GetAudiotime(void)
    574542{
    575543    /* Returns the current timecode of audio leaving the soundcard, based
    576544       on the 'audiotime' computed earlier, and the delay since it was computed.
     
    586554    if (audiotime == 0)
    587555        return 0;
    588556
    589     pthread_mutex_lock(&avsync_lock);
     557    QMutexLocker lock(&avsync_lock);
    590558
    591559    gettimeofday(&now, NULL);
    592560
     
    607575
    608576    ret += audiotime;
    609577
    610     pthread_mutex_unlock(&avsync_lock);
    611578    return (int)ret;
    612579}
    613580
     
    636603       'ms/byte' is given by '25000/effdsp'...
    637604     */
    638605
    639     pthread_mutex_lock(&audio_buflock);
    640     pthread_mutex_lock(&avsync_lock);
     606    QMutexLocker lock1(&audio_buflock);
     607    QMutexLocker lock2(&avsync_lock);
    641608
    642609    soundcard_buffer = GetBufferedOnSoundcard(); // bytes
    643610    totalbuffer = audiolen(false) + soundcard_buffer;
     
    676643            .arg(audio_bytes_per_sample)
    677644            .arg(audio_stretchfactor));
    678645#endif
    679 
    680     pthread_mutex_unlock(&avsync_lock);
    681     pthread_mutex_unlock(&audio_buflock);
    682646}
    683647
    684 int AudioOutputBase::GetAudioBufferedTime(void) const
     648int AudioOutputBase::GetAudioBufferedTime(void)
    685649{
    686650     return audbuf_timecode - GetAudiotime();
    687651}
     
    831795                    QString("(need %1, available %2)").arg(len).arg(afree));
    832796
    833797            // wait for more space
    834             pthread_cond_wait(&audio_bufsig, &audio_buflock);
     798            audio_bufsig.wait(&audio_buflock);
    835799            afree = audiofree(false);
    836800        }
    837801        else
     
    857821void AudioOutputBase::_AddSamples(void *buffer, bool interleaved, int samples,
    858822                                  long long timecode)
    859823{
    860     pthread_mutex_lock(&audio_buflock);
     824    audio_buflock.lock();
    861825
    862826    int len; // = samples * audio_bytes_per_sample;
    863827    int audio_bytes = audio_bits / 8;
     
    885849        {
    886850            // just in case it does a processing cycle, release the lock
    887851            // to allow the output loop to do output
    888             pthread_mutex_unlock(&audio_buflock);
     852            audio_buflock.unlock();
    889853            if (audio_bytes == 2)
    890854            {
    891855                itemp += upmixer->putSamples(
     
    902866                    source_audio_channels,
    903867                    (interleaved) ? 0 : samples);
    904868            }
    905             pthread_mutex_lock(&audio_buflock);
     869            audio_buflock.lock();
    906870
    907871            int copy_samples = upmixer->numSamples();
    908872            if (copy_samples)
     
    11031067        }
    11041068    }
    11051069
    1106     pthread_mutex_unlock(&audio_buflock);
     1070    audio_buflock.unlock();
    11071071}
    11081072
    11091073void AudioOutputBase::Status()
     
    11281092    }
    11291093}
    11301094
    1131 void AudioOutputBase::GetBufferStatus(uint &fill, uint &total) const
     1095void AudioOutputBase::GetBufferStatus(uint &fill, uint &total)
    11321096{
    11331097    fill = kAudioRingBufferSize - audiofree(true);
    11341098    total = kAudioRingBufferSize;
     
    12211185
    12221186            //VERBOSE(VB_AUDIO+VB_TIMESTAMP,
    12231187            //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();
    12271191
    12281192            usleep(2000);
    12291193            continue;
     
    12671231
    12681232int AudioOutputBase::GetAudioData(unsigned char *buffer, int buf_size, bool full_buffer)
    12691233{
    1270     pthread_mutex_lock(&audio_buflock); // begin critical section
     1234    audio_buflock.lock(); // begin critical section
    12711235
    12721236    // re-check audiolen() in case things changed.
    12731237    // for example, ClearAfterSeek() might have run
     
    12971261        /* update raud */
    12981262        raud = (raud + fragment_size) % kAudioRingBufferSize;
    12991263        VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + "Broadcasting free space avail");
    1300         pthread_cond_broadcast(&audio_bufsig);
     1264        audio_bufsig.wakeAll();
    13011265
    13021266        written_size = fragment_size;
    13031267    }
    1304     pthread_mutex_unlock(&audio_buflock); // end critical section
     1268    audio_buflock.unlock();
    13051269
    13061270    // Mute individual channels through mono->stereo duplication
    13071271    kMuteState mute_state = GetMute();
     
    13371301    }
    13381302}
    13391303
    1340 void *AudioOutputBase::kickoffOutputAudioLoop(void *player)
     1304void AudioOutputBase::run(void)
    13411305{
    13421306    VERBOSE(VB_AUDIO, LOC + QString("kickoffOutputAudioLoop: pid = %1")
    13431307                                    .arg(getpid()));
    1344     ((AudioOutputBase *)player)->OutputAudioLoop();
     1308    OutputAudioLoop();
    13451309    VERBOSE(VB_AUDIO, LOC + "kickoffOutputAudioLoop exiting");
    1346     return NULL;
    13471310}
    13481311
    13491312int AudioOutputBase::readOutputData(unsigned char*, int)
  • libs/libmyth/audiooutput.cpp

     
    11#include <cstdio>
    22#include <cstdlib>
    33
    4 #include <Q3DeepCopy>
    5 
    64using namespace std;
    75
    86#include "mythconfig.h"
     
    124122
    125123void AudioOutput::Error(const QString &msg)
    126124{
    127     lastError = Q3DeepCopy<QString>(msg);
     125    lastError = msg;
     126    lastError.detach();
    128127    VERBOSE(VB_IMPORTANT, "AudioOutput Error: " + lastError);
    129128}
    130129
    131130void AudioOutput::Warn(const QString &msg)
    132131{
    133     lastWarn = Q3DeepCopy<QString>(msg);
     132    lastWarn = msg;
     133    lastWarn.detach();
    134134    VERBOSE(VB_IMPORTANT, "AudioOutput Warning: " + lastWarn);
    135135}
    136136
  • libs/libmyth/mythdialogs.cpp

     
    2525#endif
    2626
    2727#include <iostream>
    28 #include <pthread.h>
    2928using namespace std;
    3029
    31 #ifdef USE_LIRC
    32 #include "lirc.h"
    33 #include "lircevent.h"
    34 #endif
    35 
    36 #ifdef USE_JOYSTICK_MENU
    37 #include "jsmenu.h"
    38 #include "jsmenuevent.h"
    39 #endif
    40 
    4130#include "uitypes.h"
    4231#include "uilistbtntype.h"
    4332#include "xmlparse.h"
  • libs/libmyth/audiosettings.h

     
    88#ifndef _AUDIO_SETTINGS_H_
    99#define _AUDIO_SETTINGS_H_
    1010
    11 #include <qstring.h>
     11#include <QString>
    1212
    1313#include "mythexp.h"
    1414
  • libs/libmyth/audiooutputca.h

     
    11#ifndef AUDIOOUTPUTCA
    22#define AUDIOOUTPUTCA
    33
    4 #include <vector>
    5 #include <qstring.h>
    6 
    74#include "audiooutputbase.h"
    85
    96using namespace std;
     
    2118    AudioOutputCA(const AudioSettings &settings);
    2219    virtual ~AudioOutputCA();
    2320   
    24     virtual int GetAudiotime(void) const;
     21    virtual int GetAudiotime(void);
    2522    void        SetAudiotime(void);
    2623
    2724    // callback for delivering audio to output device
  • libs/libmyth/audiooutputoss.cpp

     
    1010#include <cstring>
    1111
    1212#include <iostream>
    13 #include <qdatetime.h>
    1413#include "config.h"
    1514
    1615#ifdef HAVE_SYS_SOUNDCARD_H
  • libs/libmyth/audiooutputarts.cpp

     
    11#include <cstdio>
    22#include <cstdlib>
    33
    4 
    54using namespace std;
    65
    76#include "mythcontext.h"
  • libs/libmyth/audiooutputdx.cpp

     
    310310    paused = pause;
    311311}
    312312
    313 int AudioOutputDX::GetAudiotime(void) const
     313int AudioOutputDX::GetAudiotime(void)
    314314{
    315315    DWORD play_pos;
    316316    HRESULT dsresult;
  • libs/libmyth/audiooutputnull.h

     
    11#ifndef AUDIOOUTPUTNULL
    22#define AUDIOOUTPUTNULL
    33
    4 #include <qmutex.h>
    5 #include <pthread.h>
    6 
    74#include "audiooutputbase.h"
    85
    96#define NULLAUDIO_OUTPUT_BUFFER_SIZE 32768
  • libs/libmyth/audiooutput.h

     
    11#ifndef AUDIOOUTPUT
    22#define AUDIOOUTPUT
    33
    4 #include <qstring.h>
     4#include <QString>
    55
    66#include "audiosettings.h"
    77#include "mythcontext.h"
     
    5151    // Wait for all data to finish playing
    5252    virtual void Drain(void) = 0;
    5353
    54     virtual int GetAudiotime(void) const = 0;
     54    virtual int GetAudiotime(void) = 0;
    5555
    5656    /// report amount of audio buffered in milliseconds.
    57     virtual int GetAudioBufferedTime(void) const { return 0; }
     57    virtual int GetAudioBufferedTime(void) { return 0; }
    5858
    5959    virtual void SetSourceBitrate(int ) { }
    6060
    6161    QString GetError(void)   const { return lastError; }
    6262    QString GetWarning(void) const { return lastWarn; }
    6363
    64     virtual void GetBufferStatus(uint &fill, uint &total) const
     64    virtual void GetBufferStatus(uint &fill, uint &total)
    6565        { fill = total = 0; }
    6666
    6767    //  Only really used by the AudioOutputNULL object
  • libs/libmyth/audiooutputnull.cpp

     
    1212#include <cerrno>
    1313#include <cstring>
    1414#include <iostream>
    15 #include <qdatetime.h>
     15
    1616#include "config.h"
    1717
    1818using namespace std;
  • libs/libmyth/audiooutputarts.h

     
    11#ifndef AUDIOOUTPUTARTS
    22#define AUDIOOUTPUTARTS
    33
    4 #include <qstring.h>
    5 
    64#define ARTS_PCM_NEW_HW_PARAMS_API
    75#define ARTS_PCM_NEW_SW_PARAMS_API
    86#include <artsc.h>
  • libs/libmyth/audiooutputdx.h

     
    88#include <windows.h> // HACK HACK HACK
    99#include <dsound.h>  // HACK HACK HACK
    1010
    11 // Qt headers
    12 #include <qstring.h>
    13 
    1411// MythTV headers
    1512#include "audiooutputbase.h"
    1613
     
    4340
    4441    virtual void Drain(void);
    4542
    46     virtual int GetAudiotime(void) const;
     43    virtual int GetAudiotime(void);
    4744
    4845    // Volume control
    4946    virtual int GetVolumeChannel(int channel) const; // Returns 0-100
  • libs/libmyth/audiooutputalsa.h

     
    11#ifndef AUDIOOUTPUTALSA
    22#define AUDIOOUTPUTALSA
    33
    4 #include <vector>
    5 #include <qstring.h>
    6 #include <qmutex.h>
    7 
    84#define ALSA_PCM_NEW_HW_PARAMS_API
    95#define ALSA_PCM_NEW_SW_PARAMS_API
    106#include <alsa/asoundlib.h>
     
    9086    QMutex       killAudioLock;
    9187    snd_mixer_t *mixer_handle;
    9288    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);
    9591};
    9692
    9793#endif
  • programs/mythtranscode/transcode.cpp

     
    167167        return;
    168168    }
    169169
    170     virtual int GetAudiotime(void) const
     170    virtual int GetAudiotime(void)
    171171    {
    172172        return last_audiotime;
    173173    }