summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Yves Avenard <jyavenard@mythtv.org>2011-10-06 04:57:20 (GMT)
committer Jean-Yves Avenard <jyavenard@mythtv.org>2011-10-06 04:57:20 (GMT)
commit35468d7d5ce5af18280c8753775e3b54f7ceaf40 (patch)
tree3a6a94b275c3fbdb3c721372f6dbfdc2c55ee581
parent19b31f302a5674493f71559e878d28be2ff59095 (diff)
Fix possible audio corruption.
Under some circumstances, audio already played could be heard again. This was the result of an incorrect audio circular buffer pointer calculation
-rw-r--r--mythtv/libs/libmyth/audiooutputbase.cpp33
-rw-r--r--mythtv/libs/libmyth/audiooutputbase.h9
2 files changed, 22 insertions, 20 deletions
diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
index aeb8261..8cb4248 100644
--- a/mythtv/libs/libmyth/audiooutputbase.cpp
+++ b/mythtv/libs/libmyth/audiooutputbase.cpp
@@ -959,7 +959,7 @@ int AudioOutputBase::CheckFreeSpace(int &frames)
* Returns the number of frames written, which may be less than requested
* if the upmixer buffered some (or all) of them
*/
-int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
+int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, uint &org_waud)
{
int len = CheckFreeSpace(frames);
int bdiff = kAudioRingBufferSize - org_waud;
@@ -978,7 +978,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
}
if (num > 0)
memcpy(WPOS, buffer + off, num);
- org_waud += num;
+ org_waud = (org_waud + num) % kAudioRingBufferSize;
return len;
}
@@ -996,7 +996,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (frames > 0)
AudioOutputUtil::MonoToStereo(WPOS, buffer + off, frames);
- org_waud += frames * bpf;
+ org_waud = (org_waud + frames * bpf) % kAudioRingBufferSize;
return len;
}
@@ -1031,7 +1031,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
if (nFrames > 0)
upmixer->receiveFrames((float *)(WPOS), nFrames);
- org_waud += nFrames * bpf;
+ org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
}
return len;
}
@@ -1044,12 +1044,13 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
int64_t timecode)
{
- int org_waud = waud, afree = audiofree();
- int frames = in_frames;
- void *buffer = in_buffer;
- int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
- int used = kAudioRingBufferSize - afree;
- bool music = false;
+ uint org_waud = waud;
+ int afree = audiofree();
+ int frames = in_frames;
+ void *buffer = in_buffer;
+ int bpf = bytes_per_frame, len = frames * source_bytes_per_frame;
+ int used = kAudioRingBufferSize - afree;
+ bool music = false;
int bdiff;
VBAUDIOTS(QString("AddFrames frames=%1, bytes=%2, used=%3, free=%4, "
@@ -1202,7 +1203,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
nFrames = pSoundStretch->receiveSamples((STST *)(WPOS),
nFrames);
- org_waud += nFrames * bpf;
+ org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
}
if (internal_vol && SWVolume())
@@ -1220,7 +1221,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
if (num > 0)
AudioOutputUtil::AdjustVolume(WPOS, num, volume,
music, needs_upmix && upmixer);
- org_waud += num;
+ org_waud = (org_waud + num) % kAudioRingBufferSize;
}
if (encoder)
@@ -1253,7 +1254,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
else
{
to_get = encoder->Encode(WPOS, len, processing);
- org_waud += len;
+ org_waud = (org_waud + len) % kAudioRingBufferSize;
}
bdiff = kAudioRingBufferSize - org_waud2;
@@ -1266,7 +1267,7 @@ bool AudioOutputBase::AddFrames(void *in_buffer, int in_frames,
if (to_get > 0)
encoder->GetFrames(audiobuffer + org_waud2, to_get);
- org_waud2 += to_get;
+ org_waud2 = (org_waud2 + to_get) % kAudioRingBufferSize;
}
while (remaining > 0);
org_waud = org_waud2;
@@ -1387,7 +1388,7 @@ void AudioOutputBase::OutputAudioLoop(void)
// delay setting raud until after phys buffer is filled
// so GetAudiotime will be accurate without locking
reset_active.TestAndDeref();
- int next_raud = raud;
+ volatile uint next_raud = raud;
if (GetAudioData(fragment, fragment_size, true, &next_raud))
{
if (!reset_active.TestAndDeref())
@@ -1419,7 +1420,7 @@ void AudioOutputBase::OutputAudioLoop(void)
* available. Returns the number of bytes copied.
*/
int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer,
- int *local_raud)
+ volatile uint *local_raud)
{
#define LRPOS audiobuffer + *local_raud
diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
index 30a071b..68788ec 100644
--- a/mythtv/libs/libmyth/audiooutputbase.h
+++ b/mythtv/libs/libmyth/audiooutputbase.h
@@ -99,7 +99,7 @@ class AudioOutputBase : public AudioOutput, public QThread
static const uint kAudioSRCInputSize = 32768;
/// Audio Buffer Size -- should be divisible by 32,24,16,12,10,8,6,4,2..
- static const uint kAudioRingBufferSize = 3072000;
+ static const uint kAudioRingBufferSize = 3072000u;
protected:
// Following function must be called from subclass constructor
@@ -120,7 +120,8 @@ class AudioOutputBase : public AudioOutput, public QThread
virtual bool StartOutputThread(void);
virtual void StopOutputThread(void);
- int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer, int *local_raud = NULL);
+ int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer,
+ volatile uint *local_raud = NULL);
void OutputAudioLoop(void);
@@ -169,7 +170,7 @@ class AudioOutputBase : public AudioOutput, public QThread
int src_quality;
private:
- int CopyWithUpmix(char *buffer, int frames, int &org_waud);
+ int CopyWithUpmix(char *buffer, int frames, uint &org_waud);
void SetAudiotime(int frames, int64_t timecode);
AudioOutputSettings *output_settingsraw;
AudioOutputSettings *output_settings;
@@ -208,7 +209,7 @@ class AudioOutputBase : public AudioOutput, public QThread
int64_t audiotime;
/* Audio circular buffer */
- int raud, waud; /* read and write positions */
+ volatile uint raud, waud; /* read and write positions */
// timecode of audio most recently placed into buffer
int64_t audbuf_timecode;
AsyncLooseLock reset_active;