Skip to content

Commit afbbb6e

Browse files
committed
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
1 parent 819649f commit afbbb6e

File tree

2 files changed

+21
-20
lines changed

2 files changed

+21
-20
lines changed

mythtv/libs/libmyth/audio/audiooutputbase.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ int AudioOutputBase::CheckFreeSpace(int &frames)
11561156
* Returns the number of frames written, which may be less than requested
11571157
* if the upmixer buffered some (or all) of them
11581158
*/
1159-
int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
1159+
int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, uint &org_waud)
11601160
{
11611161
int len = CheckFreeSpace(frames);
11621162
int bdiff = kAudioRingBufferSize - org_waud;
@@ -1176,7 +1176,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
11761176
}
11771177
if (num > 0)
11781178
memcpy(WPOS, buffer + off, num);
1179-
org_waud += num;
1179+
org_waud = (org_waud + num) % kAudioRingBufferSize;
11801180
return len;
11811181
}
11821182

@@ -1194,7 +1194,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
11941194
if (frames > 0)
11951195
AudioOutputUtil::MonoToStereo(WPOS, buffer + off, frames);
11961196

1197-
org_waud += frames * bpf;
1197+
org_waud = (org_waud + frames * bpf) % kAudioRingBufferSize;
11981198
return len;
11991199
}
12001200

@@ -1225,7 +1225,7 @@ int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud)
12251225
if (nFrames > 0)
12261226
upmixer->receiveFrames((float *)(WPOS), nFrames);
12271227

1228-
org_waud += nFrames * bpf;
1228+
org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
12291229
}
12301230
return len;
12311231
}
@@ -1276,9 +1276,9 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
12761276
// Don't write new samples if we're resetting the buffer or reconfiguring
12771277
QMutexLocker lock(&audio_buflock);
12781278

1279-
int org_waud = waud;
1280-
int afree = audiofree();
1281-
int used = kAudioRingBufferSize - afree;
1279+
uint org_waud = waud;
1280+
int afree = audiofree();
1281+
int used = kAudioRingBufferSize - afree;
12821282

12831283
if (passthru && m_spdifenc)
12841284
{
@@ -1336,13 +1336,16 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
13361336
AudioOutputSettings::SampleSize(format) * len;
13371337

13381338
// Account for changes in number of channels
1339-
if (needs_upmix || needs_downmix)
1340-
len = (len / source_channels) * configured_channels;
1339+
if (needs_downmix)
1340+
len = (len * configured_channels ) / source_channels;
13411341

13421342
// Check we have enough space to write the data
13431343
if (need_resampler && src_ctx)
13441344
len = (int)ceilf(float(len) * src_data.src_ratio);
13451345

1346+
if (needs_upmix)
1347+
len = (len * configured_channels ) / source_channels;
1348+
13461349
// Include samples in upmix buffer that may be flushed
13471350
if (needs_upmix && upmixer)
13481351
len += upmixer->numUnprocessedFrames() * bpf;
@@ -1452,7 +1455,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
14521455
nFrames = pSoundStretch->receiveSamples((STST *)(WPOS),
14531456
nFrames);
14541457

1455-
org_waud += nFrames * bpf;
1458+
org_waud = (org_waud + nFrames * bpf) % kAudioRingBufferSize;
14561459
}
14571460

14581461
if (internal_vol && SWVolume())
@@ -1470,7 +1473,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
14701473
if (num > 0)
14711474
AudioOutputUtil::AdjustVolume(WPOS, num, volume,
14721475
music, needs_upmix && upmixer);
1473-
org_waud += num;
1476+
org_waud = (org_waud + num) % kAudioRingBufferSize;
14741477
}
14751478

14761479
if (encoder)
@@ -1499,7 +1502,7 @@ bool AudioOutputBase::AddData(void *in_buffer, int in_len,
14991502
if (to_get > 0)
15001503
encoder->GetFrames(WPOS, to_get);
15011504

1502-
org_waud += to_get;
1505+
org_waud = (org_waud + to_get) % kAudioRingBufferSize;
15031506
}
15041507

15051508
waud = org_waud;
@@ -1612,7 +1615,7 @@ void AudioOutputBase::OutputAudioLoop(void)
16121615
// delay setting raud until after phys buffer is filled
16131616
// so GetAudiotime will be accurate without locking
16141617
reset_active.TestAndDeref();
1615-
int next_raud = raud;
1618+
volatile uint next_raud = raud;
16161619
if (GetAudioData(fragment, fragment_size, true, &next_raud))
16171620
{
16181621
if (!reset_active.TestAndDeref())
@@ -1644,7 +1647,7 @@ void AudioOutputBase::OutputAudioLoop(void)
16441647
* available. Returns the number of bytes copied.
16451648
*/
16461649
int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer,
1647-
int *local_raud)
1650+
volatile uint *local_raud)
16481651
{
16491652

16501653
#define LRPOS audiobuffer + *local_raud
@@ -1743,5 +1746,3 @@ int AudioOutputBase::readOutputData(unsigned char*, int)
17431746
VBERROR("AudioOutputBase should not be getting asked to readOutputData()");
17441747
return 0;
17451748
}
1746-
1747-

mythtv/libs/libmyth/audio/audiooutputbase.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class AudioOutputBase : public AudioOutput, public MThread
111111
static const uint kAudioSRCInputSize = 16384;
112112

113113
/// Audio Buffer Size -- should be divisible by 32,24,16,12,10,8,6,4,2..
114-
static const uint kAudioRingBufferSize = 3072000;
114+
static const uint kAudioRingBufferSize = 3072000u;
115115

116116
protected:
117117
// Following function must be called from subclass constructor
@@ -137,7 +137,7 @@ class AudioOutputBase : public AudioOutput, public MThread
137137
virtual void StopOutputThread(void);
138138

139139
int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer,
140-
int *local_raud = NULL);
140+
volatile uint *local_raud = NULL);
141141

142142
void OutputAudioLoop(void);
143143

@@ -191,7 +191,7 @@ class AudioOutputBase : public AudioOutput, public MThread
191191
bool SetupPassthrough(int codec, int codec_profile,
192192
int &samplerate_tmp, int &channels_tmp);
193193
AudioOutputSettings* OutputSettings(bool digital = true);
194-
int CopyWithUpmix(char *buffer, int frames, int &org_waud);
194+
int CopyWithUpmix(char *buffer, int frames, uint &org_waud);
195195
void SetAudiotime(int frames, int64_t timecode);
196196
AudioOutputSettings *output_settingsraw;
197197
AudioOutputSettings *output_settings;
@@ -240,7 +240,7 @@ class AudioOutputBase : public AudioOutput, public MThread
240240
/**
241241
* Audio circular buffer
242242
*/
243-
int raud, waud; // read and write positions
243+
volatile uint raud, waud; // read and write positions
244244
/**
245245
* timecode of audio most recently placed into buffer
246246
*/

0 commit comments

Comments
 (0)