avcodec/mpeg12dec: Remove disabled frame-threading code

The MPEG-1 decoder has an update_thread_context function set,
yet it was never enabled (missing AV_CODEC_CAP_FRAME_THREADS
flag). So remove it and also the ff_thread_finish_setup() call
as well as the progress reporting.

(Simply setting the flag would not be enough. The main problems
are:
a) The update_thread_context function relies on memcpy'ing
the whole context instead of only copying the necessary fields.
This leads to data races which is undefined behaviour.
(Btw: The check for whether the non-MpegEncContext fields
of Mpeg1Context should be copied has been broken in
7f0efe232475d7a704924a3cb308281973e8add3.)
b) Even an AVBufferRef* is simply copied, without creating a new
reference.
c) Copying the whole context happens only during init; when parameters
change lateron, the change is not propagated to the next thread.
This affects at least the quant matrix (for MPEG-1).
d) The MPEG-1/2 decoders are made to decode both MPEG-1 and MPEG-2.
When MPEG-2 is decoded, another complication arises: In case of
coded fields, both fields can be in one AVPacket or they can be
in separate AVPackets. One would need to parse enough of the data
to be able to determine whether the next thread needs to start
a new frame or decode the second field of the current frame;
for this one would need to either postpone calling
ff_thread_finish_setup() for coded slices altogether or implement
some form of ff_h2645_packet_split().
One would also need a second ThreadProgress to signal progress
of each field.
e) One would need to reenable waiting in ff_mpv_reconstruct_mb()
for MPEG-1/2 (and H.261).
f) Probably lots of other stuff for invalid input that I am currently
not thinking about.
If this were done, nothing from the current update_thread_context
would remain, so one can just nuke it altogether.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-04-29 19:09:16 +02:00
parent 763b7ceb31
commit 554b52b1b3

View File

@ -58,7 +58,6 @@
#include "mpegvideodec.h" #include "mpegvideodec.h"
#include "profiles.h" #include "profiles.h"
#include "startcode.h" #include "startcode.h"
#include "thread.h"
#define A53_MAX_CC_COUNT 2000 #define A53_MAX_CC_COUNT 2000
@ -786,28 +785,6 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx)
return 0; return 0;
} }
#if HAVE_THREADS
static int mpeg_decode_update_thread_context(AVCodecContext *avctx,
const AVCodecContext *avctx_from)
{
Mpeg1Context *ctx = avctx->priv_data, *ctx_from = avctx_from->priv_data;
MpegEncContext *s = &ctx->mpeg_enc_ctx, *s1 = &ctx_from->mpeg_enc_ctx;
int err;
if (avctx == avctx_from || !s1->context_initialized)
return 0;
err = ff_mpeg_update_thread_context(avctx, avctx_from);
if (err)
return err;
if (!s->context_initialized)
memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext));
return 0;
}
#endif
static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = {
#if CONFIG_MPEG1_NVDEC_HWACCEL #if CONFIG_MPEG1_NVDEC_HWACCEL
AV_PIX_FMT_CUDA, AV_PIX_FMT_CUDA,
@ -1321,9 +1298,6 @@ static int mpeg_field_start(Mpeg1Context *s1, const uint8_t *buf, int buf_size)
*sd->data = s1->afd; *sd->data = s1->afd;
s1->has_afd = 0; s1->has_afd = 0;
} }
if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME))
ff_thread_finish_setup(avctx);
} else { // second field } else { // second field
second_field = 1; second_field = 1;
if (!s->cur_pic.ptr) { if (!s->cur_pic.ptr) {
@ -1528,7 +1502,6 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
int left; int left;
ff_mpeg_draw_horiz_band(s, mb_size * (s->mb_y >> field_pic), mb_size); ff_mpeg_draw_horiz_band(s, mb_size * (s->mb_y >> field_pic), mb_size);
ff_mpv_report_decode_progress(s);
s->mb_x = 0; s->mb_x = 0;
s->mb_y += 1 << field_pic; s->mb_y += 1 << field_pic;
@ -2667,7 +2640,6 @@ const FFCodec ff_mpeg1video_decoder = {
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
.flush = flush, .flush = flush,
.p.max_lowres = 3, .p.max_lowres = 3,
UPDATE_THREAD_CONTEXT(mpeg_decode_update_thread_context),
.hw_configs = (const AVCodecHWConfigInternal *const []) { .hw_configs = (const AVCodecHWConfigInternal *const []) {
#if CONFIG_MPEG1_NVDEC_HWACCEL #if CONFIG_MPEG1_NVDEC_HWACCEL
HWACCEL_NVDEC(mpeg1), HWACCEL_NVDEC(mpeg1),