Fix v4l2 data race
The v4l2_sink implementation directly read the internal video_buffer field "pending_frame_consumed", which is protected by the internal video_buffer mutex. But this mutex was not locked, so reads were racy. Lock using the v4l2_sink mutex in addition, and use a separate field to avoid depending on the video_buffer internal data.
This commit is contained in:
parent
33fbdc86c7
commit
5caeab5f6d
2 changed files with 11 additions and 3 deletions
|
@ -112,7 +112,7 @@ run_v4l2_sink(void *data) {
|
|||
for (;;) {
|
||||
sc_mutex_lock(&vs->mutex);
|
||||
|
||||
while (!vs->stopped && vs->vb.pending_frame_consumed) {
|
||||
while (!vs->stopped && !vs->has_frame) {
|
||||
sc_cond_wait(&vs->cond, &vs->mutex);
|
||||
}
|
||||
|
||||
|
@ -121,9 +121,11 @@ run_v4l2_sink(void *data) {
|
|||
break;
|
||||
}
|
||||
|
||||
video_buffer_consume(&vs->vb, vs->frame);
|
||||
vs->has_frame = false;
|
||||
|
||||
sc_mutex_unlock(&vs->mutex);
|
||||
|
||||
video_buffer_consume(&vs->vb, vs->frame);
|
||||
bool ok = encode_and_write_frame(vs, vs->frame);
|
||||
av_frame_unref(vs->frame);
|
||||
if (!ok) {
|
||||
|
@ -241,6 +243,7 @@ sc_v4l2_sink_open(struct sc_v4l2_sink *vs) {
|
|||
goto error_av_frame_free;
|
||||
}
|
||||
|
||||
vs->has_frame = false;
|
||||
vs->header_written = false;
|
||||
vs->stopped = false;
|
||||
|
||||
|
@ -299,14 +302,18 @@ sc_v4l2_sink_close(struct sc_v4l2_sink *vs) {
|
|||
|
||||
static bool
|
||||
sc_v4l2_sink_push(struct sc_v4l2_sink *vs, const AVFrame *frame) {
|
||||
sc_mutex_lock(&vs->mutex);
|
||||
|
||||
bool ok = video_buffer_push(&vs->vb, frame, NULL);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// signal possible change of vs->vb.pending_frame_consumed
|
||||
vs->has_frame = true;
|
||||
sc_cond_signal(&vs->cond);
|
||||
|
||||
sc_mutex_unlock(&vs->mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ struct sc_v4l2_sink {
|
|||
sc_thread thread;
|
||||
sc_mutex mutex;
|
||||
sc_cond cond;
|
||||
bool has_frame;
|
||||
bool stopped;
|
||||
bool header_written;
|
||||
|
||||
|
|
Loading…
Reference in a new issue