ffmpeg-devel
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
December 2025
- 42 participants
- 307 discussions
[PATCH] avformat/vorbiscomment: fix writing huge chapter numbers and time offets to vorbiscomment (PR #21322)
by Marton Balint 30 Dec '25
by Marton Balint 30 Dec '25
30 Dec '25
PR #21322 opened by Marton Balint (cus)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21322
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21322.patch
Previous code truncated chapter numbers more than 999 and and time offsets more
than 99 hours.
The Vorbis chapter extension only allows 1000 chapters, but there is a
trivial way to extend the syntax, so let's do that instead. Alternate would be
to reject it or only write the first 1000 chapters.
In any case, it is better than the current code which writes truncated entries.
This also fixes the GCC warnings for truncated strings.
From 27df50b1b31422191c4ae7f1d174dc3fa3d816ce Mon Sep 17 00:00:00 2001
From: Marton Balint <cus(a)passwd.hu>
Date: Thu, 25 Dec 2025 20:03:32 +0100
Subject: [PATCH 1/3] avformat/aviobuf: return error for ffio_close_null_buf()
if written bytes exceed INT_MAX
Also check return value where it is used.
Signed-off-by: Marton Balint <cus(a)passwd.hu>
---
libavformat/avio_internal.h | 2 +-
libavformat/aviobuf.c | 4 +++-
libavformat/movenc.c | 7 ++++++-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index 7d4756db0c..fadf19dae5 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -259,7 +259,7 @@ int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
* Close a null buffer.
*
* @param s an IO context opened by ffio_open_null_buf
- * @return the number of bytes written to the null buffer
+ * @return the number of bytes written to the null buffer, negative on error
*/
int ffio_close_null_buf(AVIOContext *s);
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 9beac8bcd5..373a48eea5 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -1451,6 +1451,8 @@ static int null_buf_write(void *opaque, const uint8_t *buf, int buf_size)
{
DynBuffer *d = opaque;
+ if ((unsigned)d->pos + (unsigned)buf_size > INT_MAX)
+ return AVERROR(ERANGE);
d->pos += buf_size;
if (d->pos > d->size)
d->size = d->pos;
@@ -1474,7 +1476,7 @@ int ffio_close_null_buf(AVIOContext *s)
avio_flush(s);
- size = d->size;
+ size = s->error ? s->error : d->size;
avio_context_free(&s);
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 8d8acd2aff..e844be483c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -5845,8 +5845,11 @@ static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
total_size);
}
- if (round == 0)
+ if (round == 0) {
total_size = ffio_close_null_buf(avio_buf);
+ if (total_size < 0)
+ return total_size;
+ }
}
return 0;
}
@@ -5911,6 +5914,8 @@ static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
return ret;
mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
moof_size = ffio_close_null_buf(avio_buf);
+ if (moof_size < 0)
+ return moof_size;
if (mov->flags & FF_MOV_FLAG_DASH &&
!(mov->flags & (FF_MOV_FLAG_GLOBAL_SIDX | FF_MOV_FLAG_SKIP_SIDX)))
--
2.49.1
From bc662906eda8fb7af81b9d96d2f3701ac35d5ca5 Mon Sep 17 00:00:00 2001
From: Marton Balint <cus(a)passwd.hu>
Date: Tue, 23 Dec 2025 02:52:59 +0100
Subject: [PATCH 2/3] avformat/vorbiscomment: use null buf to calculate vorbis
comment length
Also check possible failures when calculating length, and change return type to
int as bigger return values are no longer possible.
---
libavformat/flacenc.c | 4 +++-
libavformat/matroskaenc.c | 4 +++-
libavformat/oggenc.c | 5 ++++-
libavformat/vorbiscomment.c | 35 +++++++++++++++--------------------
libavformat/vorbiscomment.h | 4 ++--
5 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index a8beec7750..711119efec 100644
--- a/libavformat/flacenc.c
+++ b/libavformat/flacenc.c
@@ -64,11 +64,13 @@ static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
int last_block, int bitexact)
{
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
- int64_t len;
+ int len;
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
+ if (len < 0)
+ return len;
if (len >= ((1<<24) - 4))
return AVERROR(EINVAL);
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 18f17f4329..50188c396c 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -1061,12 +1061,14 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb,
"Lavf" : LIBAVFORMAT_IDENT;
AVDictionary *dict = NULL;
uint8_t buf[32];
- int64_t len;
+ int len;
snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask);
av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
len = ff_vorbiscomment_length(dict, vendor, NULL, 0);
+ if (len < 0)
+ return len;
av_assert1(len < (1 << 24) - 4);
avio_w8(pb, 0x84);
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index 9a548a8d29..be85386a6a 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -295,7 +295,10 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
- size = offset + ff_vorbiscomment_length(*m, vendor, chapters, nb_chapters) + framing_bit;
+ size = ff_vorbiscomment_length(*m, vendor, chapters, nb_chapters);
+ if (size < 0)
+ return NULL;
+ size += offset + framing_bit;
if (size > INT_MAX)
return NULL;
p = av_mallocz(size);
diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c
index abe12fd586..fede6b68de 100644
--- a/libavformat/vorbiscomment.c
+++ b/libavformat/vorbiscomment.c
@@ -20,6 +20,7 @@
*/
#include "avio.h"
+#include "avio_internal.h"
#include "avformat.h"
#include "metadata.h"
#include "vorbiscomment.h"
@@ -38,27 +39,21 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
{ 0 }
};
-int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
- AVChapter **chapters, unsigned int nb_chapters)
+int ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
+ AVChapter **chapters, unsigned int nb_chapters)
{
- int64_t len = 8;
- len += strlen(vendor_string);
- if (chapters && nb_chapters) {
- for (int i = 0; i < nb_chapters; i++) {
- const AVDictionaryEntry *tag = NULL;
- len += 4 + 12 + 1 + 10;
- while ((tag = av_dict_iterate(chapters[i]->metadata, tag))) {
- int64_t len1 = !strcmp(tag->key, "title") ? 4 : strlen(tag->key);
- len += 4 + 10 + len1 + 1 + strlen(tag->value);
- }
- }
- }
- if (m) {
- const AVDictionaryEntry *tag = NULL;
- while ((tag = av_dict_iterate(m, tag))) {
- len += 4 +strlen(tag->key) + 1 + strlen(tag->value);
- }
- }
+ AVIOContext *avio_buf;
+ int ret, len;
+
+ ret = ffio_open_null_buf(&avio_buf);
+ if (ret < 0)
+ return ret;
+
+ ret = ff_vorbiscomment_write(avio_buf, m, vendor_string, chapters, nb_chapters);
+ len = ffio_close_null_buf(avio_buf);
+ if (ret < 0)
+ return ret;
+
return len;
}
diff --git a/libavformat/vorbiscomment.h b/libavformat/vorbiscomment.h
index 7cacd0b2a0..cd8b325fb6 100644
--- a/libavformat/vorbiscomment.h
+++ b/libavformat/vorbiscomment.h
@@ -34,8 +34,8 @@
* For no string, set to an empty string.
* @return The length in bytes.
*/
-int64_t ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
- AVChapter **chapters, unsigned int nb_chapters);
+int ff_vorbiscomment_length(const AVDictionary *m, const char *vendor_string,
+ AVChapter **chapters, unsigned int nb_chapters);
/**
* Write a VorbisComment into an AVIOContext. The output size can be obtained
--
2.49.1
From d859b6014b5b1439e360eaa8ba0a875ceeaf33c4 Mon Sep 17 00:00:00 2001
From: Marton Balint <cus(a)passwd.hu>
Date: Thu, 25 Dec 2025 19:20:51 +0100
Subject: [PATCH 3/3] avformat/vorbiscomment: fix writing huge chapter numbers
and time offets to vorbiscomment
Previous code truncated chapter numbers more than 999 and and time offsets more
than 99 hours.
The Vorbis chapter extension only allows 1000 chapters, but there is a
trivial way to extend the syntax, so let's do that instead. Alternate would be
to reject it or only write the first 1000 chapters.
In any case, it is better than the current code which writes truncated entries.
This also fixes the GCC warnings for truncated strings.
Signed-off-by: Marton Balint <cus(a)passwd.hu>
---
libavformat/vorbiscomment.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c
index fede6b68de..8d846f5c1b 100644
--- a/libavformat/vorbiscomment.c
+++ b/libavformat/vorbiscomment.c
@@ -24,6 +24,7 @@
#include "avformat.h"
#include "metadata.h"
#include "vorbiscomment.h"
+#include "libavutil/bprint.h"
#include "libavutil/dict.h"
/**
@@ -86,8 +87,7 @@ int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
}
for (int i = 0; i < nb_chapters; i++) {
AVChapter *chp = chapters[i];
- char chapter_time[13];
- char chapter_number[4];
+ AVBPrint bp;
int h, m, s, ms;
s = av_rescale(chp->start, chp->time_base.num, chp->time_base.den);
@@ -95,23 +95,21 @@ int ff_vorbiscomment_write(AVIOContext *pb, const AVDictionary *m,
m = (s / 60) % 60;
ms = av_rescale_q(chp->start, chp->time_base, av_make_q( 1, 1000)) % 1000;
s = s % 60;
- snprintf(chapter_number, sizeof(chapter_number), "%03d", i);
- snprintf(chapter_time, sizeof(chapter_time), "%02d:%02d:%02d.%03d", h, m, s, ms);
- avio_wl32(pb, 10 + 1 + 12);
- avio_write(pb, "CHAPTER", 7);
- avio_write(pb, chapter_number, 3);
- avio_w8(pb, '=');
- avio_write(pb, chapter_time, 12);
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&bp, "CHAPTER%03d=%02d:%02d:%02d.%03d", i, h, m, s, ms);
+ avio_wl32(pb, bp.len);
+ avio_write(pb, bp.str, bp.len);
tag = NULL;
while ((tag = av_dict_iterate(chapters[i]->metadata, tag))) {
int64_t len1 = !strcmp(tag->key, "title") ? 4 : strlen(tag->key);
int64_t len2 = strlen(tag->value);
- if (len1+1+len2+10 > UINT32_MAX)
+ av_bprint_clear(&bp);
+ av_bprintf(&bp, "CHAPTER%03d", i);
+ if (len1+1+len2+bp.len > UINT32_MAX)
return AVERROR(EINVAL);
- avio_wl32(pb, 10 + len1 + 1 + len2);
- avio_write(pb, "CHAPTER", 7);
- avio_write(pb, chapter_number, 3);
+ avio_wl32(pb, bp.len + len1 + 1 + len2);
+ avio_printf(pb, bp.str, bp.len);
if (!strcmp(tag->key, "title"))
avio_write(pb, "NAME", 4);
else
--
2.49.1
1
0
[PATCH] avformat/file: respect pkt_size even in streaming mode (PR #21321)
by Marton Balint 30 Dec '25
by Marton Balint 30 Dec '25
30 Dec '25
PR #21321 opened by Marton Balint (cus)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21321
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21321.patch
Also clarify the documentation a bit.
Signed-off-by: Marton Balint <cus(a)passwd.hu>
From 3c14b23663d09be291799af0b6a62dfe553a072a Mon Sep 17 00:00:00 2001
From: Marton Balint <cus(a)passwd.hu>
Date: Tue, 30 Dec 2025 02:36:04 +0100
Subject: [PATCH] avformat/file: respect pkt_size even in streaming mode
Also clarify the documentation a bit.
Signed-off-by: Marton Balint <cus(a)passwd.hu>
---
doc/protocols.texi | 12 +++++++-----
libavformat/file.c | 18 +++++++++++-------
2 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/doc/protocols.texi b/doc/protocols.texi
index b5330a1160..350c52a465 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -354,13 +354,15 @@ overriding this might speed up opening certain files at the cost of losing some
features (e.g. accurate seeking).
@item pkt_size
-Set the maximum packet size used for file I/O.
+Set the maximum packet size used for file I/O. A smaller value may reduce
+memory usage. A higher value may increase throughput especially with networked
+filesystems.
-For writing, this sets the size of each write operation. The default is
-262144 bytes.
For reading, if explicitly set, it overrides the default internal buffer size
-(32768 bytes) and limits the maximum amount of data read per operation.
-Setting a smaller value may reduce memory usage when reading files sequentially.
+(32 KB) and limits the maximum amount of data read per operation.
+
+For writing, this sets the size of each write operation. The default is 256 KB
+for regular files, 32 KB otherwise.
@end table
@section ftp
diff --git a/libavformat/file.c b/libavformat/file.c
index 23dc7081d3..3ceddc8c25 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -312,14 +312,18 @@ static int file_open(URLContext *h, const char *filename, int flags)
h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);
- /* Buffer writes more than the default 32k to improve throughput especially
- * with networked file systems */
- if (!h->is_streamed) {
- if (flags & AVIO_FLAG_WRITE)
- h->min_packet_size = h->max_packet_size = c->pkt_size ? c->pkt_size : 262144;
- else if (flags & AVIO_FLAG_READ && c->pkt_size)
- h->max_packet_size = c->pkt_size;
+ if (c->pkt_size) {
+ h->max_packet_size = c->pkt_size;
+ } else {
+ /* Buffer writes more than the default 32k to improve throughput especially
+ * with networked file systems */
+ if (!h->is_streamed && flags & AVIO_FLAG_WRITE)
+ h->max_packet_size = 262144;
}
+ /* Disable per-packet flushing by default to improve throughput especially
+ * with networked file systems */
+ if (!h->is_streamed && flags & AVIO_FLAG_WRITE)
+ h->min_packet_size = h->max_packet_size;
if (c->seekable >= 0)
h->is_streamed = !c->seekable;
--
2.49.1
1
0
[PATCH] avcodec/mpegvideo: Move permutated_intra scans to {H263Dec,MPVEnc}Ctx (PR #21320)
by mkver 30 Dec '25
by mkver 30 Dec '25
30 Dec '25
PR #21320 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21320
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21320.patch
Also split WMV2DSP into idct and (decoder-only) motion compensation.
From f391f3f08f3ecabe23f04410a0e96b597f77f3c1 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 04:45:57 +0200
Subject: [PATCH 01/14] avcodec/wmv2: Don't initialize BlockDSPContext
redundantly
ff_mpv_common_init() already does it for us.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/wmv2.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c
index c2bcb988c4..903c1c9a44 100644
--- a/libavcodec/wmv2.c
+++ b/libavcodec/wmv2.c
@@ -29,7 +29,6 @@ av_cold void ff_wmv2_common_init(MpegEncContext *s)
{
WMV2Context *const w = s->private_ctx;
- ff_blockdsp_init(&s->bdsp);
ff_wmv2dsp_init(&w->wdsp);
s->idsp.perm_type = w->wdsp.idct_perm;
ff_init_scantable_permutation(s->idsp.idct_permutation,
--
2.49.1
From d840b947afbcaa016c06f90824e5c637eac17be7 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 05:37:05 +0200
Subject: [PATCH 02/14] avcodec/msmpeg4: Initialize WMV2 generically
WMV1 and WMV2 use other scantables and therefore
ff_msmpeg4_common_init() reinitializes them. Yet WMV2
also uses a different IDCT overwriting the ordinary one,
so that the IDCT permutation changes and therefore
ff_wmv2_common_init() (called after ff_msmpeg4_common_init())
needs to reinitialize the scantables again.
Avoid this by calling ff_wmv2_common_init() in
ff_msmpeg4_common_init().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/msmpeg4.c | 8 +++++++-
libavcodec/wmv2.c | 9 ---------
libavcodec/wmv2dec.c | 2 --
libavcodec/wmv2enc.c | 2 --
4 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index 5ceb100333..79a43602b1 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -28,6 +28,7 @@
*/
#include "config.h"
+#include "config_components.h"
#include "libavutil/thread.h"
#if ARCH_X86
@@ -42,6 +43,7 @@
#include "mpeg4videodata.h"
#include "msmpeg4data.h"
#include "msmpeg4_vc1_data.h"
+#include "wmv2.h"
/*
* You can also call this codec: MPEG-4 with a twist!
@@ -133,8 +135,12 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table;
}
break;
- case MSMP4_WMV1:
+#if CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER
case MSMP4_WMV2:
+ ff_wmv2_common_init(s);
+ // fallthrough
+#endif
+ case MSMP4_WMV1:
s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
break;
diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c
index 903c1c9a44..d36ae66581 100644
--- a/libavcodec/wmv2.c
+++ b/libavcodec/wmv2.c
@@ -21,7 +21,6 @@
#include "avcodec.h"
#include "idctdsp.h"
#include "mpegvideo.h"
-#include "msmpeg4_vc1_data.h"
#include "wmv2.h"
@@ -33,14 +32,6 @@ av_cold void ff_wmv2_common_init(MpegEncContext *s)
s->idsp.perm_type = w->wdsp.idct_perm;
ff_init_scantable_permutation(s->idsp.idct_permutation,
w->wdsp.idct_perm);
- ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,
- ff_wmv1_scantable[1]);
- ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,
- ff_wmv1_scantable[0]);
- ff_permute_scantable(s->permutated_intra_h_scantable, ff_wmv1_scantable[2],
- s->idsp.idct_permutation);
- ff_permute_scantable(s->permutated_intra_v_scantable, ff_wmv1_scantable[3],
- s->idsp.idct_permutation);
s->idsp.idct_put = w->wdsp.idct_put;
s->idsp.idct_add = w->wdsp.idct_add;
s->idsp.idct = NULL;
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 512d63b23e..5bac48385f 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -578,8 +578,6 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx)
h->decode_header = wmv2_decode_picture_header;
h->decode_mb = wmv2_decode_mb;
- ff_wmv2_common_init(s);
-
decode_ext_header(w);
return ff_intrax8_common_init(avctx, &w->x8, h->block[0],
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index b6811fde0e..5b3e2ae116 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -233,8 +233,6 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx)
if (ret < 0)
return ret;
- ff_wmv2_common_init(&s->c);
-
avctx->extradata_size = WMV2_EXTRADATA_SIZE;
avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata)
--
2.49.1
From 0e7028d99d46a96fbc266e5af27e39efc341bee7 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 07:08:41 +0200
Subject: [PATCH 03/14] avcodec/msmpeg4: Avoid branch
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/msmpeg4.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index 79a43602b1..45c56a9ad9 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -143,18 +143,14 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
case MSMP4_WMV1:
s->y_dc_scale_table= ff_wmv1_y_dc_scale_table;
s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
- break;
- }
-
- if (s->msmpeg4_version >= MSMP4_WMV1) {
ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]);
ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]);
ff_permute_scantable(s->permutated_intra_h_scantable, ff_wmv1_scantable[2],
s->idsp.idct_permutation);
ff_permute_scantable(s->permutated_intra_v_scantable, ff_wmv1_scantable[3],
s->idsp.idct_permutation);
+ break;
}
- //Note the default tables are set in common_init in mpegvideo.c
ff_thread_once(&init_static_once, msmpeg4_common_init_static);
}
--
2.49.1
From 4330861e6a6a91126e8e787228fa1a3b6a13bf2d Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 07:22:06 +0200
Subject: [PATCH 04/14] avcodec/wmv2dec: Don't put skip_type in context
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/wmv2dec.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 5bac48385f..f4b4b4ac84 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -51,7 +51,6 @@ typedef struct WMV2DecContext {
int cbp_table_index;
int top_left_mv_flag;
int per_mb_rl_bit;
- int skip_type;
DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64];
} WMV2DecContext;
@@ -106,8 +105,8 @@ static int parse_mb_skip(WMV2DecContext *w)
int coded_mb_count = 0;
uint32_t *const mb_type = h->c.cur_pic.mb_type;
- w->skip_type = get_bits(&h->gb, 2);
- switch (w->skip_type) {
+ int skip_type = get_bits(&h->gb, 2);
+ switch (skip_type) {
case SKIP_TYPE_NONE:
for (int mb_y = 0; mb_y < h->c.mb_height; mb_y++)
for (int mb_x = 0; mb_x < h->c.mb_width; mb_x++)
--
2.49.1
From 1cedc7d0d8417d8a1a5631fd5768b69e85151b6c Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 07:33:13 +0200
Subject: [PATCH 05/14] avcodec/wmv2dec: Mark unreachable code as unreachable
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/wmv2dec.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index f4b4b4ac84..2421513adf 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/avassert.h"
#include "libavutil/mem_internal.h"
#include "avcodec.h"
@@ -77,7 +78,7 @@ static void wmv2_add_block(WMV2DecContext *w, int16_t blocks1[][64],
h->c.bdsp.clear_block(w->abt_block2[n]);
break;
default:
- av_log(h->c.avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n");
+ av_unreachable("abt_type_table is read via decode012");
}
}
}
--
2.49.1
From 98ee3df4a07ce262893339284b61f3400020a53b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Tue, 30 Dec 2025 12:24:02 +0100
Subject: [PATCH 06/14] avcodec/msmpeg4: Mark unreachable code as unreachable
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/msmpeg4.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index 45c56a9ad9..bca8dbd524 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -30,6 +30,7 @@
#include "config.h"
#include "config_components.h"
+#include "libavutil/avassert.h"
#include "libavutil/thread.h"
#if ARCH_X86
#include "libavutil/x86/asm.h"
@@ -122,6 +123,8 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
static AVOnce init_static_once = AV_ONCE_INIT;
switch(s->msmpeg4_version){
+ default:
+ av_unreachable("ff_msmpeg4_common_init only called MSMP4 1-3 and WMV1/2");
case MSMP4_V1:
case MSMP4_V2:
// Correct *_dc_scale_tables (ff_mpeg1_dc_scale_table) is the default
--
2.49.1
From 0fed11931b698ce228c5de59646acb781e8cbb38 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 08:30:22 +0200
Subject: [PATCH 07/14] avcodec/wmv2: Move ff_msmpel_motion() to the decoder
mspel is not supported by the encoder.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/mpegvideo_motion.c | 8 ++--
libavcodec/wmv2.c | 90 -----------------------------------
libavcodec/wmv2.h | 7 ---
libavcodec/wmv2dec.c | 89 ++++++++++++++++++++++++++++++++++
libavcodec/wmv2dec.h | 6 +++
5 files changed, 100 insertions(+), 100 deletions(-)
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
index a48b898dac..741927d809 100644
--- a/libavcodec/mpegvideo_motion.c
+++ b/libavcodec/mpegvideo_motion.c
@@ -34,7 +34,7 @@
#include "mpegvideo.h"
#include "mpeg4videodec.h"
#include "qpeldsp.h"
-#include "wmv2.h"
+#include "wmv2dec.h"
static inline int hpel_motion(MpegEncContext *s,
uint8_t *dest, uint8_t *src,
@@ -706,11 +706,13 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
0, 0, 0,
ref_picture, pix_op, qpix_op,
s->mv[dir][0][0], s->mv[dir][0][1], 16);
- } else if (!is_mpeg12 && (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) &&
- s->mspel && s->codec_id == AV_CODEC_ID_WMV2) {
+#if CONFIG_WMV2_DECODER
+ } else if (!is_mpeg12 && s->mspel && s->codec_id == AV_CODEC_ID_WMV2) {
+ av_assert2(av_codec_is_decoder(s->avctx->codec));
ff_mspel_motion(s, dest_y, dest_cb, dest_cr,
ref_picture, pix_op,
s->mv[dir][0][0], s->mv[dir][0][1], 16);
+#endif
} else {
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
ref_picture, pix_op,
diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c
index d36ae66581..b29037cacb 100644
--- a/libavcodec/wmv2.c
+++ b/libavcodec/wmv2.c
@@ -18,7 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "avcodec.h"
#include "idctdsp.h"
#include "mpegvideo.h"
#include "wmv2.h"
@@ -36,92 +35,3 @@ av_cold void ff_wmv2_common_init(MpegEncContext *s)
s->idsp.idct_add = w->wdsp.idct_add;
s->idsp.idct = NULL;
}
-
-void ff_mspel_motion(MpegEncContext *s, uint8_t *dest_y,
- uint8_t *dest_cb, uint8_t *dest_cr,
- uint8_t *const *ref_picture,
- const op_pixels_func (*pix_op)[4],
- int motion_x, int motion_y, int h)
-{
- WMV2Context *const w = s->private_ctx;
- const uint8_t *ptr;
- int dxy, mx, my, src_x, src_y, v_edge_pos;
- ptrdiff_t offset, linesize, uvlinesize;
- int emu = 0;
-
- dxy = ((motion_y & 1) << 1) | (motion_x & 1);
- dxy = 2 * dxy + w->hshift;
- src_x = s->mb_x * 16 + (motion_x >> 1);
- src_y = s->mb_y * 16 + (motion_y >> 1);
-
- /* WARNING: do no forget half pels */
- v_edge_pos = s->v_edge_pos;
- src_x = av_clip(src_x, -16, s->width);
- src_y = av_clip(src_y, -16, s->height);
-
- if (src_x <= -16 || src_x >= s->width)
- dxy &= ~3;
- if (src_y <= -16 || src_y >= s->height)
- dxy &= ~4;
-
- linesize = s->linesize;
- uvlinesize = s->uvlinesize;
- ptr = ref_picture[0] + (src_y * linesize) + src_x;
-
- if (src_x < 1 || src_y < 1 || src_x + 17 >= s->h_edge_pos ||
- src_y + h + 1 >= v_edge_pos) {
- s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr - 1 - s->linesize,
- s->linesize, s->linesize, 19, 19,
- src_x - 1, src_y - 1,
- s->h_edge_pos, s->v_edge_pos);
- ptr = s->sc.edge_emu_buffer + 1 + s->linesize;
- emu = 1;
- }
-
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y, ptr, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8, ptr + 8, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 * linesize, ptr + 8 * linesize, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 + 8 * linesize, ptr + 8 + 8 * linesize, linesize);
-
- if (s->avctx->flags & AV_CODEC_FLAG_GRAY)
- return;
-
- dxy = 0;
- if ((motion_x & 3) != 0)
- dxy |= 1;
- if ((motion_y & 3) != 0)
- dxy |= 2;
- mx = motion_x >> 2;
- my = motion_y >> 2;
-
- src_x = s->mb_x * 8 + mx;
- src_y = s->mb_y * 8 + my;
- src_x = av_clip(src_x, -8, s->width >> 1);
- if (src_x == (s->width >> 1))
- dxy &= ~1;
- src_y = av_clip(src_y, -8, s->height >> 1);
- if (src_y == (s->height >> 1))
- dxy &= ~2;
- offset = (src_y * uvlinesize) + src_x;
- ptr = ref_picture[1] + offset;
- if (emu) {
- s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
- s->uvlinesize, s->uvlinesize,
- 9, 9,
- src_x, src_y,
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
- ptr = s->sc.edge_emu_buffer;
- }
- pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1);
-
- ptr = ref_picture[2] + offset;
- if (emu) {
- s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
- s->uvlinesize, s->uvlinesize,
- 9, 9,
- src_x, src_y,
- s->h_edge_pos >> 1, s->v_edge_pos >> 1);
- ptr = s->sc.edge_emu_buffer;
- }
- pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1);
-}
diff --git a/libavcodec/wmv2.h b/libavcodec/wmv2.h
index 409d9456ab..b2767c6ca4 100644
--- a/libavcodec/wmv2.h
+++ b/libavcodec/wmv2.h
@@ -37,13 +37,6 @@ typedef struct WMV2Context {
void ff_wmv2_common_init(MpegEncContext *s);
-void ff_mspel_motion(MpegEncContext *s,
- uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
- uint8_t *const *ref_picture,
- const op_pixels_func (*pix_op)[4],
- int motion_x, int motion_y, int h);
-
-
static av_always_inline int wmv2_get_cbp_table_index(int qscale, int cbp_index)
{
static const uint8_t map[3][3] = {
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 2421513adf..554b784a5d 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -56,6 +56,95 @@ typedef struct WMV2DecContext {
DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64];
} WMV2DecContext;
+void ff_mspel_motion(MPVContext *const s, uint8_t *dest_y,
+ uint8_t *dest_cb, uint8_t *dest_cr,
+ uint8_t *const *ref_picture,
+ const op_pixels_func (*pix_op)[4],
+ int motion_x, int motion_y, int h)
+{
+ WMV2Context *const w = s->private_ctx;
+ const uint8_t *ptr;
+ int dxy, mx, my, src_x, src_y, v_edge_pos;
+ ptrdiff_t offset, linesize, uvlinesize;
+ int emu = 0;
+
+ dxy = ((motion_y & 1) << 1) | (motion_x & 1);
+ dxy = 2 * dxy + w->hshift;
+ src_x = s->mb_x * 16 + (motion_x >> 1);
+ src_y = s->mb_y * 16 + (motion_y >> 1);
+
+ /* WARNING: do no forget half pels */
+ v_edge_pos = s->v_edge_pos;
+ src_x = av_clip(src_x, -16, s->width);
+ src_y = av_clip(src_y, -16, s->height);
+
+ if (src_x <= -16 || src_x >= s->width)
+ dxy &= ~3;
+ if (src_y <= -16 || src_y >= s->height)
+ dxy &= ~4;
+
+ linesize = s->linesize;
+ uvlinesize = s->uvlinesize;
+ ptr = ref_picture[0] + (src_y * linesize) + src_x;
+
+ if (src_x < 1 || src_y < 1 || src_x + 17 >= s->h_edge_pos ||
+ src_y + h + 1 >= v_edge_pos) {
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr - 1 - s->linesize,
+ s->linesize, s->linesize, 19, 19,
+ src_x - 1, src_y - 1,
+ s->h_edge_pos, s->v_edge_pos);
+ ptr = s->sc.edge_emu_buffer + 1 + s->linesize;
+ emu = 1;
+ }
+
+ w->wdsp.put_mspel_pixels_tab[dxy](dest_y, ptr, linesize);
+ w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8, ptr + 8, linesize);
+ w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 * linesize, ptr + 8 * linesize, linesize);
+ w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 + 8 * linesize, ptr + 8 + 8 * linesize, linesize);
+
+ if (s->avctx->flags & AV_CODEC_FLAG_GRAY)
+ return;
+
+ dxy = 0;
+ if ((motion_x & 3) != 0)
+ dxy |= 1;
+ if ((motion_y & 3) != 0)
+ dxy |= 2;
+ mx = motion_x >> 2;
+ my = motion_y >> 2;
+
+ src_x = s->mb_x * 8 + mx;
+ src_y = s->mb_y * 8 + my;
+ src_x = av_clip(src_x, -8, s->width >> 1);
+ if (src_x == (s->width >> 1))
+ dxy &= ~1;
+ src_y = av_clip(src_y, -8, s->height >> 1);
+ if (src_y == (s->height >> 1))
+ dxy &= ~2;
+ offset = (src_y * uvlinesize) + src_x;
+ ptr = ref_picture[1] + offset;
+ if (emu) {
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9,
+ src_x, src_y,
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ptr = s->sc.edge_emu_buffer;
+ }
+ pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1);
+
+ ptr = ref_picture[2] + offset;
+ if (emu) {
+ s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
+ s->uvlinesize, s->uvlinesize,
+ 9, 9,
+ src_x, src_y,
+ s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+ ptr = s->sc.edge_emu_buffer;
+ }
+ pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1);
+}
+
static void wmv2_add_block(WMV2DecContext *w, int16_t blocks1[][64],
uint8_t *dst, int stride, int n)
{
diff --git a/libavcodec/wmv2dec.h b/libavcodec/wmv2dec.h
index 1bd0d13725..d19760b6c9 100644
--- a/libavcodec/wmv2dec.h
+++ b/libavcodec/wmv2dec.h
@@ -28,4 +28,10 @@ int ff_wmv2_decode_secondary_picture_header(struct H263DecContext *const h);
void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64],
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr);
+void ff_mspel_motion(MPVContext *const s,
+ uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
+ uint8_t *const *ref_picture,
+ const op_pixels_func (*pix_op)[4],
+ int motion_x, int motion_y, int h);
+
#endif
--
2.49.1
From d8b8e8700d6de977a3b6d0a1c8cc6ebb4f82a32b Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 08:44:18 +0200
Subject: [PATCH 08/14] avcodec/wmv2dsp: Move mspel motion functions out of
WMV2DSPContext
They are only used by the decoder (which has them twice, because
the IntraX8Context contains a WMV2DSPContext whose put_mspel_pixels
functions were unused), so move them there.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
configure | 3 +-
libavcodec/wmv2dec.c | 137 +++++++++++++++++++++++++++++++++++++++++--
libavcodec/wmv2dsp.c | 119 -------------------------------------
libavcodec/wmv2dsp.h | 5 +-
4 files changed, 133 insertions(+), 131 deletions(-)
diff --git a/configure b/configure
index 301a3e5e3e..74e0345d88 100755
--- a/configure
+++ b/configure
@@ -2963,7 +2963,6 @@ msmpeg4dec_select="h263_decoder"
msmpeg4enc_select="h263_encoder"
vc1dsp_select="h264chroma startcode"
vvc_sei_select="atsc_a53 golomb"
-wmv2dsp_select="qpeldsp"
# decoders / encoders
aac_decoder_select="adts_header mpeg4audio sinewin"
@@ -3225,7 +3224,7 @@ wmav2_encoder_select="sinewin wma_freqs"
wmavoice_decoder_select="lsp sinewin"
wmv1_decoder_select="msmpeg4dec"
wmv1_encoder_select="msmpeg4enc"
-wmv2_decoder_select="blockdsp error_resilience idctdsp intrax8 msmpeg4dec videodsp wmv2dsp"
+wmv2_decoder_select="blockdsp error_resilience idctdsp intrax8 msmpeg4dec qpeldsp videodsp wmv2dsp"
wmv2_encoder_select="msmpeg4enc wmv2dsp"
wmv3_decoder_select="vc1_decoder"
wmv3image_decoder_select="wmv3_decoder"
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 554b784a5d..749a8608a2 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -32,6 +32,7 @@
#include "msmpeg4.h"
#include "msmpeg4_vc1_data.h"
#include "msmpeg4dec.h"
+#include "qpeldsp.h"
#include "simple_idct.h"
#include "wmv2.h"
#include "wmv2data.h"
@@ -41,6 +42,9 @@ typedef struct WMV2DecContext {
MSMP4DecContext ms;
WMV2Context common;
IntraX8Context x8;
+
+ qpel_mc_func put_mspel_pixels_tab[8];
+
int j_type_bit;
int j_type;
int abt_flag;
@@ -56,20 +60,139 @@ typedef struct WMV2DecContext {
DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64];
} WMV2DecContext;
+static void wmv2_mspel8_h_lowpass(uint8_t *dst, const uint8_t *src,
+ int dstStride, int srcStride, int h)
+{
+ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
+
+ for (int i = 0; i < h; i++) {
+ dst[0] = cm[(9 * (src[0] + src[1]) - (src[-1] + src[2]) + 8) >> 4];
+ dst[1] = cm[(9 * (src[1] + src[2]) - (src[0] + src[3]) + 8) >> 4];
+ dst[2] = cm[(9 * (src[2] + src[3]) - (src[1] + src[4]) + 8) >> 4];
+ dst[3] = cm[(9 * (src[3] + src[4]) - (src[2] + src[5]) + 8) >> 4];
+ dst[4] = cm[(9 * (src[4] + src[5]) - (src[3] + src[6]) + 8) >> 4];
+ dst[5] = cm[(9 * (src[5] + src[6]) - (src[4] + src[7]) + 8) >> 4];
+ dst[6] = cm[(9 * (src[6] + src[7]) - (src[5] + src[8]) + 8) >> 4];
+ dst[7] = cm[(9 * (src[7] + src[8]) - (src[6] + src[9]) + 8) >> 4];
+ dst += dstStride;
+ src += srcStride;
+ }
+}
+
+static void wmv2_mspel8_v_lowpass(uint8_t *dst, const uint8_t *src,
+ int dstStride, int srcStride, int w)
+{
+ const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
+
+ for (int i = 0; i < w; i++) {
+ const int src_1 = src[-srcStride];
+ const int src0 = src[0];
+ const int src1 = src[srcStride];
+ const int src2 = src[2 * srcStride];
+ const int src3 = src[3 * srcStride];
+ const int src4 = src[4 * srcStride];
+ const int src5 = src[5 * srcStride];
+ const int src6 = src[6 * srcStride];
+ const int src7 = src[7 * srcStride];
+ const int src8 = src[8 * srcStride];
+ const int src9 = src[9 * srcStride];
+ dst[0 * dstStride] = cm[(9 * (src0 + src1) - (src_1 + src2) + 8) >> 4];
+ dst[1 * dstStride] = cm[(9 * (src1 + src2) - (src0 + src3) + 8) >> 4];
+ dst[2 * dstStride] = cm[(9 * (src2 + src3) - (src1 + src4) + 8) >> 4];
+ dst[3 * dstStride] = cm[(9 * (src3 + src4) - (src2 + src5) + 8) >> 4];
+ dst[4 * dstStride] = cm[(9 * (src4 + src5) - (src3 + src6) + 8) >> 4];
+ dst[5 * dstStride] = cm[(9 * (src5 + src6) - (src4 + src7) + 8) >> 4];
+ dst[6 * dstStride] = cm[(9 * (src6 + src7) - (src5 + src8) + 8) >> 4];
+ dst[7 * dstStride] = cm[(9 * (src7 + src8) - (src6 + src9) + 8) >> 4];
+ src++;
+ dst++;
+ }
+}
+
+static void put_mspel8_mc10_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ uint8_t half[64];
+
+ wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
+ ff_put_pixels8_l2_8(dst, src, half, stride, stride, 8, 8);
+}
+
+static void put_mspel8_mc20_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc30_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ uint8_t half[64];
+
+ wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
+ ff_put_pixels8_l2_8(dst, src + 1, half, stride, stride, 8, 8);
+}
+
+static void put_mspel8_mc02_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8);
+}
+
+static void put_mspel8_mc12_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ uint8_t halfH[88];
+ uint8_t halfV[64];
+ uint8_t halfHV[64];
+
+ wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
+ wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8);
+ wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8);
+ ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);
+}
+
+static void put_mspel8_mc32_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ uint8_t halfH[88];
+ uint8_t halfV[64];
+ uint8_t halfHV[64];
+
+ wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
+ wmv2_mspel8_v_lowpass(halfV, src + 1, 8, stride, 8);
+ wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8);
+ ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);
+}
+
+static void put_mspel8_mc22_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
+{
+ uint8_t halfH[88];
+
+ wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
+ wmv2_mspel8_v_lowpass(dst, halfH + 8, stride, 8, 8);
+}
+
+static av_cold void wmv2_mspel_init(WMV2DecContext *w)
+{
+ w->put_mspel_pixels_tab[0] = ff_put_pixels8x8_c;
+ w->put_mspel_pixels_tab[1] = put_mspel8_mc10_c;
+ w->put_mspel_pixels_tab[2] = put_mspel8_mc20_c;
+ w->put_mspel_pixels_tab[3] = put_mspel8_mc30_c;
+ w->put_mspel_pixels_tab[4] = put_mspel8_mc02_c;
+ w->put_mspel_pixels_tab[5] = put_mspel8_mc12_c;
+ w->put_mspel_pixels_tab[6] = put_mspel8_mc22_c;
+ w->put_mspel_pixels_tab[7] = put_mspel8_mc32_c;
+}
+
void ff_mspel_motion(MPVContext *const s, uint8_t *dest_y,
uint8_t *dest_cb, uint8_t *dest_cr,
uint8_t *const *ref_picture,
const op_pixels_func (*pix_op)[4],
int motion_x, int motion_y, int h)
{
- WMV2Context *const w = s->private_ctx;
+ WMV2DecContext *const w = (WMV2DecContext *) s;
const uint8_t *ptr;
int dxy, mx, my, src_x, src_y, v_edge_pos;
ptrdiff_t offset, linesize, uvlinesize;
int emu = 0;
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
- dxy = 2 * dxy + w->hshift;
+ dxy = 2 * dxy + w->common.hshift;
src_x = s->mb_x * 16 + (motion_x >> 1);
src_y = s->mb_y * 16 + (motion_y >> 1);
@@ -97,10 +220,10 @@ void ff_mspel_motion(MPVContext *const s, uint8_t *dest_y,
emu = 1;
}
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y, ptr, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8, ptr + 8, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 * linesize, ptr + 8 * linesize, linesize);
- w->wdsp.put_mspel_pixels_tab[dxy](dest_y + 8 + 8 * linesize, ptr + 8 + 8 * linesize, linesize);
+ w->put_mspel_pixels_tab[dxy](dest_y, ptr, linesize);
+ w->put_mspel_pixels_tab[dxy](dest_y + 8, ptr + 8, linesize);
+ w->put_mspel_pixels_tab[dxy](dest_y + 8 * linesize, ptr + 8 * linesize, linesize);
+ w->put_mspel_pixels_tab[dxy](dest_y + 8 + 8 * linesize, ptr + 8 + 8 * linesize, linesize);
if (s->avctx->flags & AV_CODEC_FLAG_GRAY)
return;
@@ -659,6 +782,8 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx)
MpegEncContext *const s = &h->c;
int ret;
+ wmv2_mspel_init(w);
+
s->private_ctx = &w->common;
if ((ret = ff_msmpeg4_decode_init(avctx)) < 0)
diff --git a/libavcodec/wmv2dsp.c b/libavcodec/wmv2dsp.c
index 4ad8a596b8..2616f133ba 100644
--- a/libavcodec/wmv2dsp.c
+++ b/libavcodec/wmv2dsp.c
@@ -21,7 +21,6 @@
#include "libavutil/common.h"
#include "idctdsp.h"
#include "mathops.h"
-#include "qpeldsp.h"
#include "wmv2dsp.h"
#define W0 2048
@@ -140,130 +139,12 @@ static void wmv2_idct_put_c(uint8_t *dest, ptrdiff_t line_size, int16_t *block)
}
}
-static void wmv2_mspel8_h_lowpass(uint8_t *dst, const uint8_t *src,
- int dstStride, int srcStride, int h)
-{
- const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
- int i;
-
- for (i = 0; i < h; i++) {
- dst[0] = cm[(9 * (src[0] + src[1]) - (src[-1] + src[2]) + 8) >> 4];
- dst[1] = cm[(9 * (src[1] + src[2]) - (src[0] + src[3]) + 8) >> 4];
- dst[2] = cm[(9 * (src[2] + src[3]) - (src[1] + src[4]) + 8) >> 4];
- dst[3] = cm[(9 * (src[3] + src[4]) - (src[2] + src[5]) + 8) >> 4];
- dst[4] = cm[(9 * (src[4] + src[5]) - (src[3] + src[6]) + 8) >> 4];
- dst[5] = cm[(9 * (src[5] + src[6]) - (src[4] + src[7]) + 8) >> 4];
- dst[6] = cm[(9 * (src[6] + src[7]) - (src[5] + src[8]) + 8) >> 4];
- dst[7] = cm[(9 * (src[7] + src[8]) - (src[6] + src[9]) + 8) >> 4];
- dst += dstStride;
- src += srcStride;
- }
-}
-
-static void wmv2_mspel8_v_lowpass(uint8_t *dst, const uint8_t *src,
- int dstStride, int srcStride, int w)
-{
- const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
- int i;
-
- for (i = 0; i < w; i++) {
- const int src_1 = src[-srcStride];
- const int src0 = src[0];
- const int src1 = src[srcStride];
- const int src2 = src[2 * srcStride];
- const int src3 = src[3 * srcStride];
- const int src4 = src[4 * srcStride];
- const int src5 = src[5 * srcStride];
- const int src6 = src[6 * srcStride];
- const int src7 = src[7 * srcStride];
- const int src8 = src[8 * srcStride];
- const int src9 = src[9 * srcStride];
- dst[0 * dstStride] = cm[(9 * (src0 + src1) - (src_1 + src2) + 8) >> 4];
- dst[1 * dstStride] = cm[(9 * (src1 + src2) - (src0 + src3) + 8) >> 4];
- dst[2 * dstStride] = cm[(9 * (src2 + src3) - (src1 + src4) + 8) >> 4];
- dst[3 * dstStride] = cm[(9 * (src3 + src4) - (src2 + src5) + 8) >> 4];
- dst[4 * dstStride] = cm[(9 * (src4 + src5) - (src3 + src6) + 8) >> 4];
- dst[5 * dstStride] = cm[(9 * (src5 + src6) - (src4 + src7) + 8) >> 4];
- dst[6 * dstStride] = cm[(9 * (src6 + src7) - (src5 + src8) + 8) >> 4];
- dst[7 * dstStride] = cm[(9 * (src7 + src8) - (src6 + src9) + 8) >> 4];
- src++;
- dst++;
- }
-}
-
-static void put_mspel8_mc10_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- uint8_t half[64];
-
- wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
- ff_put_pixels8_l2_8(dst, src, half, stride, stride, 8, 8);
-}
-
-static void put_mspel8_mc20_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8);
-}
-
-static void put_mspel8_mc30_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- uint8_t half[64];
-
- wmv2_mspel8_h_lowpass(half, src, 8, stride, 8);
- ff_put_pixels8_l2_8(dst, src + 1, half, stride, stride, 8, 8);
-}
-
-static void put_mspel8_mc02_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8);
-}
-
-static void put_mspel8_mc12_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- uint8_t halfH[88];
- uint8_t halfV[64];
- uint8_t halfHV[64];
-
- wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
- wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8);
- wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8);
- ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);
-}
-
-static void put_mspel8_mc32_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- uint8_t halfH[88];
- uint8_t halfV[64];
- uint8_t halfHV[64];
-
- wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
- wmv2_mspel8_v_lowpass(halfV, src + 1, 8, stride, 8);
- wmv2_mspel8_v_lowpass(halfHV, halfH + 8, 8, 8, 8);
- ff_put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);
-}
-
-static void put_mspel8_mc22_c(uint8_t *dst, const uint8_t *src, ptrdiff_t stride)
-{
- uint8_t halfH[88];
-
- wmv2_mspel8_h_lowpass(halfH, src - stride, 8, stride, 11);
- wmv2_mspel8_v_lowpass(dst, halfH + 8, stride, 8, 8);
-}
-
av_cold void ff_wmv2dsp_init(WMV2DSPContext *c)
{
c->idct_add = wmv2_idct_add_c;
c->idct_put = wmv2_idct_put_c;
c->idct_perm = FF_IDCT_PERM_NONE;
- c->put_mspel_pixels_tab[0] = ff_put_pixels8x8_c;
- c->put_mspel_pixels_tab[1] = put_mspel8_mc10_c;
- c->put_mspel_pixels_tab[2] = put_mspel8_mc20_c;
- c->put_mspel_pixels_tab[3] = put_mspel8_mc30_c;
- c->put_mspel_pixels_tab[4] = put_mspel8_mc02_c;
- c->put_mspel_pixels_tab[5] = put_mspel8_mc12_c;
- c->put_mspel_pixels_tab[6] = put_mspel8_mc22_c;
- c->put_mspel_pixels_tab[7] = put_mspel8_mc32_c;
-
#if ARCH_MIPS
ff_wmv2dsp_init_mips(c);
#endif
diff --git a/libavcodec/wmv2dsp.h b/libavcodec/wmv2dsp.h
index 5e40b30a20..6906dc29f2 100644
--- a/libavcodec/wmv2dsp.h
+++ b/libavcodec/wmv2dsp.h
@@ -19,16 +19,13 @@
#ifndef AVCODEC_WMV2DSP_H
#define AVCODEC_WMV2DSP_H
+#include <stddef.h>
#include <stdint.h>
-#include "qpeldsp.h"
-
typedef struct WMV2DSPContext {
void (*idct_add)(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
void (*idct_put)(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
- qpel_mc_func put_mspel_pixels_tab[8];
-
int idct_perm;
} WMV2DSPContext;
--
2.49.1
From 0e1dc227f8d4b14e3d632a9f27f26366a6d87951 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Tue, 30 Dec 2025 11:38:59 +0100
Subject: [PATCH 09/14] avcodec/wmv2dsp: Modify IDCTDSPContext directly
This allows to remove ff_wmv2_common_init() altogether.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/Makefile | 4 ++--
libavcodec/intrax8.c | 15 +++++-------
libavcodec/intrax8.h | 4 ++--
libavcodec/mips/wmv2dsp_init_mips.c | 4 +++-
libavcodec/mips/wmv2dsp_mips.h | 3 ++-
libavcodec/msmpeg4.c | 4 ++--
libavcodec/wmv2.c | 37 -----------------------------
libavcodec/wmv2.h | 8 +++----
libavcodec/wmv2dec.c | 2 +-
libavcodec/wmv2dsp.c | 7 ++++--
libavcodec/wmv2dsp.h | 14 +++--------
11 files changed, 29 insertions(+), 73 deletions(-)
delete mode 100644 libavcodec/wmv2.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 28ad85afb4..3d60347a19 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -854,8 +854,8 @@ OBJS-$(CONFIG_WMAV2_ENCODER) += wmaenc.o wma.o wma_common.o aactab.o
OBJS-$(CONFIG_WMAVOICE_DECODER) += wmavoice.o \
celp_filters.o \
acelp_vectors.o acelp_filters.o
-OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2data.o
-OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2data.o
+OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2data.o
+OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2data.o
OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o
OBJS-$(CONFIG_WRAPPED_AVFRAME_DECODER) += wrapped_avframe.o
OBJS-$(CONFIG_WRAPPED_AVFRAME_ENCODER) += wrapped_avframe.o
diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c
index 89b70e5902..ada5fc317f 100644
--- a/libavcodec/intrax8.c
+++ b/libavcodec/intrax8.c
@@ -437,7 +437,7 @@ static void x8_ac_compensation(IntraX8Context *const w, const int direction,
const int dc_level)
{
int t;
-#define B(x,y) w->block[w->idct_permutation[(x) + (y) * 8]]
+#define B(x,y) w->block[w->idsp.idct_permutation[(x) + (y) * 8]]
#define T(x) ((x) * dc_level + 0x8000) >> 16;
switch (direction) {
case 0:
@@ -637,7 +637,7 @@ static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)
w->frame->linesize[!!chroma]);
}
if (!zeros_only)
- w->wdsp.idct_add(w->dest[chroma],
+ w->idsp.idct_add(w->dest[chroma],
w->frame->linesize[!!chroma],
w->block);
@@ -693,17 +693,14 @@ av_cold int ff_intrax8_common_init(AVCodecContext *avctx,
if (!w->prediction_table)
return AVERROR(ENOMEM);
- ff_wmv2dsp_init(&w->wdsp);
-
- ff_init_scantable_permutation(w->idct_permutation,
- w->wdsp.idct_perm);
+ ff_wmv2dsp_init(&w->idsp);
ff_permute_scantable(w->permutated_scantable[0], ff_wmv1_scantable[0],
- w->idct_permutation);
+ w->idsp.idct_permutation);
ff_permute_scantable(w->permutated_scantable[1], ff_wmv1_scantable[2],
- w->idct_permutation);
+ w->idsp.idct_permutation);
ff_permute_scantable(w->permutated_scantable[2], ff_wmv1_scantable[3],
- w->idct_permutation);
+ w->idsp.idct_permutation);
ff_intrax8dsp_init(&w->dsp);
ff_blockdsp_init(&w->bdsp);
diff --git a/libavcodec/intrax8.h b/libavcodec/intrax8.h
index 2ec90963a8..a936299fbb 100644
--- a/libavcodec/intrax8.h
+++ b/libavcodec/intrax8.h
@@ -21,6 +21,7 @@
#include "blockdsp.h"
#include "get_bits.h"
+#include "idctdsp.h"
#include "intrax8dsp.h"
#include "wmv2dsp.h"
#include "mpegpicture.h"
@@ -35,8 +36,7 @@ typedef struct IntraX8Context {
// set by ff_intrax8_common_init
uint8_t *prediction_table; // 2 * (mb_w * 2)
uint8_t permutated_scantable[3][64];
- WMV2DSPContext wdsp;
- uint8_t idct_permutation[64];
+ IDCTDSPContext idsp;
AVCodecContext *avctx;
int16_t *block;
diff --git a/libavcodec/mips/wmv2dsp_init_mips.c b/libavcodec/mips/wmv2dsp_init_mips.c
index af1400731a..e48413b9a4 100644
--- a/libavcodec/mips/wmv2dsp_init_mips.c
+++ b/libavcodec/mips/wmv2dsp_init_mips.c
@@ -21,9 +21,11 @@
#include "libavutil/mips/cpu.h"
#include "config.h"
#include "libavutil/attributes.h"
+#include "libavcodec/idctdsp.h"
+#include "libavcodec/wmv2dsp.h"
#include "wmv2dsp_mips.h"
-av_cold void ff_wmv2dsp_init_mips(WMV2DSPContext *c)
+av_cold void ff_wmv2dsp_init_mips(IDCTDSPContext *c)
{
int cpu_flags = av_get_cpu_flags();
diff --git a/libavcodec/mips/wmv2dsp_mips.h b/libavcodec/mips/wmv2dsp_mips.h
index c96b3d94c7..94fbd8f6b7 100644
--- a/libavcodec/mips/wmv2dsp_mips.h
+++ b/libavcodec/mips/wmv2dsp_mips.h
@@ -21,7 +21,8 @@
#ifndef AVCODEC_MIPS_WMV2DSP_MIPS_H
#define AVCODEC_MIPS_WMV2DSP_MIPS_H
-#include "libavcodec/wmv2dsp.h"
+#include <stddef.h>
+#include <stdint.h>
void ff_wmv2_idct_add_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
void ff_wmv2_idct_put_mmi(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index bca8dbd524..3711c37e5c 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -44,7 +44,7 @@
#include "mpeg4videodata.h"
#include "msmpeg4data.h"
#include "msmpeg4_vc1_data.h"
-#include "wmv2.h"
+#include "wmv2dsp.h"
/*
* You can also call this codec: MPEG-4 with a twist!
@@ -140,7 +140,7 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
break;
#if CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER
case MSMP4_WMV2:
- ff_wmv2_common_init(s);
+ ff_wmv2dsp_init(&s->idsp);
// fallthrough
#endif
case MSMP4_WMV1:
diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c
deleted file mode 100644
index b29037cacb..0000000000
--- a/libavcodec/wmv2.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2002 The FFmpeg Project
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "idctdsp.h"
-#include "mpegvideo.h"
-#include "wmv2.h"
-
-
-av_cold void ff_wmv2_common_init(MpegEncContext *s)
-{
- WMV2Context *const w = s->private_ctx;
-
- ff_wmv2dsp_init(&w->wdsp);
- s->idsp.perm_type = w->wdsp.idct_perm;
- ff_init_scantable_permutation(s->idsp.idct_permutation,
- w->wdsp.idct_perm);
- s->idsp.idct_put = w->wdsp.idct_put;
- s->idsp.idct_add = w->wdsp.idct_add;
- s->idsp.idct = NULL;
-}
diff --git a/libavcodec/wmv2.h b/libavcodec/wmv2.h
index b2767c6ca4..e97ee658ba 100644
--- a/libavcodec/wmv2.h
+++ b/libavcodec/wmv2.h
@@ -21,8 +21,9 @@
#ifndef AVCODEC_WMV2_H
#define AVCODEC_WMV2_H
-#include "mpegvideo.h"
-#include "wmv2dsp.h"
+#include <stdint.h>
+
+#include "libavutil/attributes.h"
#define SKIP_TYPE_NONE 0
#define SKIP_TYPE_MPEG 1
@@ -31,12 +32,9 @@
typedef struct WMV2Context {
- WMV2DSPContext wdsp;
int hshift;
} WMV2Context;
-void ff_wmv2_common_init(MpegEncContext *s);
-
static av_always_inline int wmv2_get_cbp_table_index(int qscale, int cbp_index)
{
static const uint8_t map[3][3] = {
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 749a8608a2..756ab9a44d 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -277,7 +277,7 @@ static void wmv2_add_block(WMV2DecContext *w, int16_t blocks1[][64],
int16_t *block1 = blocks1[n];
switch (w->abt_type_table[n]) {
case 0:
- w->common.wdsp.idct_add(dst, stride, block1);
+ h->c.idsp.idct_add(dst, stride, block1);
break;
case 1:
ff_simple_idct84_add(dst, stride, block1);
diff --git a/libavcodec/wmv2dsp.c b/libavcodec/wmv2dsp.c
index 2616f133ba..7ebe4b614c 100644
--- a/libavcodec/wmv2dsp.c
+++ b/libavcodec/wmv2dsp.c
@@ -139,13 +139,16 @@ static void wmv2_idct_put_c(uint8_t *dest, ptrdiff_t line_size, int16_t *block)
}
}
-av_cold void ff_wmv2dsp_init(WMV2DSPContext *c)
+av_cold void ff_wmv2dsp_init(IDCTDSPContext *c)
{
c->idct_add = wmv2_idct_add_c;
c->idct_put = wmv2_idct_put_c;
- c->idct_perm = FF_IDCT_PERM_NONE;
+ c->idct = NULL;
+ c->perm_type = FF_IDCT_PERM_NONE;
#if ARCH_MIPS
ff_wmv2dsp_init_mips(c);
#endif
+ ff_init_scantable_permutation(c->idct_permutation,
+ c->perm_type);
}
diff --git a/libavcodec/wmv2dsp.h b/libavcodec/wmv2dsp.h
index 6906dc29f2..1402dbb96d 100644
--- a/libavcodec/wmv2dsp.h
+++ b/libavcodec/wmv2dsp.h
@@ -19,17 +19,9 @@
#ifndef AVCODEC_WMV2DSP_H
#define AVCODEC_WMV2DSP_H
-#include <stddef.h>
-#include <stdint.h>
+struct IDCTDSPContext;
-typedef struct WMV2DSPContext {
- void (*idct_add)(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
- void (*idct_put)(uint8_t *dest, ptrdiff_t line_size, int16_t *block);
-
- int idct_perm;
-} WMV2DSPContext;
-
-void ff_wmv2dsp_init(WMV2DSPContext *c);
-void ff_wmv2dsp_init_mips(WMV2DSPContext *c);
+void ff_wmv2dsp_init(struct IDCTDSPContext *c);
+void ff_wmv2dsp_init_mips(struct IDCTDSPContext *c);
#endif /* AVCODEC_WMV2DSP_H */
--
2.49.1
From 90910655ed5809b3915ce75997b5b12c1f3de7ba Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 09:10:26 +0200
Subject: [PATCH 10/14] avcodec/wmv2: Remove WMV2Context
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/wmv2.h | 5 -----
libavcodec/wmv2dec.c | 12 +++++-------
libavcodec/wmv2enc.c | 3 +--
3 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/libavcodec/wmv2.h b/libavcodec/wmv2.h
index e97ee658ba..aef3126867 100644
--- a/libavcodec/wmv2.h
+++ b/libavcodec/wmv2.h
@@ -30,11 +30,6 @@
#define SKIP_TYPE_ROW 2
#define SKIP_TYPE_COL 3
-
-typedef struct WMV2Context {
- int hshift;
-} WMV2Context;
-
static av_always_inline int wmv2_get_cbp_table_index(int qscale, int cbp_index)
{
static const uint8_t map[3][3] = {
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 756ab9a44d..22102ef6df 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -40,7 +40,6 @@
typedef struct WMV2DecContext {
MSMP4DecContext ms;
- WMV2Context common;
IntraX8Context x8;
qpel_mc_func put_mspel_pixels_tab[8];
@@ -56,6 +55,7 @@ typedef struct WMV2DecContext {
int cbp_table_index;
int top_left_mv_flag;
int per_mb_rl_bit;
+ int hshift;
DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64];
} WMV2DecContext;
@@ -192,7 +192,7 @@ void ff_mspel_motion(MPVContext *const s, uint8_t *dest_y,
int emu = 0;
dxy = ((motion_y & 1) << 1) | (motion_x & 1);
- dxy = 2 * dxy + w->common.hshift;
+ dxy = 2 * dxy + w->hshift;
src_x = s->mb_x * 16 + (motion_x >> 1);
src_y = s->mb_y * 16 + (motion_y >> 1);
@@ -564,9 +564,9 @@ static inline void wmv2_decode_motion(WMV2DecContext *w, int *mx_ptr, int *my_pt
ff_msmpeg4_decode_motion(&w->ms, mx_ptr, my_ptr);
if ((((*mx_ptr) | (*my_ptr)) & 1) && h->c.mspel)
- w->common.hshift = get_bits1(&h->gb);
+ w->hshift = get_bits1(&h->gb);
else
- w->common.hshift = 0;
+ w->hshift = 0;
}
static int16_t *wmv2_pred_motion(WMV2DecContext *w, int *px, int *py)
@@ -678,7 +678,7 @@ static int wmv2_decode_mb(H263DecContext *const h)
h->c.mv[0][0][0] = 0;
h->c.mv[0][0][1] = 0;
h->c.mb_skipped = 1;
- w->common.hshift = 0;
+ w->hshift = 0;
return 0;
}
if (get_bits_left(&h->gb) <= 0)
@@ -784,8 +784,6 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx)
wmv2_mspel_init(w);
- s->private_ctx = &w->common;
-
if ((ret = ff_msmpeg4_decode_init(avctx)) < 0)
return ret;
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index 5b3e2ae116..4082b58179 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -35,7 +35,6 @@
typedef struct WMV2EncContext {
MSMPEG4EncContext msmpeg4;
- WMV2Context common;
int j_type_bit;
int j_type;
int abt_flag;
@@ -228,7 +227,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx)
w->msmpeg4.m.encode_picture_header = wmv2_encode_picture_header;
s->encode_mb = wmv2_encode_mb;
- s->c.private_ctx = &w->common;
+
ret = ff_mpv_encode_init(avctx);
if (ret < 0)
return ret;
--
2.49.1
From 4e99ab3262578f4d5bdfbff9ef04c5706fbfd221 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 09:16:36 +0200
Subject: [PATCH 11/14] avcodec/wmv2dec: Avoid indirection
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/wmv2dec.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 22102ef6df..22b9b15e44 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -376,17 +376,17 @@ static int parse_mb_skip(WMV2DecContext *w)
return 0;
}
-static int decode_ext_header(WMV2DecContext *w)
+static av_cold int decode_ext_header(AVCodecContext *avctx, WMV2DecContext *w)
{
H263DecContext *const h = &w->ms.h;
GetBitContext gb;
int fps;
int code;
- if (h->c.avctx->extradata_size < 4)
+ if (avctx->extradata_size < 4)
return AVERROR_INVALIDDATA;
- init_get_bits(&gb, h->c.avctx->extradata, 32);
+ init_get_bits(&gb, avctx->extradata, 32);
fps = get_bits(&gb, 5);
w->ms.bit_rate = get_bits(&gb, 11) * 1024;
@@ -403,8 +403,8 @@ static int decode_ext_header(WMV2DecContext *w)
h->slice_height = h->c.mb_height / code;
- if (h->c.avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(h->c.avctx, AV_LOG_DEBUG,
+ if (avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(avctx, AV_LOG_DEBUG,
"fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, "
"tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, "
"slices:%d\n",
@@ -790,7 +790,7 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx)
h->decode_header = wmv2_decode_picture_header;
h->decode_mb = wmv2_decode_mb;
- decode_ext_header(w);
+ decode_ext_header(avctx, w);
return ff_intrax8_common_init(avctx, &w->x8, h->block[0],
s->mb_width, s->mb_height);
--
2.49.1
From 500355be1d635b5c20f2d97ba3faaf73cac226e2 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Wed, 25 Jun 2025 09:39:52 +0200
Subject: [PATCH 12/14] avcodec/mpegvideo: Move permutated_intra scans to
{H263Dec,MPVEnc}Ctx
Only used by these two.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/h263dec.c | 5 +++++
libavcodec/h263dec.h | 3 +++
libavcodec/ituh263dec.c | 4 ++--
libavcodec/ituh263enc.c | 6 ++++++
libavcodec/mpeg4videodec.c | 30 ++++++++++++++++--------------
libavcodec/mpeg4videoenc.c | 4 ++--
libavcodec/mpegvideo.c | 4 ----
libavcodec/mpegvideo.h | 3 ---
libavcodec/mpegvideoenc.h | 3 +++
libavcodec/msmpeg4.c | 8 +++++---
libavcodec/msmpeg4.h | 4 +++-
libavcodec/msmpeg4dec.c | 7 ++++---
libavcodec/msmpeg4enc.c | 3 ++-
13 files changed, 51 insertions(+), 33 deletions(-)
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index b4c8aa38f5..23fd16b726 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -108,6 +108,11 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
s->y_dc_scale_table =
s->c_dc_scale_table = ff_mpeg1_dc_scale_table;
+ ff_permute_scantable(h->permutated_intra_h_scantable, ff_alternate_horizontal_scan,
+ s->idsp.idct_permutation);
+ ff_permute_scantable(h->permutated_intra_v_scantable, ff_alternate_vertical_scan,
+ s->idsp.idct_permutation);
+
ff_mpv_unquantize_init(&unquant_dsp_ctx,
avctx->flags & AV_CODEC_FLAG_BITEXACT, 0);
// dct_unquantize defaults for H.263;
diff --git a/libavcodec/h263dec.h b/libavcodec/h263dec.h
index 4c25a833cf..ab647f5224 100644
--- a/libavcodec/h263dec.h
+++ b/libavcodec/h263dec.h
@@ -97,6 +97,9 @@ typedef struct H263DecContext {
GetBitContext last_resync_gb; ///< used to search for the next resync marker
+ uint8_t permutated_intra_h_scantable[64];
+ uint8_t permutated_intra_v_scantable[64];
+
DECLARE_ALIGNED_32(int16_t, block)[6][64];
} H263DecContext;
diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c
index a1472ce0a0..53ead30c48 100644
--- a/libavcodec/ituh263dec.c
+++ b/libavcodec/ituh263dec.c
@@ -542,9 +542,9 @@ static int h263_decode_block(H263DecContext *const h, int16_t block[64],
rl = &ff_rl_intra_aic;
if (h->c.ac_pred) {
if (h->c.h263_aic_dir)
- scan_table = h->c.permutated_intra_v_scantable; /* left */
+ scan_table = h->permutated_intra_v_scantable; /* left */
else
- scan_table = h->c.permutated_intra_h_scantable; /* top */
+ scan_table = h->permutated_intra_h_scantable; /* top */
}
} else if (h->c.mb_intra) {
/* DC coef */
diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c
index 85008443da..56259783b0 100644
--- a/libavcodec/ituh263enc.c
+++ b/libavcodec/ituh263enc.c
@@ -38,6 +38,7 @@
#include "codec_internal.h"
#include "mpegvideo.h"
#include "flvenc.h"
+#include "mpegvideodata.h"
#include "mpegvideoenc.h"
#include "h263.h"
#include "h263enc.h"
@@ -824,6 +825,11 @@ av_cold void ff_h263_encode_init(MPVMainEncContext *const m)
ff_h263dsp_init(&s->c.h263dsp);
+ ff_permute_scantable(s->permutated_intra_h_scantable, ff_alternate_horizontal_scan,
+ s->c.idsp.idct_permutation);
+ ff_permute_scantable(s->permutated_intra_v_scantable, ff_alternate_vertical_scan,
+ s->c.idsp.idct_permutation);
+
if (s->c.codec_id == AV_CODEC_ID_MPEG4)
return;
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index e4a765d5ec..3d20f7c389 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -1425,9 +1425,9 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block,
}
if (h->c.ac_pred) {
if (dc_pred_dir == 0)
- scan_table = h->c.permutated_intra_v_scantable; /* left */
+ scan_table = h->permutated_intra_v_scantable; /* left */
else
- scan_table = h->c.permutated_intra_h_scantable; /* top */
+ scan_table = h->permutated_intra_h_scantable; /* top */
} else {
scan_table = h->c.intra_scantable.permutated;
}
@@ -3232,14 +3232,14 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb,
if (h->c.alternate_scan) {
ff_init_scantable(h->c.idsp.idct_permutation, &h->c.intra_scantable, ff_alternate_vertical_scan);
- ff_permute_scantable(h->c.permutated_intra_h_scantable, ff_alternate_vertical_scan,
+ ff_permute_scantable(h->permutated_intra_h_scantable, ff_alternate_vertical_scan,
h->c.idsp.idct_permutation);
} else {
ff_init_scantable(h->c.idsp.idct_permutation, &h->c.intra_scantable, ff_zigzag_direct);
- ff_permute_scantable(h->c.permutated_intra_h_scantable, ff_alternate_horizontal_scan,
+ ff_permute_scantable(h->permutated_intra_h_scantable, ff_alternate_horizontal_scan,
h->c.idsp.idct_permutation);
}
- ff_permute_scantable(h->c.permutated_intra_v_scantable, ff_alternate_vertical_scan,
+ ff_permute_scantable(h->permutated_intra_v_scantable, ff_alternate_vertical_scan,
h->c.idsp.idct_permutation);
if (h->c.pict_type == AV_PICTURE_TYPE_S) {
@@ -3609,21 +3609,23 @@ static av_cold void permute_quant_matrix(uint16_t matrix[64],
}
static av_cold void switch_to_xvid_idct(AVCodecContext *const avctx,
- MpegEncContext *const s)
+ H263DecContext *const h)
{
uint8_t old_permutation[64];
- memcpy(old_permutation, s->idsp.idct_permutation, sizeof(old_permutation));
+ memcpy(old_permutation, h->c.idsp.idct_permutation, sizeof(old_permutation));
avctx->idct_algo = FF_IDCT_XVID;
- ff_mpv_idct_init(s);
- ff_permute_scantable(s->permutated_intra_h_scantable,
- s->alternate_scan ? ff_alternate_vertical_scan : ff_alternate_horizontal_scan,
- s->idsp.idct_permutation);
+ ff_mpv_idct_init(&h->c);
+ ff_permute_scantable(h->permutated_intra_h_scantable,
+ h->c.alternate_scan ? ff_alternate_vertical_scan : ff_alternate_horizontal_scan,
+ h->c.idsp.idct_permutation);
+ ff_permute_scantable(h->permutated_intra_v_scantable, ff_alternate_vertical_scan,
+ h->c.idsp.idct_permutation);
// Normal (i.e. non-studio) MPEG-4 does not use the chroma matrices.
- permute_quant_matrix(s->inter_matrix, s->idsp.idct_permutation, old_permutation);
- permute_quant_matrix(s->intra_matrix, s->idsp.idct_permutation, old_permutation);
+ permute_quant_matrix(h->c.inter_matrix, h->c.idsp.idct_permutation, old_permutation);
+ permute_quant_matrix(h->c.intra_matrix, h->c.idsp.idct_permutation, old_permutation);
}
void ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
@@ -3735,7 +3737,7 @@ void ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
if (ctx->xvid_build >= 0 &&
avctx->idct_algo == FF_IDCT_AUTO && !h->c.studio_profile) {
- switch_to_xvid_idct(avctx, &h->c);
+ switch_to_xvid_idct(avctx, h);
}
}
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index ced4ad24e7..a10da6af82 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -223,7 +223,7 @@ static inline int decide_ac_pred(MPVEncContext *const s, int16_t block[6][64],
ac_val1[i + 8] = level;
}
}
- st[n] = s->c.permutated_intra_h_scantable;
+ st[n] = s->permutated_intra_h_scantable;
} else {
const int xy = s->c.mb_x - 1 + s->c.mb_y * s->c.mb_stride;
/* left prediction */
@@ -245,7 +245,7 @@ static inline int decide_ac_pred(MPVEncContext *const s, int16_t block[6][64],
ac_val1[i + 8] = block[n][s->c.idsp.idct_permutation[i]];
}
}
- st[n] = s->c.permutated_intra_v_scantable;
+ st[n] = s->permutated_intra_v_scantable;
}
for (i = 63; i > 0; i--) // FIXME optimize
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 7ca2c8f701..09e5a96239 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -94,10 +94,6 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s)
ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct);
ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct);
}
- ff_permute_scantable(s->permutated_intra_h_scantable, ff_alternate_horizontal_scan,
- s->idsp.idct_permutation);
- ff_permute_scantable(s->permutated_intra_v_scantable, ff_alternate_vertical_scan,
- s->idsp.idct_permutation);
}
av_cold int ff_mpv_init_duplicate_contexts(MpegEncContext *s)
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 6aff5fbcd0..c9ec79cfad 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -79,9 +79,6 @@ typedef struct MpegEncContext {
/* WARNING: changes above this line require updates to hardcoded
* offsets used in ASM. */
- uint8_t permutated_intra_h_scantable[64];
- uint8_t permutated_intra_v_scantable[64];
-
struct AVCodecContext *avctx;
/* The following pointer is intended for codecs sharing code
* between decoder and encoder and in need of a common context to do so. */
diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h
index 4366e78f90..9003d017e5 100644
--- a/libavcodec/mpegvideoenc.h
+++ b/libavcodec/mpegvideoenc.h
@@ -193,6 +193,9 @@ typedef struct MPVEncContext {
int intra_penalty;
+ uint8_t permutated_intra_h_scantable[64];
+ uint8_t permutated_intra_v_scantable[64];
+
DECLARE_ALIGNED_32(int16_t, blocks)[2][12][64]; // for HQ mode we need to keep the best block
} MPVEncContext;
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index 3711c37e5c..8dfe0b095d 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -118,7 +118,9 @@ static av_cold void msmpeg4_common_init_static(void)
init_h263_dc_for_msmpeg4();
}
-av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
+av_cold void ff_msmpeg4_common_init(MPVContext *const s,
+ uint8_t permutated_intra_h_scantable[64],
+ uint8_t permutated_intra_v_scantable[64])
{
static AVOnce init_static_once = AV_ONCE_INIT;
@@ -148,9 +150,9 @@ av_cold void ff_msmpeg4_common_init(MpegEncContext *s)
s->c_dc_scale_table= ff_wmv1_c_dc_scale_table;
ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]);
ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable, ff_wmv1_scantable[0]);
- ff_permute_scantable(s->permutated_intra_h_scantable, ff_wmv1_scantable[2],
+ ff_permute_scantable(permutated_intra_h_scantable, ff_wmv1_scantable[2],
s->idsp.idct_permutation);
- ff_permute_scantable(s->permutated_intra_v_scantable, ff_wmv1_scantable[3],
+ ff_permute_scantable(permutated_intra_v_scantable, ff_wmv1_scantable[3],
s->idsp.idct_permutation);
break;
}
diff --git a/libavcodec/msmpeg4.h b/libavcodec/msmpeg4.h
index b918028fe1..69299c0004 100644
--- a/libavcodec/msmpeg4.h
+++ b/libavcodec/msmpeg4.h
@@ -31,7 +31,9 @@
#define DC_MAX 119
-void ff_msmpeg4_common_init(MpegEncContext *s);
+void ff_msmpeg4_common_init(MPVContext *const s,
+ uint8_t permutated_intra_h_scantable[64],
+ uint8_t permutated_intra_v_scantable[64]);
int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n,
uint8_t **coded_block_ptr);
diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c
index f2ab99ecb5..23f302dee3 100644
--- a/libavcodec/msmpeg4dec.c
+++ b/libavcodec/msmpeg4dec.c
@@ -655,9 +655,9 @@ int ff_msmpeg4_decode_block(MSMP4DecContext *const ms, int16_t * block,
}
if (h->c.ac_pred) {
if (dc_pred_dir == 0)
- scan_table = h->c.permutated_intra_v_scantable; /* left */
+ scan_table = h->permutated_intra_v_scantable; /* left */
else
- scan_table = h->c.permutated_intra_h_scantable; /* top */
+ scan_table = h->permutated_intra_h_scantable; /* top */
} else {
scan_table = h->c.intra_scantable.permutated;
}
@@ -849,7 +849,8 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx)
h->decode_header = msmpeg4_decode_picture_header;
- ff_msmpeg4_common_init(&h->c);
+ ff_msmpeg4_common_init(&h->c, h->permutated_intra_h_scantable,
+ h->permutated_intra_v_scantable);
switch (h->c.msmpeg4_version) {
case MSMP4_V1:
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index 874e0c1f2b..6141c63e1c 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -675,7 +675,8 @@ av_cold void ff_msmpeg4_encode_init(MPVMainEncContext *const m)
MPVEncContext *const s = &m->s;
static AVOnce init_static_once = AV_ONCE_INIT;
- ff_msmpeg4_common_init(&s->c);
+ ff_msmpeg4_common_init(&s->c, s->permutated_intra_h_scantable,
+ s->permutated_intra_v_scantable);
if (s->c.msmpeg4_version <= MSMP4_WMV1) {
m->encode_picture_header = msmpeg4_encode_picture_header;
--
2.49.1
From fec9b330e44e1863c9141869d16d793d27b2a72e Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Tue, 30 Dec 2025 13:26:33 +0100
Subject: [PATCH 13/14] avcodec/h261: Remove H261Context
It only contains a single field, so add this directly to MPVContext
and remove private_ctx. This avoids an indirection in
ff_h261_loop_filter().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/h261.c | 3 +--
libavcodec/h261.h | 7 -------
libavcodec/h261dec.c | 20 ++++++++------------
libavcodec/h261enc.c | 32 ++++++++++++++------------------
libavcodec/mpegvideo.h | 6 +++---
5 files changed, 26 insertions(+), 42 deletions(-)
diff --git a/libavcodec/h261.c b/libavcodec/h261.c
index 8e0e13459a..babbd48dcb 100644
--- a/libavcodec/h261.c
+++ b/libavcodec/h261.c
@@ -60,14 +60,13 @@ static void h261_loop_filter(uint8_t *src, ptrdiff_t stride)
void ff_h261_loop_filter(MpegEncContext *s)
{
- H261Context *const h = s->private_ctx;
const ptrdiff_t linesize = s->linesize;
const ptrdiff_t uvlinesize = s->uvlinesize;
uint8_t *dest_y = s->dest[0];
uint8_t *dest_cb = s->dest[1];
uint8_t *dest_cr = s->dest[2];
- if (!(IS_FIL(h->mtype)))
+ if (!(IS_FIL(s->mtype)))
return;
h261_loop_filter(dest_y, linesize);
diff --git a/libavcodec/h261.h b/libavcodec/h261.h
index fb5fc6f940..14d5b4a2fd 100644
--- a/libavcodec/h261.h
+++ b/libavcodec/h261.h
@@ -31,13 +31,6 @@
#include "mpegutils.h"
#include "rl.h"
-/**
- * H261Context
- */
-typedef struct H261Context {
- int mtype;
-} H261Context;
-
#define MB_TYPE_H261_FIL MB_TYPE_CODEC_SPECIFIC
extern const uint8_t ff_h261_mba_code[35];
diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index 32d41903e7..a25595faf6 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -59,8 +59,6 @@ typedef struct H261DecContext {
GetBitContext gb;
- H261Context common;
-
int current_mba;
int mba_diff;
int current_mv_x;
@@ -104,7 +102,6 @@ static av_cold int h261_decode_init(AVCodecContext *avctx)
* for all frames and override it after having decoded the frame. */
s->pict_type = AV_PICTURE_TYPE_P;
- s->private_ctx = &h->common;
// set defaults
ret = ff_mpv_decode_init(s, avctx);
if (ret < 0)
@@ -211,7 +208,7 @@ static int h261_decode_mb_skipped(H261DecContext *h, int mba1, int mba2)
s->mv[0][0][0] = 0;
s->mv[0][0][1] = 0;
s->mb_skipped = 1;
- h->common.mtype &= ~MB_TYPE_H261_FIL;
+ s->mtype &= ~MB_TYPE_H261_FIL;
if (s->cur_pic.motion_val[0]) {
int b_stride = 2*s->mb_width + 1;
@@ -352,7 +349,6 @@ static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded
static int h261_decode_mb(H261DecContext *h)
{
MpegEncContext *const s = &h->s;
- H261Context *const com = &h->common;
int i, cbp, xy;
cbp = 63;
@@ -389,23 +385,23 @@ static int h261_decode_mb(H261DecContext *h)
h261_init_dest(s);
// Read mtype
- com->mtype = get_vlc2(&h->gb, h261_mtype_vlc, H261_MTYPE_VLC_BITS, 2);
- if (com->mtype < 0) {
+ s->mtype = get_vlc2(&h->gb, h261_mtype_vlc, H261_MTYPE_VLC_BITS, 2);
+ if (s->mtype < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid mtype index\n");
return SLICE_ERROR;
}
// Read mquant
- if (IS_QUANT(com->mtype)) {
+ if (IS_QUANT(s->mtype)) {
s->qscale = get_bits(&h->gb, 5);
if (!s->qscale)
s->qscale = 1;
}
- s->mb_intra = IS_INTRA4x4(com->mtype);
+ s->mb_intra = IS_INTRA4x4(s->mtype);
// Read mv
- if (IS_16X16(com->mtype)) {
+ if (IS_16X16(s->mtype)) {
/* Motion vector data is included for all MC macroblocks. MVD is
* obtained from the macroblock vector by subtracting the vector
* of the preceding macroblock. For this calculation the vector
@@ -428,7 +424,7 @@ static int h261_decode_mb(H261DecContext *h)
}
// Read cbp
- if (HAS_CBP(com->mtype))
+ if (HAS_CBP(s->mtype))
cbp = get_vlc2(&h->gb, h261_cbp_vlc, H261_CBP_VLC_BITS, 1) + 1;
if (s->mb_intra) {
@@ -452,7 +448,7 @@ static int h261_decode_mb(H261DecContext *h)
intra:
/* decode each block */
- if (s->mb_intra || HAS_CBP(com->mtype)) {
+ if (s->mb_intra || HAS_CBP(s->mtype)) {
s->bdsp.clear_blocks(h->block[0]);
for (i = 0; i < 6; i++) {
if (h261_decode_block(h, h->block[i], i, cbp & 32) < 0)
diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index c75e029d68..d13511a6f4 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -58,8 +58,6 @@ static uint8_t h261_mv_codes[64][2];
typedef struct H261EncContext {
MPVMainEncContext s;
- H261Context common;
-
int gob_number;
enum {
H261_QCIF = 0,
@@ -232,12 +230,11 @@ static void h261_encode_mb(MPVEncContext *const s, int16_t block[6][64],
/* The following is only allowed because this encoder
* does not use slice threading. */
H261EncContext *const h = (H261EncContext *)s;
- H261Context *const com = &h->common;
int mvd, mv_diff_x, mv_diff_y, i, cbp;
cbp = 63; // avoid warning
mvd = 0;
- com->mtype = 0;
+ s->c.mtype = 0;
if (!s->c.mb_intra) {
/* compute cbp */
@@ -264,34 +261,34 @@ static void h261_encode_mb(MPVEncContext *const s, int16_t block[6][64],
/* calculate MTYPE */
if (!s->c.mb_intra) {
- com->mtype++;
+ s->c.mtype++;
if (mvd || s->loop_filter)
- com->mtype += 3;
+ s->c.mtype += 3;
if (s->loop_filter)
- com->mtype += 3;
+ s->c.mtype += 3;
if (cbp)
- com->mtype++;
- av_assert1(com->mtype > 1);
+ s->c.mtype++;
+ av_assert1(s->c.mtype > 1);
}
if (s->dquant && cbp) {
- com->mtype++;
+ s->c.mtype++;
} else
s->c.qscale -= s->dquant;
put_bits(&s->pb,
- ff_h261_mtype_bits[com->mtype],
- ff_h261_mtype_code[com->mtype]);
+ ff_h261_mtype_bits[s->c.mtype],
+ ff_h261_mtype_code[s->c.mtype]);
- com->mtype = ff_h261_mtype_map[com->mtype];
+ s->c.mtype = ff_h261_mtype_map[s->c.mtype];
- if (IS_QUANT(com->mtype)) {
+ if (IS_QUANT(s->c.mtype)) {
ff_set_qscale(&s->c, s->c.qscale + s->dquant);
put_bits(&s->pb, 5, s->c.qscale);
}
- if (IS_16X16(com->mtype)) {
+ if (IS_16X16(s->c.mtype)) {
mv_diff_x = (motion_x >> 1) - s->c.last_mv[0][0][0];
mv_diff_y = (motion_y >> 1) - s->c.last_mv[0][0][1];
s->c.last_mv[0][0][0] = (motion_x >> 1);
@@ -300,7 +297,7 @@ static void h261_encode_mb(MPVEncContext *const s, int16_t block[6][64],
h261_encode_motion(&s->pb, mv_diff_y);
}
- if (HAS_CBP(com->mtype)) {
+ if (HAS_CBP(s->c.mtype)) {
av_assert1(cbp > 0);
put_bits(&s->pb,
ff_h261_cbp_tab[cbp - 1][1],
@@ -310,7 +307,7 @@ static void h261_encode_mb(MPVEncContext *const s, int16_t block[6][64],
/* encode each block */
h261_encode_block(h, block[i], i);
- if (!IS_16X16(com->mtype)) {
+ if (!IS_16X16(s->c.mtype)) {
s->c.last_mv[0][0][0] = 0;
s->c.last_mv[0][0][1] = 0;
}
@@ -370,7 +367,6 @@ static av_cold int h261_encode_init(AVCodecContext *avctx)
avctx->width, avctx->height);
return AVERROR(EINVAL);
}
- s->c.private_ctx = &h->common;
h->s.encode_picture_header = h261_encode_picture_header;
s->encode_mb = h261_encode_mb;
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index c9ec79cfad..d448ac6b5a 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -80,9 +80,6 @@ typedef struct MpegEncContext {
* offsets used in ASM. */
struct AVCodecContext *avctx;
- /* The following pointer is intended for codecs sharing code
- * between decoder and encoder and in need of a common context to do so. */
- void *private_ctx;
/* the following parameters must be initialized before encoding */
int width, height;///< picture size. must be a multiple of 16
enum OutputFormat out_format; ///< output format
@@ -210,6 +207,9 @@ typedef struct MpegEncContext {
int resync_mb_x; ///< x position of last resync marker
int resync_mb_y; ///< y position of last resync marker
+ /* H.261 specific */
+ int mtype;
+
/* H.263 specific */
int obmc; ///< overlapped block motion compensation
--
2.49.1
From 607329c2a4d28272699649a40642310486c47eef Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
Date: Tue, 30 Dec 2025 14:13:41 +0100
Subject: [PATCH 14/14] avcodec/vc1_block: Simplify vc1_coded_block_pred()
Make it already apply the prediction, avoiding the pointer indirection.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
---
libavcodec/vc1_block.c | 23 +++++++----------------
1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 4fa03f287a..10cb459082 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -476,8 +476,7 @@ static inline int ff_vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n,
* @{
*/
-static inline int vc1_coded_block_pred(MpegEncContext * s, int n,
- uint8_t **coded_block_ptr)
+static inline int vc1_coded_block_pred(MPVContext *const s, int n, int diff)
{
int xy, wrap, pred, a, b, c;
@@ -498,9 +497,9 @@ static inline int vc1_coded_block_pred(MpegEncContext * s, int n,
}
/* store value */
- *coded_block_ptr = &s->coded_block[xy];
+ s->coded_block[xy] = pred ^ diff;
- return pred;
+ return pred ^ diff;
}
/**
@@ -2507,7 +2506,6 @@ static void vc1_decode_i_blocks(VC1Context *v)
int k, j;
MpegEncContext *s = &v->s;
int cbp, val;
- uint8_t *coded_val;
int mb_pos;
/* select coding mode used for VLC tables selection */
@@ -2566,11 +2564,8 @@ static void vc1_decode_i_blocks(VC1Context *v)
val = ((cbp >> (5 - k)) & 1);
- if (k < 4) {
- int pred = vc1_coded_block_pred(&v->s, k, &coded_val);
- val = val ^ pred;
- *coded_val = val;
- }
+ if (k < 4)
+ val = vc1_coded_block_pred(&v->s, k, val);
cbp |= val << (5 - k);
vc1_decode_i_block(v, v->block[v->cur_blk_idx][block_map[k]], k, val, (k < 4) ? v->codingset : v->codingset2);
@@ -2627,7 +2622,6 @@ static int vc1_decode_i_blocks_adv(VC1Context *v)
MpegEncContext *s = &v->s;
GetBitContext *const gb = &v->gb;
int cbp, val;
- uint8_t *coded_val;
int mb_pos;
int mquant;
int mqdiff;
@@ -2712,11 +2706,8 @@ static int vc1_decode_i_blocks_adv(VC1Context *v)
val = ((cbp >> (5 - k)) & 1);
- if (k < 4) {
- int pred = vc1_coded_block_pred(&v->s, k, &coded_val);
- val = val ^ pred;
- *coded_val = val;
- }
+ if (k < 4)
+ val = vc1_coded_block_pred(&v->s, k, val);
cbp |= val << (5 - k);
v->a_avail = !s->first_slice_line || (k == 2 || k == 3);
--
2.49.1
1
0
PR #21319 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21319
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21319.patch
A macro and a few other changes.
From 08c31b1d55395f5d23eb555689ee41156b08c6cf Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Sun, 28 Dec 2025 19:04:27 +0100
Subject: [PATCH 01/10] hwcontext_vulkan: enable subgroup extended types
Like, of course I want to use int16_t in subgroups, what a stupid
question was that?
---
libavutil/hwcontext_vulkan.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index aa5f72e7f2..bb767f6c96 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -305,6 +305,7 @@ static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceF
COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
COPY_VAL(vulkan_1_2.uniformBufferStandardLayout);
COPY_VAL(vulkan_1_2.runtimeDescriptorArray);
+ COPY_VAL(vulkan_1_2.shaderSubgroupExtendedTypes);
COPY_VAL(vulkan_1_3.dynamicRendering);
COPY_VAL(vulkan_1_3.maintenance4);
--
2.49.1
From 99cba5a342406d84be78269d3d5eda2d3ad1997c Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Fri, 19 Dec 2025 23:49:43 +0000
Subject: [PATCH 02/10] vulkan: use HOST_CACHED memory flag only if such a heap
exists
NVK does not offer such, so our code failed to allocate memory.
---
libavcodec/ffv1enc_vulkan.c | 5 ++---
libavcodec/vulkan_encode.c | 2 +-
libavutil/hwcontext_vulkan.c | 2 +-
libavutil/vulkan.c | 4 ++++
libavutil/vulkan.h | 2 ++
5 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
index 86521af6c5..1dc6aa8e90 100644
--- a/libavcodec/ffv1enc_vulkan.c
+++ b/libavcodec/ffv1enc_vulkan.c
@@ -365,9 +365,8 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
NULL, maxsize,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
(maxsize < fv->max_heap_size ?
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0) |
- (!(fv->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) ?
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT : 0x0)));
+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT :
+ fv->s.host_cached_flag)));
out_data_buf = (FFVkBuffer *)fd->out_data_ref->data;
ff_vk_exec_add_dep_buf(&fv->s, exec, &fd->out_data_ref, 1, 1);
diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
index 7b534ffa30..5b84ad9db7 100644
--- a/libavcodec/vulkan_encode.c
+++ b/libavcodec/vulkan_encode.c
@@ -182,7 +182,7 @@ static int vulkan_encode_issue(AVCodecContext *avctx,
VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
&ctx->profile_list, max_pkt_size,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+ ctx->s.host_cached_flag);
if (err < 0)
return err;
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index bb767f6c96..313359a4af 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -4338,7 +4338,7 @@ static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst,
err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
NULL, buf_offset,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
- VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+ p->vkctx.host_cached_flag);
if (err < 0)
return err;
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index 7858e002ed..d4ac1544d1 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -212,6 +212,10 @@ int ff_vk_load_props(FFVulkanContext *s)
vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
+ for (int i = 0; i < s->mprops.memoryTypeCount; i++)
+ s->host_cached_flag |= s->mprops.memoryTypes[i].propertyFlags &
+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+
load_enabled_qfs(s);
if (s->qf_props)
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 29116bcb2c..d42bf514fe 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -301,6 +301,8 @@ typedef struct FFVulkanContext {
VkPhysicalDeviceVulkan12Features feats_12;
VkPhysicalDeviceFeatures2 feats;
+ VkMemoryPropertyFlagBits host_cached_flag;
+
AVBufferRef *device_ref;
AVHWDeviceContext *device;
AVVulkanDeviceContext *hwctx;
--
2.49.1
From c99bfc4ee6e98b608d090be48fc34e314b589590 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Thu, 25 Dec 2025 00:18:13 +0100
Subject: [PATCH 03/10] vulkan_functions: add vkCmdDispatchBase
Its useful for multi-stage operations.
---
libavutil/vulkan_functions.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
index d2e3c77bb8..9aed48aab3 100644
--- a/libavutil/vulkan_functions.h
+++ b/libavutil/vulkan_functions.h
@@ -115,6 +115,7 @@ typedef uint64_t FFVulkanExtensions;
MACRO(1, 1, FF_VK_EXT_NO_FLAG, EndCommandBuffer) \
MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeCommandBuffers) \
MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdDispatch) \
+ MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdDispatchBase) \
\
/* Queue */ \
MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetDeviceQueue) \
--
2.49.1
From a48f37083a19ee7bacfe81f2273643b27d5d01a7 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Tue, 23 Dec 2025 19:03:45 +0100
Subject: [PATCH 04/10] vulkan: add ff_vk_buf_barrier()
This is a shorthand way of writing buffer barrier structures.
---
libavutil/vulkan.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index d42bf514fe..115e9fc940 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -507,6 +507,25 @@ int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e,
VkImageView views[AV_NUM_DATA_POINTERS],
AVFrame *f, enum FFVkShaderRepFormat rep_fmt);
+#define ff_vk_buf_barrier(dst, vkb, s_stage, s_access, s_access2, \
+ d_stage, d_access, d_access2, offs, bsz) \
+ do { \
+ dst = (VkBufferMemoryBarrier2) { \
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2, \
+ .srcStageMask = VK_PIPELINE_STAGE_2_ ##s_stage, \
+ .srcAccessMask = VK_ACCESS_2_ ##s_access | \
+ VK_ACCESS_2_ ##s_access2, \
+ .dstStageMask = VK_PIPELINE_STAGE_2_ ##d_stage, \
+ .dstAccessMask = VK_ACCESS_2_ ##d_access | \
+ VK_ACCESS_2_ ##d_access2, \
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, \
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, \
+ .buffer = vkb->buf, \
+ .offset = offs, \
+ .size = bsz \
+ }; \
+ } while(0)
+
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e,
AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
VkPipelineStageFlags2 src_stage,
--
2.49.1
From 2dbf1e1f7e1ad8923ddcba8cb40d8b54f6191909 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Tue, 23 Dec 2025 19:04:37 +0100
Subject: [PATCH 05/10] vulkan_ffv1: use ff_vk_buf_barrier()
---
libavcodec/vulkan_ffv1.c | 90 +++++++++++++++++++---------------------
1 file changed, 42 insertions(+), 48 deletions(-)
diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index 168871d5d9..7766d67511 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -366,21 +366,20 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_offset_buf, 1, 0));
fp->slice_offset_buf = NULL;
- /* Entry barrier for the slice state */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_state->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_state->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_state->buf,
- .offset = 0,
- .size = fp->slice_data_size*f->slice_count,
- };
-
+ /* Entry barrier for the slice state (not preserved between frames) */
+ if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY))
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ 0, fp->slice_data_size*f->slice_count);
+ else
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ 0, fp->slice_data_size*f->slice_count);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pImageMemoryBarriers = img_bar,
@@ -388,8 +387,6 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- slice_state->stage = buf_bar[0].dstStageMask;
- slice_state->access = buf_bar[0].dstAccessMask;
nb_buf_bar = 0;
nb_img_bar = 0;
@@ -496,18 +493,23 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
0, sizeof(pd_reset), &pd_reset);
/* Sync between setup and reset shaders */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_state->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_state->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_state->buf,
- .offset = 0,
- .size = fp->slice_data_size*f->slice_count,
- };
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ 0, fp->slice_data_size*f->slice_count);
+ /* Probability data barrier */
+ if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY))
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
+ fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
+ else
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
+ fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pImageMemoryBarriers = img_bar,
@@ -515,8 +517,6 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- slice_state->stage = buf_bar[0].dstStageMask;
- slice_state->access = buf_bar[0].dstAccessMask;
nb_buf_bar = 0;
nb_img_bar = 0;
@@ -552,21 +552,17 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pd), &pd);
- /* Sync between reset and decode shaders */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_state->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_state->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_state->buf,
- .offset = fp->slice_data_size*f->slice_count,
- .size = f->slice_count*(fp->slice_state_size - fp->slice_data_size),
- };
-
+ /* Sync probabilities between reset and decode shaders */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ 0, fp->slice_data_size*f->slice_count);
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
/* Input frame barrier */
ff_vk_frame_barrier(&ctx->s, exec, f->picture.f, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
@@ -590,8 +586,6 @@ static int vk_ffv1_end_frame(AVCodecContext *avctx)
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- slice_state->stage = buf_bar[0].dstStageMask;
- slice_state->access = buf_bar[0].dstAccessMask;
nb_img_bar = 0;
nb_buf_bar = 0;
--
2.49.1
From dfe7656dbeeb246e0bb5de90b98c740dcde9cd41 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Tue, 23 Dec 2025 19:05:14 +0100
Subject: [PATCH 06/10] nlmeans_vulkan: use ff_vk_buf_barrier()
---
libavfilter/vf_nlmeans_vulkan.c | 181 ++++++++++++--------------------
1 file changed, 67 insertions(+), 114 deletions(-)
diff --git a/libavfilter/vf_nlmeans_vulkan.c b/libavfilter/vf_nlmeans_vulkan.c
index b69e8ac0a2..7a765d9f31 100644
--- a/libavfilter/vf_nlmeans_vulkan.c
+++ b/libavfilter/vf_nlmeans_vulkan.c
@@ -740,8 +740,6 @@ static int denoise_pass(NLMeansVulkanContext *s, FFVkExecContext *exec,
{
FFVulkanContext *vkctx = &s->vkctx;
FFVulkanFunctions *vk = &vkctx->vkfn;
- VkBufferMemoryBarrier2 buf_bar[2];
- int nb_buf_bar = 0;
DenoisePushData pd = {
{ comp_offs[0], comp_offs[1], comp_offs[2], comp_offs[3] },
@@ -761,26 +759,17 @@ static int denoise_pass(NLMeansVulkanContext *s, FFVkExecContext *exec,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pd), &pd);
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = ws_vk->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = ws_vk->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = ws_vk->buf,
- .size = ws_vk->size,
- .offset = 0,
- };
-
+ VkBufferMemoryBarrier2 buf_bar;
+ ff_vk_buf_barrier(buf_bar, ws_vk,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pBufferMemoryBarriers = buf_bar,
- .bufferMemoryBarrierCount = nb_buf_bar,
+ .pBufferMemoryBarriers = &buf_bar,
+ .bufferMemoryBarrierCount = 1,
});
- ws_vk->stage = buf_bar[0].dstStageMask;
- ws_vk->access = buf_bar[0].dstAccessMask;
/* End of denoise pass */
vk->CmdDispatch(exec->buf,
@@ -924,20 +913,14 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED);
- nb_buf_bar = 0;
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = ws_vk->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
- .srcAccessMask = ws_vk->access,
- .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = ws_vk->buf,
- .size = ws_vk->size,
- .offset = 0,
- };
-
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], ws_vk,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ TRANSFER_BIT, TRANSFER_WRITE_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], integral_vk,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pImageMemoryBarriers = img_bar,
@@ -945,8 +928,8 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- ws_vk->stage = buf_bar[0].dstStageMask;
- ws_vk->access = buf_bar[0].dstAccessMask;
+ nb_buf_bar = 0;
+ nb_img_bar = 0;
/* Buffer zeroing */
vk->CmdFillBuffer(exec->buf, ws_vk->buf, 0, ws_vk->size, 0x0);
@@ -976,10 +959,10 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
ws_vk, ws_size * s-> opts.t, ws_size * s-> opts.t,
VK_FORMAT_UNDEFINED));
+ VkPipelineStageFlagBits2 ws_stage = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
+ VkAccessFlagBits2 ws_access = VK_ACCESS_2_TRANSFER_WRITE_BIT;
do {
int wg_invoc = FFMIN((s->nb_offsets - offsets_dispatched)/TYPE_ELEMS, s->opts.t);
-
- /* Integral pipeline */
IntegralPushData pd = {
{ plane_widths[0], plane_widths[1], plane_widths[2], plane_widths[3] },
{ plane_heights[0], plane_heights[1], plane_heights[2], plane_heights[3] },
@@ -993,55 +976,68 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
desc->nb_components,
};
- ff_vk_exec_bind_shader(vkctx, exec, &s->shd_vertical);
- ff_vk_shader_update_push_const(vkctx, exec, &s->shd_vertical,
- VK_SHADER_STAGE_COMPUTE_BIT,
- 0, sizeof(pd), &pd);
-
- nb_buf_bar = 0;
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = integral_vk->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = integral_vk->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = integral_vk->buf,
- .size = integral_vk->size,
- .offset = 0,
- };
+ /* Vertical pass */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], integral_vk,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- integral_vk->stage = buf_bar[0].dstStageMask;
- integral_vk->access = buf_bar[0].dstAccessMask;
+ nb_buf_bar = 0;
- /* End of vertical pass */
+ ff_vk_exec_bind_shader(vkctx, exec, &s->shd_vertical);
+ ff_vk_shader_update_push_const(vkctx, exec, &s->shd_vertical,
+ VK_SHADER_STAGE_COMPUTE_BIT,
+ 0, sizeof(pd), &pd);
vk->CmdDispatch(exec->buf,
- FFALIGN(vkctx->output_width, s->shd_vertical.lg_size[0])/s->shd_vertical.lg_size[0],
+ FFALIGN(vkctx->output_width, s->shd_vertical.lg_size[0]) /
+ s->shd_vertical.lg_size[0],
desc->nb_components,
wg_invoc);
+ /* Horizontal pass */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], integral_vk,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ 0, VK_WHOLE_SIZE);
+ vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .pBufferMemoryBarriers = buf_bar,
+ .bufferMemoryBarrierCount = nb_buf_bar,
+ });
+ nb_buf_bar = 0;
+
ff_vk_exec_bind_shader(vkctx, exec, &s->shd_horizontal);
ff_vk_shader_update_push_const(vkctx, exec, &s->shd_horizontal,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pd), &pd);
+ vk->CmdDispatch(exec->buf,
+ FFALIGN(vkctx->output_height, s->shd_horizontal.lg_size[0]) /
+ s->shd_horizontal.lg_size[0],
+ desc->nb_components,
+ wg_invoc);
- nb_buf_bar = 0;
+ /* Weights pass */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], integral_vk,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
+ SHADER_STORAGE_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = integral_vk->stage,
+ .srcStageMask = ws_stage,
.dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = integral_vk->access,
+ .srcAccessMask = ws_access,
.dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = integral_vk->buf,
- .size = integral_vk->size,
+ .buffer = ws_vk->buf,
+ .size = ws_vk->size,
.offset = 0,
};
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
@@ -1049,16 +1045,10 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- integral_vk->stage = buf_bar[0].dstStageMask;
- integral_vk->access = buf_bar[0].dstAccessMask;
+ nb_buf_bar = 0;
+ ws_stage = buf_bar[1].dstStageMask;
+ ws_access = buf_bar[1].dstAccessMask;
- /* End of horizontal pass */
- vk->CmdDispatch(exec->buf,
- FFALIGN(vkctx->output_height, s->shd_horizontal.lg_size[0])/s->shd_horizontal.lg_size[0],
- desc->nb_components,
- wg_invoc);
-
- /* Weights pipeline */
WeightsPushData wpd = {
{ plane_widths[0], plane_widths[1], plane_widths[2], plane_widths[3] },
{ plane_heights[0], plane_heights[1], plane_heights[2], plane_heights[3] },
@@ -1075,52 +1065,15 @@ static int nlmeans_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
ws_count,
desc->nb_components,
};
-
ff_vk_exec_bind_shader(vkctx, exec, &s->shd_weights);
ff_vk_shader_update_push_const(vkctx, exec, &s->shd_weights,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(wpd), &wpd);
-
- nb_buf_bar = 0;
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = integral_vk->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = integral_vk->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = integral_vk->buf,
- .size = integral_vk->size,
- .offset = 0,
- };
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = ws_vk->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = ws_vk->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = ws_vk->buf,
- .size = ws_vk->size,
- .offset = 0,
- };
- vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pBufferMemoryBarriers = buf_bar,
- .bufferMemoryBarrierCount = nb_buf_bar,
- });
- integral_vk->stage = buf_bar[0].dstStageMask;
- integral_vk->access = buf_bar[0].dstAccessMask;
- ws_vk->stage = buf_bar[1].dstStageMask;
- ws_vk->access = buf_bar[1].dstAccessMask;
-
- /* End of weights pass */
vk->CmdDispatch(exec->buf,
- FFALIGN(vkctx->output_width, s->shd_weights.lg_size[0])/s->shd_weights.lg_size[0],
- FFALIGN(vkctx->output_height, s->shd_weights.lg_size[1])/s->shd_weights.lg_size[1],
+ FFALIGN(vkctx->output_width, s->shd_weights.lg_size[0]) /
+ s->shd_weights.lg_size[0],
+ FFALIGN(vkctx->output_height, s->shd_weights.lg_size[1]) /
+ s->shd_weights.lg_size[1],
wg_invoc * desc->nb_components);
offsets_dispatched += wg_invoc * TYPE_ELEMS;
--
2.49.1
From e6f09619ec4d35384d3035faf59ca2f2f660ea79 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Wed, 24 Dec 2025 01:08:53 +0100
Subject: [PATCH 07/10] ffv1enc_vulkan: use ff_vk_buf_barrier()
---
libavcodec/ffv1enc_vulkan.c | 220 +++++++++++++++---------------------
1 file changed, 93 insertions(+), 127 deletions(-)
diff --git a/libavcodec/ffv1enc_vulkan.c b/libavcodec/ffv1enc_vulkan.c
index 1dc6aa8e90..3f3da6bbae 100644
--- a/libavcodec/ffv1enc_vulkan.c
+++ b/libavcodec/ffv1enc_vulkan.c
@@ -414,41 +414,16 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
VK_NULL_HANDLE);
/* Add a buffer barrier between previous and current frame */
- if (!f->key_frame) {
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_data_buf->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_data_buf->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_data_buf->buf,
- .size = VK_WHOLE_SIZE,
- .offset = 0,
- };
- }
-
- if (fv->optimize_rct) {
- RET(run_rct_search(avctx, exec,
- src, src_views,
- slice_data_buf, slice_data_size));
-
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_data_buf->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_data_buf->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_data_buf->buf,
- .size = slice_data_size*f->slice_count,
- .offset = 0,
- };
- }
-
+ if (!f->key_frame)
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ 0, slice_data_size*f->slice_count);
+ else
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ 0, slice_data_size*f->slice_count);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pImageMemoryBarriers = img_bar,
@@ -457,9 +432,23 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
.bufferMemoryBarrierCount = nb_buf_bar,
});
nb_img_bar = 0;
- if (nb_buf_bar) {
- slice_data_buf->stage = buf_bar[0].dstStageMask;
- slice_data_buf->access = buf_bar[0].dstAccessMask;
+ nb_buf_bar = 0;
+
+ if (fv->optimize_rct) {
+ RET(run_rct_search(avctx, exec,
+ src, src_views,
+ slice_data_buf, slice_data_size));
+
+ /* Make sure the writes are visible to the setup shader */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ 0, slice_data_size*f->slice_count);
+ vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .pBufferMemoryBarriers = buf_bar,
+ .bufferMemoryBarrierCount = nb_buf_bar,
+ });
nb_buf_bar = 0;
}
@@ -526,87 +515,78 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
}));
}
- /* Setup shader modified the slice data buffer */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_data_buf->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_data_buf->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_data_buf->buf,
- .size = slice_data_size*f->slice_count,
- .offset = 0,
+ /* Sync between setup and reset shaders */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE_KHR,
+ 0, slice_data_size*f->slice_count);
+ /* Prepare the probabilities */
+ if (!f->key_frame)
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ slice_data_size*f->slice_count, VK_WHOLE_SIZE);
+ else
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ slice_data_size*f->slice_count, VK_WHOLE_SIZE);
+ vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .pBufferMemoryBarriers = buf_bar,
+ .bufferMemoryBarrierCount = nb_buf_bar,
+ });
+ nb_buf_bar = 0;
+
+ /* Run reset shader */
+ FFv1VkResetParameters pd_reset;
+ ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->reset,
+ 1, 0, 0,
+ slice_data_buf,
+ 0, slice_data_size*f->slice_count,
+ VK_FORMAT_UNDEFINED);
+ ff_vk_exec_bind_shader(&fv->s, exec, &fv->reset);
+ pd_reset = (FFv1VkResetParameters) {
+ .slice_state = slice_data_buf->address + f->slice_count*256,
+ .plane_state_size = plane_state_size,
+ .codec_planes = f->plane_count,
+ .key_frame = f->key_frame,
};
+ for (int i = 0; i < f->quant_table_count; i++)
+ pd_reset.context_count[i] = f->context_count[i];
- if (f->key_frame || f->version > 3) {
- FFv1VkResetParameters pd_reset;
+ ff_vk_shader_update_push_const(&fv->s, exec, &fv->reset,
+ VK_SHADER_STAGE_COMPUTE_BIT,
+ 0, sizeof(pd_reset), &pd_reset);
+ vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices,
+ f->plane_count);
- ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->reset,
- 1, 0, 0,
- slice_data_buf,
- 0, slice_data_size*f->slice_count,
- VK_FORMAT_UNDEFINED);
+ /* Sync between reset and encode shaders */
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ 0, slice_data_size*f->slice_count);
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, SHADER_WRITE_BIT,
+ slice_data_size*f->slice_count, VK_WHOLE_SIZE);
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], results_data_buf,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], out_data_buf,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
- /* Run setup shader */
- ff_vk_exec_bind_shader(&fv->s, exec, &fv->reset);
- pd_reset = (FFv1VkResetParameters) {
- .slice_state = slice_data_buf->address + f->slice_count*256,
- .plane_state_size = plane_state_size,
- .codec_planes = f->plane_count,
- .key_frame = f->key_frame,
- };
- for (int i = 0; i < f->quant_table_count; i++)
- pd_reset.context_count[i] = f->context_count[i];
-
- ff_vk_shader_update_push_const(&fv->s, exec, &fv->reset,
- VK_SHADER_STAGE_COMPUTE_BIT,
- 0, sizeof(pd_reset), &pd_reset);
-
- /* Sync between setup and reset shaders */
- vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .pBufferMemoryBarriers = buf_bar,
- .bufferMemoryBarrierCount = nb_buf_bar,
- });
- slice_data_buf->stage = buf_bar[0].dstStageMask;
- slice_data_buf->access = buf_bar[0].dstAccessMask;
- nb_buf_bar = 0;
-
- vk->CmdDispatch(exec->buf, fv->ctx.num_h_slices, fv->ctx.num_v_slices,
- f->plane_count);
- }
-
- /* If the reset shader ran, insert a barrier now. */
- if (f->key_frame || f->version > 3) {
- /* Reset shader modified the slice data buffer */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = slice_data_buf->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = slice_data_buf->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT |
- VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = slice_data_buf->buf,
- .size = slice_data_buf->size - slice_data_size*f->slice_count,
- .offset = slice_data_size*f->slice_count,
- };
- }
-
- if (fv->is_rgb) {
+ if (fv->is_rgb)
ff_vk_frame_barrier(&fv->s, exec, tmp, img_bar, &nb_img_bar,
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED);
- }
- /* Final barrier before encoding */
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pImageMemoryBarriers = img_bar,
@@ -615,11 +595,7 @@ static int vulkan_encode_ffv1_submit_frame(AVCodecContext *avctx,
.bufferMemoryBarrierCount = nb_buf_bar,
});
nb_img_bar = 0;
- if (nb_buf_bar) {
- slice_data_buf->stage = buf_bar[0].dstStageMask;
- slice_data_buf->access = buf_bar[0].dstAccessMask;
- nb_buf_bar = 0;
- }
+ nb_buf_bar = 0;
/* Main encode shader */
ff_vk_shader_update_desc_buffer(&fv->s, exec, &fv->enc,
@@ -705,25 +681,15 @@ static int transfer_slices(AVCodecContext *avctx,
mapped_ref = NULL; /* Ownership passed */
/* Ensure the output buffer is finished */
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = out_data_buf->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
- .srcAccessMask = out_data_buf->access,
- .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = out_data_buf->buf,
- .size = VK_WHOLE_SIZE,
- .offset = 0,
- };
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], out_data_buf,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ TRANSFER_BIT, TRANSFER_READ_BIT, NONE_KHR,
+ 0, VK_WHOLE_SIZE);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pBufferMemoryBarriers = buf_bar,
.bufferMemoryBarrierCount = nb_buf_bar,
});
- out_data_buf->stage = buf_bar[0].dstStageMask;
- out_data_buf->access = buf_bar[0].dstAccessMask;
nb_buf_bar = 0;
for (int i = 0; i < nb_regions; i++)
--
2.49.1
From 2226b5d0386c3ca7239220cb1e9afbf0c305d625 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Wed, 24 Dec 2025 01:27:59 +0100
Subject: [PATCH 08/10] vulkan_prores: use ff_vk_buf_barrier()
---
libavcodec/vulkan_prores.c | 44 +++++++++++---------------------------
1 file changed, 12 insertions(+), 32 deletions(-)
diff --git a/libavcodec/vulkan_prores.c b/libavcodec/vulkan_prores.c
index afea8857e8..7e7c2ace9c 100644
--- a/libavcodec/vulkan_prores.c
+++ b/libavcodec/vulkan_prores.c
@@ -250,27 +250,17 @@ static int vk_prores_end_frame(AVCodecContext *avctx)
/* Input barrier, or synchronization between clear and vld shader */
ff_vk_frame_barrier(&ctx->s, exec, f, img_bar, &nb_img_bar,
- pr->first_field ? VK_PIPELINE_STAGE_2_CLEAR_BIT : VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
+ pr->first_field ? VK_PIPELINE_STAGE_2_CLEAR_BIT :
+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED);
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = metadata->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = metadata->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = metadata->buf,
- .offset = pp->slice_offsets_sz,
- .size = pp->mb_params_sz,
- };
- metadata->stage = buf_bar[0].dstStageMask;
- metadata->access = buf_bar[0].dstAccessMask;
-
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], metadata,
+ ALL_COMMANDS_BIT, NONE_KHR, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ pp->slice_offsets_sz, pp->mb_params_sz);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pBufferMemoryBarriers = buf_bar,
@@ -302,7 +292,8 @@ static int vk_prores_end_frame(AVCodecContext *avctx)
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(pd), &pd);
- vk->CmdDispatch(exec->buf, AV_CEIL_RSHIFT(pr->slice_count / pr->mb_height, 3), AV_CEIL_RSHIFT(pr->mb_height, 3),
+ vk->CmdDispatch(exec->buf, AV_CEIL_RSHIFT(pr->slice_count / pr->mb_height, 3),
+ AV_CEIL_RSHIFT(pr->mb_height, 3),
3 + !!pr->alpha_info);
/* Synchronize vld and idct shaders */
@@ -313,21 +304,10 @@ static int vk_prores_end_frame(AVCodecContext *avctx)
VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED);
- buf_bar[nb_buf_bar++] = (VkBufferMemoryBarrier2) {
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
- .srcStageMask = metadata->stage,
- .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
- .srcAccessMask = metadata->access,
- .dstAccessMask = VK_ACCESS_2_SHADER_STORAGE_READ_BIT,
- .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
- .buffer = metadata->buf,
- .offset = pp->slice_offsets_sz,
- .size = pp->mb_params_sz,
- };
- metadata->stage = buf_bar[0].dstStageMask;
- metadata->access = buf_bar[0].dstAccessMask;
-
+ ff_vk_buf_barrier(buf_bar[nb_buf_bar++], metadata,
+ COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE_KHR,
+ COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE_KHR,
+ pp->slice_offsets_sz, pp->mb_params_sz);
vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
.pBufferMemoryBarriers = buf_bar,
--
2.49.1
From 16e217541b4fec616b52b95e082f77513433be15 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Tue, 23 Dec 2025 19:08:04 +0100
Subject: [PATCH 09/10] vulkan: remove FFVkBuffer.stage and access
Keeping global state for every buffer is unncessary and possibly
suboptimal.
---
libavutil/vulkan.c | 2 --
libavutil/vulkan.h | 4 ----
2 files changed, 6 deletions(-)
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index d4ac1544d1..33d7e8aace 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -1309,8 +1309,6 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool,
return AVERROR(ENOMEM);
data = (FFVkBuffer *)ref->data;
- data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
- data->access = VK_ACCESS_2_NONE;
if (data->size >= size)
return 0;
diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 115e9fc940..cde2876e46 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -91,10 +91,6 @@ typedef struct FFVkBuffer {
size_t size;
VkDeviceAddress address;
- /* Local use only */
- VkPipelineStageFlags2 stage;
- VkAccessFlags2 access;
-
/* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE or
* via ff_vk_host_map_buffer */
uint8_t *mapped_mem;
--
2.49.1
From 5a7e16ce2df5b9bcf6bde0fedbec39cbcf7f1f36 Mon Sep 17 00:00:00 2001
From: Lynne <dev(a)lynne.ee>
Date: Wed, 24 Dec 2025 04:10:39 +0100
Subject: [PATCH 10/10] prores_raw_idct: use the same prores_idct method for
copying coeffs
This saves 2 barriers.
---
libavcodec/vulkan/prores_raw_idct.comp | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/libavcodec/vulkan/prores_raw_idct.comp b/libavcodec/vulkan/prores_raw_idct.comp
index ffd71d1d73..c9850d17d7 100644
--- a/libavcodec/vulkan/prores_raw_idct.comp
+++ b/libavcodec/vulkan/prores_raw_idct.comp
@@ -63,30 +63,32 @@ void main(void)
uint8_t qmat_buf[64] = qmat;
[[unroll]]
- for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x) {
- int v = int(imageLoad(dst, offs + 2*ivec2(BLOCK_ID*8, 0) + scan[i])[0]);
+ for (uint y = 0; y < 8; y++) {
+ uint block_off = y*8 + ROW_ID;
+ int v = int(imageLoad(dst, offs + 2*ivec2(BLOCK_ID*8, 0) + scan[block_off])[0]);
float vf = float(sign_extend(v, 16)) / 32768.0;
- vf *= qmat_buf[i] * qscale;
- blocks[BLOCK_ID][COMP_ID*64 + i] = (vf / (64*4.56)) *
- idct_scale[i];
+ vf *= qmat_buf[block_off] * qscale;
+ blocks[BLOCK_ID][COMP_ID*72 + y*9 + ROW_ID] = (vf / (64*4.56)) *
+ idct_scale[block_off];
}
+ /* Column-wise iDCT */
+ idct8(BLOCK_ID, COMP_ID*72 + ROW_ID, 9);
barrier();
- idct8(BLOCK_ID, COMP_ID*64 + ROW_ID*8, 1);
- blocks[BLOCK_ID][COMP_ID*64 + ROW_ID] += 0.5;
+ blocks[BLOCK_ID][COMP_ID*72 + ROW_ID * 9] += 0.5f;
+ /* Row-wise iDCT */
+ idct8(BLOCK_ID, COMP_ID*72 + ROW_ID * 9, 1);
barrier();
- idct8(BLOCK_ID, COMP_ID*64 + ROW_ID, 8);
- barrier();
[[unroll]]
- for (uint i = gl_LocalInvocationID.x; i < 64; i += gl_WorkGroupSize.x) {
- int v = int(round(blocks[BLOCK_ID][COMP_ID*64 + i]*4095.0));
+ for (uint y = 0; y < 8; y++) {
+ int v = int(round(blocks[BLOCK_ID][COMP_ID*72 + y*9 + ROW_ID]*4095.0));
v = clamp(v, 0, 4095);
v <<= 4;
imageStore(dst,
- offs + 2*ivec2(BLOCK_ID*8 + (i & 7), i >> 3),
+ offs + 2*ivec2(BLOCK_ID*8 + ROW_ID, y),
ivec4(v));
}
}
--
2.49.1
1
0
[PATCH] avfilter/src_movie: fix support multiple frames per packet (PR #21318)
by ngaullier 30 Dec '25
by ngaullier 30 Dec '25
30 Dec '25
PR #21318 opened by ngaullier
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21318
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21318.patch
Fixes #20827.
Signed-off-by: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
From 26ac8a2c0719c3cc60e9d965b6021a314e219e24 Mon Sep 17 00:00:00 2001
From: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
Date: Mon, 29 Dec 2025 18:51:01 +0100
Subject: [PATCH] avfilter/src_movie: fix support multiple frames per packet
Fixes #20827.
Signed-off-by: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
---
libavfilter/src_movie.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index adb21e019e..ae2e74c1b6 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -519,7 +519,7 @@ static int decode_packet(AVFilterContext *ctx, int i)
AVCodecContext *dec = movie->st[i].codec_ctx;
AVFrame *frame = movie->st[i].frame;
AVPacket *pkt = movie->pkt;
- int ret = 0;
+ int ret = 0, has_frame = 0;
// submit the packet to the decoder
if (!movie->eof) {
@@ -529,15 +529,16 @@ static int decode_packet(AVFilterContext *ctx, int i)
}
// get all the available frames from the decoder
- if (ret >= 0) {
+ while (ret >= 0) {
ret = avcodec_receive_frame(dec, frame);
if (ret < 0) {
// those two return values are special and mean there is no output
// frame available, but there were no errors during decoding
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
- return 0;
+ return has_frame;
return ret;
}
+ has_frame |= 1;
frame->pts = frame->best_effort_timestamp;
if (frame->pts != AV_NOPTS_VALUE) {
@@ -558,8 +559,6 @@ static int decode_packet(AVFilterContext *ctx, int i)
ret = ff_filter_frame(outlink, av_frame_clone(frame));
if (ret < 0)
return ret;
- if (ret == 0)
- return 1;
}
return 0;
--
2.49.1
1
0
Hi FFmpeg maintainers,
I’m Sara, a member of the open source team at Spotify, along with Dave
Zolotusky, Principal Engineer. In 2022, we started the Spotify FOSS Fund
<https://engineering.atspotify.com/2024/11/congratulations-to-the-recipients…>
as
a way of giving back to the open source community and to provide
maintainers with funds that will allow them to continue the maintenance of
their projects. Recipients were nominated and voted on by Spotify employees
and selected by an internal committee.
We’re excited to let you know that FFmpeg has been selected as a recipient
of the 2025 Spotify FOSS Fund!
We are in the process of providing you, the maintainers, with 30,000 Euros
to put towards maintaining and continuing the success of FFmpeg. We will be
announcing the winners on our public Spotify channels by the end of January
2026. For the purposes of our announcement, could you provide responses to
any of the following questions:
-
What is the vision for the project?
-
How will these funds go toward supporting the future of the project?
-
What kind of impact do you think FOSS funds have on the open source
ecosystem in general? Is any amount welcome? In addition to the money, does
exposure from the fund provide value, as well?
-
What are other ways you think the community and/or companies can better
support open source?
Thank you for your work and congratulations!
Best,
Sara
4
3
[PATCH] lavc/vvc: Prevent OOB write to slice_top_left_ctu_x in PPS CBS (PR #21317)
by frankplow 29 Dec '25
by frankplow 29 Dec '25
29 Dec '25
PR #21317 opened by frankplow
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21317
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21317.patch
Prior to the fix, in the case of a tile containing multiple slices
(pps_num_exp_slices_in_tile != 0) the number of slices was temporarily
allowed to exceed pps_num_slices_in_pic_minus1+1 and therefore
VVC_MAX_SLICES. The number of slices was later verified, but while the
current slice index was higher than expected it was used to write to a
array of size VVC_MAX_SLICES, leading to an OOB write.
To rectify this, the patch adds some checks at an earlier stage, to
ensure that the slice index i + j at no point exceeds
pps_num_slices_in_pic_minus1.
Fixes #YWH-PGM40646-30
From 65574e151d92613cda0f8861f71de891c0e060b9 Mon Sep 17 00:00:00 2001
From: Frank Plowman <post(a)frankplowman.com>
Date: Mon, 29 Dec 2025 22:14:53 +0000
Subject: [PATCH] lavc/vvc: Prevent OOB write to slice_top_left_ctu_x in PPS
CBS
Prior to the fix, in the case of a tile containing multiple slices
(pps_num_exp_slices_in_tile != 0) the number of slices was temporarily
allowed to exceed pps_num_slices_in_pic_minus1+1 and therefore
VVC_MAX_SLICES. The number of slices was later verified, but while the
current slice index was higher than expected it was used to write to a
array of size VVC_MAX_SLICES, leading to an OOB write.
To rectify this, the patch adds some checks at an earlier stage, to
ensure that the slice index i + j at no point exceeds
pps_num_slices_in_pic_minus1.
Fixes #YWH-PGM40646-30
---
libavcodec/cbs_h266_syntax_template.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c
index d9a65a9c19..4f6ae76e27 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -2011,6 +2011,12 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw,
slice_top_left_ctu_y[i] = ctu_y;
} else {
uint16_t slice_height_in_ctus;
+ int num_uniform_slices;
+
+ if (i + current->pps_num_exp_slices_in_tile[i] >
+ current->pps_num_slices_in_pic_minus1 + 1)
+ return AVERROR_INVALIDDATA;
+
for (j = 0; j < current->pps_num_exp_slices_in_tile[i];
j++) {
ues(pps_exp_slice_height_in_ctus_minus1[i][j], 0,
@@ -2031,6 +2037,13 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw,
uniform_slice_height = 1 +
(j == 0 ? current->row_height_val[tile_y] - 1:
current->pps_exp_slice_height_in_ctus_minus1[i][j-1]);
+
+ num_uniform_slices = (remaining_height_in_ctbs_y + uniform_slice_height - 1)
+ / uniform_slice_height;
+ if (i + current->pps_num_exp_slices_in_tile[i] + num_uniform_slices >
+ current->pps_num_slices_in_pic_minus1 + 1)
+ return AVERROR_INVALIDDATA;
+
while (remaining_height_in_ctbs_y > uniform_slice_height) {
current->slice_height_in_ctus[i + j] =
uniform_slice_height;
--
2.49.1
1
0
[PATCH] avcodec/av1dec: fix handling of frame size and format changes (PR #21316)
by cgutman 29 Dec '25
by cgutman 29 Dec '25
29 Dec '25
PR #21316 opened by cgutman
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21316
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21316.patch
`ff_get_format()` must be called to reinitialize the hwaccel when the pixel format or frame size changes.
This also fixes a bug where `ff_get_format()` was never called when `AVCodecContext.pix_fmt` was initialized by the user.
This PR supersedes #20720 and fixes a regression introduced by 194414f.
From 87ac3d092472db9676a8075a681194308554fb37 Mon Sep 17 00:00:00 2001
From: Cameron Gutman <aicommander(a)gmail.com>
Date: Mon, 29 Dec 2025 14:19:37 -0600
Subject: [PATCH] avcodec/av1dec: fix handling of frame size and format changes
ff_get_format() must be called to reinitialize the hwaccel when the
pixel format or frame size changes.
This also fixes a bug where ff_get_format() was never called when
AVCodecContext.pix_fmt was initialized by the user.
Signed-off-by: Cameron Gutman <aicommander(a)gmail.com>
---
libavcodec/av1dec.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index 1dffc7c1b9..6b278dc958 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -656,12 +656,6 @@ static int get_pixel_format(AVCodecContext *avctx)
*fmtp++ = pix_fmt;
*fmtp = AV_PIX_FMT_NONE;
- for (int i = 0; pix_fmts[i] != pix_fmt; i++)
- if (pix_fmts[i] == avctx->pix_fmt) {
- s->pix_fmt = pix_fmt;
- return 1;
- }
-
ret = ff_get_format(avctx, pix_fmts);
/**
@@ -768,6 +762,7 @@ static av_cold int av1_decode_free(AVCodecContext *avctx)
static int set_context_with_sequence(AVCodecContext *avctx,
const AV1RawSequenceHeader *seq)
{
+ AV1DecContext *s = avctx->priv_data;
int width = seq->max_frame_width_minus_1 + 1;
int height = seq->max_frame_height_minus_1 + 1;
@@ -804,7 +799,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
int ret = ff_set_dimensions(avctx, width, height);
if (ret < 0)
return ret;
- }
+ s->pix_fmt = AV_PIX_FMT_NONE;
+ } else if (s->pix_fmt != get_sw_pixel_format(avctx, seq))
+ s->pix_fmt = AV_PIX_FMT_NONE;
if (seq->timing_info_present_flag)
avctx->framerate = ff_av1_framerate(1LL + seq->timing_info.num_ticks_per_picture_minus_1,
@@ -820,6 +817,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
static int update_context_with_frame_header(AVCodecContext *avctx,
const AV1RawFrameHeader *header)
{
+ AV1DecContext *s = avctx->priv_data;
AVRational aspect_ratio;
int width = header->frame_width_minus_1 + 1;
int height = header->frame_height_minus_1 + 1;
@@ -831,6 +829,7 @@ static int update_context_with_frame_header(AVCodecContext *avctx,
ret = ff_set_dimensions(avctx, width, height);
if (ret < 0)
return ret;
+ s->pix_fmt = AV_PIX_FMT_NONE;
}
av_reduce(&aspect_ratio.num, &aspect_ratio.den,
@@ -924,12 +923,6 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f)
AVFrame *frame;
int ret;
- ret = update_context_with_frame_header(avctx, header);
- if (ret < 0) {
- av_log(avctx, AV_LOG_ERROR, "Failed to update context with frame header\n");
- return ret;
- }
-
ret = ff_progress_frame_get_buffer(avctx, &f->pf, AV_GET_BUFFER_FLAG_REF);
if (ret < 0)
goto fail;
@@ -1234,6 +1227,12 @@ static int get_current_frame(AVCodecContext *avctx)
avctx->skip_frame >= AVDISCARD_ALL)
return 0;
+ ret = update_context_with_frame_header(avctx, s->raw_frame_header);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to update context with frame header\n");
+ return ret;
+ }
+
if (s->pix_fmt == AV_PIX_FMT_NONE) {
ret = get_pixel_format(avctx);
if (ret < 0) {
@@ -1317,8 +1316,6 @@ static int av1_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
s->operating_point_idc = s->raw_seq->operating_point_idc[s->operating_point];
- s->pix_fmt = AV_PIX_FMT_NONE;
-
if (FF_HW_HAS_CB(avctx, decode_params)) {
ret = FF_HW_CALL(avctx, decode_params, AV1_OBU_SEQUENCE_HEADER,
s->seq_data_ref->data, s->seq_data_ref->size);
--
2.49.1
1
0
[PATCH] Revert "avcodec/jpeglsdec: Check get_bits_left() before decoding a picture" (PR #21315)
by Ramiro Polla 29 Dec '25
by Ramiro Polla 29 Dec '25
29 Dec '25
PR #21315 opened by Ramiro Polla (ramiro)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21315
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21315.patch
This check has been made redundant by f80224ed19a and fe7fbf3a227.
This reverts commit 4bc3008d04451cd31818e21703ed7ed96b6ff074.
From a46cc099244aae039cf1f2742152e7bff9023591 Mon Sep 17 00:00:00 2001
From: Ramiro Polla <ramiro.polla(a)gmail.com>
Date: Mon, 29 Dec 2025 20:03:10 +0100
Subject: [PATCH] Revert "avcodec/jpeglsdec: Check get_bits_left() before
decoding a picture"
This check has been made redundant by f80224ed19a and fe7fbf3a227.
This reverts commit 4bc3008d04451cd31818e21703ed7ed96b6ff074.
---
libavcodec/jpeglsdec.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c
index 5f463c9660..39f50a263e 100644
--- a/libavcodec/jpeglsdec.c
+++ b/libavcodec/jpeglsdec.c
@@ -418,10 +418,6 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near,
av_log(s->avctx, AV_LOG_DEBUG, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n",
ilv, point_transform, s->bits, s->cur_scan);
}
- if (get_bits_left(&s->gb) < s->height) {
- ret = AVERROR_INVALIDDATA;
- goto end;
- }
if (ilv == 0) { /* separate planes */
if (s->cur_scan > s->nb_components) {
ret = AVERROR_INVALIDDATA;
--
2.49.1
1
0
[PATCH] avutil/opt: fix av_opt_is_set_to_default() for array options with no default value (PR #21314)
by James Almer 29 Dec '25
by James Almer 29 Dec '25
29 Dec '25
PR #21314 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21314
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21314.patch
If `AVOptionArrayDef.def` is `NULL`, `av_opt_is_set_to_default` should return true when the field in the object is `NULL`.
From fcdd5c49ed82c74f681fb6a2312c4a28206f6e55 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Mon, 29 Dec 2025 15:48:51 -0300
Subject: [PATCH 1/2] avutil/opt: fix av_opt_is_set_to_default() for array
options with no default value
If AVOptionArrayDef.def is NULL, av_opt_is_set_to_default() should return true
when the field in the object is NULL.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavutil/opt.c | 2 ++
tests/ref/fate/opt | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/libavutil/opt.c b/libavutil/opt.c
index fc5834e168..911e064914 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -2602,6 +2602,8 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o)
ret = 0;
else if (val)
ret = !strcmp(val, def);
+ else
+ ret = 1;
av_freep(&val);
diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt
index 1f82f7e4bd..04e787f01d 100644
--- a/tests/ref/fate/opt
+++ b/tests/ref/fate/opt
@@ -86,7 +86,7 @@ name: bool2 default:0 error:
name: bool3 default:1 error:
name: dict1 default:1 error:
name: dict2 default:0 error:
-name: array_int default:0 error:
+name: array_int default:1 error:
name: array_str default:0 error:
name:array_dict default:0 error:
name: num default:1 error:
@@ -117,7 +117,7 @@ name: bool2 default:1 error:
name: bool3 default:1 error:
name: dict1 default:1 error:
name: dict2 default:1 error:
-name: array_int default:0 error:
+name: array_int default:1 error:
name: array_str default:1 error:
name:array_dict default:1 error:
@@ -191,7 +191,7 @@ Setting entry with key 'array_int' to value ''
Setting entry with key 'array_str' to value 'str0|str\|1|str\\2'
Setting entry with key 'array_dict' to value 'k00=v\\\\00:k01=v\,01,k10=v\\=1\\:0'
num=0,unum=2147483648,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=4294967296,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-),array_int=,array_str=str0|str\\|1|str\\\\2,array_dict=k00\=v\\\\\\\\00:k01\=v\\\,01\,k10\=v\\\\\=1\\\\:0
-child_num=0,flt=0.333333,dbl=0.333333,array_int=
+child_num=0,flt=0.333333,dbl=0.333333
Testing av_set_options_string()
Setting options string ''
--
2.49.1
From 83d3bd3e56edfa7b2ac8404ef9702a888e07999f Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Mon, 29 Dec 2025 16:04:25 -0300
Subject: [PATCH 2/2] avutil/iamf: remove default value from
demixing_matrix_def
It's not required sice the previous commit, and fixes memleaks introduced by
a6e5fa3fbb5562f14a666964b77cb7560e1a92cd.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavutil/iamf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavutil/iamf.c b/libavutil/iamf.c
index c18069220e..ea0c87428f 100644
--- a/libavutil/iamf.c
+++ b/libavutil/iamf.c
@@ -239,7 +239,7 @@ AVIAMFParamDefinition *av_iamf_param_definition_alloc(enum AVIAMFParamDefinition
//
// Audio Element
//
-static const AVOptionArrayDef demixing_matrix_def = { .def = "0|0", .size_max = (255 + 255) * 255, .sep = '|' };
+static const AVOptionArrayDef demixing_matrix_def = { .size_max = (255 + 255) * 255, .sep = '|' };
#undef OFFSET
#define OFFSET(x) offsetof(AVIAMFLayer, x)
--
2.49.1
1
0