Relax v4l2_sink lock constraints
To fix a data race, commit 5caeab5f6d
called video_buffer_push() and video_buffer_consume() under the
v4l2_sink lock.
Instead, use the previous_skipped indication (initialized with video
buffer locked) to lock only for protecting the has_frame flag.
This enables the possibility for the video_buffer to notify new frames
via callbacks without lock inversion issues.
This commit is contained in:
parent
32e692d5d2
commit
28bce48d47
1 changed files with 10 additions and 9 deletions
|
@ -121,11 +121,11 @@ run_v4l2_sink(void *data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
video_buffer_consume(&vs->vb, vs->frame);
|
|
||||||
vs->has_frame = false;
|
vs->has_frame = false;
|
||||||
|
|
||||||
sc_mutex_unlock(&vs->mutex);
|
sc_mutex_unlock(&vs->mutex);
|
||||||
|
|
||||||
|
video_buffer_consume(&vs->vb, vs->frame);
|
||||||
|
|
||||||
bool ok = encode_and_write_frame(vs, vs->frame);
|
bool ok = encode_and_write_frame(vs, vs->frame);
|
||||||
av_frame_unref(vs->frame);
|
av_frame_unref(vs->frame);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
@ -303,17 +303,18 @@ sc_v4l2_sink_close(struct sc_v4l2_sink *vs) {
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sc_v4l2_sink_push(struct sc_v4l2_sink *vs, const AVFrame *frame) {
|
sc_v4l2_sink_push(struct sc_v4l2_sink *vs, const AVFrame *frame) {
|
||||||
sc_mutex_lock(&vs->mutex);
|
bool previous_skipped;
|
||||||
|
bool ok = video_buffer_push(&vs->vb, frame, &previous_skipped);
|
||||||
bool ok = video_buffer_push(&vs->vb, frame, NULL);
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vs->has_frame = true;
|
if (!previous_skipped) {
|
||||||
sc_cond_signal(&vs->cond);
|
sc_mutex_lock(&vs->mutex);
|
||||||
|
vs->has_frame = true;
|
||||||
sc_mutex_unlock(&vs->mutex);
|
sc_cond_signal(&vs->cond);
|
||||||
|
sc_mutex_unlock(&vs->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue