Fix deadlock on exit if SKIP_FRAMES disabled
On exit, the renderer will not consume frames anymore, so signal the condition variable to wake up the decoder.
This commit is contained in:
parent
629c296207
commit
127e56780a
5 changed files with 28 additions and 6 deletions
|
@ -152,6 +152,10 @@ SDL_bool decoder_start(struct decoder *decoder) {
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void decoder_stop(struct decoder *decoder) {
|
||||
frames_stop(decoder->frames);
|
||||
}
|
||||
|
||||
void decoder_join(struct decoder *decoder) {
|
||||
SDL_WaitThread(decoder->thread, NULL);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ struct decoder {
|
|||
};
|
||||
|
||||
SDL_bool decoder_start(struct decoder *decoder);
|
||||
void decoder_stop(struct decoder *decoder);
|
||||
void decoder_join(struct decoder *decoder);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@ SDL_bool frames_init(struct frames *frames) {
|
|||
SDL_DestroyMutex(frames->mutex);
|
||||
goto error_2;
|
||||
}
|
||||
frames->stopped = SDL_FALSE;
|
||||
#endif
|
||||
|
||||
// there is initially no rendering frame, so consider it has already been
|
||||
|
@ -60,24 +61,23 @@ static void frames_swap(struct frames *frames) {
|
|||
|
||||
SDL_bool frames_offer_decoded_frame(struct frames *frames) {
|
||||
mutex_lock(frames->mutex);
|
||||
SDL_bool previous_frame_consumed;
|
||||
#ifndef SKIP_FRAMES
|
||||
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
||||
// frame to be consumed
|
||||
while (!frames->rendering_frame_consumed) {
|
||||
while (!frames->rendering_frame_consumed && !frames->stopped) {
|
||||
cond_wait(frames->rendering_frame_consumed_cond, frames->mutex);
|
||||
}
|
||||
// by definition, we are not skipping the frames
|
||||
previous_frame_consumed = SDL_TRUE;
|
||||
#else
|
||||
previous_frame_consumed = frames->rendering_frame_consumed;
|
||||
if (!previous_frame_consumed) {
|
||||
if (!frames->rendering_frame_consumed) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Skip frame");
|
||||
}
|
||||
#endif
|
||||
|
||||
frames_swap(frames);
|
||||
|
||||
SDL_bool previous_frame_consumed = frames->rendering_frame_consumed;
|
||||
frames->rendering_frame_consumed = SDL_FALSE;
|
||||
|
||||
mutex_unlock(frames->mutex);
|
||||
return previous_frame_consumed;
|
||||
}
|
||||
|
@ -92,3 +92,15 @@ const AVFrame *frames_consume_rendered_frame(struct frames *frames) {
|
|||
#endif
|
||||
return frames->rendering_frame;
|
||||
}
|
||||
|
||||
void frames_stop(struct frames *frames) {
|
||||
#ifdef SKIP_FRAMES
|
||||
(void) frames; // unused
|
||||
#else
|
||||
mutex_lock(frames->mutex);
|
||||
frames->stopped = SDL_TRUE;
|
||||
mutex_unlock(frames->mutex);
|
||||
// wake up blocking wait
|
||||
cond_signal(frames->rendering_frame_consumed_cond);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ struct frames {
|
|||
AVFrame *rendering_frame;
|
||||
SDL_mutex *mutex;
|
||||
#ifndef SKIP_FRAMES
|
||||
SDL_bool stopped;
|
||||
SDL_cond *rendering_frame_consumed_cond;
|
||||
#endif
|
||||
SDL_bool rendering_frame_consumed;
|
||||
|
@ -33,4 +34,7 @@ SDL_bool frames_offer_decoded_frame(struct frames *frames);
|
|||
// unlocking frames->mutex
|
||||
const AVFrame *frames_consume_rendered_frame(struct frames *frames);
|
||||
|
||||
// wake up and avoid any blocking call
|
||||
void frames_stop(struct frames *frames);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -180,6 +180,7 @@ finally_stop_and_join_controller:
|
|||
finally_destroy_controller:
|
||||
controller_destroy(&controller);
|
||||
finally_stop_decoder:
|
||||
decoder_stop(&decoder);
|
||||
// kill the server before decoder_join() to wake up the decoder
|
||||
server_stop(&server, serial);
|
||||
decoder_join(&decoder);
|
||||
|
|
Loading…
Reference in a new issue