Fixed concurrency issue inside audio codec module: after calling codec_stop() the codec resulted free before the effective shutdown of the internal thread, causing codec_decode() to lock inside the outputStream_start() in case of a fast sequence of decode - stop - decode
This commit is contained in:
parent
d0d603901e
commit
10dcf04a92
|
|
@ -34,6 +34,8 @@ static streamId audioStream;
|
||||||
|
|
||||||
static uint8_t initCnt = 0;
|
static uint8_t initCnt = 0;
|
||||||
static bool running;
|
static bool running;
|
||||||
|
|
||||||
|
static bool stopThread;
|
||||||
static pthread_t codecThread;
|
static pthread_t codecThread;
|
||||||
static pthread_mutex_t mutex;
|
static pthread_mutex_t mutex;
|
||||||
static pthread_cond_t not_empty;
|
static pthread_cond_t not_empty;
|
||||||
|
|
@ -66,8 +68,11 @@ void codec_init()
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
initCnt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
initCnt = 1;
|
|
||||||
running = false;
|
running = false;
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
writePos = 0;
|
writePos = 0;
|
||||||
|
|
@ -106,15 +111,21 @@ bool codec_startEncode(const enum AudioSource source)
|
||||||
if(running) return false;
|
if(running) return false;
|
||||||
if(audioBuf == NULL) return false;
|
if(audioBuf == NULL) return false;
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
|
||||||
audioStream = inputStream_start(source, PRIO_TX, audioBuf, 320,
|
audioStream = inputStream_start(source, PRIO_TX, audioBuf, 320,
|
||||||
BUF_CIRC_DOUBLE, 8000);
|
BUF_CIRC_DOUBLE, 8000);
|
||||||
|
|
||||||
if(audioStream == -1) return false;
|
if(audioStream == -1)
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
writePos = 0;
|
writePos = 0;
|
||||||
numElements = 0;
|
numElements = 0;
|
||||||
running = true;
|
stopThread = false;
|
||||||
startThread(encodeFunc);
|
startThread(encodeFunc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -125,16 +136,22 @@ bool codec_startDecode(const enum AudioSink destination)
|
||||||
if(running) return false;
|
if(running) return false;
|
||||||
if(audioBuf == NULL) return false;
|
if(audioBuf == NULL) return false;
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
|
||||||
memset(audioBuf, 0x00, 320 * sizeof(stream_sample_t));
|
memset(audioBuf, 0x00, 320 * sizeof(stream_sample_t));
|
||||||
audioStream = outputStream_start(destination, PRIO_RX, audioBuf, 320,
|
audioStream = outputStream_start(destination, PRIO_RX, audioBuf, 320,
|
||||||
BUF_CIRC_DOUBLE, 8000);
|
BUF_CIRC_DOUBLE, 8000);
|
||||||
|
|
||||||
if(audioStream == -1) return false;
|
if(audioStream == -1)
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
writePos = 0;
|
writePos = 0;
|
||||||
numElements = 0;
|
numElements = 0;
|
||||||
running = true;
|
stopThread = false;
|
||||||
startThread(decodeFunc);
|
startThread(decodeFunc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -144,8 +161,10 @@ void codec_stop()
|
||||||
{
|
{
|
||||||
if(running == false) return;
|
if(running == false) return;
|
||||||
|
|
||||||
running = false;
|
stopThread = true;
|
||||||
pthread_join(codecThread, NULL);
|
pthread_join(codecThread, NULL);
|
||||||
|
|
||||||
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool codec_popFrame(uint8_t *frame, const bool blocking)
|
bool codec_popFrame(uint8_t *frame, const bool blocking)
|
||||||
|
|
@ -177,7 +196,7 @@ bool codec_popFrame(uint8_t *frame, const bool blocking)
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
// Do memcpy after mutex unlock to reduce execution time spent inside the
|
// Do memcpy after mutex unlock to reduce execution time spent inside the
|
||||||
// critical section
|
// critical section
|
||||||
memcpy(frame, &element, 8);
|
memcpy(frame, &element, 8);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -231,7 +250,7 @@ static void *encodeFunc(void *arg)
|
||||||
|
|
||||||
codec2 = codec2_create(CODEC2_MODE_3200);
|
codec2 = codec2_create(CODEC2_MODE_3200);
|
||||||
|
|
||||||
while(running)
|
while(stopThread == false)
|
||||||
{
|
{
|
||||||
dataBlock_t audio = inputStream_getData(audioStream);
|
dataBlock_t audio = inputStream_getData(audioStream);
|
||||||
|
|
||||||
|
|
@ -285,7 +304,7 @@ static void *decodeFunc(void *arg)
|
||||||
|
|
||||||
codec2 = codec2_create(CODEC2_MODE_3200);
|
codec2 = codec2_create(CODEC2_MODE_3200);
|
||||||
|
|
||||||
while(running)
|
while(stopThread == false)
|
||||||
{
|
{
|
||||||
// Try popping data from the queue
|
// Try popping data from the queue
|
||||||
uint64_t frame = 0;
|
uint64_t frame = 0;
|
||||||
|
|
@ -324,7 +343,9 @@ static void *decodeFunc(void *arg)
|
||||||
outputStream_sync(audioStream, true);
|
outputStream_sync(audioStream, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop stream and wait until its effective termination
|
||||||
outputStream_stop(audioStream);
|
outputStream_stop(audioStream);
|
||||||
|
outputStream_sync(audioStream, false);
|
||||||
codec2_destroy(codec2);
|
codec2_destroy(codec2);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue