[FFmpeg-devel] [PATCH] frame_thread_encoder: make task indexing deterministic.
Ronald S. Bultje
rsbultje at gmail.com
Fri Mar 31 17:20:43 EEST 2017
Fixes tsan warnings in fate-utvideoenc. Example warning from
utvideoenc_rgb_left:
WARNING: ThreadSanitizer: data race (pid=19929)
Read of size 8 at 0x7d840001cf18 by main thread:
#0 ff_thread_video_encode_frame src/libavcodec/frame_thread_encoder.c:276 (ffmpeg+0x00000136a39d)
#1 avcodec_encode_video2 src/libavcodec/utils.c:1986 (ffmpeg+0x000000f34a18)
[..]
Previous write of size 8 at 0x7d840001cf18 by thread T14 (mutexes: write M1348):
#0 worker src/libavcodec/frame_thread_encoder.c:100 (ffmpeg+0x000001369964)
We prevent that by using the same mechanism as frame-mt decoding, and
assuming that we're encoding N packets in parallel (where N=n_threads),
and thus the first N calls to encode_video() won't produce a packet.
---
libavcodec/frame_thread_encoder.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c
index 27ae356..8db9290 100644
--- a/libavcodec/frame_thread_encoder.c
+++ b/libavcodec/frame_thread_encoder.c
@@ -251,6 +251,7 @@ int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVF
ThreadContext *c = avctx->internal->frame_thread_encoder;
Task task;
int ret;
+ unsigned idx;
av_assert1(!*got_packet_ptr);
@@ -264,32 +265,33 @@ int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVF
return ret;
}
- task.index = c->task_index;
+ task.index = c->task_index % BUFFER_SIZE;
task.indata = (void*)new;
pthread_mutex_lock(&c->task_fifo_mutex);
av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL);
pthread_cond_signal(&c->task_fifo_cond);
pthread_mutex_unlock(&c->task_fifo_mutex);
- c->task_index = (c->task_index+1) % BUFFER_SIZE;
+ c->task_index++;
- if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count)
+ if (c->task_index - c->finished_task_index < avctx->thread_count)
return 0;
}
if(c->task_index == c->finished_task_index)
return 0;
+ idx = c->finished_task_index % BUFFER_SIZE;
pthread_mutex_lock(&c->finished_task_mutex);
- while (!c->finished_tasks[c->finished_task_index].outdata) {
+ while (!c->finished_tasks[idx].outdata) {
pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
}
- task = c->finished_tasks[c->finished_task_index];
+ task = c->finished_tasks[idx];
*pkt = *(AVPacket*)(task.outdata);
if(pkt->data)
*got_packet_ptr = 1;
- av_freep(&c->finished_tasks[c->finished_task_index].outdata);
- c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE;
+ av_freep(&c->finished_tasks[idx].outdata);
+ c->finished_task_index++;
pthread_mutex_unlock(&c->finished_task_mutex);
return task.return_code;
--
2.8.1
More information about the ffmpeg-devel
mailing list