diff --git a/src/playlist.cpp b/src/playlist.cpp index 26fc71d4..29542506 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -38,11 +38,12 @@ struct GroovePlaylistPrivate { struct GroovePlaylist externals; struct Groove *groove; pthread_t thread_id; - atomic_bool abort_request; + bool thread_inited; + bool abort_request; AVPacket audio_pkt_temp; AVFrame *in_frame; - int paused; + atomic_bool paused; int in_sample_rate; uint64_t in_channel_layout; @@ -678,9 +679,8 @@ static void *decode_thread(void *arg) { struct GroovePlaylistPrivate *p = (GroovePlaylistPrivate *)arg; struct GroovePlaylist *playlist = &p->externals; - while (!p->abort_request.load()) { - pthread_mutex_lock(&p->decode_head_mutex); - + pthread_mutex_lock(&p->decode_head_mutex); + while (!p->abort_request) { // if we don't have anything to decode, wait until we do if (!p->decode_head) { if (!p->sent_end_of_q) { @@ -688,7 +688,6 @@ static void *decode_thread(void *arg) { p->sent_end_of_q = 1; } pthread_cond_wait(&p->decode_head_cond, &p->decode_head_mutex); - pthread_mutex_unlock(&p->decode_head_mutex); continue; } p->sent_end_of_q = 0; @@ -729,8 +728,8 @@ static void *decode_thread(void *arg) { } } - pthread_mutex_unlock(&p->decode_head_mutex); } + pthread_mutex_unlock(&p->decode_head_mutex); return NULL; } @@ -996,11 +995,12 @@ struct GroovePlaylist * groove_playlist_create(struct Groove *groove) { return NULL; } - if (pthread_create(&p->thread_id, NULL, decode_thread, playlist) != 0) { + if (pthread_create(&p->thread_id, NULL, decode_thread, playlist)) { groove_playlist_destroy(playlist); av_log(NULL, AV_LOG_ERROR, "unable to create playlist thread\n"); return NULL; } + p->thread_inited = true; p->volume_filter = avfilter_get_by_name("volume"); if (!p->volume_filter) { @@ -1053,9 +1053,19 @@ void groove_playlist_destroy(struct GroovePlaylist *playlist) { struct GroovePlaylistPrivate *p = (struct GroovePlaylistPrivate *) playlist; // wait for decode thread to finish - p->abort_request.store(true); - pthread_cond_signal(&p->decode_head_cond); - pthread_cond_signal(&p->sink_drain_cond); + if (p->thread_inited) { + pthread_mutex_lock(&p->decode_head_mutex); + p->abort_request = true; + pthread_cond_signal(&p->decode_head_cond); + pthread_mutex_unlock(&p->decode_head_mutex); + } + + if (p->drain_cond_mutex_inited) { + pthread_mutex_lock(&p->drain_cond_mutex); + pthread_cond_signal(&p->sink_drain_cond); + pthread_mutex_unlock(&p->drain_cond_mutex); + } + pthread_join(p->thread_id, NULL); every_sink(playlist, groove_sink_detach, 0); @@ -1080,19 +1090,15 @@ void groove_playlist_destroy(struct GroovePlaylist *playlist) { void groove_playlist_play(struct GroovePlaylist *playlist) { struct GroovePlaylistPrivate *p = (struct GroovePlaylistPrivate *) playlist; - // no mutex needed for this boolean flag - if (p->paused == 0) + if (!p->paused.exchange(false)) return; - p->paused = 0; every_sink(playlist, groove_sink_play, 0); } void groove_playlist_pause(struct GroovePlaylist *playlist) { struct GroovePlaylistPrivate *p = (struct GroovePlaylistPrivate *) playlist; - // no mutex needed for this boolean flag - if (p->paused == 1) + if (p->paused.exchange(true)) return; - p->paused = 1; every_sink(playlist, groove_sink_pause, 0); }