[FFmpeg-devel] [PATCH] submit_thread should also lock the mutex that guards the source avctx (prev_thread->avctx) when calling update_context_from_thread.
Wan-Teh Chang
wtc at google.com
Fri Feb 26 23:35:09 CET 2016
On Fri, Feb 26, 2016 at 1:17 PM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
>
> I'm happy to help out if you tell me which field/member tsan is complaining
> about.
Hi Ronald,
I am using an old version of ffmpeg. Here is the ThreadSanitizer
warning on the data race and the relevant source code from that ffmpeg
source tree.
The data race is reported on the |qscale| member of MpegEncContext.
(In the current version, the corresponding thing seems to be the
|qscale| member in H264SliceContext.)
I will also try to reproduce the data race with the current version of
ffmpeg. The relevant code in the current version looks similar, but it
is certainly possible that the data race is gone.
Thanks a lot for your help!
Wan-Teh Chang
==============================
WARNING: ThreadSanitizer: data race (pid=161600)
Write of size 4 at 0x7f53af71a830 by thread T8 (mutexes: write M16537):
#0 ff_h264_decode_mb_cabac ffmpeg/libavcodec/h264_cabac.c:2336:23
(754b7d528ac43192f37741068b3495f5+0x000000673706)
#1 decode_slice ffmpeg/libavcodec/h264.c:3553:23
(754b7d528ac43192f37741068b3495f5+0x000000667e37)
#2 execute_decode_slices ffmpeg/libavcodec/h264.c:3709:16
(754b7d528ac43192f37741068b3495f5+0x00000066691d)
#3 decode_nal_units ffmpeg/libavcodec/h264.c:4010:17
(754b7d528ac43192f37741068b3495f5+0x000000633530)
#4 decode_frame ffmpeg/libavcodec/h264.c:4132:17
(754b7d528ac43192f37741068b3495f5+0x00000064a6eb)
#5 frame_worker_thread ffmpeg/libavcodec/pthread.c:389:21
(754b7d528ac43192f37741068b3495f5+0x00000098669f)
Previous read of size 8 at 0x7f53af71a830 by main thread (mutexes:
write M16539):
#0 memcpy llvm/llvm/projects/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:685:5
(754b7d528ac43192f37741068b3495f5+0x0000000d6600)
#1 ff_mpeg_update_thread_context
ffmpeg/libavcodec/mpegvideo.c:542:9
(754b7d528ac43192f37741068b3495f5+0x0000008e08e7)
#2 decode_update_thread_context ffmpeg/libavcodec/h264.c:1178:11
(754b7d528ac43192f37741068b3495f5+0x00000064965a)
#3 update_context_from_thread ffmpeg/libavcodec/pthread.c:462:19
(754b7d528ac43192f37741068b3495f5+0x000000983a5e)
#4 submit_packet ffmpeg/libavcodec/pthread.c:563:15
(754b7d528ac43192f37741068b3495f5+0x000000982e0c)
#5 ff_thread_decode_frame ffmpeg/libavcodec/pthread.c:624
(754b7d528ac43192f37741068b3495f5+0x000000982e0c)
#6 avcodec_decode_video2 ffmpeg/libavcodec/utils.c:1565:19
(754b7d528ac43192f37741068b3495f5+0x000000a8e401)
Code snippets for the stack trace of the first thread (thread T8):
libavcodec/h264_cabac.c
2316 // decode_cabac_mb_dqp
2317 if(get_cabac_noinline( &h->cabac, &h->cabac_state[60 +
(h->last_qscale_diff != 0)])){
2318 int val = 1;
2319 int ctx= 2;
2320 const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8);
2321
2322 while( get_cabac_noinline( &h->cabac,
&h->cabac_state[60 + ctx] ) ) {
2323 ctx= 3;
2324 val++;
2325 if(val > 2*max_qp){ //prevent infinite loop
2326 av_log(h->s.avctx, AV_LOG_ERROR, "cabac
decode of qscale diff failed at %d %d\n", s->mb_x, s->mb_y);
2327 return -1;
2328 }
2329 }
2330
2331 if( val&0x01 )
2332 val= (val + 1)>>1 ;
2333 else
2334 val= -((val + 1)>>1);
2335 h->last_qscale_diff = val;
2336 s->qscale += val;
2337 if(((unsigned)s->qscale) > max_qp){
2338 if(s->qscale<0) s->qscale+= max_qp+1;
2339 else s->qscale-= max_qp+1;
2340 }
2341 h->chroma_qp[0] = get_chroma_qp(h, 0, s->qscale);
2342 h->chroma_qp[1] = get_chroma_qp(h, 1, s->qscale);
2343 }else
libavcodec/h264.c (the first two code snippets are in
libavcodec/h264_slice.c in the current version):
3525 static int decode_slice(struct AVCodecContext *avctx, void *arg)
3526 {
3527 H264Context *h = *(void **)arg;
3528 MpegEncContext *const s = &h->s;
3529 const int part_mask = s->partitioned_frame ? (ER_AC_END |
ER_AC_ERROR)
3530 : 0x7F;
3531 int lf_x_start = s->mb_x;
3532
3533 s->mb_skip_run = -1;
3534
3535 h->is_complex = FRAME_MBAFF || s->picture_structure != PICT_FRAME ||
3536 s->codec_id != AV_CODEC_ID_H264 ||
3537 (CONFIG_GRAY && (s->flags & CODEC_FLAG_GRAY));
3538
3539 if (h->pps.cabac) {
3540 /* realign */
3541 align_get_bits(&s->gb);
3542
3543 /* init cabac */
3544 ff_init_cabac_states();
3545 ff_init_cabac_decoder(&h->cabac,
3546 s->gb.buffer + get_bits_count(&s->gb) / 8,
3547 (get_bits_left(&s->gb) + 7) / 8);
3548
3549 ff_h264_init_cabac_states(h);
3550
3551 for (;;) {
3552 // START_TIMER
3553 int ret = ff_h264_decode_mb_cabac(h);
3554 int eos;
3555 // STOP_TIMER("decode_mb_cabac")
3556
3557 if (ret >= 0)
3558 ff_h264_hl_decode_mb(h);
...
3698 static int execute_decode_slices(H264Context *h, int context_count)
3699 {
3700 MpegEncContext *const s = &h->s;
3701 AVCodecContext *const avctx = s->avctx;
3702 H264Context *hx;
3703 int i;
3704
3705 if (s->avctx->hwaccel ||
3706 s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
3707 return 0;
3708 if (context_count == 1) {
3709 return decode_slice(avctx, &h);
3710 } else {
...
3997 case NAL_AUD:
3998 case NAL_END_SEQUENCE:
3999 case NAL_END_STREAM:
4000 case NAL_FILLER_DATA:
4001 case NAL_SPS_EXT:
4002 case NAL_AUXILIARY_SLICE:
4003 break;
4004 default:
4005 av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d
(%d bits)\n",
4006 hx->nal_unit_type, bit_length);
4007 }
4008
4009 if (context_count == h->max_contexts) {
4010 execute_decode_slices(h, context_count);
4011 context_count = 0;
4012 }
...
4121 if (h->is_avc && av_packet_get_side_data(avpkt,
AV_PKT_DATA_NEW_EXTRADATA, NULL)) {
4122 int side_size;
4123 uint8_t *side = av_packet_get_side_data(avpkt,
AV_PKT_DATA_NEW_EXTRADATA, &side_size);
4124 if (is_extra(side, side_size))
4125 ff_h264_decode_extradata(h, side, side_size);
4126 }
4127 if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 &&
(buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){
4128 if(is_extra(buf, buf_size))
4129 return ff_h264_decode_extradata(h, buf, buf_size);
4130 }
4131
4132 buf_index = decode_nal_units(h, buf, buf_size);
4133 if (buf_index < 0)
4134 return -1;
libavcodec/pthread.c (this is in libavcodec/pthread_frame.c in the
current version of ffmpeg)
368 static attribute_align_arg void *frame_worker_thread(void *arg)
369 {
370 PerThreadContext *p = arg;
371 FrameThreadContext *fctx = p->parent;
372 AVCodecContext *avctx = p->avctx;
373 const AVCodec *codec = avctx->codec;
374
375 pthread_mutex_lock(&p->mutex);
376 while (1) {
377 int i;
378 while (p->state == STATE_INPUT_READY && !fctx->die)
379 pthread_cond_wait(&p->input_cond, &p->mutex);
380
381 if (fctx->die) break;
382
383 if (!codec->update_thread_context &&
(avctx->thread_safe_callbacks || avctx->get_buffer ==
avcodec_default_get_buffer))
384 ff_thread_finish_setup(avctx);
385
386 avcodec_get_frame_defaults(&p->frame);
387 p->got_frame = 0;
388 int did_split = av_packet_split_side_data(&p->avpkt);
389 p->result = codec->decode(avctx, &p->frame,
&p->got_frame, &p->avpkt);
390 if (did_split) {
391 av_packet_free_side_data(&p->avpkt);
392 }
Code snippets for the stack trace of the first thread (main thread):
libavcodec/mpegvideo.c
531 int ff_mpeg_update_thread_context(AVCodecContext *dst,
532 const AVCodecContext *src)
533 {
534 MpegEncContext *s = dst->priv_data, *s1 = src->priv_data;
535
536 if (dst == src)
537 return 0;
538
539 // FIXME can parameters change on I-frames?
540 // in that case dst may need a reinit
541 if (!s->context_initialized) {
542 memcpy(s, s1, sizeof(MpegEncContext));
543
544 s->avctx = dst;
545 s->bitstream_buffer = NULL;
546 s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0;
547
548 if (s1->context_initialized){
549 s->picture_range_start += MAX_PICTURE_COUNT;
550 s->picture_range_end += MAX_PICTURE_COUNT;
551 ff_MPV_common_init(s);
552 }
553 }
libavcodec/h264.c (I can't quite figure out where this code is now. It
seems to be the ff_h264_update_thread_context function in
libavcodec/h264_slice.c)
1167 static int decode_update_thread_context(AVCodecContext *dst,
1168 const AVCodecContext *src)
1169 {
1170 H264Context *h = dst->priv_data, *h1 = src->priv_data;
1171 MpegEncContext *const s = &h->s, *const s1 = &h1->s;
1172 int inited = s->context_initialized, err;
1173 int i;
1174
1175 if (dst == src)
1176 return 0;
1177
1178 err = ff_mpeg_update_thread_context(dst, src);
1179 if (err)
1180 return err;
1181
1182 // FIXME handle width/height changing
1183 if (!inited) {
1184 for (i = 0; i < MAX_SPS_COUNT; i++)
1185 av_freep(h->sps_buffers + i);
1186
1187 for (i = 0; i < MAX_PPS_COUNT; i++)
1188 av_freep(h->pps_buffers + i);
libavcodec/pthread.c (this is in libavcodec/pthread_frame.c in the
current version of ffmpeg)
424 static int update_context_from_thread(AVCodecContext *dst,
AVCodecContext *src, int for_user)
425 {
426 int err = 0;
427
428 if (dst != src) {
429 dst->time_base = src->time_base;
430 dst->width = src->width;
431 dst->height = src->height;
432 dst->pix_fmt = src->pix_fmt;
...
451 dst->color_trc = src->color_trc;
452 dst->colorspace = src->colorspace;
453 dst->color_range = src->color_range;
454 dst->chroma_sample_location = src->chroma_sample_location;
455 }
456
457 if (for_user) {
458 dst->delay = src->thread_count - 1;
459 dst->coded_frame = src->coded_frame;
460 } else {
461 if (dst->codec->update_thread_context)
462 err = dst->codec->update_thread_context(dst, src);
463 }
464
465 return err;
466 }
...
541 static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
542 {
543 FrameThreadContext *fctx = p->parent;
544 PerThreadContext *prev_thread = fctx->prev_thread;
545 const AVCodec *codec = p->avctx->codec;
546 uint8_t *buf = p->avpkt.data;
547
548 if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0;
549
550 pthread_mutex_lock(&p->mutex);
551
552 release_delayed_buffers(p);
553
554 if (prev_thread) {
555 int err;
556 if (prev_thread->state == STATE_SETTING_UP) {
557 pthread_mutex_lock(&prev_thread->progress_mutex);
558 while (prev_thread->state == STATE_SETTING_UP)
559 pthread_cond_wait(&prev_thread->progress_cond,
&prev_thread->progress_mutex);
560 pthread_mutex_unlock(&prev_thread->progress_mutex);
561 }
562
563 err = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
564 if (err) {
565 pthread_mutex_unlock(&p->mutex);
566 return err;
567 }
568 }
569
570 av_fast_malloc(&buf, &p->allocated_buf_size, avpkt->size +
FF_INPUT_BUFFER_PADDING_SIZE);
571 p->avpkt = *avpkt;
572 p->avpkt.data = buf;
573 memcpy(buf, avpkt->data, avpkt->size);
574 memset(buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
575
576 p->state = STATE_SETTING_UP;
577 pthread_cond_signal(&p->input_cond);
578 pthread_mutex_unlock(&p->mutex);
...
608 int ff_thread_decode_frame(AVCodecContext *avctx,
609 AVFrame *picture, int *got_picture_ptr,
610 AVPacket *avpkt)
611 {
612 FrameThreadContext *fctx = avctx->thread_opaque;
613 int finished = fctx->next_finished;
614 PerThreadContext *p;
615 int err;
616
617 /*
618 * Submit a packet to the next decoding thread.
619 */
620
621 p = &fctx->threads[fctx->next_decoding];
622 err = update_context_from_user(p->avctx, avctx);
623 if (err) return err;
624 err = submit_packet(p, avpkt);
625 if (err) return err;
libavcodec/utils.c
1543 int attribute_align_arg avcodec_decode_video2(AVCodecContext
*avctx, AVFrame *picture,
1544 int *got_picture_ptr,
1545 const AVPacket *avpkt)
1546 {
1547 int ret;
1548 // copy to ensure we do not change avpkt
1549 AVPacket tmp = *avpkt;
1550
1551 if (avctx->codec->type != AVMEDIA_TYPE_VIDEO) {
1552 av_log(avctx, AV_LOG_ERROR, "Invalid media type for video\n");
1553 return AVERROR(EINVAL);
1554 }
1555
1556 *got_picture_ptr = 0;
1557 if ((avctx->coded_width || avctx->coded_height) &&
av_image_check_size(avctx->coded_width, avctx->coded_height, 0,
avctx))
1558 return AVERROR(EINVAL);
1559
1560 if ((avctx->codec->capabilities & CODEC_CAP_DELAY) ||
avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
1561 int did_split = 0;
1562 apply_param_change(avctx, &tmp);
1563 avctx->pkt = &tmp;
1564 if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
1565 ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
1566 &tmp);
1567 else {
1568 did_split = av_packet_split_side_data(&tmp);
1569 ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
1570 &tmp);
1571 picture->pkt_dts = avpkt->dts;
1572
1573 if(!avctx->has_b_frames){
1574 picture->pkt_pos = avpkt->pos;
1575 }
1576 //FIXME these should be under if(!avctx->has_b_frames)
1577 if (!picture->sample_aspect_ratio.num)
picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
1578 if (!picture->width) picture->width
= avctx->width;
1579 if (!picture->height)
picture->height = avctx->height;
1580 if (picture->format == PIX_FMT_NONE)
picture->format = avctx->pix_fmt;
1581 }
More information about the ffmpeg-devel
mailing list