mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-05-17 15:08:09 +08:00
avcodec/mpegvideo_dec: Move memcpy'ing ctx to mpeg4videodec.c
When the destination MpegEncContext in ff_mpeg_update_thread_context() is not initialized, the source MpegEncContext is simply copied over it before (potentially) calling ff_mpv_common_init(). This leads to data races when this code is executed which is why it should be replaced with only copying the necessary fields (this is for future commits). Given that the RV30 and RV40 decoders always call said function with an already initialized MpegEncContext (they use context_reinit in case of frame size changes), they don't need this ugly initialization (and are therefore race-free). This means that this code can be moved to the only decoder that actually needs it: MPEG-4. This commit does so. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
@ -3774,15 +3774,40 @@ int ff_mpeg4_frame_end(AVCodecContext *avctx, const AVPacket *pkt)
|
||||
|
||||
#if CONFIG_MPEG4_DECODER
|
||||
#if HAVE_THREADS
|
||||
static int update_mpvctx(MpegEncContext *s, const MpegEncContext *s1)
|
||||
{
|
||||
AVCodecContext *avctx = s->avctx;
|
||||
// FIXME the following leads to a data race; instead copy only
|
||||
// the necessary fields.
|
||||
memcpy(s, s1, sizeof(*s));
|
||||
|
||||
s->context_initialized = 0;
|
||||
s->context_reinit = 0;
|
||||
s->avctx = avctx;
|
||||
|
||||
if (s1->context_initialized) {
|
||||
int err = ff_mpv_common_init(s);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpeg4_update_thread_context(AVCodecContext *dst,
|
||||
const AVCodecContext *src)
|
||||
{
|
||||
Mpeg4DecContext *s = dst->priv_data;
|
||||
const Mpeg4DecContext *s1 = src->priv_data;
|
||||
int init = s->m.context_initialized;
|
||||
int ret;
|
||||
|
||||
int ret = ff_mpeg_update_thread_context(dst, src);
|
||||
if (!init) {
|
||||
ret = update_mpvctx(&s->m, &s1->m);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ff_mpeg_update_thread_context(dst, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -87,25 +87,6 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
|
||||
|
||||
av_assert0(s != s1);
|
||||
|
||||
// FIXME can parameters change on I-frames?
|
||||
// in that case dst may need a reinit
|
||||
if (!s->context_initialized) {
|
||||
void *private_ctx = s->private_ctx;
|
||||
int err;
|
||||
memcpy(s, s1, sizeof(*s));
|
||||
|
||||
s->context_initialized = 0;
|
||||
s->context_reinit = 0;
|
||||
s->avctx = dst;
|
||||
s->private_ctx = private_ctx;
|
||||
|
||||
if (s1->context_initialized) {
|
||||
if ((err = ff_mpv_common_init(s)) < 0)
|
||||
return err;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
|
||||
s->height = s1->height;
|
||||
s->width = s1->width;
|
||||
|
Reference in New Issue
Block a user