MultiAudioNode: Fix and polish output locking issues

* For people involved please review, too much confusion seems
to have been done in past.
* The fBufferFreeSem is removed as it didn't make sense. It was
used to detected when the output thread should be stopped, a
boolean flag is used instead.
* Avoid to allocate a BAutolocker at begin of the _OutputThread,
plain Lock/Unlock is used instead.
* The fBufferLock is now locked when a buffer is handled.
This commit is contained in:
Dario Casalinuovo
2017-01-20 20:52:35 +01:00
parent 0563e540b0
commit 19da5e15c3
2 changed files with 11 additions and 22 deletions
@@ -173,6 +173,7 @@ MultiAudioNode::MultiAudioNode(BMediaAddOn* addon, const char* name,
BBufferConsumer(B_MEDIA_RAW_AUDIO), BBufferConsumer(B_MEDIA_RAW_AUDIO),
BBufferProducer(B_MEDIA_RAW_AUDIO), BBufferProducer(B_MEDIA_RAW_AUDIO),
BMediaEventLooper(), BMediaEventLooper(),
fRunOutput(false),
fBufferLock("multi audio buffers"), fBufferLock("multi audio buffers"),
fThread(-1), fThread(-1),
fDevice(device), fDevice(device),
@@ -1172,6 +1173,8 @@ MultiAudioNode::_HandleBuffer(const media_timed_event* event,
fprintf(stderr," <- LATE BUFFER : %" B_PRIdBIGTIME "\n", lateness); fprintf(stderr," <- LATE BUFFER : %" B_PRIdBIGTIME "\n", lateness);
buffer->Recycle(); buffer->Recycle();
} else { } else {
BAutolock _(fBufferLock);
//WriteBuffer(buffer, *channel); //WriteBuffer(buffer, *channel);
// TODO: This seems like a very fragile mechanism to wait until // TODO: This seems like a very fragile mechanism to wait until
// the previous buffer for this channel has been processed... // the previous buffer for this channel has been processed...
@@ -1777,18 +1780,13 @@ MultiAudioNode::_OutputThread()
// init the performance time computation // init the performance time computation
{ {
BAutolock locker(fBufferLock); fBufferLock.Lock();
fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate, fTimeComputer.Init(fOutputPreferredFormat.u.raw_audio.frame_rate,
system_time()); system_time());
fBufferLock.Unlock();
} }
while (true) { while (fRunOutput) {
// TODO: why this semaphore??
if (acquire_sem_etc(fBufferFreeSem, 1, B_RELATIVE_TIMEOUT, 0)
== B_BAD_SEM_ID) {
return B_OK;
}
BAutolock locker(fBufferLock); BAutolock locker(fBufferLock);
// make sure the buffers don't change while we're playing with them // make sure the buffers don't change while we're playing with them
@@ -1836,9 +1834,6 @@ MultiAudioNode::_OutputThread()
_WriteZeros(*input, input->fBufferCycle); _WriteZeros(*input, input->fBufferCycle);
//PRINT(("MultiAudioNode::Runthread WriteZeros\n")); //PRINT(("MultiAudioNode::Runthread WriteZeros\n"));
} }
// mark buffer free
release_sem(fBufferFreeSem);
} else { } else {
//PRINT(("playback_buffer_cycle non ok input : %i\n", i)); //PRINT(("playback_buffer_cycle non ok input : %i\n", i));
} }
@@ -2048,21 +2043,14 @@ MultiAudioNode::_StartOutputThreadIfNeeded()
if (fThread >= 0) if (fThread >= 0)
return B_OK; return B_OK;
// allocate buffer free semaphore fRunOutput = true;
fBufferFreeSem = create_sem(
fDevice->BufferList().return_playback_buffers - 1,
"multi_audio out buffer free");
if (fBufferFreeSem < B_OK)
return fBufferFreeSem;
PublishTime(-50, 0, 0); PublishTime(-50, 0, 0);
fThread = spawn_thread(_OutputThreadEntry, "multi_audio audio output", fThread = spawn_thread(_OutputThreadEntry, "multi_audio audio output",
B_REAL_TIME_PRIORITY, this); B_REAL_TIME_PRIORITY, this);
if (fThread < B_OK) { if (fThread < B_OK)
delete_sem(fBufferFreeSem);
return fThread; return fThread;
}
resume_thread(fThread); resume_thread(fThread);
return B_OK; return B_OK;
@@ -2073,7 +2061,8 @@ status_t
MultiAudioNode::_StopOutputThread() MultiAudioNode::_StopOutputThread()
{ {
CALLED(); CALLED();
delete_sem(fBufferFreeSem);
fRunOutput = false;
status_t exitValue; status_t exitValue;
wait_for_thread(fThread, &exitValue); wait_for_thread(fThread, &exitValue);
@@ -208,6 +208,7 @@ private:
private: private:
status_t fInitStatus; status_t fInitStatus;
bool fRunOutput;
BMediaAddOn* fAddOn; BMediaAddOn* fAddOn;
int32 fId; int32 fId;
@@ -227,7 +228,6 @@ private:
// not the defaults that are in the parameters // not the defaults that are in the parameters
bigtime_t fBufferPeriod; bigtime_t fBufferPeriod;
sem_id fBufferFreeSem;
thread_id fThread; thread_id fThread;
MultiAudioDevice* fDevice; MultiAudioDevice* fDevice;
bool fTimeSourceStarted; bool fTimeSourceStarted;