From 478898b2bce89fca8370c51a567eb32e5e634513 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michael at niedermayer.cc>
Date: Fri, 4 Jul 2025 14:57:21 +0800
Subject: [PATCH] avfilter/vf_yadif: Fix handing of tiny images
libavcodec/v4l2_m2m.c | 18 +++++++++++-------
libavcodec/v4l2_m2m_dec.c | 2 --
libavfilter/af_tremolo.c | 8 +++++---
libavfilter/vf_vmafmotion.c | 4 ++++
libavfilter/vf_yadif.c | 35 +++++++++++++++++++++--------------
libavformat/avienc.c | 22 +++++++++++++++++-----
libavformat/mpegenc.c | 31 +++++++++++++++++++------------
libavformat/nutenc.c | 2 +-
8 files changed, 78 insertions(+), 44 deletions(-)
@@ -312,7 +312,7 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context)
sem_destroy(&s->refsync);
close(s->fd);
-
+ ;
av_free(s);
}
@@ -322,14 +322,18 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx)
V4L2m2mContext* s = priv->context;
int ret;
- ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
- if (ret)
- av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
+ if (!s)
+ return 0;
- ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
- if (ret)
- av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
+ if (s->fd >= 0) {
+ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF);
+ if (ret)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name);
+ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF);
+ if (ret)
+ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name);
+ }
ff_v4l2_context_release(&s->output);
s->self_ref = NULL;
@@ -190,8 +190,6 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx)
if (ret) {
V4L2m2mPriv *priv = avctx->priv_data;
av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n");
- s->self_ref = NULL;
- av_buffer_unref(&priv->context_ref);
return ret;
}
@@ -28,6 +28,7 @@ typedef struct TremoloContext {
double freq;
double depth;
double *table;
+ int table_size;
int index;
} TremoloContext;
@@ -72,7 +73,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
dst += channels;
src += channels;
s->index++;
- if (s->index >= inlink->sample_rate / s->freq)
+ if (s->index >= s->table_size)
s->index = 0;
}
@@ -125,11 +126,12 @@ static int config_input(AVFilterLink *inlink)
const double offset = 1. - s->depth / 2.;
int i;
- s->table = av_malloc_array(inlink->sample_rate / s->freq, sizeof(*s->table));
+ s->table_size = inlink->sample_rate / s->freq;
+ s->table = av_malloc_array(s->table_size, sizeof(*s->table));
if (!s->table)
return AVERROR(ENOMEM);
- for (i = 0; i < inlink->sample_rate / s->freq; i++) {
+ for (i = 0; i < s->table_size; i++) {
double env = s->freq * i / inlink->sample_rate;
env = sin(2 * M_PI * fmod(env + 0.25, 1.0));
s->table[i] = env * (1 - fabs(offset)) + offset;
@@ -238,6 +238,10 @@ int ff_vmafmotion_init(VMAFMotionData *s,
int i;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+ if (w < 3 || h < 3)
+ return AVERROR(EINVAL);
+
+
s->width = w;
s->height = h;
s->stride = FFALIGN(w * sizeof(uint16_t), 32);
@@ -123,20 +123,23 @@ static void filter_edges(void *dst1, void *prev1, void *cur1, void *next1,
uint8_t *next2 = parity ? cur : next;
const int edge = MAX_ALIGN - 1;
+ int offset = FFMAX(w - edge, 3);
/* Only edge pixels need to be processed here. A constant value of false
* for is_not_edge should let the compiler ignore the whole branch. */
- FILTER(0, 3, 0)
+ FILTER(0, FFMIN(3, w), 0)
+
+ dst = (uint8_t*)dst1 + offset;
+ prev = (uint8_t*)prev1 + offset;
+ cur = (uint8_t*)cur1 + offset;
+ next = (uint8_t*)next1 + offset;
- dst = (uint8_t*)dst1 + w - edge;
- prev = (uint8_t*)prev1 + w - edge;
- cur = (uint8_t*)cur1 + w - edge;
- next = (uint8_t*)next1 + w - edge;
prev2 = (uint8_t*)(parity ? prev : cur);
next2 = (uint8_t*)(parity ? cur : next);
- FILTER(w - edge, w - 3, 1)
- FILTER(w - 3, w, 0)
+ FILTER(offset, w - 3, 1)
+ offset = FFMAX(offset, w - 3);
+ FILTER(offset, w, 0)
}
@@ -170,21 +173,25 @@ static void filter_edges_16bit(void *dst1, void *prev1, void *cur1, void *next1,
uint16_t *next2 = parity ? cur : next;
const int edge = MAX_ALIGN / 2 - 1;
+ int offset = FFMAX(w - edge, 3);
mrefs /= 2;
prefs /= 2;
- FILTER(0, 3, 0)
+ FILTER(0, FFMIN(3, w), 0)
+
+ dst = (uint16_t*)dst1 + offset;
+ prev = (uint16_t*)prev1 + offset;
+ cur = (uint16_t*)cur1 + offset;
+ next = (uint16_t*)next1 + offset;
- dst = (uint16_t*)dst1 + w - edge;
- prev = (uint16_t*)prev1 + w - edge;
- cur = (uint16_t*)cur1 + w - edge;
- next = (uint16_t*)next1 + w - edge;
prev2 = (uint16_t*)(parity ? prev : cur);
next2 = (uint16_t*)(parity ? cur : next);
- FILTER(w - edge, w - 3, 1)
- FILTER(w - 3, w, 0)
+ FILTER(offset, w - 3, 1)
+ offset = FFMAX(offset, w - 3);
+ FILTER(offset, w, 0)
+
}
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
@@ -917,7 +917,7 @@ static int avi_write_trailer(AVFormatContext *s)
AVIContext *avi = s->priv_data;
AVIOContext *pb = s->pb;
int res = 0;
- int i, j, n, nb_frames;
+ int i, n, nb_frames;
int64_t file_size;
for (i = 0; i < s->nb_streams; i++) {
@@ -970,10 +970,6 @@ static int avi_write_trailer(AVFormatContext *s)
for (i = 0; i < s->nb_streams; i++) {
AVIStream *avist = s->streams[i]->priv_data;
- for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++)
- av_freep(&avist->indexes.cluster[j]);
- av_freep(&avist->indexes.cluster);
- avist->indexes.ents_allocated = avist->indexes.entry = 0;
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET);
avio_wl32(pb, avist->max_size);
@@ -983,6 +979,21 @@ static int avi_write_trailer(AVFormatContext *s)
return res;
}
+static void avi_deinit(AVFormatContext *s)
+{
+ for (int i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
+ if (!avist)
+ continue;
+ for (int j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++)
+ av_freep(&avist->indexes.cluster[j]);
+ av_freep(&avist->indexes.cluster);
+ avist->indexes.ents_allocated = avist->indexes.entry = 0;
+ }
+}
+
+
+
#define OFFSET(x) offsetof(AVIContext, x)
#define ENC AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
@@ -1007,6 +1018,7 @@ AVOutputFormat ff_avi_muxer = {
.audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3,
.video_codec = AV_CODEC_ID_MPEG4,
.init = avi_init,
+ .deinit = avi_deinit,
.write_header = avi_write_header,
.write_packet = avi_write_packet,
.write_trailer = avi_write_trailer,
@@ -315,7 +315,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
if (ctx->packet_size < 20 || ctx->packet_size > (1 << 23) + 10) {
av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n",
ctx->packet_size);
- goto fail;
+ return AVERROR(EINVAL);
}
s->packet_size = ctx->packet_size;
} else
@@ -343,7 +343,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
st = ctx->streams[i];
stream = av_mallocz(sizeof(StreamInfo));
if (!stream)
- goto fail;
+ return AVERROR(EINVAL);
st->priv_data = stream;
avpriv_set_pts_info(st, 64, 1, 90000);
@@ -377,11 +377,11 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
for (sr = 0; sr < 4; sr++)
av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]);
av_log(ctx, AV_LOG_INFO, "\n");
- goto fail;
+ return AVERROR(EINVAL);
}
if (st->codecpar->channels > 8) {
av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n");
- goto fail;
+ return AVERROR(EINVAL);
}
stream->lpcm_header[0] = 0x0c;
stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4);
@@ -416,7 +416,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
st->codecpar->codec_id != AV_CODEC_ID_MP2 &&
st->codecpar->codec_id != AV_CODEC_ID_MP3) {
av_log(ctx, AV_LOG_ERROR, "Unsupported audio codec. Must be one of mp1, mp2, mp3, 16-bit pcm_dvd, pcm_s16be, ac3 or dts.\n");
- goto fail;
+ return AVERROR(EINVAL);
} else {
stream->id = mpa_id++;
}
@@ -460,7 +460,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
}
stream->fifo = av_fifo_alloc(16);
if (!stream->fifo)
- goto fail;
+ return AVERROR(EINVAL);
}
bitrate = 0;
audio_bitrate = 0;
@@ -560,11 +560,6 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
s->system_header_size = get_system_header_size(ctx);
s->last_scr = AV_NOPTS_VALUE;
return 0;
-
-fail:
- for (i = 0; i < ctx->nb_streams; i++)
- av_freep(&ctx->streams[i]->priv_data);
- return AVERROR(ENOMEM);
}
static inline void put_timestamp(AVIOContext *pb, int id, int64_t timestamp)
@@ -1255,11 +1250,19 @@ static int mpeg_mux_end(AVFormatContext *ctx)
stream = ctx->streams[i]->priv_data;
av_assert0(av_fifo_size(stream->fifo) == 0);
- av_fifo_freep(&stream->fifo);
}
return 0;
}
+static void mpeg_mux_deinit(AVFormatContext *ctx)
+{
+ for (int i = 0; i < ctx->nb_streams; i++) {
+ StreamInfo *stream = ctx->streams[i]->priv_data;
+ av_fifo_freep(&stream->fifo);
+ }
+}
+
+
#define OFFSET(x) offsetof(MpegMuxContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
@@ -1289,6 +1292,7 @@ AVOutputFormat ff_mpeg1system_muxer = {
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &mpeg_class,
};
#endif
@@ -1305,6 +1309,7 @@ AVOutputFormat ff_mpeg1vcd_muxer = {
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &vcd_class,
};
#endif
@@ -1322,6 +1327,7 @@ AVOutputFormat ff_mpeg2vob_muxer = {
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &vob_class,
};
#endif
@@ -1340,6 +1346,7 @@ AVOutputFormat ff_mpeg2svcd_muxer = {
.write_header = mpeg_mux_init,
.write_packet = mpeg_mux_write_packet,
.write_trailer = mpeg_mux_end,
+ .deinit = mpeg_mux_deinit,
.priv_class = &svcd_class,
};
#endif
@@ -1172,7 +1172,7 @@ static int nut_write_trailer(AVFormatContext *s)
write_headers(s, bc);
ret = avio_open_dyn_buf(&dyn_bc);
- if (ret >= 0 && nut->sp_count) {
+ if (ret >= 0) {
av_assert1(nut->write_index); // sp_count should be 0 if no index is going to be written
write_index(nut, dyn_bc);
put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE);
--
2.43.0