summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Yves Avenard <jyavenard@mythtv.org>2011-10-05 07:54:38 (GMT)
committer Jean-Yves Avenard <jyavenard@mythtv.org>2011-10-05 07:54:38 (GMT)
commitafbbb6e1d42725d2bdd2bedfdadb04c83196ef41 (patch)
tree15c8382e782334114ea745746fa1dae57effa3ed
parent819649ffd2811fb1012beb62985225bf747c59e4 (diff)
Fix possible audio corruption.
Under some circumstances, audio already played could be heard again. This was the result of an incorrect audio buffer circular buffer pointer calculation
-rw-r--r--mythtv/libs/libmyth/audio/audiooutputbase.cpp33
-rw-r--r--mythtv/libs/libmyth/audio/audiooutputbase.h8
2 files changed, 21 insertions, 20 deletions
diff --git a/mythtv/libs/libmyth/audio/audiooutputbase.cpp b/mythtv/libs/libmyth/audio/audiooutputbase.cpp
index cce6f40..0c8d95c 100644
--- a/mythtv/libs/libmyth/audio/audiooutputbase.cpp
+++ b/mythtv/libs/libmyth/audio/audiooutputbase.cpp
@@ -1156,7 +1156,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;
@@ -1176,7 +1176,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;
}
@@ -1194,7 +1194,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;
}
@@ -1225,7 +1225,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;
}
@@ -1276,9 +1276,9 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
// Don't write new samples if we're resetting the buffer or reconfiguring
QMutexLocker lock(&audio_buflock);
- int org_waud = waud;
- int afree = audiofree();
- int used = kAudioRingBufferSize - afree;
+ uint org_waud = waud;
+ int afree = audiofree();
+ int used = kAudioRingBufferSize - afree;
if (passthru && m_spdifenc)
{
@@ -1336,13 +1336,16 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
AudioOutputSettings::SampleSize(format) * len;
// Account for changes in number of channels
- if (needs_upmix || needs_downmix)
- len = (len / source_channels) * configured_channels;
+ if (needs_downmix)
+ len = (len * configured_channels ) / source_channels;
// Check we have enough space to write the data
if (need_resampler && src_ctx)
len = (int)ceilf(float(len) * src_data.src_ratio);
+ if (needs_upmix)
+ len = (len * configured_channels ) / source_channels;
+
// Include samples in upmix buffer that may be flushed
if (needs_upmix && upmixer)
len += upmixer->numUnprocessedFrames() * bpf;
@@ -1452,7 +1455,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
nFrames = pSoundStretch->receiveSamples((STST *)(WPOS),
nFrames);
- org_waud += nFrames * bpf;
+ org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
}
if (internal_vol && SWVolume())
@@ -1470,7 +1473,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
if (num > 0)
AudioOutputUtil::AdjustVolume(WPOS, num, volume,
music, needs_upmix && upmixer);
- org_waud += num;
+ org_waud = (org_waud + num) % kAudioRingBufferSize;
}
if (encoder)
@@ -1499,7 +1502,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
if (to_get > 0)
encoder->GetFrames(WPOS, to_get);
- org_waud += to_get;
+ org_waud = (org_waud + to_get) % kAudioRingBufferSize;
}
waud = org_waud;
@@ -1612,7 +1615,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())
@@ -1644,7 +1647,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
@@ -1743,5 +1746,3 @@ int AudioOutputBase::readOutputData(unsigned char*, int)
VBERROR("AudioOutputBase should not be getting asked to readOutputData()");
return 0;
}
-
-
diff --git a/mythtv/libs/libmyth/audio/audiooutputbase.h b/mythtv/libs/libmyth/audio/audiooutputbase.h
index 301c16c..2f59db9 100644
--- a/mythtv/libs/libmyth/audio/audiooutputbase.h
+++ b/mythtv/libs/libmyth/audio/audiooutputbase.h
@@ -111,7 +111,7 @@ class AudioOutputBase : public AudioOutput, public MThread
static const uint kAudioSRCInputSize = 16384;
/// 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
@@ -137,7 +137,7 @@ class AudioOutputBase : public AudioOutput, public MThread
virtual void StopOutputThread(void);
int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer,
- int *local_raud = NULL);
+ volatile uint *local_raud = NULL);
void OutputAudioLoop(void);
@@ -191,7 +191,7 @@ class AudioOutputBase : public AudioOutput, public MThread
bool SetupPassthrough(int codec, int codec_profile,
int &samplerate_tmp, int &channels_tmp);
AudioOutputSettings* OutputSettings(bool digital = true);
- 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;
@@ -240,7 +240,7 @@ class AudioOutputBase : public AudioOutput, public MThread
/**
* 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
*/