Re: [FFmpeg-devel] [PATCH WIP 01/10] ffbuild/bin2c: Use zlib directly instead of gzip

2025-06-10 Thread softworkz .



> -Original Message-
> From: ffmpeg-devel  On Behalf Of
> Andreas Rheinhardt
> Sent: Dienstag, 3. Juni 2025 16:34
> To: ffmpeg-devel@ffmpeg.org
> Subject: Re: [FFmpeg-devel] [PATCH WIP 01/10] ffbuild/bin2c: Use zlib
> directly instead of gzip
> 

Hi Andreas,

thinking about the direction of this patchset, I came to this idea:

How about ditching zlib altogether for this and replace it with some 
compact compression code right away?

Something like these might be suitable:

https://github.com/ariya/FastLZ/blob/master/fastlz.c
https://github.com/richgel999/miniz/blob/master/miniz.c
(licenses should be compatible for including the code)


This would solve both problems:

- zlib detection during build
- zlib being unavailable at runtime when linked dynamically


How do you think about this?

I think it wouldn't matter when the compression is slightly less effective..

Best regards
sw

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Michael Niedermayer
Hi Pavel

On Tue, Jun 10, 2025 at 11:27:37AM -0600, Pavel Koshevoy wrote:
> On Tue, Jun 10, 2025 at 9:29 AM Michael Niedermayer 
[...]

> I have never had any intention of introducing a
> security vulnerability.

do you agree that the patch should be reverted ?
(and also the 2 backports of it)


> If people want to keep this, it should be behind a flag and
> > disabled by default.
> 
> 
> I am not familiar with such flags ... are you suggesting a compile-time
> flag, or a run-time flag?
> A runtime flag would be preferable, because that would save me from having
> to cross-compile win64 ffmpeg libs myself.

runtime


> 
> 
> Its not enough to fix our code that crashes, other applications
> > similarly wont expect such id and type changes mid stream
> 
> 
> IDK how likely a media type change is outside the 1_poc.mp4.

100% likelyness an exploit of this will use it


> The sample
> files I have don't do that.

Your sample files are not exploits i assume. So obviously
they dont


> I can provide a 61MB clip of one such file, just a few seconds of SDR mpeg2
> video/audio slate followed by a few seconds of HDR10 hevc video and eac3
> audio... in case someone wants to work on making fftools support this.

This file certainly is valuable and should be added to samples.ffmpeg.org

BUT this security issue needs to be fixed, regardless of
anyone adding support for such samples

I dont think backporting midstream codec_id/type changes is a good
idea btw.

IMHO this should all be reverted (its a small 3 line patch)
and then again start from scratch with review, testing, fuzzing, and
runtime flag.

PS: The researcher also wants a CVE# for this issue.

thx

[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

What is money laundering? Its paying someone and not telling the government.


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 2/3] avutil/aes: remove superfluous rounds argument

2025-06-10 Thread James Almer
It's set during int and never changed.

Signed-off-by: James Almer 
---
 libavutil/aes.c  | 10 +-
 libavutil/aes_internal.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavutil/aes.c b/libavutil/aes.c
index 3c8ac1c349..7fe42a5548 100644
--- a/libavutil/aes.c
+++ b/libavutil/aes.c
@@ -137,10 +137,10 @@ static inline void aes_crypt(AVAES *a, int s, const 
uint8_t *sbox,
 }
 
 static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
-int count, uint8_t *iv, int rounds)
+int count, uint8_t *iv)
 {
 while (count--) {
-addkey_s(&a->state[1], src, &a->round_key[rounds]);
+addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
 if (iv)
 addkey_s(&a->state[1], iv, &a->state[1]);
 aes_crypt(a, 2, sbox, enc_multbl);
@@ -153,10 +153,10 @@ static void aes_encrypt(AVAES *a, uint8_t *dst, const 
uint8_t *src,
 }
 
 static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
-int count, uint8_t *iv, int rounds)
+int count, uint8_t *iv)
 {
 while (count--) {
-addkey_s(&a->state[1], src, &a->round_key[rounds]);
+addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
 aes_crypt(a, 0, inv_sbox, dec_multbl);
 if (iv) {
 addkey_s(&a->state[0], iv, &a->state[0]);
@@ -171,7 +171,7 @@ static void aes_decrypt(AVAES *a, uint8_t *dst, const 
uint8_t *src,
 void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src,
   int count, uint8_t *iv, int decrypt)
 {
-a->crypt(a, dst, src, count, iv, a->rounds);
+a->crypt(a, dst, src, count, iv);
 }
 
 static void init_multbl2(uint32_t tbl[][256], const int c[4],
diff --git a/libavutil/aes_internal.h b/libavutil/aes_internal.h
index 17f79d3ce3..e2de382f26 100644
--- a/libavutil/aes_internal.h
+++ b/libavutil/aes_internal.h
@@ -37,7 +37,7 @@ typedef struct AVAES {
 DECLARE_ALIGNED(16, av_aes_block, round_key)[15];
 DECLARE_ALIGNED(16, av_aes_block, state)[2];
 int rounds;
-void (*crypt)(struct AVAES *a, uint8_t *dst, const uint8_t *src, int 
count, uint8_t *iv, int rounds);
+void (*crypt)(struct AVAES *a, uint8_t *dst, const uint8_t *src, int 
count, uint8_t *iv);
 } AVAES;
 
 void ff_init_aes_x86(AVAES *a, int decrypt);
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 1/3] avutil/aes_ctr: rename AES_BLOCK_SIZE to FF_AES_BLOCK_SIZE

2025-06-10 Thread James Almer
This is in preparation for the following commit, to prevent redefinitions from
namespace collisions.

Signed-off-by: James Almer 
---
 libavutil/aes_ctr.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c
index 63dcb20d3a..76333ede33 100644
--- a/libavutil/aes_ctr.c
+++ b/libavutil/aes_ctr.c
@@ -29,11 +29,11 @@
 #include "mem.h"
 #include "random_seed.h"
 
-#define AES_BLOCK_SIZE (16)
+#define FF_AES_BLOCK_SIZE (16)
 
 typedef struct AVAESCTR {
-DECLARE_ALIGNED(8, uint8_t, counter)[AES_BLOCK_SIZE];
-DECLARE_ALIGNED(8, uint8_t, encrypted_counter)[AES_BLOCK_SIZE];
+DECLARE_ALIGNED(8, uint8_t, counter)[FF_AES_BLOCK_SIZE];
+DECLARE_ALIGNED(8, uint8_t, encrypted_counter)[FF_AES_BLOCK_SIZE];
 AVAES aes;
 } AVAESCTR;
 
@@ -96,19 +96,19 @@ void av_aes_ctr_increment_iv(struct AVAESCTR *a)
 
 void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, 
int count)
 {
-while (count >= AES_BLOCK_SIZE) {
+while (count >= FF_AES_BLOCK_SIZE) {
 av_aes_crypt(&a->aes, a->encrypted_counter, a->counter, 1, NULL, 0);
 av_aes_ctr_increment_be64(a->counter + 8);
 #if HAVE_FAST_64BIT
-for (int len = 0; len < AES_BLOCK_SIZE; len += 8)
+for (int len = 0; len < FF_AES_BLOCK_SIZE; len += 8)
 AV_WN64(&dst[len], AV_RN64(&src[len]) ^ 
AV_RN64A(&a->encrypted_counter[len]));
 #else
-for (int len = 0; len < AES_BLOCK_SIZE; len += 4)
+for (int len = 0; len < FF_AES_BLOCK_SIZE; len += 4)
 AV_WN32(&dst[len], AV_RN32(&src[len]) ^ 
AV_RN32A(&a->encrypted_counter[len]));
 #endif
-dst += AES_BLOCK_SIZE;
-src += AES_BLOCK_SIZE;
-count -= AES_BLOCK_SIZE;
+dst += FF_AES_BLOCK_SIZE;
+src += FF_AES_BLOCK_SIZE;
+count -= FF_AES_BLOCK_SIZE;
 }
 
 if (count > 0) {
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 3/3] avutil/aes: add an OpenSSL-libcrypto backed implementation

2025-06-10 Thread James Almer
OpenSSL has optimizations for more architectures than x86-AESNI, so use it if
libavutil is configured with libcrypto explicitly (Enabling OpenSSL alone will
not make use of it).

Signed-off-by: James Almer 
---
 configure|  8 +++-
 libavutil/aes.c  | 37 ++---
 libavutil/aes_internal.h | 11 ++-
 libavutil/x86/aes_init.c |  2 ++
 4 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 534b443f7d..c7b4fbb2fe 100755
--- a/configure
+++ b/configure
@@ -223,6 +223,7 @@ External library support:
   --enable-libcelt enable CELT decoding via libcelt [no]
   --enable-libcdio enable audio CD grabbing with libcdio [no]
   --enable-libcodec2   enable codec2 en/decoding using libcodec2 [no]
+  --enable-libcrypto   enable crypto via libcrypto (AES only) [no]
   --enable-libdav1denable AV1 decoding via libdav1d [no]
   --enable-libdavs2enable AVS2 decoding via libdavs2 [no]
   --enable-libdc1394   enable IIDC-1394 grabbing using libdc1394
@@ -1931,6 +1932,7 @@ EXTERNAL_LIBRARY_LIST="
 libcaca
 libcelt
 libcodec2
+libcrypto
 libdav1d
 libdc1394
 libflite
@@ -4091,7 +4093,7 @@ avfilter_deps="avutil"
 avfilter_suggest="libm stdatomic spirv_compiler"
 avformat_deps="avcodec avutil"
 avformat_suggest="libm network zlib stdatomic"
-avutil_suggest="clock_gettime ffnvcodec gcrypt libm libdrm libmfx opencl 
openssl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia 
bcrypt stdatomic"
+avutil_suggest="clock_gettime ffnvcodec gcrypt libcrypto libm libdrm libmfx 
opencl openssl user32 vaapi vulkan videotoolbox corefoundation corevideo 
coremedia bcrypt stdatomic"
 swresample_deps="avutil"
 swresample_suggest="libm libsoxr stdatomic"
 swscale_deps="avutil"
@@ -7193,6 +7195,10 @@ enabled openssl   && { { check_pkg_config 
openssl "openssl >= 3.0.0" ope
check_lib openssl openssl/ssl.h 
SSL_library_init -lssl32 -leay32 ||
check_lib openssl openssl/ssl.h 
SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
die "ERROR: openssl not found"; }
+enabled libcrypto && { { check_pkg_config libcrypto "libcrypto >= 
3.0.0" openssl/aes.h AES_set_encrypt_key &&
+ { enabled gplv3 || ! enabled gpl || enabled 
nonfree || die "ERROR: OpenSSL-libcrypto >= 3.0.0 requires --enable-version3"; 
}; } ||
+   { enabled gpl && ! enabled nonfree && die 
"ERROR: OpenSSL-libcrypto < 3.0.0 is incompatible with the gpl"; } ||
+   require_pkg_config libcrypto libcrypto 
openssl/aes.h AES_set_encrypt_key; }
 enabled pocketsphinx  && require_pkg_config pocketsphinx pocketsphinx 
pocketsphinx/pocketsphinx.h ps_init
 enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp  
rockchip/rk_mpi.h mpp_create &&
require_pkg_config rockchip_mpp "rockchip_mpp 
>= 1.3.7" rockchip/rk_mpi.h mpp_create &&
diff --git a/libavutil/aes.c b/libavutil/aes.c
index 7fe42a5548..3a0d4e1385 100644
--- a/libavutil/aes.c
+++ b/libavutil/aes.c
@@ -39,6 +39,7 @@ struct AVAES *av_aes_alloc(void)
 return av_mallocz(sizeof(struct AVAES));
 }
 
+#if !CONFIG_LIBCRYPTO
 static const uint8_t rcon[10] = {
 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
 };
@@ -137,7 +138,7 @@ static inline void aes_crypt(AVAES *a, int s, const uint8_t 
*sbox,
 }
 
 static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
-int count, uint8_t *iv)
+int count, uint8_t *iv, int decrypt)
 {
 while (count--) {
 addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
@@ -153,7 +154,7 @@ static void aes_encrypt(AVAES *a, uint8_t *dst, const 
uint8_t *src,
 }
 
 static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
-int count, uint8_t *iv)
+int count, uint8_t *iv, int decrypt)
 {
 while (count--) {
 addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
@@ -168,12 +169,32 @@ static void aes_decrypt(AVAES *a, uint8_t *dst, const 
uint8_t *src,
 }
 }
 
+#else
+
+static void aes_libcrypto(AVAES *a, uint8_t *dst, const uint8_t *src,
+  int count, uint8_t *iv, int decrypt)
+{
+if (iv)
+AES_cbc_encrypt((const unsigned char *)src,
+(unsigned char *)dst,
+count, &a->key,
+(unsigned char *)iv, !decrypt);
+else {
+for (int i = 0; i < count; i++)
+AES_ecb_encrypt((const unsigned char *)&src[i*16],
+(unsigned char *)&dst[i*16],
+&a->key, !decrypt);
+}
+}
+#endif
+
 void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src,
   int count, uin

Re: [FFmpeg-devel] [PATCH 1/2] avcodec/decode: Workaround for media100 decoding failure issue

2025-06-10 Thread Zhao Zhili


> On Jun 11, 2025, at 13:55, Andreas Rheinhardt 
>  wrote:
> 
> Zhao Zhili:
>> From: Zhao Zhili 
>> 
>> This is a regression since 1c170613.
>> ---
>> libavcodec/decode.c | 11 ---
>> 1 file changed, 8 insertions(+), 3 deletions(-)
>> 
>> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
>> index ef09568381..7e47a2971c 100644
>> --- a/libavcodec/decode.c
>> +++ b/libavcodec/decode.c
>> @@ -204,9 +204,14 @@ static int decode_bsfs_init(AVCodecContext *avctx)
>> ret = av_bsf_init(avci->bsf);
>> if (ret < 0)
>> goto fail;
>> -ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
>> -if (ret < 0)
>> -goto fail;
>> +/* Don't copy par_out to avcodec context if bsf changed codec ID,
>> + * e.g., media100_to_mjpegb
>> + */
>> +if (avctx->codec_id == avci->bsf->par_out->codec_id) {
>> +ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
>> +if (ret < 0)
>> +goto fail;
>> +}
>> 
>> return 0;
>> fail:
> 
> We should rather use a clean revert; after all, the internal BSF is
> supposed to be internal and not change the user-visible extradata etc.

Then how to let decoder see new extradata? Access bsf directly?
I’m OK to revert this after extradata can be synced to decoder properly.

AVCodecContext::extradata is owned by codec. Updating extradata can
be a little surprise, but it’s less surprise than change codec id in bsf.

What are the boundaries/limits of bsf’s functionality? Is it allowed for a bsf
to update media type? I remember there is a trac with samples which
can be handled with a video to audio bsf.

> 
> - Andreas
> 
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 2/2] tests: Add media100 decoder test

2025-06-10 Thread Andreas Rheinhardt
Zhao Zhili:
> From: Zhao Zhili 
> 
> ---
> The sample comes from 
> https://trac.ffmpeg.org/attachment/ticket/959/12%2027_Volcano%20Zoom-Dissolve-F-8.mov
> put it to mjpegb/media100.mov
> 
>  tests/fate/video.mak|  3 +++
>  tests/ref/fate/media100 | 30 ++
>  2 files changed, 33 insertions(+)
>  create mode 100644 tests/ref/fate/media100
> 
> diff --git a/tests/fate/video.mak b/tests/fate/video.mak
> index dd886843e7..24889824b4 100644
> --- a/tests/fate/video.mak
> +++ b/tests/fate/video.mak
> @@ -257,6 +257,9 @@ fate-mimic: CMD = framecrc -idct simple -i 
> $(TARGET_SAMPLES)/mimic/mimic2-womanl
>  FATE_VIDEO-$(call FRAMECRC, MOV, MJPEGB) += fate-mjpegb
>  fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i 
> $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an
>  
> +FATE_VIDEO-$(call FRAMECRC, MOV, MEDIA100) += fate-media100
> +fate-media100: CMD = framecrc -idct simple -fflags +bitexact -i 
> $(TARGET_SAMPLES)/mjpegb/media100.mov
> +
>  FATE_VIDEO-$(call FRAMECRC, AVI, MJPEG) += fate-mjpeg-ticket3229
>  fate-mjpeg-ticket3229: CMD = framecrc -idct simple -fflags +bitexact -i 
> $(TARGET_SAMPLES)/mjpeg/mjpeg_field_order.avi -an
>  
> diff --git a/tests/ref/fate/media100 b/tests/ref/fate/media100
> new file mode 100644
> index 00..7a92c5cc21
> --- /dev/null
> +++ b/tests/ref/fate/media100
> @@ -0,0 +1,30 @@
> +#tb 0: 1/25
> +#media_type 0: video
> +#codec_id 0: rawvideo
> +#dimensions 0: 768x576
> +#sar 0: 0/1
> +0,  0,  0,1,   884736, 0x22304315
> +0,  1,  1,1,   884736, 0x896fcaf0
> +0,  2,  2,1,   884736, 0x2e25b031
> +0,  3,  3,1,   884736, 0x9d0cdf84
> +0,  4,  4,1,   884736, 0x90c799b6
> +0,  5,  5,1,   884736, 0x80ac6b03
> +0,  6,  6,1,   884736, 0x46cfbd02
> +0,  7,  7,1,   884736, 0xee2b4bdb
> +0,  8,  8,1,   884736, 0x7876581e
> +0,  9,  9,1,   884736, 0x19490d15
> +0, 10, 10,1,   884736, 0x6c37db8d
> +0, 11, 11,1,   884736, 0xe6a198ae
> +0, 12, 12,1,   884736, 0x893d08af
> +0, 13, 13,1,   884736, 0xb52bd038
> +0, 14, 14,1,   884736, 0x7074bb1b
> +0, 15, 15,1,   884736, 0xd32ed044
> +0, 16, 16,1,   884736, 0x9592d482
> +0, 17, 17,1,   884736, 0x9fcd144b
> +0, 18, 18,1,   884736, 0xba1c73a2
> +0, 19, 19,1,   884736, 0x5fd7c0e7
> +0, 20, 20,1,   884736, 0xc3f05ed4
> +0, 21, 21,1,   884736, 0x333d0e9c
> +0, 22, 22,1,   884736, 0x9063fd20
> +0, 23, 23,1,   884736, 0xc4508928
> +0, 24, 24,1,   884736, 0x1428b800

That sample is way too big; only one packet is needed (the last,
smallest one).

- Andreas

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 1/2] avcodec/decode: Workaround for media100 decoding failure issue

2025-06-10 Thread Andreas Rheinhardt
Zhao Zhili:
> From: Zhao Zhili 
> 
> This is a regression since 1c170613.
> ---
>  libavcodec/decode.c | 11 ---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/libavcodec/decode.c b/libavcodec/decode.c
> index ef09568381..7e47a2971c 100644
> --- a/libavcodec/decode.c
> +++ b/libavcodec/decode.c
> @@ -204,9 +204,14 @@ static int decode_bsfs_init(AVCodecContext *avctx)
>  ret = av_bsf_init(avci->bsf);
>  if (ret < 0)
>  goto fail;
> -ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
> -if (ret < 0)
> -goto fail;
> +/* Don't copy par_out to avcodec context if bsf changed codec ID,
> + * e.g., media100_to_mjpegb
> + */
> +if (avctx->codec_id == avci->bsf->par_out->codec_id) {
> +ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
> +if (ret < 0)
> +goto fail;
> +}
>  
>  return 0;
>  fail:

We should rather use a clean revert; after all, the internal BSF is
supposed to be internal and not change the user-visible extradata etc.

- Andreas

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 3/3] avutil/aes: add an OpenSSL-libcrypto backed implementation

2025-06-10 Thread Andreas Rheinhardt
James Almer:
> OpenSSL has optimizations for more architectures than x86-AESNI, so use it if
> libavutil is configured with libcrypto explicitly (Enabling OpenSSL alone will
> not make use of it).
> 
> Signed-off-by: James Almer 
> ---
>  configure|  8 +++-
>  libavutil/aes.c  | 37 ++---
>  libavutil/aes_internal.h | 11 ++-
>  libavutil/x86/aes_init.c |  2 ++
>  4 files changed, 53 insertions(+), 5 deletions(-)
> 
> diff --git a/configure b/configure
> index 534b443f7d..c7b4fbb2fe 100755
> --- a/configure
> +++ b/configure
> @@ -223,6 +223,7 @@ External library support:
>--enable-libcelt enable CELT decoding via libcelt [no]
>--enable-libcdio enable audio CD grabbing with libcdio [no]
>--enable-libcodec2   enable codec2 en/decoding using libcodec2 [no]
> +  --enable-libcrypto   enable crypto via libcrypto (AES only) [no]
>--enable-libdav1denable AV1 decoding via libdav1d [no]
>--enable-libdavs2enable AVS2 decoding via libdavs2 [no]
>--enable-libdc1394   enable IIDC-1394 grabbing using libdc1394
> @@ -1931,6 +1932,7 @@ EXTERNAL_LIBRARY_LIST="
>  libcaca
>  libcelt
>  libcodec2
> +libcrypto
>  libdav1d
>  libdc1394
>  libflite
> @@ -4091,7 +4093,7 @@ avfilter_deps="avutil"
>  avfilter_suggest="libm stdatomic spirv_compiler"
>  avformat_deps="avcodec avutil"
>  avformat_suggest="libm network zlib stdatomic"
> -avutil_suggest="clock_gettime ffnvcodec gcrypt libm libdrm libmfx opencl 
> openssl user32 vaapi vulkan videotoolbox corefoundation corevideo coremedia 
> bcrypt stdatomic"
> +avutil_suggest="clock_gettime ffnvcodec gcrypt libcrypto libm libdrm libmfx 
> opencl openssl user32 vaapi vulkan videotoolbox corefoundation corevideo 
> coremedia bcrypt stdatomic"
>  swresample_deps="avutil"
>  swresample_suggest="libm libsoxr stdatomic"
>  swscale_deps="avutil"
> @@ -7193,6 +7195,10 @@ enabled openssl   && { { check_pkg_config 
> openssl "openssl >= 3.0.0" ope
> check_lib openssl openssl/ssl.h 
> SSL_library_init -lssl32 -leay32 ||
> check_lib openssl openssl/ssl.h 
> SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
> die "ERROR: openssl not found"; }
> +enabled libcrypto && { { check_pkg_config libcrypto "libcrypto >= 
> 3.0.0" openssl/aes.h AES_set_encrypt_key &&
> + { enabled gplv3 || ! enabled gpl || enabled 
> nonfree || die "ERROR: OpenSSL-libcrypto >= 3.0.0 requires 
> --enable-version3"; }; } ||
> +   { enabled gpl && ! enabled nonfree && die 
> "ERROR: OpenSSL-libcrypto < 3.0.0 is incompatible with the gpl"; } ||
> +   require_pkg_config libcrypto libcrypto 
> openssl/aes.h AES_set_encrypt_key; }
>  enabled pocketsphinx  && require_pkg_config pocketsphinx pocketsphinx 
> pocketsphinx/pocketsphinx.h ps_init
>  enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp  
> rockchip/rk_mpi.h mpp_create &&
> require_pkg_config rockchip_mpp "rockchip_mpp 
> >= 1.3.7" rockchip/rk_mpi.h mpp_create &&
> diff --git a/libavutil/aes.c b/libavutil/aes.c
> index 7fe42a5548..3a0d4e1385 100644
> --- a/libavutil/aes.c
> +++ b/libavutil/aes.c
> @@ -39,6 +39,7 @@ struct AVAES *av_aes_alloc(void)
>  return av_mallocz(sizeof(struct AVAES));
>  }
>  
> +#if !CONFIG_LIBCRYPTO
>  static const uint8_t rcon[10] = {
>  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
>  };
> @@ -137,7 +138,7 @@ static inline void aes_crypt(AVAES *a, int s, const 
> uint8_t *sbox,
>  }
>  
>  static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
> -int count, uint8_t *iv)
> +int count, uint8_t *iv, int decrypt)
>  {
>  while (count--) {
>  addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
> @@ -153,7 +154,7 @@ static void aes_encrypt(AVAES *a, uint8_t *dst, const 
> uint8_t *src,
>  }
>  
>  static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
> -int count, uint8_t *iv)
> +int count, uint8_t *iv, int decrypt)
>  {
>  while (count--) {
>  addkey_s(&a->state[1], src, &a->round_key[a->rounds]);
> @@ -168,12 +169,32 @@ static void aes_decrypt(AVAES *a, uint8_t *dst, const 
> uint8_t *src,
>  }
>  }
>  
> +#else
> +
> +static void aes_libcrypto(AVAES *a, uint8_t *dst, const uint8_t *src,
> +  int count, uint8_t *iv, int decrypt)
> +{
> +if (iv)
> +AES_cbc_encrypt((const unsigned char *)src,
> +(unsigned char *)dst,
> +count, &a->key,
> +(unsigned char *)iv, !decrypt);
> +else {
> +for (int i = 0; i < count; i++)
> +AES_ecb_encrypt((const unsi

[FFmpeg-devel] [PATCH v5 02/19] swscale/format: rename legacy format conversion table

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

---
 libswscale/format.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index e4c1348b90..b77081dd7a 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -24,14 +24,14 @@
 
 #include "format.h"
 
-typedef struct FormatEntry {
+typedef struct LegacyFormatEntry {
 uint8_t is_supported_in :1;
 uint8_t is_supported_out:1;
 uint8_t is_supported_endianness :1;
-} FormatEntry;
+} LegacyFormatEntry;
 
 /* Format support table for legacy swscale */
-static const FormatEntry format_entries[] = {
+static const LegacyFormatEntry legacy_format_entries[] = {
 [AV_PIX_FMT_YUV420P]= { 1, 1 },
 [AV_PIX_FMT_YUYV422]= { 1, 1 },
 [AV_PIX_FMT_RGB24]  = { 1, 1 },
@@ -262,20 +262,20 @@ static const FormatEntry format_entries[] = {
 
 int sws_isSupportedInput(enum AVPixelFormat pix_fmt)
 {
-return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
-   format_entries[pix_fmt].is_supported_in : 0;
+return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
+legacy_format_entries[pix_fmt].is_supported_in : 0;
 }
 
 int sws_isSupportedOutput(enum AVPixelFormat pix_fmt)
 {
-return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
-   format_entries[pix_fmt].is_supported_out : 0;
+return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
+legacy_format_entries[pix_fmt].is_supported_out : 0;
 }
 
 int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt)
 {
-return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ?
-   format_entries[pix_fmt].is_supported_endianness : 0;
+return (unsigned)pix_fmt < FF_ARRAY_ELEMS(legacy_format_entries) ?
+legacy_format_entries[pix_fmt].is_supported_endianness : 0;
 }
 
 /**
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 11/19] swscale/ops: add dispatch layer

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This handles the low-level execution of an op list, and integration into
the SwsGraph infrastructure. To handle frames with insufficient padding in
the stride (or a width smaller than one block size), we use a fallback loop
that pads the last column of pixels using `memcpy` into an appropriately
sized buffer.
---
 libswscale/ops.c  | 269 ++
 libswscale/ops.h  |  14 ++
 libswscale/ops_internal.h |  18 ++-
 3 files changed, 294 insertions(+), 7 deletions(-)

diff --git a/libswscale/ops.c b/libswscale/ops.c
index c71601a0d1..5330b37b22 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -583,3 +583,272 @@ int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList 
*ops, SwsCompiledOp *out
 ff_sws_op_list_print(ctx, AV_LOG_WARNING, ops);
 return AVERROR(ENOTSUP);
 }
+
+typedef struct SwsOpPass {
+SwsCompiledOp comp;
+SwsOpExec exec_base;
+int num_blocks;
+int tail_off_in;
+int tail_off_out;
+int tail_size_in;
+int tail_size_out;
+int pixel_bits_in;
+int pixel_bits_out;
+bool memcpy_in;
+bool memcpy_out;
+} SwsOpPass;
+
+static void op_pass_free(void *ptr)
+{
+SwsOpPass *p = ptr;
+if (!p)
+return;
+
+if (p->comp.free)
+p->comp.free(p->comp.priv);
+
+av_free(p);
+}
+
+static void op_pass_setup(const SwsImg *out, const SwsImg *in, const SwsPass 
*pass)
+{
+const AVPixFmtDescriptor *indesc  = av_pix_fmt_desc_get(in->fmt);
+const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(out->fmt);
+
+SwsOpPass *p = pass->priv;
+SwsOpExec *exec = &p->exec_base;
+const SwsCompiledOp *comp = &p->comp;
+const int block_size = comp->block_size;
+p->num_blocks = (pass->width + block_size - 1) / block_size;
+
+/* Set up main loop parameters */
+const int aligned_w  = p->num_blocks * block_size;
+const int safe_width = (p->num_blocks - 1) * block_size;
+const int tail_size  = pass->width - safe_width;
+p->tail_off_in   = safe_width * p->pixel_bits_in  >> 3;
+p->tail_off_out  = safe_width * p->pixel_bits_out >> 3;
+p->tail_size_in  = tail_size  * p->pixel_bits_in  >> 3;
+p->tail_size_out = tail_size  * p->pixel_bits_out >> 3;
+p->memcpy_in = false;
+p->memcpy_out= false;
+
+for (int i = 0; i < 4 && in->data[i]; i++) {
+const int sub_x  = (i == 1 || i == 2) ? indesc->log2_chroma_w : 0;
+const int plane_w= (aligned_w + sub_x) >> sub_x;
+const int plane_pad  = (comp->over_read + sub_x) >> sub_x;
+const int plane_size = plane_w * p->pixel_bits_in >> 3;
+p->memcpy_in |= plane_size + plane_pad > in->linesize[i];
+exec->in_stride[i] = in->linesize[i];
+}
+
+for (int i = 0; i < 4 && out->data[i]; i++) {
+const int sub_x  = (i == 1 || i == 2) ? outdesc->log2_chroma_w : 0;
+const int plane_w= (aligned_w + sub_x) >> sub_x;
+const int plane_pad  = (comp->over_write + sub_x) >> sub_x;
+const int plane_size = plane_w * p->pixel_bits_out >> 3;
+p->memcpy_out |= plane_size + plane_pad > out->linesize[i];
+exec->out_stride[i] = out->linesize[i];
+}
+
+/* Pre-fill pointer bump for the main section only; this value does not
+ * matter at all for the tail / last row handlers because they only ever
+ * process a single line */
+const int blocks_main = p->num_blocks - p->memcpy_out;
+for (int i = 0; i < 4; i++) {
+exec->in_bump[i]  = in->linesize[i]  - blocks_main * 
exec->block_size_in;
+exec->out_bump[i] = out->linesize[i] - blocks_main * 
exec->block_size_out;
+}
+}
+
+/* Dispatch kernel over the last column of the image using memcpy */
+static av_always_inline void
+handle_tail(const SwsOpPass *p, SwsOpExec *exec,
+const SwsImg *out_base, const bool copy_out,
+const SwsImg *in_base, const bool copy_in,
+int y, const int h)
+{
+DECLARE_ALIGNED_64(uint8_t, tmp)[2][4][sizeof(uint32_t[128])];
+
+const SwsCompiledOp *comp = &p->comp;
+const int tail_size_in  = p->tail_size_in;
+const int tail_size_out = p->tail_size_out;
+const int bx = p->num_blocks - 1;
+
+SwsImg in  = ff_sws_img_shift(in_base,  y);
+SwsImg out = ff_sws_img_shift(out_base, y);
+for (int i = 0; i < 4 && in.data[i]; i++) {
+in.data[i]  += p->tail_off_in;
+if (copy_in) {
+exec->in[i] = (void *) tmp[0][i];
+exec->in_stride[i] = sizeof(tmp[0][i]);
+} else {
+exec->in[i] = in.data[i];
+}
+}
+
+for (int i = 0; i < 4 && out.data[i]; i++) {
+out.data[i] += p->tail_off_out;
+if (copy_out) {
+exec->out[i] = (void *) tmp[1][i];
+exec->out_stride[i] = sizeof(tmp[1][i]);
+} else {
+exec->out[i] = out.data[i];
+}
+}
+
+for (int y_end = y + h; y < y_end; y++) {
+if (copy_in) {
+  

[FFmpeg-devel] [PATCH v5 09/19] swscale/optimizer: add high-level ops optimizer

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This is responsible for taking a "naive" ops list and optimizing it
as much as possible. Also includes a small analyzer that generates component
metadata for use by the optimizer.
---
 libswscale/Makefile|   1 +
 libswscale/ops.h   |  12 +
 libswscale/ops_optimizer.c | 782 +
 3 files changed, 795 insertions(+)
 create mode 100644 libswscale/ops_optimizer.c

diff --git a/libswscale/Makefile b/libswscale/Makefile
index e0beef4e69..810c9dee78 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -16,6 +16,7 @@ OBJS = alphablend.o \
input.o  \
lut3d.o  \
ops.o\
+   ops_optimizer.o  \
options.o\
output.o \
rgb2rgb.o\
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 71841c1572..a90701cf50 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -237,4 +237,16 @@ void ff_sws_op_list_remove_at(SwsOpList *ops, int index, 
int count);
  */
 void ff_sws_op_list_print(void *log_ctx, int log_level, const SwsOpList *ops);
 
+/**
+ * Infer + propagate known information about components. Called automatically
+ * when needed by the optimizer and compiler.
+ */
+void ff_sws_op_list_update_comps(SwsOpList *ops);
+
+/**
+ * Fuse compatible and eliminate redundant operations, as well as replacing
+ * some operations with more efficient alternatives.
+ */
+int ff_sws_op_list_optimize(SwsOpList *ops);
+
 #endif
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
new file mode 100644
index 00..80e75ed34b
--- /dev/null
+++ b/libswscale/ops_optimizer.c
@@ -0,0 +1,782 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 "libavutil/avassert.h"
+#include "libavutil/rational.h"
+
+#include "ops.h"
+
+#define Q(N) ((AVRational) { N, 1 })
+
+#define RET(x) 
\
+do {   
\
+if ((ret = (x)) < 0)   
\
+return ret;
\
+} while (0)
+
+/* Returns true for operations that are independent per channel. These can
+ * usually be commuted freely other such operations. */
+static bool op_type_is_independent(SwsOpType op)
+{
+switch (op) {
+case SWS_OP_SWAP_BYTES:
+case SWS_OP_LSHIFT:
+case SWS_OP_RSHIFT:
+case SWS_OP_CONVERT:
+case SWS_OP_DITHER:
+case SWS_OP_MIN:
+case SWS_OP_MAX:
+case SWS_OP_SCALE:
+return true;
+case SWS_OP_INVALID:
+case SWS_OP_READ:
+case SWS_OP_WRITE:
+case SWS_OP_SWIZZLE:
+case SWS_OP_CLEAR:
+case SWS_OP_LINEAR:
+case SWS_OP_PACK:
+case SWS_OP_UNPACK:
+return false;
+case SWS_OP_TYPE_NB:
+break;
+}
+
+av_assert0(!"Invalid operation type!");
+return false;
+}
+
+static AVRational expand_factor(SwsPixelType from, SwsPixelType to)
+{
+const int src = ff_sws_pixel_type_size(from);
+const int dst = ff_sws_pixel_type_size(to);
+int scale = 0;
+for (int i = 0; i < dst / src; i++)
+scale = scale << src * 8 | 1;
+return Q(scale);
+}
+
+/* merge_comp_flags() forms a monoid with flags_identity as the null element */
+static const unsigned flags_identity = SWS_COMP_ZERO | SWS_COMP_EXACT;
+static unsigned merge_comp_flags(unsigned a, unsigned b)
+{
+const unsigned flags_or  = SWS_COMP_GARBAGE;
+const unsigned flags_and = SWS_COMP_ZERO | SWS_COMP_EXACT;
+return ((a & b) & flags_and) | ((a | b) & flags_or);
+}
+
+/* Infer + propagate known information about components */
+void ff_sws_op_list_update_comps(SwsOpList *ops)
+{
+SwsComps next = { .unused = {true, true, true, true} };
+SwsComps prev = { .flags = {
+SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE, SWS_COMP_GARBAGE,
+}};
+
+

[FFmpeg-devel] [PATCH v5 04/19] tests/checkasm: increase number of runs in between measurements

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Sometimes, when measuring very small functions, rdtsc is not accurate enough
to get a reliable measurement. This increases the number of runs inside the
inner loop from 4 to 32, which should help a lot. Less important when using
the more precise linux-perf API, but still useful.

There should be no user-visible change since the number of runs is adjusted
to keep the total time spent measuring the same.
---
 tests/checkasm/checkasm.c |  2 +-
 tests/checkasm/checkasm.h | 24 +++-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 0734cd26bf..71d1e5766c 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -628,7 +628,7 @@ static inline double avg_cycles_per_call(const CheckasmPerf 
*const p)
 if (p->iterations) {
 const double cycles = (double)(10 * p->cycles) / p->iterations - 
state.nop_time;
 if (cycles > 0.0)
-return cycles / 4.0; /* 4 calls per iteration */
+return cycles / 32.0; /* 32 calls per iteration */
 }
 return 0.0;
 }
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 146bfdec35..ad7ed10613 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -342,6 +342,22 @@ typedef struct CheckasmPerf {
 #define PERF_STOP(t)  t = AV_READ_TIME() - t
 #endif
 
+#define CALL4(...)\
+do {\
+tfunc(__VA_ARGS__); \
+tfunc(__VA_ARGS__); \
+tfunc(__VA_ARGS__); \
+tfunc(__VA_ARGS__); \
+} while (0)
+
+#define CALL16(...)\
+do {\
+CALL4(__VA_ARGS__); \
+CALL4(__VA_ARGS__); \
+CALL4(__VA_ARGS__); \
+CALL4(__VA_ARGS__); \
+} while (0)
+
 /* Benchmark the function */
 #define bench_new(...)\
 do {\
@@ -352,14 +368,12 @@ typedef struct CheckasmPerf {
 uint64_t tsum = 0;\
 uint64_t ti, tcount = 0;\
 uint64_t t = 0; \
-const uint64_t truns = bench_runs;\
+const uint64_t truns = FFMAX(bench_runs >> 3, 1);\
 checkasm_set_signal_handler_state(1);\
 for (ti = 0; ti < truns; ti++) {\
 PERF_START(t);\
-tfunc(__VA_ARGS__);\
-tfunc(__VA_ARGS__);\
-tfunc(__VA_ARGS__);\
-tfunc(__VA_ARGS__);\
+CALL16(__VA_ARGS__);\
+CALL16(__VA_ARGS__);\
 PERF_STOP(t);\
 if (t*tcount <= tsum*4 && ti > 0) {\
 tsum += t;\
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 08/19] swscale/ops: introduce new low level framework

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

See docs/swscale-v2.txt for an in-depth introduction to the new approach.

This commit merely introduces the ops definitions and boilerplate functions.
The subsequent commits will flesh out the underlying implementation.
---
 libswscale/Makefile |   1 +
 libswscale/ops.c| 520 
 libswscale/ops.h| 240 
 3 files changed, 761 insertions(+)
 create mode 100644 libswscale/ops.c
 create mode 100644 libswscale/ops.h

diff --git a/libswscale/Makefile b/libswscale/Makefile
index d5e10d17dc..e0beef4e69 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -15,6 +15,7 @@ OBJS = alphablend.o \
graph.o  \
input.o  \
lut3d.o  \
+   ops.o\
options.o\
output.o \
rgb2rgb.o\
diff --git a/libswscale/ops.c b/libswscale/ops.c
new file mode 100644
index 00..c6e8f691cb
--- /dev/null
+++ b/libswscale/ops.c
@@ -0,0 +1,520 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 "libavutil/avassert.h"
+#include "libavutil/bswap.h"
+#include "libavutil/mem.h"
+#include "libavutil/rational.h"
+#include "libavutil/refstruct.h"
+
+#include "ops.h"
+
+#define Q(N) ((AVRational) { N, 1 })
+
+const char *ff_sws_pixel_type_name(SwsPixelType type)
+{
+switch (type) {
+case SWS_PIXEL_U8:   return "u8";
+case SWS_PIXEL_U16:  return "u16";
+case SWS_PIXEL_U32:  return "u32";
+case SWS_PIXEL_F32:  return "f32";
+case SWS_PIXEL_NONE: return "none";
+case SWS_PIXEL_TYPE_NB: break;
+}
+
+av_assert0(!"Invalid pixel type!");
+return "ERR";
+}
+
+int ff_sws_pixel_type_size(SwsPixelType type)
+{
+switch (type) {
+case SWS_PIXEL_U8:  return sizeof(uint8_t);
+case SWS_PIXEL_U16: return sizeof(uint16_t);
+case SWS_PIXEL_U32: return sizeof(uint32_t);
+case SWS_PIXEL_F32: return sizeof(float);
+case SWS_PIXEL_NONE: break;
+case SWS_PIXEL_TYPE_NB: break;
+}
+
+av_assert0(!"Invalid pixel type!");
+return 0;
+}
+
+bool ff_sws_pixel_type_is_int(SwsPixelType type)
+{
+switch (type) {
+case SWS_PIXEL_U8:
+case SWS_PIXEL_U16:
+case SWS_PIXEL_U32:
+return true;
+case SWS_PIXEL_F32:
+return false;
+case SWS_PIXEL_NONE:
+case SWS_PIXEL_TYPE_NB: break;
+}
+
+av_assert0(!"Invalid pixel type!");
+return false;
+}
+
+SwsPixelType ff_sws_pixel_type_to_uint(SwsPixelType type)
+{
+if (!type)
+return type;
+
+switch (ff_sws_pixel_type_size(type)) {
+case 8:  return SWS_PIXEL_U8;
+case 16: return SWS_PIXEL_U16;
+case 32: return SWS_PIXEL_U32;
+}
+
+av_assert0(!"Invalid pixel type!");
+return SWS_PIXEL_NONE;
+}
+
+/* biased towards `a` */
+static AVRational av_min_q(AVRational a, AVRational b)
+{
+return av_cmp_q(a, b) == 1 ? b : a;
+}
+
+static AVRational av_max_q(AVRational a, AVRational b)
+{
+return av_cmp_q(a, b) == -1 ? b : a;
+}
+
+static AVRational expand_factor(SwsPixelType from, SwsPixelType to)
+{
+const int src = ff_sws_pixel_type_size(from);
+const int dst = ff_sws_pixel_type_size(to);
+int scale = 0;
+for (int i = 0; i < dst / src; i++)
+scale = scale << src * 8 | 1;
+return Q(scale);
+}
+
+void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
+{
+switch (op->op) {
+case SWS_OP_READ:
+case SWS_OP_WRITE:
+return;
+case SWS_OP_UNPACK: {
+unsigned val = x[0].num;
+int shift = ff_sws_pixel_type_size(op->type) * 8;
+for (int i = 0; i < 4; i++) {
+const unsigned mask = (1 << op->pack.pattern[i]) - 1;
+shift -= op->pack.pattern[i];
+x[i] = Q((val >> shift) & mask);
+}
+return;
+}
+case SWS_OP_PACK: {
+unsigned val = 0;
+int shift = ff_sws_pixel_type_size(op->type) * 8;
+for (int i = 0; i < 4; i++

[FFmpeg-devel] [PATCH v5 12/19] swscale/optimizer: add packed shuffle solver

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This can turn any compatible sequence of operations into a single packed
shuffle, including packed swizzling, grayscale->RGB conversion, endianness
swapping, RGB bit depth conversions, rgb24->rgb0 alpha clearing and more.
---
 libswscale/ops_internal.h  | 28 +++
 libswscale/ops_optimizer.c | 96 ++
 2 files changed, 124 insertions(+)

diff --git a/libswscale/ops_internal.h b/libswscale/ops_internal.h
index 2fbd8a55d0..e7b6fb1c4c 100644
--- a/libswscale/ops_internal.h
+++ b/libswscale/ops_internal.h
@@ -109,4 +109,32 @@ int ff_sws_ops_compile_backend(SwsContext *ctx, const 
SwsOpBackend *backend,
  */
 int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp 
*out);
 
+/**
+ * "Solve" an op list into a fixed shuffle mask, with an optional ability to
+ * also directly clear the output value (for e.g. rgb24 -> rgb0). This can
+ * accept any operation chain that only consists of the following operations:
+ *
+ * - SWS_OP_READ (non-planar, non-fractional)
+ * - SWS_OP_SWIZZLE
+ * - SWS_OP_SWAP_BYTES
+ * - SWS_OP_CLEAR to zero (when clear_val is specified)
+ * - SWS_OP_CONVERT (integer expand)
+ * - SWS_OP_WRITE (non-planar, non-fractional)
+ *
+ * Basically, any operation that purely consists of moving around and reording
+ * bytes within a single plane, can be turned into a shuffle mask.
+ *
+ * @param ops The operation list to decompose.
+ * @param shuffle The output shuffle mask.
+ * @param sizeThe size (in bytes) of the output shuffle mask.
+ * @param clear_val   If nonzero, this index will be used to clear the output.
+ * @param read_bytes  Returns the number of bytes read per shuffle iteration.
+ * @param write_bytes Returns the number of bytes written per shuffle 
iteration.
+ *
+ * @return  The number of pixels processed per iteration, or a negative error
+code; in particular AVERROR(ENOTSUP) for unsupported operations.
+ */
+int ff_sws_solve_shuffle(const SwsOpList *ops, uint8_t shuffle[], int size,
+ uint8_t clear_val, int *read_bytes, int *write_bytes);
+
 #endif
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 80e75ed34b..23c9aae76d 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -19,9 +19,11 @@
  */
 
 #include "libavutil/avassert.h"
+#include 
 #include "libavutil/rational.h"
 
 #include "ops.h"
+#include "ops_internal.h"
 
 #define Q(N) ((AVRational) { N, 1 })
 
@@ -780,3 +782,97 @@ retry:
 
 return 0;
 }
+
+int ff_sws_solve_shuffle(const SwsOpList *const ops, uint8_t shuffle[],
+ int shuffle_size, uint8_t clear_val,
+ int *out_read_bytes, int *out_write_bytes)
+{
+const SwsOp read = ops->ops[0];
+const int read_size = ff_sws_pixel_type_size(read.type);
+uint32_t mask[4] = {0};
+
+if (!ops->num_ops || read.op != SWS_OP_READ)
+return AVERROR(EINVAL);
+if (read.rw.frac || (!read.rw.packed && read.rw.elems > 1))
+return AVERROR(ENOTSUP);
+
+for (int i = 0; i < read.rw.elems; i++)
+mask[i] = 0x01010101 * i * read_size + 0x03020100;
+
+for (int opidx = 1; opidx < ops->num_ops; opidx++) {
+const SwsOp *op = &ops->ops[opidx];
+switch (op->op) {
+case SWS_OP_SWIZZLE: {
+uint32_t orig[4] = { mask[0], mask[1], mask[2], mask[3] };
+for (int i = 0; i < 4; i++)
+mask[i] = orig[op->swizzle.in[i]];
+break;
+}
+
+case SWS_OP_SWAP_BYTES:
+for (int i = 0; i < 4; i++) {
+switch (ff_sws_pixel_type_size(op->type)) {
+case 2: mask[i] = av_bswap16(mask[i]); break;
+case 4: mask[i] = av_bswap32(mask[i]); break;
+}
+}
+break;
+
+case SWS_OP_CLEAR:
+for (int i = 0; i < 4; i++) {
+if (!op->c.q4[i].den)
+continue;
+if (op->c.q4[i].num != 0 || !clear_val)
+return AVERROR(ENOTSUP);
+mask[i] = 0x1010101ul * clear_val;
+}
+break;
+
+case SWS_OP_CONVERT: {
+if (!op->convert.expand)
+return AVERROR(ENOTSUP);
+for (int i = 0; i < 4; i++) {
+switch (ff_sws_pixel_type_size(op->type)) {
+case 1: mask[i] = 0x01010101 * (mask[i] & 0xFF);   break;
+case 2: mask[i] = 0x00010001 * (mask[i] & 0x); break;
+}
+}
+break;
+}
+
+case SWS_OP_WRITE: {
+if (op->rw.frac || (!op->rw.packed && op->rw.elems > 1))
+return AVERROR(ENOTSUP);
+
+/* Initialize to no-op */
+memset(shuffle, clear_val, shuffle_size);
+
+const int write_size  = ff_sws_pixel_type_size(op->type);
+const int read_chunk  = read.rw.elems * read_s

[FFmpeg-devel] [PATCH v5 06/19] avutil/mem: add av_dynarray2_dup

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Like av_memdup() but correctly rounds up to the nearest power of two so that
av_dynarray2_add() will continue to work on the duplicated list.
---
 libavutil/mem.c |  9 +
 libavutil/mem.h | 14 ++
 2 files changed, 23 insertions(+)

diff --git a/libavutil/mem.c b/libavutil/mem.c
index b205d3fb25..2ed4553069 100644
--- a/libavutil/mem.c
+++ b/libavutil/mem.c
@@ -39,6 +39,7 @@
 
 #include "attributes.h"
 #include "avassert.h"
+#include "common.h"
 #include "dynarray.h"
 #include "error.h"
 #include "internal.h"
@@ -358,6 +359,14 @@ void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t 
elem_size,
 return tab_elem_data;
 }
 
+void *av_dynarray2_dup(void *tab, int nb, size_t elem_size)
+{
+if (nb)
+nb = 1 << av_ceil_log2(nb);
+
+return av_memdup(tab, nb * elem_size);
+}
+
 static void fill16(uint8_t *dst, int len)
 {
 uint32_t v = AV_RN16(dst - 2);
diff --git a/libavutil/mem.h b/libavutil/mem.h
index ab7648ac57..7815327a88 100644
--- a/libavutil/mem.h
+++ b/libavutil/mem.h
@@ -562,6 +562,20 @@ int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, 
void *elem);
 void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
const uint8_t *elem_data);
 
+/**
+ * Duplicate an array allocated by `av_dynarray2_add`. Preserves the size of
+ * the underlying allocation, so that the returned array can be again modified
+ * using `av_dynarray2_add`.
+ *
+ * @param[in] tab   Pointer to the array to duplicate
+ * @param[in] nbNumber of elements in the array
+ * @param[in] elem_size Size in bytes of an element in the array
+ *
+ * @return Pointer to the newly allocated array, or `NULL` on failure.
+ * @see av_dynarray2_add()
+ */
+void *av_dynarray2_dup(void *tab, int nb, size_t elem_size);
+
 /**
  * @}
  */
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 10/19] swscale/ops_internal: add internal ops backend API

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This adds an internal API for ops backends, which are responsible for
compiling op lists into executable functions.
---
 libswscale/ops.c  |  65 +++
 libswscale/ops_internal.h | 108 ++
 2 files changed, 173 insertions(+)
 create mode 100644 libswscale/ops_internal.h

diff --git a/libswscale/ops.c b/libswscale/ops.c
index c6e8f691cb..c71601a0d1 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -25,9 +25,22 @@
 #include "libavutil/refstruct.h"
 
 #include "ops.h"
+#include "ops_internal.h"
+
+const SwsOpBackend * const ff_sws_op_backends[] = {
+NULL
+};
+
+const int ff_sws_num_op_backends = FF_ARRAY_ELEMS(ff_sws_op_backends) - 1;
 
 #define Q(N) ((AVRational) { N, 1 })
 
+#define RET(x) 
\
+do {   
\
+if ((ret = (x)) < 0)   
\
+return ret;
\
+} while (0)
+
 const char *ff_sws_pixel_type_name(SwsPixelType type)
 {
 switch (type) {
@@ -518,3 +531,55 @@ void ff_sws_op_list_print(void *log, int lev, const 
SwsOpList *ops)
 
 av_log(log, lev, "(X = unused, + = exact, 0 = zero)\n");
 }
+
+int ff_sws_ops_compile_backend(SwsContext *ctx, const SwsOpBackend *backend,
+   const SwsOpList *ops, SwsCompiledOp *out)
+{
+SwsOpList *copy, rest;
+SwsCompiledOp compiled = {0};
+int ret = 0;
+
+copy = ff_sws_op_list_duplicate(ops);
+if (!copy)
+return AVERROR(ENOMEM);
+
+/* Ensure these are always set during compilation */
+ff_sws_op_list_update_comps(copy);
+
+/* Make an on-stack copy of `ops` to ensure we can still properly clean up
+ * the copy afterwards */
+rest = *copy;
+
+ret = backend->compile(ctx, &rest, &compiled);
+if (ret == AVERROR(ENOTSUP)) {
+av_log(ctx, AV_LOG_TRACE, "Backend '%s' does not support 
operations:\n", backend->name);
+ff_sws_op_list_print(ctx, AV_LOG_TRACE, &rest);
+} else if (ret < 0) {
+av_log(ctx, AV_LOG_ERROR, "Failed to compile operations: %s\n", 
av_err2str(ret));
+ff_sws_op_list_print(ctx, AV_LOG_ERROR, &rest);
+} else {
+*out = compiled;
+}
+
+ff_sws_op_list_free(©);
+return ret;
+}
+
+int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp 
*out)
+{
+for (int n = 0; ff_sws_op_backends[n]; n++) {
+const SwsOpBackend *backend = ff_sws_op_backends[n];
+if (ff_sws_ops_compile_backend(ctx, backend, ops, out) < 0)
+continue;
+
+av_log(ctx, AV_LOG_VERBOSE, "Compiled using backend '%s': "
+   "block size = %d, over-read = %d, over-write = %d, cpu flags = 
0x%x\n",
+   backend->name, out->block_size, out->over_read, out->over_write,
+   out->cpu_flags);
+return 0;
+}
+
+av_log(ctx, AV_LOG_WARNING, "No backend found for operations:\n");
+ff_sws_op_list_print(ctx, AV_LOG_WARNING, ops);
+return AVERROR(ENOTSUP);
+}
diff --git a/libswscale/ops_internal.h b/libswscale/ops_internal.h
new file mode 100644
index 00..9fd866430b
--- /dev/null
+++ b/libswscale/ops_internal.h
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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
+ */
+
+#ifndef SWSCALE_OPS_INTERNAL_H
+#define SWSCALE_OPS_INTERNAL_H
+
+#include "libavutil/mem_internal.h"
+
+#include "ops.h"
+
+/**
+ * Global execution context for all compiled functions.
+ *
+ * Note: This struct is hard-coded in assembly, so do not change the layout
+ * without updating the corresponding assembly definitions.
+ */
+typedef struct SwsOpExec {
+/* The data pointers point to the first pixel to process */
+DECLARE_ALIGNED_32(const uint8_t, *in[4]);
+DECLARE_ALIGNED_32(uint8_t, *out[4]);
+
+/* Separation between lines in bytes */
+DECLARE_ALIGNED_32(ptrdiff_t, in_stride[4]);
+DECLARE_ALIGNED_32(ptrdiff_t, out_stride[4]);
+
+/* Extra metadata, may or may not be useful */
+int32_t width, height;  /* Overall image dimensions */
+int32_

[FFmpeg-devel] [PATCH v5 13/19] swscale/ops_chain: add internal abstraction for kernel linking

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

See doc/swscale-v2.txt for design details.
---
 libswscale/Makefile|   1 +
 libswscale/ops_chain.c | 291 +
 libswscale/ops_chain.h | 134 +++
 3 files changed, 426 insertions(+)
 create mode 100644 libswscale/ops_chain.c
 create mode 100644 libswscale/ops_chain.h

diff --git a/libswscale/Makefile b/libswscale/Makefile
index 810c9dee78..c9dfa78c89 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -16,6 +16,7 @@ OBJS = alphablend.o \
input.o  \
lut3d.o  \
ops.o\
+   ops_chain.o  \
ops_optimizer.o  \
options.o\
output.o \
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
new file mode 100644
index 00..09a7a195ad
--- /dev/null
+++ b/libswscale/ops_chain.c
@@ -0,0 +1,291 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "libavutil/rational.h"
+
+#include "ops_chain.h"
+
+#define Q(N) ((AVRational) { N, 1 })
+
+SwsOpChain *ff_sws_op_chain_alloc(void)
+{
+return av_mallocz(sizeof(SwsOpChain));
+}
+
+void ff_sws_op_chain_free(SwsOpChain *chain)
+{
+if (!chain)
+return;
+
+for (int i = 0; i < chain->num_impl + 1; i++) {
+if (chain->free[i])
+chain->free[i](chain->impl[i].priv.ptr);
+}
+
+av_free(chain);
+}
+
+int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func,
+   void (*free)(void *), SwsOpPriv priv)
+{
+const int idx = chain->num_impl;
+if (idx == SWS_MAX_OPS)
+return AVERROR(EINVAL);
+
+av_assert1(func);
+chain->impl[idx].cont = func;
+chain->impl[idx + 1].priv = priv;
+chain->free[idx + 1] = free;
+chain->num_impl++;
+return 0;
+}
+
+/**
+ * Match an operation against a reference operation. Returns a score for how
+ * well the reference matches the operation, or 0 if there is no match.
+ *
+ * If `ref->comps` has any flags set, they must be set in `op` as well.
+ * Likewise, if `ref->comps` has any components marked as unused, they must be
+ * marked as as unused in `ops` as well.
+ *
+ * For SWS_OP_LINEAR, `ref->linear.mask` must be a strict superset of
+ * `op->linear.mask`, but may not contain any columns explicitly ignored by
+ * `op->comps.unused`.
+ *
+ * For SWS_OP_READ, SWS_OP_WRITE, SWS_OP_SWAP_BYTES and SWS_OP_SWIZZLE, the
+ * exact type is not checked, just the size.
+ *
+ * Components set in `next.unused` are ignored when matching. If `flexible`
+ * is true, the op body is ignored - only the operation, pixel type, and
+ * component masks are checked.
+ */
+static int op_match(const SwsOp *op, const SwsOpEntry *entry, const SwsComps 
next)
+{
+int score = 10;
+if (op->op != entry->op)
+return 0;
+
+switch (op->op) {
+case SWS_OP_READ:
+case SWS_OP_WRITE:
+case SWS_OP_SWAP_BYTES:
+case SWS_OP_SWIZZLE:
+/* Only the size matters for these operations */
+if (ff_sws_pixel_type_size(op->type) != 
ff_sws_pixel_type_size(entry->type))
+return 0;
+break;
+default:
+if (op->type != entry->type)
+return 0;
+break;
+}
+
+for (int i = 0; i < 4; i++) {
+if (entry->unused[i]) {
+if (op->comps.unused[i])
+score += 1; /* Operating on fewer components is better .. */
+else
+return false; /* .. but not too few! */
+}
+}
+
+if (op->op == SWS_OP_CLEAR) {
+/* Clear pattern must match exactly, regardless of `entry->flexible` */
+for (int i = 0; i < 4; i++) {
+if (entry->unused[i] != !!op->c.q4[i].den)
+return 0;
+}
+}
+
+/* Flexible variants always match, but lower the score to prioritize more
+ * specific implementations if they exist */
+if (entry->flexib

[FFmpeg-devel] [PATCH v5 15/19] swscale/ops_memcpy: add 'memcpy' backend for plane->plane copies

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Provides a generic fast path for any operation list that can be decomposed
into a series of memcpy and memset operations.

25% faster than the x86 backend for yuv444p -> yuva444p
33% faster than the x86 backend for gray -> yuvj444p
---
 libswscale/Makefile |   1 +
 libswscale/ops.c|   2 +
 libswscale/ops_memcpy.c | 132 
 3 files changed, 135 insertions(+)
 create mode 100644 libswscale/ops_memcpy.c

diff --git a/libswscale/Makefile b/libswscale/Makefile
index d3cb7bc555..0fed799542 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -18,6 +18,7 @@ OBJS = alphablend.o \
ops.o\
ops_backend.o\
ops_chain.o  \
+   ops_memcpy.o \
ops_optimizer.o  \
options.o\
output.o \
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 5b259e13be..6a5b4f4158 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -28,8 +28,10 @@
 #include "ops_internal.h"
 
 extern SwsOpBackend backend_c;
+extern SwsOpBackend backend_murder;
 
 const SwsOpBackend * const ff_sws_op_backends[] = {
+&backend_murder,
 &backend_c,
 NULL
 };
diff --git a/libswscale/ops_memcpy.c b/libswscale/ops_memcpy.c
new file mode 100644
index 00..ef4784faa4
--- /dev/null
+++ b/libswscale/ops_memcpy.c
@@ -0,0 +1,132 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 "libavutil/avassert.h"
+
+#include "ops_backend.h"
+
+typedef struct MemcpyPriv {
+int num_planes;
+int index[4]; /* or -1 to clear plane */
+uint8_t clear_value[4];
+} MemcpyPriv;
+
+/* Memcpy backend for trivial cases */
+
+static void process(const SwsOpExec *exec, const void *priv,
+int x_start, int y_start, int x_end, int y_end)
+{
+const MemcpyPriv *p = priv;
+const int lines = y_end - y_start;
+av_assert1(x_start == 0 && x_end == exec->width);
+
+for (int i = 0; i < p->num_planes; i++) {
+uint8_t *out = exec->out[i];
+const int idx = p->index[i];
+if (idx < 0) {
+memset(out, p->clear_value[i], exec->out_stride[i] * lines);
+} else if (exec->out_stride[i] == exec->in_stride[idx]) {
+memcpy(out, exec->in[idx], exec->out_stride[i] * lines);
+} else {
+const int bytes = x_end * exec->block_size_out;
+const uint8_t *in = exec->in[idx];
+for (int y = y_start; y < y_end; y++) {
+memcpy(out, in, bytes);
+out += exec->out_stride[i];
+in  += exec->in_stride[idx];
+}
+}
+}
+}
+
+static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
+{
+MemcpyPriv p = {0};
+
+for (int n = 0; n < ops->num_ops; n++) {
+const SwsOp *op = &ops->ops[n];
+switch (op->op) {
+case SWS_OP_READ:
+if ((op->rw.packed && op->rw.elems != 1) || op->rw.frac)
+return AVERROR(ENOTSUP);
+for (int i = 0; i < op->rw.elems; i++)
+p.index[i] = i;
+break;
+
+case SWS_OP_SWIZZLE: {
+const MemcpyPriv orig = p;
+for (int i = 0; i < 4; i++) {
+/* Explicitly exclude swizzle masks that contain duplicates,
+ * because these are wasteful to implement as a memcpy */
+for (int j = 0; j < i; j++) {
+if (op->swizzle.in[i] == op->swizzle.in[j])
+return AVERROR(ENOTSUP);
+}
+p.index[i] = orig.index[op->swizzle.in[i]];
+}
+break;
+}
+
+case SWS_OP_CLEAR:
+for (int i = 0; i < 4; i++) {
+if (!op->c.q4[i].den)
+continue;
+if (op->c.q4[i].den != 1)
+return AVERROR(ENOTSUP);
+
+/* Ensure all bytes to be cleared are the same, be

[FFmpeg-devel] [PATCH v5 07/19] swscale: add SWS_UNSTABLE flag

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Give users and developers a way to opt in to the new format conversion code,
and more code from the swscale rewrite in general, even while development is
still ongoing.
---
 doc/APIchanges   | 3 +++
 doc/scaler.texi  | 4 
 libswscale/options.c | 1 +
 libswscale/swscale.h | 7 +++
 libswscale/version.h | 2 +-
 5 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 91710bb27d..ae5e4b366b 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
 
 API changes, most recent first:
 
+2025-04-xx - xx - lsws 9.1.100 - swscale.h
+  Add SWS_UNSTABLE flag.
+
 2025-05-21 - xx - lavu 60.3.100 - avassert.h
   Add av_unreachable() and av_assume() macros.
 
diff --git a/doc/scaler.texi b/doc/scaler.texi
index eb045de6b7..42b2377761 100644
--- a/doc/scaler.texi
+++ b/doc/scaler.texi
@@ -68,6 +68,10 @@ Select full chroma input.
 
 @item bitexact
 Enable bitexact output.
+
+@item unstable
+Allow the use of experimental new code. May subtly affect the output or even
+produce wrong results. For testing only.
 @end table
 
 @item srcw @var{(API only)}
diff --git a/libswscale/options.c b/libswscale/options.c
index feecae8c89..06e51dcfe9 100644
--- a/libswscale/options.c
+++ b/libswscale/options.c
@@ -50,6 +50,7 @@ static const AVOption swscale_options[] = {
 { "full_chroma_inp", "full chroma input", 0,  
AV_OPT_TYPE_CONST, { .i64 = SWS_FULL_CHR_H_INP }, .flags = VE, .unit = 
"sws_flags" },
 { "bitexact","bit-exact mode",0,  
AV_OPT_TYPE_CONST, { .i64 = SWS_BITEXACT   }, .flags = VE, .unit = 
"sws_flags" },
 { "error_diffusion", "error diffusion dither",0,  
AV_OPT_TYPE_CONST, { .i64 = SWS_ERROR_DIFFUSION}, .flags = VE, .unit = 
"sws_flags" },
+{ "unstable","allow experimental new code",   0,  
AV_OPT_TYPE_CONST, { .i64 = SWS_UNSTABLE   }, .flags = VE, .unit = 
"sws_flags" },
 
 { "param0",  "scaler param 0", OFFSET(scaler_params[0]), 
AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
 { "param1",  "scaler param 1", OFFSET(scaler_params[1]), 
AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, VE },
diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index b04aa182d2..4aa072009c 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -155,6 +155,13 @@ typedef enum SwsFlags {
 SWS_ACCURATE_RND   = 1 << 18,
 SWS_BITEXACT   = 1 << 19,
 
+/**
+ * Allow using experimental new code paths. This may be faster, slower,
+ * or produce different output, with semantics subject to change at any
+ * point in time. For testing and debugging purposes only.
+ */
+SWS_UNSTABLE = 1 << 20,
+
 /**
  * Deprecated flags.
  */
diff --git a/libswscale/version.h b/libswscale/version.h
index 148efd83eb..4e54701aba 100644
--- a/libswscale/version.h
+++ b/libswscale/version.h
@@ -28,7 +28,7 @@
 
 #include "version_major.h"
 
-#define LIBSWSCALE_VERSION_MINOR   0
+#define LIBSWSCALE_VERSION_MINOR   1
 #define LIBSWSCALE_VERSION_MICRO 100
 
 #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 19/19] swscale/graph: allow experimental use of new format handler

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Now, make it a Killer-Feature!
---
 libswscale/graph.c | 84 --
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/libswscale/graph.c b/libswscale/graph.c
index edf243823f..c72bc6540f 100644
--- a/libswscale/graph.c
+++ b/libswscale/graph.c
@@ -34,6 +34,7 @@
 #include "lut3d.h"
 #include "swscale_internal.h"
 #include "graph.h"
+#include "ops.h"
 
 static int pass_alloc_output(SwsPass *pass)
 {
@@ -455,6 +456,85 @@ static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat 
src, SwsFormat dst,
 return 0;
 }
 
+/*
+ * Format conversion *
+ */
+
+static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
+SwsPass *input, SwsPass **output)
+{
+const SwsPixelType type = SWS_PIXEL_F32;
+
+SwsContext *ctx = graph->ctx;
+SwsOpList *ops = NULL;
+int ret = AVERROR(ENOTSUP);
+
+/* Mark the entire new ops infrastructure as experimental for now */
+if (!(ctx->flags & SWS_UNSTABLE))
+goto fail;
+
+/* The new format conversion layer cannot scale for now */
+if (src.width != dst.width || src.height != dst.height ||
+src.desc->log2_chroma_h || src.desc->log2_chroma_w ||
+dst.desc->log2_chroma_h || dst.desc->log2_chroma_w)
+goto fail;
+
+/* The new code does not yet support alpha blending */
+if (src.desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
+ctx->alpha_blend != SWS_ALPHA_BLEND_NONE)
+goto fail;
+
+ops = ff_sws_op_list_alloc();
+if (!ops)
+return AVERROR(ENOMEM);
+ops->src = src;
+ops->dst = dst;
+
+ret = ff_sws_decode_pixfmt(ops, src.format);
+if (ret < 0)
+goto fail;
+ret = ff_sws_decode_colors(ctx, type, ops, src, &graph->incomplete);
+if (ret < 0)
+goto fail;
+ret = ff_sws_encode_colors(ctx, type, ops, dst, &graph->incomplete);
+if (ret < 0)
+goto fail;
+ret = ff_sws_encode_pixfmt(ops, dst.format);
+if (ret < 0)
+goto fail;
+
+av_log(ctx, AV_LOG_VERBOSE, "Conversion pass for %s -> %s:\n",
+   av_get_pix_fmt_name(src.format), av_get_pix_fmt_name(dst.format));
+
+av_log(ctx, AV_LOG_DEBUG, "Unoptimized operation list:\n");
+ff_sws_op_list_print(ctx, AV_LOG_DEBUG, ops);
+av_log(ctx, AV_LOG_DEBUG, "Optimized operation list:\n");
+
+ff_sws_op_list_optimize(ops);
+if (ops->num_ops == 0) {
+av_log(ctx, AV_LOG_VERBOSE, "  optimized into memcpy\n");
+ff_sws_op_list_free(&ops);
+*output = input;
+return 0;
+}
+
+ff_sws_op_list_print(ctx, AV_LOG_VERBOSE, ops);
+
+ret = ff_sws_compile_pass(graph, ops, 0, dst, input, output);
+if (ret < 0)
+goto fail;
+
+ret = 0;
+/* fall through */
+
+fail:
+ff_sws_op_list_free(&ops);
+if (ret == AVERROR(ENOTSUP))
+return add_legacy_sws_pass(graph, src, dst, input, output);
+return ret;
+}
+
+
 /**
  * Gamut and tone mapping *
  **/
@@ -524,7 +604,7 @@ static int adapt_colors(SwsGraph *graph, SwsFormat src, 
SwsFormat dst,
 if (fmt_in != src.format) {
 SwsFormat tmp = src;
 tmp.format = fmt_in;
-ret = add_legacy_sws_pass(graph, src, tmp, input, &input);
+ret = add_convert_pass(graph, src, tmp, input, &input);
 if (ret < 0)
 return ret;
 }
@@ -566,7 +646,7 @@ static int init_passes(SwsGraph *graph)
 src.color  = dst.color;
 
 if (!ff_fmt_equal(&src, &dst)) {
-ret = add_legacy_sws_pass(graph, src, dst, pass, &pass);
+ret = add_convert_pass(graph, src, dst, pass, &pass);
 if (ret < 0)
 return ret;
 }
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH v5 06/19] avutil/mem: add av_dynarray2_dup

2025-06-10 Thread Andreas Rheinhardt
Niklas Haas:
> On Tue, 10 Jun 2025 15:04:57 +0200 Niklas Haas  wrote:
>> From: Niklas Haas 
>>
>> Like av_memdup() but correctly rounds up to the nearest power of two so that
>> av_dynarray2_add() will continue to work on the duplicated list.
> 
> Just realized this is public, will add a Changelog entry and bump the API
> version before merging.
Is this version supposed to be merged?
Anyway, this function seems way too specialised to me.

- Andreas

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH v5 06/19] avutil/mem: add av_dynarray2_dup

2025-06-10 Thread Niklas Haas
On Tue, 10 Jun 2025 15:04:57 +0200 Niklas Haas  wrote:
> From: Niklas Haas 
>
> Like av_memdup() but correctly rounds up to the nearest power of two so that
> av_dynarray2_add() will continue to work on the duplicated list.

Just realized this is public, will add a Changelog entry and bump the API
version before merging.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH v5 06/19] avutil/mem: add av_dynarray2_dup

2025-06-10 Thread Andreas Rheinhardt
Niklas Haas:
> On Tue, 10 Jun 2025 15:55:35 +0200 Andreas Rheinhardt 
>  wrote:
>> Niklas Haas:
>>> On Tue, 10 Jun 2025 15:04:57 +0200 Niklas Haas  wrote:
 From: Niklas Haas 

 Like av_memdup() but correctly rounds up to the nearest power of two so 
 that
 av_dynarray2_add() will continue to work on the duplicated list.
>>>
>>> Just realized this is public, will add a Changelog entry and bump the API
>>> version before merging.
>> Is this version supposed to be merged?
>> Anyway, this function seems way too specialised to me.
> 
> What would you prefer? Simply having this logic inside swscale? I'm not
> very happy making cross-library assumptions about the exact resizing schedule.
> 

The behavior is documented: " * The array is reallocated when its number
of elements reaches powers of 2."
Alternatively, you could call add the elements in a loop.

> Alternatively, we could ditch the use of av_dynarray2 entirely.
> 

Fine by me.

- Andreas

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] ffprobe: add -codec: option

2025-06-10 Thread Maryla Ustarroz-Calonge via ffmpeg-devel
--- Begin Message ---
opt_codec() is mostly copied over from ffplay.c

Signed-off-by: Maryla Ustarroz-Calonge 
---
 Changelog |   2 +-
 fftools/ffprobe.c | 114 +-
 2 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/Changelog b/Changelog
index 4217449438..ae73611222 100644
--- a/Changelog
+++ b/Changelog
@@ -18,7 +18,7 @@ version :
 - APV encoding support through a libopenapv wrapper
 - VVC decoder supports all content of SCC (Screen Content Coding):
   IBC (Inter Block Copy), Palette Mode and ACT (Adaptive Color Transform
-
+- ffprobe -codec option
 
 version 7.1:
 - Raw Captions with Time (RCWT) closed caption demuxer
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 1346ed33c5..0124ce114c 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -36,6 +36,7 @@
 #include "libavutil/ambient_viewing_environment.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
+#include "libavutil/avutil.h"
 #include "libavutil/bprint.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/display.h"
@@ -130,6 +131,11 @@ static int use_byte_value_binary_prefix = 0;
 static int use_value_sexagesimal_format = 0;
 static int show_private_data= 1;
 
+static const char *audio_codec_name = NULL;
+static const char *data_codec_name = NULL;
+static const char *subtitle_codec_name = NULL;
+static const char *video_codec_name = NULL;
+
 #define SHOW_OPTIONAL_FIELDS_AUTO   -1
 #define SHOW_OPTIONAL_FIELDS_NEVER   0
 #define SHOW_OPTIONAL_FIELDS_ALWAYS  1
@@ -2284,6 +2290,64 @@ static void show_error(AVTextFormatContext *tfc, int err)
 avtext_print_section_footer(tfc);
 }
 
+static int get_decoder_by_name(const char *codec_name, const AVCodec **codec)
+{
+if (codec_name == NULL)
+return 0;
+
+*codec = avcodec_find_decoder_by_name(codec_name);
+if (*codec == NULL) {
+av_log(NULL, AV_LOG_ERROR,
+"No codec could be found with name '%s'\n", codec_name);
+return AVERROR(EINVAL);;
+}
+return 0;
+}
+
+static int set_decoders(AVFormatContext *fmt_ctx)
+{
+int ret;
+ret = get_decoder_by_name(audio_codec_name, &fmt_ctx->audio_codec);
+if (ret < 0) return ret;
+ret = get_decoder_by_name(data_codec_name, &fmt_ctx->data_codec);
+if (ret < 0) return ret;
+ret = get_decoder_by_name(subtitle_codec_name, &fmt_ctx->subtitle_codec);
+if (ret < 0) return ret;
+ret = get_decoder_by_name(video_codec_name, &fmt_ctx->video_codec);
+if (ret < 0) return ret;
+return 0;
+}
+
+static const AVCodec *get_decoder_for_stream(AVFormatContext *fmt_ctx, 
AVStream *stream)
+{
+const AVCodec *codec = NULL;
+switch (stream->codecpar->codec_type) {
+case AVMEDIA_TYPE_VIDEO:codec = fmt_ctx->video_codec; break;
+case AVMEDIA_TYPE_AUDIO:codec = fmt_ctx->audio_codec; break;
+case AVMEDIA_TYPE_SUBTITLE: codec = fmt_ctx->subtitle_codec; break;
+case AVMEDIA_TYPE_DATA: codec = fmt_ctx->data_codec; break;
+}
+
+if (codec != NULL)
+return codec;
+
+if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
+av_log(NULL, AV_LOG_WARNING,
+   "Failed to probe codec for input stream %d\n", stream->index);
+return NULL;
+}
+
+codec = avcodec_find_decoder(stream->codecpar->codec_id);
+if (codec == NULL) {
+av_log(NULL, AV_LOG_WARNING,
+   "Unsupported codec with id %d for input stream %d\n",
+   stream->codecpar->codec_id, stream->index);
+return NULL;
+}
+
+return codec;
+}
+
 static int open_input_file(InputFile *ifile, const char *filename,
const char *print_filename)
 {
@@ -2296,6 +2360,9 @@ static int open_input_file(InputFile *ifile, const char 
*filename,
 if (!fmt_ctx)
 return AVERROR(ENOMEM);
 
+err = set_decoders(fmt_ctx);
+if (err < 0)
+return err;
 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
 av_dict_set(&format_opts, "scan_all_pmts", "1", 
AV_DICT_DONT_OVERWRITE);
 scan_all_pmts_set = 1;
@@ -2350,20 +2417,10 @@ static int open_input_file(InputFile *ifile, const char 
*filename,
 
 ist->st = stream;
 
-if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
-av_log(NULL, AV_LOG_WARNING,
-   "Failed to probe codec for input stream %d\n",
-stream->index);
+codec = get_decoder_for_stream(fmt_ctx, stream);
+if (!codec)
 continue;
-}
 
-codec = avcodec_find_decoder(stream->codecpar->codec_id);
-if (!codec) {
-av_log(NULL, AV_LOG_WARNING,
-"Unsupported codec with id %d for input stream %d\n",
-stream->codecpar->codec_id, stream->index);
-continue;
-}
 {
 AVDictionary *opts;
 
@@ -2510,6 +2567,

Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Pavel Koshevoy
On Tue, Jun 10, 2025 at 4:11 PM Michael Niedermayer 
wrote:

> Hi Pavel
>
> On Tue, Jun 10, 2025 at 11:27:37AM -0600, Pavel Koshevoy wrote:
> > On Tue, Jun 10, 2025 at 9:29 AM Michael Niedermayer <
> mich...@niedermayer.cc>
> [...]
>
> > I have never had any intention of introducing a
> > security vulnerability.
>
> do you agree that the patch should be reverted ?
> (and also the 2 backports of it)
>

No, since I already provided a fix -- I would cherry-pick it to the
release/6.1 and release/7.1 as well, but you do as you wish.



>
>
> > If people want to keep this, it should be behind a flag and
> > > disabled by default.
> >
> >
> > I am not familiar with such flags ... are you suggesting a compile-time
> > flag, or a run-time flag?
> > A runtime flag would be preferable, because that would save me from
> having
> > to cross-compile win64 ffmpeg libs myself.
>
> runtime
>
>
> >
> >
> > Its not enough to fix our code that crashes, other applications
> > > similarly wont expect such id and type changes mid stream
> >
> >
> > IDK how likely a media type change is outside the 1_poc.mp4.
>
> 100% likelyness an exploit of this will use it
>
>
> > The sample
> > files I have don't do that.
>
> Your sample files are not exploits i assume. So obviously
> they dont
>
>
> > I can provide a 61MB clip of one such file, just a few seconds of SDR
> mpeg2
> > video/audio slate followed by a few seconds of HDR10 hevc video and eac3
> > audio... in case someone wants to work on making fftools support this.
>
> This file certainly is valuable and should be added to samples.ffmpeg.org
>
> BUT this security issue needs to be fixed, regardless of
> anyone adding support for such samples
>
> I dont think backporting midstream codec_id/type changes is a good
> idea btw.
>
> IMHO this should all be reverted (its a small 3 line patch)
> and then again start from scratch with review, testing, fuzzing, and
> runtime flag.
>
> PS: The researcher also wants a CVE# for this issue.
>

IDK what this means.



>
> thx
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> What is money laundering? Its paying someone and not telling the
> government.
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 1/3] vulkan: fix leak in FFVkExecPool

2025-06-10 Thread averne
---
 libavutil/vulkan.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index 
a989e080abd372b8977dce107100b9370fac8305..eea80d0775a87ed6683cb58d30ba9ba8d6c1dd26
 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -298,6 +298,8 @@ void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool 
*pool)
 av_freep(&sd->desc_sets);
 }
 
+av_freep(&pool->reg_shd);
+
 for (int i = 0; i < pool->pool_size; i++) {
 if (pool->cmd_buf_pools[i])
 vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pools[i],

-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 0/3] Fix memory leaks in vulkan ffv1 decoding

2025-06-10 Thread averne
This fixes a few leaks reported by LeakSanitizer.
I tested this on my Intel laptop running anv, with
these patches no more leaks are detected.

Signed-off-by: averne 
---
averne (3):
  vulkan: fix leak in FFVkExecPool
  vulkan/ffv1dec: fix leak in FFVulkanDecodeShared
  vulkan/ffv1dec: fix FFVkSPIRVCompiler leak

 libavcodec/vulkan_ffv1.c | 60 
 libavutil/vulkan.c   |  2 ++
 2 files changed, 27 insertions(+), 35 deletions(-)
---
base-commit: 4059bce713118f961d24b5f08a4881c5e7214f9b
change-id: 20250610-vk-ffv1-leaks-7f0722236745

Best regards,
-- 
averne 

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 3/3] vulkan/ffv1dec: fix FFVkSPIRVCompiler leak

2025-06-10 Thread averne
---
 libavcodec/vulkan_ffv1.c | 58 +++-
 1 file changed, 23 insertions(+), 35 deletions(-)

diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index 
8329b5d7dfad18de96884ea2c1f6f186682e430c..b02bc71683fd7d06dad3f4cf667ee3e8c57f3c83
 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -1033,23 +1033,17 @@ static int vk_decode_ffv1_init(AVCodecContext *avctx)
 
 /* Intermediate frame pool for RCT */
 for (int i = 0; i < 2; i++) { /* 16/32 bit */
-err = init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref[i],
-i ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16);
-if (err < 0)
-return err;
+RET(init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref[i],
+  i ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16));
 }
 
 /* Setup shader */
-err = init_setup_shader(f, &ctx->s, &ctx->exec_pool, spv, &fv->setup);
-if (err < 0)
-return err;
+RET(init_setup_shader(f, &ctx->s, &ctx->exec_pool, spv, &fv->setup));
 
 /* Reset shaders */
 for (int i = 0; i < 2; i++) { /* AC/Golomb */
-err = init_reset_shader(f, &ctx->s, &ctx->exec_pool,
-spv, &fv->reset[i], !i ? AC_RANGE_CUSTOM_TAB : 
0);
-if (err < 0)
-return err;
+RET(init_reset_shader(f, &ctx->s, &ctx->exec_pool,
+  spv, &fv->reset[i], !i ? AC_RANGE_CUSTOM_TAB : 
0));
 }
 
 /* Decode shaders */
@@ -1059,39 +1053,31 @@ static int vk_decode_ffv1_init(AVCodecContext *avctx)
 AVHWFramesContext *dec_frames_ctx;
 dec_frames_ctx = k ? (AVHWFramesContext 
*)fv->intermediate_frames_ref[i]->data :
  (AVHWFramesContext 
*)avctx->hw_frames_ctx->data;
-err = init_decode_shader(f, &ctx->s, &ctx->exec_pool,
- spv, &fv->decode[i][j][k],
- dec_frames_ctx,
- (AVHWFramesContext 
*)avctx->hw_frames_ctx->data,
- i,
- !j ? AC_RANGE_CUSTOM_TAB : 
AC_GOLOMB_RICE,
- k);
-if (err < 0)
-return err;
+RET(init_decode_shader(f, &ctx->s, &ctx->exec_pool,
+   spv, &fv->decode[i][j][k],
+   dec_frames_ctx,
+   (AVHWFramesContext 
*)avctx->hw_frames_ctx->data,
+   i,
+   !j ? AC_RANGE_CUSTOM_TAB : 
AC_GOLOMB_RICE,
+   k));
 }
 }
 }
 
 /* Range coder data */
-err = ff_ffv1_vk_init_state_transition_data(&ctx->s,
-&fv->rangecoder_static_buf,
-f);
-if (err < 0)
-return err;
+RET(ff_ffv1_vk_init_state_transition_data(&ctx->s,
+  &fv->rangecoder_static_buf,
+  f));
 
 /* Quantization table data */
-err = ff_ffv1_vk_init_quant_table_data(&ctx->s,
-   &fv->quant_buf,
-   f);
-if (err < 0)
-return err;
+RET(ff_ffv1_vk_init_quant_table_data(&ctx->s,
+ &fv->quant_buf,
+ f));
 
 /* CRC table buffer */
-err = ff_ffv1_vk_init_crc_table_data(&ctx->s,
- &fv->crc_tab_buf,
- f);
-if (err < 0)
-return err;
+RET(ff_ffv1_vk_init_crc_table_data(&ctx->s,
+   &fv->crc_tab_buf,
+   f));
 
 /* Update setup global descriptors */
 RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
@@ -1124,6 +1110,8 @@ static int vk_decode_ffv1_init(AVCodecContext *avctx)
 }
 
 fail:
+spv->uninit(&spv);
+
 return err;
 }
 

-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 2/3] vulkan/ffv1dec: fix leak in FFVulkanDecodeShared

2025-06-10 Thread averne
---
 libavcodec/vulkan_ffv1.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavcodec/vulkan_ffv1.c b/libavcodec/vulkan_ffv1.c
index 
c839f4c3879e158e0c0bfb4f5a833fff0b83d2f0..8329b5d7dfad18de96884ea2c1f6f186682e430c
 100644
--- a/libavcodec/vulkan_ffv1.c
+++ b/libavcodec/vulkan_ffv1.c
@@ -995,6 +995,8 @@ static void vk_decode_ffv1_uninit(FFVulkanDecodeShared *ctx)
 av_buffer_pool_uninit(&fv->slice_state_pool);
 av_buffer_pool_uninit(&fv->slice_offset_pool);
 av_buffer_pool_uninit(&fv->slice_status_pool);
+
+av_freep(&fv);
 }
 
 static int vk_decode_ffv1_init(AVCodecContext *avctx)

-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 1/2] lavf/webvttenc: avio_flush() output

2025-06-10 Thread Marton Balint



On Tue, 10 Jun 2025, Andreas Rheinhardt wrote:


Tomas Härdin:

Hi

These two patches are a bit of a warmup for another pass at streamable
subtitles. FATE passes.

/Tomas


Users who want this should set the generic flush_packets options
appropriately.


Agreed, explicit avio_flush() in packet writer functions is a bad idea 
because it flushes IO even on not latency critical outputs.


There is some magic in the flush_if_needed() function of mux.c, which by 
default uses avio_write_marker() to flush after every packet for streaming 
outputs only.


Regards,
Marton
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 0/3] Fix memory leaks in vulkan ffv1 decoding

2025-06-10 Thread Lynne

On 11/06/2025 03:58, averne wrote:

This fixes a few leaks reported by LeakSanitizer.
I tested this on my Intel laptop running anv, with
these patches no more leaks are detected.

Signed-off-by: averne 
---
averne (3):
   vulkan: fix leak in FFVkExecPool
   vulkan/ffv1dec: fix leak in FFVulkanDecodeShared
   vulkan/ffv1dec: fix FFVkSPIRVCompiler leak

  libavcodec/vulkan_ffv1.c | 60 
  libavutil/vulkan.c   |  2 ++
  2 files changed, 27 insertions(+), 35 deletions(-)
---
base-commit: 4059bce713118f961d24b5f08a4881c5e7214f9b
change-id: 20250610-vk-ffv1-leaks-7f0722236745

Best regards,


LGTM
Thanks, pushed the patchset.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 03/19] swscale/format: add ff_fmt_clear()

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Reset an SwsFormat to its fully unset/invalid state.
---
 libswscale/format.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/libswscale/format.h b/libswscale/format.h
index 3b6d745159..be92038f4f 100644
--- a/libswscale/format.h
+++ b/libswscale/format.h
@@ -85,6 +85,20 @@ typedef struct SwsFormat {
 SwsColor color;
 } SwsFormat;
 
+static inline void ff_fmt_clear(SwsFormat *fmt)
+{
+*fmt = (SwsFormat) {
+.format = AV_PIX_FMT_NONE,
+.range  = AVCOL_RANGE_UNSPECIFIED,
+.csp= AVCOL_SPC_UNSPECIFIED,
+.loc= AVCHROMA_LOC_UNSPECIFIED,
+.color = {
+.prim = AVCOL_PRI_UNSPECIFIED,
+.trc  = AVCOL_TRC_UNSPECIFIED,
+},
+};
+}
+
 /**
  * This function also sanitizes and strips the input data, removing irrelevant
  * fields for certain formats.
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 05/19] tests/checkasm: generalize DEF_CHECKASM_CHECK_FUNC to floats

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

We split the standard macro into its body (implementation) and declaration,
and use a macro argument in place of the raw `memcmp` call, with the major
difference that we now take the number of pixels to compare instead of the
number of bytes (to match the signature of float_near_ulp_array).
---
 tests/checkasm/checkasm.c | 52 ++-
 tests/checkasm/checkasm.h |  7 ++
 2 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 71d1e5766c..f393a0cb96 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -1187,14 +1187,8 @@ static int check_err(const char *file, int line,
 return 0;
 }
 
-#define DEF_CHECKASM_CHECK_FUNC(type, fmt) \
-int checkasm_check_##type(const char *file, int line, \
-  const type *buf1, ptrdiff_t stride1, \
-  const type *buf2, ptrdiff_t stride2, \
-  int w, int h, const char *name, \
-  int align_w, int align_h, \
-  int padding) \
-{ \
+#define DEF_CHECKASM_CHECK_BODY(compare, type, fmt) \
+do { \
 int64_t aligned_w = (w - 1LL + align_w) & ~(align_w - 1); \
 int64_t aligned_h = (h - 1LL + align_h) & ~(align_h - 1); \
 int err = 0; \
@@ -1204,7 +1198,7 @@ int checkasm_check_##type(const char *file, int line, \
 stride1 /= sizeof(*buf1); \
 stride2 /= sizeof(*buf2); \
 for (y = 0; y < h; y++) \
-if (memcmp(&buf1[y*stride1], &buf2[y*stride2], w*sizeof(*buf1))) \
+if (!compare(&buf1[y*stride1], &buf2[y*stride2], w)) \
 break; \
 if (y != h) { \
 if (check_err(file, line, name, w, h, &err)) \
@@ -1226,38 +1220,50 @@ int checkasm_check_##type(const char *file, int line, \
 buf2 -= h*stride2; \
 } \
 for (y = -padding; y < 0; y++) \
-if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
-   (w + 2*padding)*sizeof(*buf1))) { \
+if (!compare(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+ w + 2*padding)) { \
 if (check_err(file, line, name, w, h, &err)) \
 return 1; \
 fprintf(stderr, " overwrite above\n"); \
 break; \
 } \
 for (y = aligned_h; y < aligned_h + padding; y++) \
-if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
-   (w + 2*padding)*sizeof(*buf1))) { \
+if (!compare(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+ w + 2*padding)) { \
 if (check_err(file, line, name, w, h, &err)) \
 return 1; \
 fprintf(stderr, " overwrite below\n"); \
 break; \
 } \
 for (y = 0; y < h; y++) \
-if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
-   padding*sizeof(*buf1))) { \
+if (!compare(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+ padding)) { \
 if (check_err(file, line, name, w, h, &err)) \
 return 1; \
 fprintf(stderr, " overwrite left\n"); \
 break; \
 } \
 for (y = 0; y < h; y++) \
-if (memcmp(&buf1[y*stride1 + aligned_w], &buf2[y*stride2 + aligned_w], 
\
-   padding*sizeof(*buf1))) { \
+if (!compare(&buf1[y*stride1 + aligned_w], &buf2[y*stride2 + 
aligned_w], \
+ padding)) { \
 if (check_err(file, line, name, w, h, &err)) \
 return 1; \
 fprintf(stderr, " overwrite right\n"); \
 break; \
 } \
 return err; \
+} while (0)
+
+#define cmp_int(a, b, len) (!memcmp(a, b, (len) * sizeof(*(a
+#define DEF_CHECKASM_CHECK_FUNC(type, fmt) \
+int checkasm_check_##type(const char *file, int line, \
+  const type *buf1, ptrdiff_t stride1, \
+  const type *buf2, ptrdiff_t stride2, \
+  int w, int h, const char *name, \
+  int align_w, int align_h, \
+  int padding) \
+{ \
+DEF_CHECKASM_CHECK_BODY(cmp_int, type, fmt); \
 }
 
 DEF_CHECKASM_CHECK_FUNC(uint8_t,  "%02x")
@@ -1265,3 +1271,15 @@ DEF_CHECKASM_CHECK_FUNC(uint16_t, "%04x")
 DEF_CHECKASM_CHECK_FUNC(uint32_t, "%08x")
 DEF_CHECKASM_CHECK_FUNC(int16_t,  "%6d")
 DEF_CHECKASM_CHECK_FUNC(int32_t,  "%9d")
+
+int checkasm_check_float_ulp(const char *file, int line,
+ const float *buf1, ptrdiff_t stride1,
+ const float *buf2, ptrdiff_t stride2,
+ int w, int h, const char *name,
+ unsigned max_ulp, int align_w, int align_h,
+ int padding)
+{
+#define cmp_float(a, b, len) float_near_ulp_array(a, b, max_ulp, len)

Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Michael Niedermayer
On Mon, Jun 09, 2025 at 09:45:28PM -0600, Pavel Koshevoy wrote:
> Fixes 'ffprobe 1_poc.mp4' segfault introduced with
> commit 0021484d05f9b0f032fa319399de6e24eea0c04f
> 
> codec_close should not assume that the codec_id did not change.
> ---
>  libavformat/demux.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/libavformat/demux.c b/libavformat/demux.c
> index ecd4f40da9..3749ab67a3 100644
> --- a/libavformat/demux.c
> +++ b/libavformat/demux.c
> @@ -1292,9 +1292,15 @@ static int codec_close(FFStream *sti)
>  {
>  AVCodecContext *avctx_new = NULL;
>  AVCodecParameters *par_tmp = NULL;
> +const AVCodec *new_codec = NULL;
>  int ret;
>  
> -avctx_new = avcodec_alloc_context3(sti->avctx->codec);
> +new_codec =
> +  (sti->avctx->codec_id != sti->pub.codecpar->codec_id) ?
> +  avcodec_find_decoder(sti->pub.codecpar->codec_id) :
> +  sti->avctx->codec;
> +
> +avctx_new = avcodec_alloc_context3(new_codec);
>  if (!avctx_new) {
>  ret = AVERROR(ENOMEM);
>  goto fail;

This is not about request_probe
but about the mpegts demuxer randomly changeing codec id midstream

I belive the patch should be reverted that causes this. I dont think
applications expect such mid stream changes either

I hope andreas can take a look and correct me if iam missing something
but it looks a bit sketchy to me

If a codec changes mid stream i belive a new AVStream
should be created. It could be a audio stream switches to video
or data or subtitle.

If any stream as detected initially can become any other type later
this complicates user applications and filter graphs
Also the management of AVPackets is probably rather non trivial
if the stream_index is not enough to identify which decoder it belongs to

thx

[...]
-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Old school: Use the lowest level language in which you can solve the problem
conveniently.
New school: Use the highest level language in which the latest supercomputer
can solve the problem without the user falling asleep waiting.


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 0/3] tools/ffmpeg-sg: Add show-graph wrapper scripts (aka killer feature)

2025-06-10 Thread softworkz .
> -Original Message-
> From: Kieran Kunhya 
> Sent: Dienstag, 10. Juni 2025 00:49
> To: FFmpeg development discussions and patches  de...@ffmpeg.org>
> Cc: softworkz 
> Subject: Re: [FFmpeg-devel] [PATCH 0/3] tools/ffmpeg-sg: Add show-
> graph wrapper scripts (aka killer feature)
> 
> On Mon, 9 Jun 2025, 20:24 ffmpegagent,  gmail@ffmpeg.org>
> wrote:
> 
> > The "killer feature" returns!
> >
> > Different approach - same procedure:
> >
> >  * Add -sg to your FFmpeg command line
> >  * But now it's not
> >* ./ffmpeg -sg x but
> >* ./ffmpeg-sg x
> >
> 
> Why does this need to be part of FFmpeg if it's a wrapper script to
> spawn a
> web browser (nothing to do with FFmpeg's actual purpose of processing
> multimedia).
> 
> Kieran


Hi Kieran,

of course that's a legitimate question, and a question that could be asked
for almost any new feature in FFmpeg.
Obviously, there is no forcing reason for which it would _need_ to be included,
so I can only say why it _should_ be included in FFmpeg IMHO:


- Highly Useful
  
  If you haven't seen what it is and what it does, than I would suggest to
  everybody to try it out or to look at some of the examples:

  https://softworkz.github.io/ffmpeg_output_apis/2_hwa_qsv.html
  https://softworkz.github.io/ffmpeg_output_apis/3_complex_graphs.html

  This should also answer your question about what it has to do with "FFmpeg'
  actual purpose of processing multimedia": FFmpeg has a command line
  interface and it's often not clear to everybody how a certain command line
  is actually interpreted and executed by FFmpeg. This is helpful for 
  both beginners and advanced users of FFmpeg (e.g. when things get complex
  like in the second example).
  Even Michael said he finds it useful and Niklas Haas had voiced a need
  for visualizing the negotiated image formats between filters, earlier this
  year.


- Highly Convenient

  This core functionality for the above is already merged into master, but
  it's rather painful to make use of it
  - You need to remember the command line parameters
  - You need to type them
  - You need to determined a name for the output html file
  - You need to change it each time when you want to compare commands
  - You need to manually open the output in a browser

  It becomes highly convenient when the only thing you need to do and 
  remember is to append "-sg" to any command whenever you need it and
  everything else happens automatically.
  You can try many command variations and it creates tabs in your 
  browser between you can switch can compare the different graphs.


- Instant Availability

  This simply means that whenever and wherever you need it...
  => it's already there

  It is part of the build output, which means all developers that you
  can compile, test your work and when you want to visualize the graph
  you just need to append -sg and it works - without doing any extra
  work. 
  Same for make install and all kinds of distribution packages.
  When this is given, we can add a note to the documentation and make
  this available to Millions of users.
  If it would be just scripts for download from "somewhere", then it
  wouldn't be a feature available to Millions, but just something 
  for a few dozens of people who would ever know about it.


Those considerations combined is what had originally brought me
to the tag line that some found funny and others rather "immature":

Highly Useful + Convenient + Instant Availability = "Killer Feature"


It's helpful for the masses => it should be available to the masses.
This is why I believe that it should be included in FFmpeg.

Best regards,
softworkz















___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 2/2] tests: Add media100 decoder test

2025-06-10 Thread Zhao Zhili
From: Zhao Zhili 

---
The sample comes from 
https://trac.ffmpeg.org/attachment/ticket/959/12%2027_Volcano%20Zoom-Dissolve-F-8.mov
put it to mjpegb/media100.mov

 tests/fate/video.mak|  3 +++
 tests/ref/fate/media100 | 30 ++
 2 files changed, 33 insertions(+)
 create mode 100644 tests/ref/fate/media100

diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index dd886843e7..24889824b4 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -257,6 +257,9 @@ fate-mimic: CMD = framecrc -idct simple -i 
$(TARGET_SAMPLES)/mimic/mimic2-womanl
 FATE_VIDEO-$(call FRAMECRC, MOV, MJPEGB) += fate-mjpegb
 fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i 
$(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an
 
+FATE_VIDEO-$(call FRAMECRC, MOV, MEDIA100) += fate-media100
+fate-media100: CMD = framecrc -idct simple -fflags +bitexact -i 
$(TARGET_SAMPLES)/mjpegb/media100.mov
+
 FATE_VIDEO-$(call FRAMECRC, AVI, MJPEG) += fate-mjpeg-ticket3229
 fate-mjpeg-ticket3229: CMD = framecrc -idct simple -fflags +bitexact -i 
$(TARGET_SAMPLES)/mjpeg/mjpeg_field_order.avi -an
 
diff --git a/tests/ref/fate/media100 b/tests/ref/fate/media100
new file mode 100644
index 00..7a92c5cc21
--- /dev/null
+++ b/tests/ref/fate/media100
@@ -0,0 +1,30 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 768x576
+#sar 0: 0/1
+0,  0,  0,1,   884736, 0x22304315
+0,  1,  1,1,   884736, 0x896fcaf0
+0,  2,  2,1,   884736, 0x2e25b031
+0,  3,  3,1,   884736, 0x9d0cdf84
+0,  4,  4,1,   884736, 0x90c799b6
+0,  5,  5,1,   884736, 0x80ac6b03
+0,  6,  6,1,   884736, 0x46cfbd02
+0,  7,  7,1,   884736, 0xee2b4bdb
+0,  8,  8,1,   884736, 0x7876581e
+0,  9,  9,1,   884736, 0x19490d15
+0, 10, 10,1,   884736, 0x6c37db8d
+0, 11, 11,1,   884736, 0xe6a198ae
+0, 12, 12,1,   884736, 0x893d08af
+0, 13, 13,1,   884736, 0xb52bd038
+0, 14, 14,1,   884736, 0x7074bb1b
+0, 15, 15,1,   884736, 0xd32ed044
+0, 16, 16,1,   884736, 0x9592d482
+0, 17, 17,1,   884736, 0x9fcd144b
+0, 18, 18,1,   884736, 0xba1c73a2
+0, 19, 19,1,   884736, 0x5fd7c0e7
+0, 20, 20,1,   884736, 0xc3f05ed4
+0, 21, 21,1,   884736, 0x333d0e9c
+0, 22, 22,1,   884736, 0x9063fd20
+0, 23, 23,1,   884736, 0xc4508928
+0, 24, 24,1,   884736, 0x1428b800
-- 
2.46.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH 1/2] avcodec/decode: Workaround for media100 decoding failure issue

2025-06-10 Thread Zhao Zhili
From: Zhao Zhili 

This is a regression since 1c170613.
---
 libavcodec/decode.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index ef09568381..7e47a2971c 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -204,9 +204,14 @@ static int decode_bsfs_init(AVCodecContext *avctx)
 ret = av_bsf_init(avci->bsf);
 if (ret < 0)
 goto fail;
-ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
-if (ret < 0)
-goto fail;
+/* Don't copy par_out to avcodec context if bsf changed codec ID,
+ * e.g., media100_to_mjpegb
+ */
+if (avctx->codec_id == avci->bsf->par_out->codec_id) {
+ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out);
+if (ret < 0)
+goto fail;
+}
 
 return 0;
 fail:
-- 
2.46.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 00/19] swscale: new ops framework

2025-06-10 Thread Niklas Haas
Changes since v4:
- minor cosmetic fixes
- drop unneeded -Wno-uninitialized (breaks on MSVC)
- change semantics of SwsGraph.setup() to make more sense (and fix
  a bug where it would not work correctly with multiple passes)
- introduce and use av_dynarray2_dup() instead of av_memdup() for safely
  duplicating SwsOpList
- fix a double free when no backend was found for an SwsOpList
- fix insufficient logic on matching SWS_OP_CLEAR
- avoid the use of periods in asm globals called from C (breaks on macOS)

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 01/19] swscale/graph: pass per-pass image pointers to setup()

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This behavior had no real justification and was just incredibly confusing,
since the in/out pointers passet to setup() did not match those passed to
run(), all for what is arguably an exception anyways (the palette setup).
---
 libswscale/graph.c | 12 
 libswscale/graph.h |  2 --
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/libswscale/graph.c b/libswscale/graph.c
index dc7784aa49..edf243823f 100644
--- a/libswscale/graph.c
+++ b/libswscale/graph.c
@@ -169,6 +169,8 @@ static void free_legacy_swscale(void *priv)
 static void setup_legacy_swscale(const SwsImg *out, const SwsImg *in,
  const SwsPass *pass)
 {
+const SwsGraph *graph = pass->graph;
+const SwsImg *in_orig = &graph->exec.input;
 SwsContext *sws = pass->priv;
 SwsInternal *c = sws_internal(sws);
 if (sws->flags & SWS_BITEXACT && sws->dither == SWS_DITHER_ED && 
c->dither_error[0]) {
@@ -177,7 +179,7 @@ static void setup_legacy_swscale(const SwsImg *out, const 
SwsImg *in,
 }
 
 if (usePal(sws->src_format))
-ff_update_palette(c, (const uint32_t *) in->data[1]);
+ff_update_palette(c, (const uint32_t *) in_orig->data[1]);
 }
 
 static inline SwsContext *slice_ctx(const SwsPass *pass, int y)
@@ -710,10 +712,12 @@ void ff_sws_graph_run(SwsGraph *graph, uint8_t *const 
out_data[4],
 memcpy(in->linesize,  in_linesize,  sizeof(in->linesize));
 
 for (int i = 0; i < graph->num_passes; i++) {
-const SwsPass *pass = graph->passes[i];
+const SwsPass *pass= graph->passes[i];
 graph->exec.pass = pass;
-if (pass->setup)
-pass->setup(out, in, pass);
+if (pass->setup) {
+pass->setup(pass->output.fmt != AV_PIX_FMT_NONE ? &pass->output : 
out,
+pass->input ? &pass->input->output : in, pass);
+}
 avpriv_slicethread_execute(graph->slicethread, pass->num_slices, 0);
 }
 }
diff --git a/libswscale/graph.h b/libswscale/graph.h
index 0630b31ce6..b829bac88c 100644
--- a/libswscale/graph.h
+++ b/libswscale/graph.h
@@ -92,8 +92,6 @@ struct SwsPass {
 
 /**
  * Called once from the main thread before running the filter. Optional.
- * `out` and `in` always point to the main image input/output, regardless
- * of `input` and `output` fields.
  */
 void (*setup)(const SwsImg *out, const SwsImg *in, const SwsPass *pass);
 
-- 
2.49.0

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH 0/3] tools/ffmpeg-sg: Add show-graph wrapper scripts (aka killer feature)

2025-06-10 Thread softworkz .



> -Original Message-
> From: ffmpeg-devel  On Behalf Of
> softworkz .
> Sent: Dienstag, 10. Juni 2025 15:32
> To: Kieran Kunhya ; FFmpeg development
> discussions and patches 
> Subject: Re: [FFmpeg-devel] [PATCH 0/3] tools/ffmpeg-sg: Add show-
> graph wrapper scripts (aka killer feature)
> 
> > -Original Message-
> > From: Kieran Kunhya 
> > Sent: Dienstag, 10. Juni 2025 00:49
> > To: FFmpeg development discussions and patches  > de...@ffmpeg.org>
> > Cc: softworkz 
> > Subject: Re: [FFmpeg-devel] [PATCH 0/3] tools/ffmpeg-sg: Add show-
> > graph wrapper scripts (aka killer feature)
> >
> > On Mon, 9 Jun 2025, 20:24 ffmpegagent,  > gmail@ffmpeg.org>
> > wrote:
> >
> > > The "killer feature" returns!
> > >
> > > Different approach - same procedure:
> > >
> > >  * Add -sg to your FFmpeg command line
> > >  * But now it's not
> > >* ./ffmpeg -sg x but
> > >* ./ffmpeg-sg x
> > >
> >
> > Why does this need to be part of FFmpeg if it's a wrapper script to
> > spawn a
> > web browser (nothing to do with FFmpeg's actual purpose of
> processing
> > multimedia).
> >
> > Kieran
> 
> 
> Hi Kieran,
> 
> of course that's a legitimate question, and a question that could be
> asked
> for almost any new feature in FFmpeg.
> Obviously, there is no forcing reason for which it would _need_ to be
> included,
> so I can only say why it _should_ be included in FFmpeg IMHO:
> 
> 
> - Highly Useful
> 
>   If you haven't seen what it is and what it does, than I would
> suggest to
>   everybody to try it out or to look at some of the examples:
> 
>   https://softworkz.github.io/ffmpeg_output_apis/2_hwa_qsv.html
> 
> https://softworkz.github.io/ffmpeg_output_apis/3_complex_graphs.html
> 
>   This should also answer your question about what it has to do with
> "FFmpeg'
>   actual purpose of processing multimedia": FFmpeg has a command line
>   interface and it's often not clear to everybody how a certain
> command line
>   is actually interpreted and executed by FFmpeg. This is helpful for
>   both beginners and advanced users of FFmpeg (e.g. when things get
> complex
>   like in the second example).
>   Even Michael said he finds it useful and Niklas Haas had voiced a
> need
>   for visualizing the negotiated image formats between filters,
> earlier this
>   year.
> 
> 
> - Highly Convenient
> 
>   This core functionality for the above is already merged into
> master, but
>   it's rather painful to make use of it
>   - You need to remember the command line parameters
>   - You need to type them
>   - You need to determined a name for the output html file
>   - You need to change it each time when you want to compare commands
>   - You need to manually open the output in a browser
> 
>   It becomes highly convenient when the only thing you need to do and
>   remember is to append "-sg" to any command whenever you need it and
>   everything else happens automatically.
>   You can try many command variations and it creates tabs in your
>   browser between you can switch can compare the different graphs.
> 
> 
> - Instant Availability
> 
>   This simply means that whenever and wherever you need it...
>   => it's already there
> 
>   It is part of the build output, which means all developers that you
>   can compile, test your work and when you want to visualize the
> graph
>   you just need to append -sg and it works - without doing any extra
>   work.
>   Same for make install and all kinds of distribution packages.
>   When this is given, we can add a note to the documentation and make
>   this available to Millions of users.
>   If it would be just scripts for download from "somewhere", then it
>   wouldn't be a feature available to Millions, but just something
>   for a few dozens of people who would ever know about it.
> 
> 
> Those considerations combined is what had originally brought me
> to the tag line that some found funny and others rather "immature":
> 
> Highly Useful + Convenient + Instant Availability = "Killer Feature"
> 
> 
> It's helpful for the masses => it should be available to the masses.
> This is why I believe that it should be included in FFmpeg.
> 
> Best regards,
> softworkz
> 
> ___


There's also once another angle of view that should be considered when
assessing the relevance of the feature: 

Learning and Understanding FFmpeg

Looking at the documentation under https://ffmpeg.org/ffmpeg.html we
can see that a lot of effort has been taken to make FFmpeg's ways of
operation transparent and understandable to all new users.

Don't all those ASCII graphics look familiar? Essentially, the show-
graph feature gives you exactly the same insights than the introductory
topics of the documentation - not just in an exemplary way but for the
exact command lines that you are supplying to FFmpeg.
This helps to reduce the learning curve for using of FFmpeg - which 
is non-trivial - by a magnitude.

Even those who don't think that they would

Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Michael Niedermayer
Hi Pavel

On Tue, Jun 10, 2025 at 08:42:08AM -0600, Pavel Koshevoy wrote:
> On Tue, Jun 10, 2025, 07:39 Michael Niedermayer 
> wrote:
> 
> > On Mon, Jun 09, 2025 at 09:45:28PM -0600, Pavel Koshevoy wrote:
> > > Fixes 'ffprobe 1_poc.mp4' segfault introduced with
> > > commit 0021484d05f9b0f032fa319399de6e24eea0c04f
> > >
> > > codec_close should not assume that the codec_id did not change.
> > > ---
> > >  libavformat/demux.c | 8 +++-
> > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/libavformat/demux.c b/libavformat/demux.c
> > > index ecd4f40da9..3749ab67a3 100644
> > > --- a/libavformat/demux.c
> > > +++ b/libavformat/demux.c
> > > @@ -1292,9 +1292,15 @@ static int codec_close(FFStream *sti)
> > >  {
> > >  AVCodecContext *avctx_new = NULL;
> > >  AVCodecParameters *par_tmp = NULL;
> > > +const AVCodec *new_codec = NULL;
> > >  int ret;
> > >
> > > -avctx_new = avcodec_alloc_context3(sti->avctx->codec);
> > > +new_codec =
> > > +  (sti->avctx->codec_id != sti->pub.codecpar->codec_id) ?
> > > +  avcodec_find_decoder(sti->pub.codecpar->codec_id) :
> > > +  sti->avctx->codec;
> > > +
> > > +avctx_new = avcodec_alloc_context3(new_codec);
> > >  if (!avctx_new) {
> > >  ret = AVERROR(ENOMEM);
> > >  goto fail;
> >
> > This is not about request_probe
> > but about the mpegts demuxer randomly changeing codec id midstream
> >
> 
> 
> I have several real (not crafted like 1_poc.mp4 is) .ts files where codec
> changes from mpeg2video to hevc, from mpeg2audio to eac3 -- while remaining
> on the same PIDs.  I also have .ts files where codec switches between
> mpeg2video and h264.  VLC was able to play such files, but my ffmpeg based
> player (apprenticevideo) could not even see that the codecs changed prior
> to 0021484d05f9b0f032fa319399de6e24eea0c04f.

do these work ?
(work here means the result is a complete file with all frames from the input
 and is playable and seekable)
./ffmpeg -i input.ts -codec copy output.ts
./ffmpeg -i input.ts -codec copy output.mp4
./ffmpeg -i input.ts -vcodec libx264 -acodec libopus output.mkv


> Reverting isn't really an
> option for me, not unless there is a better solution presented.

is adding an exploitable security issue an option for you ?

If people want to keep this, it should be behind a flag and
disabled by default.

Its not enough to fix our code that crashes, other applications
similarly wont expect such id and type changes mid stream


> 
> As I am primarily a public ffmpeg API user -- I am well out of my depth
> when it comes to making non-trivial changes to ffmpegs internals.

Thats ok, but you applied this change to ffmpeg internals, and here
you say "I am well out of my depth when it comes to making non-trivial changes 
to ffmpegs internals."

Did someone review this ?

commit 0021484d05f9b0f032fa319399de6e24eea0c04f
Author: Pavel Koshevoy 
AuthorDate: Sun May 18 08:57:31 2025 -0600
Commit: Pavel Koshevoy 
CommitDate: Sun May 18 08:57:31 2025 -0600


thx

[...]

-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The greatest way to live with honor in this world is to be what we pretend
to be. -- Socrates


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Pavel Koshevoy
On Tue, Jun 10, 2025 at 9:29 AM Michael Niedermayer 
wrote:

> Hi Pavel
>
> On Tue, Jun 10, 2025 at 08:42:08AM -0600, Pavel Koshevoy wrote:
> > On Tue, Jun 10, 2025, 07:39 Michael Niedermayer 
> > wrote:
> >
> > > On Mon, Jun 09, 2025 at 09:45:28PM -0600, Pavel Koshevoy wrote:
> > > > Fixes 'ffprobe 1_poc.mp4' segfault introduced with
> > > > commit 0021484d05f9b0f032fa319399de6e24eea0c04f
> > > >
> > > > codec_close should not assume that the codec_id did not change.
> > > > ---
> > > >  libavformat/demux.c | 8 +++-
> > > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/libavformat/demux.c b/libavformat/demux.c
> > > > index ecd4f40da9..3749ab67a3 100644
> > > > --- a/libavformat/demux.c
> > > > +++ b/libavformat/demux.c
> > > > @@ -1292,9 +1292,15 @@ static int codec_close(FFStream *sti)
> > > >  {
> > > >  AVCodecContext *avctx_new = NULL;
> > > >  AVCodecParameters *par_tmp = NULL;
> > > > +const AVCodec *new_codec = NULL;
> > > >  int ret;
> > > >
> > > > -avctx_new = avcodec_alloc_context3(sti->avctx->codec);
> > > > +new_codec =
> > > > +  (sti->avctx->codec_id != sti->pub.codecpar->codec_id) ?
> > > > +  avcodec_find_decoder(sti->pub.codecpar->codec_id) :
> > > > +  sti->avctx->codec;
> > > > +
> > > > +avctx_new = avcodec_alloc_context3(new_codec);
> > > >  if (!avctx_new) {
> > > >  ret = AVERROR(ENOMEM);
> > > >  goto fail;
> > >
> > > This is not about request_probe
> > > but about the mpegts demuxer randomly changeing codec id midstream
> > >
> >
> >
> > I have several real (not crafted like 1_poc.mp4 is) .ts files where codec
> > changes from mpeg2video to hevc, from mpeg2audio to eac3 -- while
> remaining
> > on the same PIDs.  I also have .ts files where codec switches between
> > mpeg2video and h264.  VLC was able to play such files, but my ffmpeg
> based
> > player (apprenticevideo) could not even see that the codecs changed prior
> > to 0021484d05f9b0f032fa319399de6e24eea0c04f.
>
> do these work ?
> (work here means the result is a complete file with all frames from the
> input
>  and is playable and seekable)
> ./ffmpeg -i input.ts -codec copy output.ts
> ./ffmpeg -i input.ts -codec copy output.mp4
> ./ffmpeg -i input.ts -vcodec libx264 -acodec libopus output.mkv
>

not really relevant because if they don't work -- it's a defect in the
command line tool, not the demuxer.
I need the libavformat API to work with mpeg-ts data I have, I don't
actually care if ffprobe/ffplay/ffmpeg can handle these files ... they
couldn't handle them before and they still can't, but I'm not an fftools
maintainer so I don't think I'll be taking on a 3rd job to fix fftools as
well.



>
> > Reverting isn't really an
> > option for me, not unless there is a better solution presented.
>
> is adding an exploitable security issue an option for you ?
>

I'm not a security expert, but IIRC the patch I've posted here fixes the
segfault you are referring to?



>
> If people want to keep this, it should be behind a flag and
> disabled by default.
>
> Its not enough to fix our code that crashes, other applications
> similarly wont expect such id and type changes mid stream
>

If mpeg-ts allows the codecs to change at any time -- it's a bug in the
application if it doesn't support that.



>
>
> >
> > As I am primarily a public ffmpeg API user -- I am well out of my depth
> > when it comes to making non-trivial changes to ffmpegs internals.
>
> Thats ok, but you applied this change to ffmpeg internals, and here
> you say "I am well out of my depth when it comes to making non-trivial
> changes to ffmpegs internals."
>
> Did someone review this ?
>

No, it was ignored for weeks.



>
> commit 0021484d05f9b0f032fa319399de6e24eea0c04f
> Author: Pavel Koshevoy 
> AuthorDate: Sun May 18 08:57:31 2025 -0600
> Commit: Pavel Koshevoy 
> CommitDate: Sun May 18 08:57:31 2025 -0600
>
>
> thx
>
> [...]
>
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> The greatest way to live with honor in this world is to be what we pretend
> to be. -- Socrates
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 14/19] swscale/ops_backend: add reference backend basend on C templates

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This will serve as a reference for the SIMD backends to come. That said,
with auto-vectorization enabled, the performance of this is not atrocious.
It easily beats the old C code and sometimes even the old SIMD.

In theory, we can dramatically speed it up by using GCC vectors instead of
arrays, but the performance gains from this are too dependent on exact GCC
versions and flags, so it practice it's not a substitute for a SIMD
implementation.
---
 libswscale/Makefile  |   5 +
 libswscale/ops.c |   3 +
 libswscale/ops_backend.c | 105 ++
 libswscale/ops_backend.h | 167 ++
 libswscale/ops_tmpl_common.c | 176 ++
 libswscale/ops_tmpl_float.c  | 257 +++
 libswscale/ops_tmpl_int.c| 603 +++
 7 files changed, 1316 insertions(+)
 create mode 100644 libswscale/ops_backend.c
 create mode 100644 libswscale/ops_backend.h
 create mode 100644 libswscale/ops_tmpl_common.c
 create mode 100644 libswscale/ops_tmpl_float.c
 create mode 100644 libswscale/ops_tmpl_int.c

diff --git a/libswscale/Makefile b/libswscale/Makefile
index c9dfa78c89..d3cb7bc555 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -16,6 +16,7 @@ OBJS = alphablend.o \
input.o  \
lut3d.o  \
ops.o\
+   ops_backend.o\
ops_chain.o  \
ops_optimizer.o  \
options.o\
@@ -29,6 +30,10 @@ OBJS = alphablend.o \
yuv2rgb.o\
vscale.o \
 
+OPS-CFLAGS = -ffinite-math-only
+
+$(SUBDIR)ops_backend.o: CFLAGS += $(OPS-CFLAGS)
+
 # Objects duplicated from other libraries for shared builds
 SHLIBOBJS+= log2_tab.o half2float.o
 
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 5330b37b22..5b259e13be 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -27,7 +27,10 @@
 #include "ops.h"
 #include "ops_internal.h"
 
+extern SwsOpBackend backend_c;
+
 const SwsOpBackend * const ff_sws_op_backends[] = {
+&backend_c,
 NULL
 };
 
diff --git a/libswscale/ops_backend.c b/libswscale/ops_backend.c
new file mode 100644
index 00..47ce992bb3
--- /dev/null
+++ b/libswscale/ops_backend.c
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 "ops_backend.h"
+
+/* Array-based reference implementation */
+
+#ifndef SWS_BLOCK_SIZE
+#  define SWS_BLOCK_SIZE 32
+#endif
+
+typedef  uint8_t  u8block_t[SWS_BLOCK_SIZE];
+typedef uint16_t u16block_t[SWS_BLOCK_SIZE];
+typedef uint32_t u32block_t[SWS_BLOCK_SIZE];
+typedeffloat f32block_t[SWS_BLOCK_SIZE];
+
+#define BIT_DEPTH 8
+# include "ops_tmpl_int.c"
+#undef BIT_DEPTH
+
+#define BIT_DEPTH 16
+# include "ops_tmpl_int.c"
+#undef BIT_DEPTH
+
+#define BIT_DEPTH 32
+# include "ops_tmpl_int.c"
+# include "ops_tmpl_float.c"
+#undef BIT_DEPTH
+
+static void process(const SwsOpExec *exec, const void *priv,
+const int bx_start, const int y_start, int bx_end, int 
y_end)
+{
+const SwsOpChain *chain = priv;
+const SwsOpImpl *impl = chain->impl;
+SwsOpIter iter;
+
+for (iter.y = y_start; iter.y < y_end; iter.y++) {
+for (int i = 0; i < 4; i++) {
+iter.in[i]  = exec->in[i]  + (iter.y - y_start) * 
exec->in_stride[i];
+iter.out[i] = exec->out[i] + (iter.y - y_start) * 
exec->out_stride[i];
+}
+
+for (int block = bx_start; block < bx_end; block++) {
+iter.x = block * SWS_BLOCK_SIZE;
+((void (*)(SwsOpIter *, const SwsOpImpl *)) impl->cont)
+(&iter, &impl[1]);
+}
+}
+}
+
+static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
+{
+int ret;
+
+SwsOpChain *chain = ff_sws_op_chain_alloc();
+if (!chain)
+return AVERROR(ENOMEM);
+
+static const SwsOpTable *const tables[] = 

Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Pavel Koshevoy
On Tue, Jun 10, 2025 at 9:29 AM Michael Niedermayer 
wrote:

> Hi Pavel
>
> 

>
> is adding an exploitable security issue an option for you ?
>
>
^ that's inflammatory, I have never had any intention of introducing a
security vulnerability.


If people want to keep this, it should be behind a flag and
> disabled by default.


I am not familiar with such flags ... are you suggesting a compile-time
flag, or a run-time flag?
A runtime flag would be preferable, because that would save me from having
to cross-compile win64 ffmpeg libs myself.


Its not enough to fix our code that crashes, other applications
> similarly wont expect such id and type changes mid stream


IDK how likely a media type change is outside the 1_poc.mp4.  The sample
files I have don't do that.
I can provide a 61MB clip of one such file, just a few seconds of SDR mpeg2
video/audio slate followed by a few seconds of HDR10 hevc video and eac3
audio... in case someone wants to work on making fftools support this.

Pavel.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Nicolas George
Pavel Koshevoy (HE12025-06-10):
> ^ that's inflammatory

No, that is just sarcastic.

-- 
  Nicolas George
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Pavel Koshevoy
On Tue, Jun 10, 2025 at 11:31 AM Nicolas George  wrote:

> Pavel Koshevoy (HE12025-06-10):
> > ^ that's inflammatory
>
> No, that is just sarcastic.
>
>

it managed to ruin my morning ... no matter what you call it.

Pavel.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH v2] ogg/vorbis: implement header packet skip in chained ogg bitstreams.

2025-06-10 Thread Romain Beauxis
Hi all,


Le mer. 4 juin 2025 à 11:58, Romain Beauxis  a écrit :
>
> This is a redo of 574f634e49847e2225ee50013afebf0de03ef013 using a flat
> memory storage for the extradata.
>
> PR review comments addressed:
> * Use flat memory bytestream
> * Re-use existing xiph extradata layout

Is there any interest in reviewing this patch?

It's holding the second series that fixes chained ogg stream metadata parsing.

Better support for chained ogg streams would really make life easier
for a bunch of ffmpeg and ffmpeg libraries users.

Thanks,
-- Romain

> ---
>  libavcodec/vorbisdec.c | 42 ---
>  libavformat/oggparsevorbis.c   | 83 +-
>  tests/ref/fate/ogg-vorbis-chained-meta.txt |  3 -
>  3 files changed, 114 insertions(+), 14 deletions(-)
>
> diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c
> index adbd726183..84879462a1 100644
> --- a/libavcodec/vorbisdec.c
> +++ b/libavcodec/vorbisdec.c
> @@ -1778,11 +1778,40 @@ static int vorbis_decode_frame(AVCodecContext *avctx, 
> AVFrame *frame,
>  GetBitContext *gb = &vc->gb;
>  float *channel_ptrs[255];
>  int i, len, ret;
> +size_t new_extradata_size;
> +const uint8_t *new_extradata;
> +const uint8_t *header_start[3];
> +int header_len[3] = {0, 0, 0};
> +const uint8_t *header;
> +int header_size = 0;
> +const uint8_t *comment;
> +int comment_size = 0;
> +const uint8_t *setup;
> +int setup_size = 0;
>
>  ff_dlog(NULL, "packet length %d \n", buf_size);
>
> -if (*buf == 1 && buf_size > 7) {
> -if ((ret = init_get_bits8(gb, buf + 1, buf_size - 1)) < 0)
> +new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
> +&new_extradata_size);
> +
> +if (new_extradata) {
> +ret = avpriv_split_xiph_headers(new_extradata, new_extradata_size,
> +30, header_start, header_len);
> +if (ret < 0)
> +return ret;
> +
> +header = header_start[0];
> +header_size = header_len[0];
> +
> +comment = header_start[1];
> +comment_size = header_len[1];
> +
> +setup = header_start[2];
> +setup_size = header_len[2];
> +}
> +
> +if (header_size > 7 && *header == 1) {
> +if ((ret = init_get_bits8(gb, header + 1, header_size - 1)) < 0)
>  return ret;
>
>  vorbis_free(vc);
> @@ -1801,16 +1830,14 @@ static int vorbis_decode_frame(AVCodecContext *avctx, 
> AVFrame *frame,
>  }
>
>  avctx->sample_rate = vc->audio_samplerate;
> -return buf_size;
>  }
>
> -if (*buf == 3 && buf_size > 7) {
> +if (comment_size > 7 && *comment == 3) {
>  av_log(avctx, AV_LOG_DEBUG, "Ignoring comment header\n");
> -return buf_size;
>  }
>
> -if (*buf == 5 && buf_size > 7 && vc->channel_residues && !vc->modes) {
> -if ((ret = init_get_bits8(gb, buf + 1, buf_size - 1)) < 0)
> +if (setup_size > 7 && *setup == 5 && vc->channel_residues && !vc->modes) 
> {
> +if ((ret = init_get_bits8(gb, setup + 1, setup_size - 1)) < 0)
>  return ret;
>
>  if ((ret = vorbis_parse_setup_hdr(vc))) {
> @@ -1818,7 +1845,6 @@ static int vorbis_decode_frame(AVCodecContext *avctx, 
> AVFrame *frame,
>  vorbis_free(vc);
>  return ret;
>  }
> -return buf_size;
>  }
>
>  if (!vc->channel_residues || !vc->modes) {
> diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
> index 62cc2da6de..7859ec5a51 100644
> --- a/libavformat/oggparsevorbis.c
> +++ b/libavformat/oggparsevorbis.c
> @@ -215,6 +215,12 @@ struct oggvorbis_private {
>  AVVorbisParseContext *vp;
>  int64_t final_pts;
>  int final_duration;
> +uint8_t *header;
> +int header_size;
> +uint8_t *comment;
> +int comment_size;
> +uint8_t *setup;
> +int setup_size;
>  };
>
>  static int fixup_vorbis_headers(AVFormatContext *as,
> @@ -260,6 +266,10 @@ static void vorbis_cleanup(AVFormatContext *s, int idx)
>  av_vorbis_parse_free(&priv->vp);
>  for (i = 0; i < 3; i++)
>  av_freep(&priv->packet[i]);
> +
> +av_freep(&priv->header);
> +av_freep(&priv->comment);
> +av_freep(&priv->setup);
>  }
>  }
>
> @@ -434,6 +444,9 @@ static int vorbis_packet(AVFormatContext *s, int idx)
>  struct ogg_stream *os = ogg->streams + idx;
>  struct oggvorbis_private *priv = os->private;
>  int duration, flags = 0;
> +int skip_packet = 0;
> +int ret, new_extradata_size;
> +PutByteContext pb;
>
>  if (!priv->vp)
>  return AVERROR_INVALIDDATA;
> @@ -496,10 +509,50 @@ static int vorbis_packet(AVFormatContext *s, int idx)
>  if (duration < 0) {
>  os->pflags |= AV_PKT_FLAG_CORRUPT;
>  return 0;
> -} else if (flags & VORBIS_FLAG_COMMENT) {
> -vorbis_update_metadat

Re: [FFmpeg-devel] [PATCH] avformat/webvttdec: improve WebVTT parsing

2025-06-10 Thread Marcos Del Sol
> WebVTT is supposed to be an extensible format. Limiting to a small set of
> known values and silently aborting when anything new is introduced does
> not seem like the best option to me. Web browsers do not stop rendering
> pages when they see a new, unknown HTML tag or CSS option.

About this, for interoperability reasons I've checked other multiple
implementations of WebVTT parsers and these all follow the approach of
silently ignoring unknown chunks:

 - WebKit 
(https://github.com/WebKit/WebKit/blob/main/Source/WebCore/html/track/WebVTTParser.cpp#L224-L227)
 - Chromium's Blink parser 
(https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/html/track/vtt/vtt_parser.cc#199)
 - Mozilla's Gecko 
(https://searchfox.org/mozilla-central/source/dom/media/webvtt/vtt.sys.mjs#1674-1677)
 - VLC 
(https://code.videolan.org/videolan/vlc/-/blob/master/modules/codec/webvtt/webvtt.c)

The only one that would report an error, but will still keep parsing anyway,
is W3C's own WebVTT.js parser 
(https://github.com/w3c/webvtt.js/blob/main/parser.js#L150-L153).

If that's not enough, I found also in part 2.1 of the WebVTT specification,
also copied verbatim:

"The parsing rules are more tolerant to author errors than the syntax
allows, in order to provide for extensibility and to still render cues that
have some syntax errors."

Basically, the standard asks to follow Postel's law: "Be conservative in
what you send, be liberal in what you accept". ffmpeg should do that.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH v5 16/19] swscale/x86: add SIMD backend

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This covers most 8-bit and 16-bit ops, and some 32-bit ops. It also covers all
floating point operations. While this is not yet 100% coverage, it's good
enough for the vast majority of formats out there.

Of special note is the packed shuffle fast path, which uses pshufb at vector
sizes up to AVX512.
---
 libswscale/ops.c  |4 +
 libswscale/x86/Makefile   |6 +
 libswscale/x86/ops.c  |  723 ++
 libswscale/x86/ops_common.asm |  305 ++
 libswscale/x86/ops_float.asm  |  389 
 libswscale/x86/ops_int.asm| 1062 +
 6 files changed, 2489 insertions(+)
 create mode 100644 libswscale/x86/ops.c
 create mode 100644 libswscale/x86/ops_common.asm
 create mode 100644 libswscale/x86/ops_float.asm
 create mode 100644 libswscale/x86/ops_int.asm

diff --git a/libswscale/ops.c b/libswscale/ops.c
index 6a5b4f4158..a9cde2e5b8 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -29,9 +29,13 @@
 
 extern SwsOpBackend backend_c;
 extern SwsOpBackend backend_murder;
+extern SwsOpBackend backend_x86;
 
 const SwsOpBackend * const ff_sws_op_backends[] = {
 &backend_murder,
+#if ARCH_X86_64
+&backend_x86,
+#endif
 &backend_c,
 NULL
 };
diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile
index f00154941d..f1d6255549 100644
--- a/libswscale/x86/Makefile
+++ b/libswscale/x86/Makefile
@@ -16,3 +16,9 @@ X86ASM-OBJS += x86/input.o
  \
x86/rgb_2_rgb.o  \
x86/yuv_2_rgb.o  \
x86/yuv2yuvX.o   \
+
+ifdef ARCH_X86_64
+X86ASM-OBJS += x86/ops_int.o\
+   x86/ops_float.o  \
+   x86/ops.o
+endif
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
new file mode 100644
index 00..f427fb1d28
--- /dev/null
+++ b/libswscale/x86/ops.c
@@ -0,0 +1,723 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * 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 
+
+#include 
+#include 
+
+#include "../ops_chain.h"
+
+#define DECL_ENTRY(TYPE, NAME, ...)
 \
+static const SwsOpEntry op_##NAME = {  
 \
+.type = SWS_PIXEL_##TYPE,  
 \
+__VA_ARGS__
 \
+}
+
+#define DECL_ASM(TYPE, NAME, ...)  
 \
+void ff_##NAME(void);  
 \
+DECL_ENTRY(TYPE, NAME, 
 \
+.func = ff_##NAME, 
 \
+__VA_ARGS__)
+
+#define DECL_PATTERN(TYPE, NAME, X, Y, Z, W, ...)  
 \
+DECL_ASM(TYPE, p##X##Y##Z##W##_##NAME, 
 \
+.unused = { !X, !Y, !Z, !W },  
 \
+__VA_ARGS__
 \
+)
+
+#define REF_PATTERN(NAME, X, Y, Z, W)  
 \
+&op_p##X##Y##Z##W##_##NAME
+
+#define DECL_COMMON_PATTERNS(TYPE, NAME, ...)  
 \
+DECL_PATTERN(TYPE, NAME, 1, 0, 0, 0, __VA_ARGS__); 
 \
+DECL_PATTERN(TYPE, NAME, 1, 0, 0, 1, __VA_ARGS__); 
 \
+DECL_PATTERN(TYPE, NAME, 1, 1, 1, 0, __VA_ARGS__); 
 \
+DECL_PATTERN(TYPE, NAME, 1, 1, 1, 1, __VA_ARGS__)  
 \
+
+#define REF_COMMON_PATTERNS(NAME)  
 \
+REF_PATTERN(NAME, 1, 0, 0, 0), 
 \
+REF_PATTERN(NAME, 1, 0, 0, 1), 
 \
+REF_PATTERN(NAME, 1, 1, 1, 0), 
 \
+REF_PATTERN(NAME, 1, 1, 1, 1)
+
+#define D

[FFmpeg-devel] [PATCH v5 17/19] tests/checkasm: add checkasm tests for swscale ops

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

Because of the lack of an external ABI on low-level kernels, we cannot
directly test internal functions. Instead, we construct a minimal op chain
consisting of a read, the op to be tested, and a write.

The bigger complication arises from the fact that the backend may generate
arbitrary internal state that needs to be passed back to the implementation,
which means we cannot directly call `func_ref` on the generated chain. To get
around this, always compile the op chain twice - once using the backend to be
tested, and once using the reference C backend.

The actual entry point may also just be a shared wrapper, so we need to
be very careful to run checkasm_check_func() on a pseudo-pointer that will
actually be unique for each combination of backend and active CPU flags.
---
 tests/checkasm/Makefile   |   8 +-
 tests/checkasm/checkasm.c |   1 +
 tests/checkasm/checkasm.h |   1 +
 tests/checkasm/sw_ops.c   | 776 ++
 tests/fate/checkasm.mak   |   1 +
 5 files changed, 786 insertions(+), 1 deletion(-)
 create mode 100644 tests/checkasm/sw_ops.c

diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index fabbf595b4..d38ec371df 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -66,7 +66,13 @@ AVFILTEROBJS-$(CONFIG_SOBEL_FILTER)  += vf_convolution.o
 CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes)
 
 # swscale tests
-SWSCALEOBJS += sw_gbrp.o sw_range_convert.o 
sw_rgb.o sw_scale.o sw_yuv2rgb.o sw_yuv2yuv.o
+SWSCALEOBJS += sw_gbrp.o\
+   sw_ops.o \
+   sw_range_convert.o   \
+   sw_rgb.o \
+   sw_scale.o   \
+   sw_yuv2rgb.o \
+   sw_yuv2yuv.o
 
 CHECKASMOBJS-$(CONFIG_SWSCALE)  += $(SWSCALEOBJS)
 
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index f393a0cb96..11bd5668cf 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -298,6 +298,7 @@ static const struct {
 { "sw_scale", checkasm_check_sw_scale },
 { "sw_yuv2rgb", checkasm_check_sw_yuv2rgb },
 { "sw_yuv2yuv", checkasm_check_sw_yuv2yuv },
+{ "sw_ops", checkasm_check_sw_ops },
 #endif
 #if CONFIG_AVUTIL
 { "aes",   checkasm_check_aes },
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 9be9b47d58..678d6cc1d9 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -132,6 +132,7 @@ void checkasm_check_sw_rgb(void);
 void checkasm_check_sw_scale(void);
 void checkasm_check_sw_yuv2rgb(void);
 void checkasm_check_sw_yuv2yuv(void);
+void checkasm_check_sw_ops(void);
 void checkasm_check_takdsp(void);
 void checkasm_check_utvideodsp(void);
 void checkasm_check_v210dec(void);
diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c
new file mode 100644
index 00..c8cba96879
--- /dev/null
+++ b/tests/checkasm/sw_ops.c
@@ -0,0 +1,776 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem_internal.h"
+#include "libavutil/refstruct.h"
+
+#include "libswscale/ops.h"
+#include "libswscale/ops_internal.h"
+
+#include "checkasm.h"
+
+enum {
+LINES  = 2,
+PLANES = 4,
+PIXELS = 64,
+};
+
+enum {
+U8  = SWS_PIXEL_U8,
+U16 = SWS_PIXEL_U16,
+U32 = SWS_PIXEL_U32,
+F32 = SWS_PIXEL_F32,
+};
+
+#define FMT(fmt, ...) tprintf((char[256]) {0}, 256, fmt, __VA_ARGS__)
+static const char *tprintf(char buf[], size_t size, const char *fmt, ...)
+{
+va_list ap;
+va_start(ap, fmt);
+vsnprintf(buf, size, fmt, ap);
+va_end(ap);
+return buf;
+}
+
+static int rw_pixel_bits(const SwsOp *op)
+{
+const int elems = op->rw.packed ? op->rw.elems : 1;
+const int size  = ff_sws_pixel_type_size(op->type);
+const int bits  = 8 >> op->rw.frac;
+av_assert1(bits >= 1);
+return elems * size * bits;
+}
+
+static float rndf(void)
+{
+union { uint32_t u; float f; } x;
+do {
+  

[FFmpeg-devel] [PATCH v5 18/19] swscale/format: add new format decode/encode logic

2025-06-10 Thread Niklas Haas
From: Niklas Haas 

This patch adds format handling code for the new operations. This entails
fully decoding a format to standardized RGB, and the inverse.

Handling it this way means we can always guarantee that a conversion path
exists from A to B without having to explicitly cover logic for each path;
and choosing RGB instead of YUV as the intermediate (as was done in swscale
v1) is more flexible with regards to enabling further operations such as
primaries conversions, linear scaling, etc.

In the case of YUV->YUV transform, the redundant matrix multiplication will
be canceled out anyways.
---
 libswscale/format.c | 926 
 libswscale/format.h |  23 ++
 2 files changed, 949 insertions(+)

diff --git a/libswscale/format.c b/libswscale/format.c
index b77081dd7a..7cbc5b37db 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -21,8 +21,22 @@
 #include "libavutil/avassert.h"
 #include "libavutil/hdr_dynamic_metadata.h"
 #include "libavutil/mastering_display_metadata.h"
+#include "libavutil/refstruct.h"
 
 #include "format.h"
+#include "csputils.h"
+#include "ops_internal.h"
+
+#define Q(N) ((AVRational) { N, 1 })
+#define Q0   Q(0)
+#define Q1   Q(1)
+
+#define RET(x) 
\
+do {   
\
+int __ret = (x);   
\
+if (__ret  < 0)
\
+return __ret;  
\
+} while (0)
 
 typedef struct LegacyFormatEntry {
 uint8_t is_supported_in :1;
@@ -582,3 +596,915 @@ int sws_is_noop(const AVFrame *dst, const AVFrame *src)
 
 return 1;
 }
+
+/* Returns the type suitable for a pixel after fully decoding/unpacking it */
+static SwsPixelType fmt_pixel_type(enum AVPixelFormat fmt)
+{
+const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+const int bits = FFALIGN(desc->comp[0].depth, 8);
+if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) {
+switch (bits) {
+case 32: return SWS_PIXEL_F32;
+}
+} else {
+switch (bits) {
+case  8: return SWS_PIXEL_U8;
+case 16: return SWS_PIXEL_U16;
+case 32: return SWS_PIXEL_U32;
+}
+}
+
+return SWS_PIXEL_NONE;
+}
+
+static SwsSwizzleOp fmt_swizzle(enum AVPixelFormat fmt)
+{
+switch (fmt) {
+case AV_PIX_FMT_ARGB:
+case AV_PIX_FMT_0RGB:
+case AV_PIX_FMT_AYUV64LE:
+case AV_PIX_FMT_AYUV64BE:
+case AV_PIX_FMT_AYUV:
+case AV_PIX_FMT_X2RGB10LE:
+case AV_PIX_FMT_X2RGB10BE:
+return (SwsSwizzleOp) {{ .x = 3, 0, 1, 2 }};
+case AV_PIX_FMT_BGR24:
+case AV_PIX_FMT_BGR8:
+case AV_PIX_FMT_BGR4:
+case AV_PIX_FMT_BGR4_BYTE:
+case AV_PIX_FMT_BGRA:
+case AV_PIX_FMT_BGR565BE:
+case AV_PIX_FMT_BGR565LE:
+case AV_PIX_FMT_BGR555BE:
+case AV_PIX_FMT_BGR555LE:
+case AV_PIX_FMT_BGR444BE:
+case AV_PIX_FMT_BGR444LE:
+case AV_PIX_FMT_BGR48BE:
+case AV_PIX_FMT_BGR48LE:
+case AV_PIX_FMT_BGRA64BE:
+case AV_PIX_FMT_BGRA64LE:
+case AV_PIX_FMT_BGR0:
+case AV_PIX_FMT_VUYA:
+case AV_PIX_FMT_VUYX:
+return (SwsSwizzleOp) {{ .x = 2, 1, 0, 3 }};
+case AV_PIX_FMT_ABGR:
+case AV_PIX_FMT_0BGR:
+case AV_PIX_FMT_X2BGR10LE:
+case AV_PIX_FMT_X2BGR10BE:
+return (SwsSwizzleOp) {{ .x = 3, 2, 1, 0 }};
+case AV_PIX_FMT_YA8:
+case AV_PIX_FMT_YA16BE:
+case AV_PIX_FMT_YA16LE:
+return (SwsSwizzleOp) {{ .x = 0, 3, 1, 2 }};
+case AV_PIX_FMT_XV30BE:
+case AV_PIX_FMT_XV30LE:
+return (SwsSwizzleOp) {{ .x = 3, 2, 0, 1 }};
+case AV_PIX_FMT_VYU444:
+case AV_PIX_FMT_V30XBE:
+case AV_PIX_FMT_V30XLE:
+return (SwsSwizzleOp) {{ .x = 2, 0, 1, 3 }};
+case AV_PIX_FMT_XV36BE:
+case AV_PIX_FMT_XV36LE:
+case AV_PIX_FMT_XV48BE:
+case AV_PIX_FMT_XV48LE:
+case AV_PIX_FMT_UYVA:
+return (SwsSwizzleOp) {{ .x = 1, 0, 2, 3 }};
+case AV_PIX_FMT_GBRP:
+case AV_PIX_FMT_GBRP9BE:
+case AV_PIX_FMT_GBRP9LE:
+case AV_PIX_FMT_GBRP10BE:
+case AV_PIX_FMT_GBRP10LE:
+case AV_PIX_FMT_GBRP12BE:
+case AV_PIX_FMT_GBRP12LE:
+case AV_PIX_FMT_GBRP14BE:
+case AV_PIX_FMT_GBRP14LE:
+case AV_PIX_FMT_GBRP16BE:
+case AV_PIX_FMT_GBRP16LE:
+case AV_PIX_FMT_GBRPF16BE:
+case AV_PIX_FMT_GBRPF16LE:
+case AV_PIX_FMT_GBRAP:
+case AV_PIX_FMT_GBRAP10LE:
+case AV_PIX_FMT_GBRAP10BE:
+case AV_PIX_FMT_GBRAP12LE:
+case AV_PIX_FMT_GBRAP12BE:
+case AV_PIX_FMT_GBRAP14LE:
+case AV_PIX_FMT_GBRAP14BE:
+case AV_PIX_FMT_GBRAP16LE:
+case AV_PIX_FMT_GBRAP16BE:
+case AV_PIX_FMT_GBRPF32BE:
+case AV_PIX_FMT_GBRPF32LE:
+case AV_PIX_FMT_GBRAPF16BE:
+case AV_PIX_FMT_GBRAPF16LE:
+case AV_PIX_FMT_GBRAPF32BE:
+case AV_PIX_FMT_GBRAPF32LE:
+ 

Re: [FFmpeg-devel] [PATCH v5 06/19] avutil/mem: add av_dynarray2_dup

2025-06-10 Thread Niklas Haas
On Tue, 10 Jun 2025 15:55:35 +0200 Andreas Rheinhardt 
 wrote:
> Niklas Haas:
> > On Tue, 10 Jun 2025 15:04:57 +0200 Niklas Haas  wrote:
> >> From: Niklas Haas 
> >>
> >> Like av_memdup() but correctly rounds up to the nearest power of two so 
> >> that
> >> av_dynarray2_add() will continue to work on the duplicated list.
> >
> > Just realized this is public, will add a Changelog entry and bump the API
> > version before merging.
> Is this version supposed to be merged?
> Anyway, this function seems way too specialised to me.

What would you prefer? Simply having this logic inside swscale? I'm not
very happy making cross-library assumptions about the exact resizing schedule.

Alternatively, we could ditch the use of av_dynarray2 entirely.

>
> - Andreas
>
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] avformat/demux: Fix segfault due to avcodec_open2 failure (v2)

2025-06-10 Thread Pavel Koshevoy
On Tue, Jun 10, 2025, 07:39 Michael Niedermayer 
wrote:

> On Mon, Jun 09, 2025 at 09:45:28PM -0600, Pavel Koshevoy wrote:
> > Fixes 'ffprobe 1_poc.mp4' segfault introduced with
> > commit 0021484d05f9b0f032fa319399de6e24eea0c04f
> >
> > codec_close should not assume that the codec_id did not change.
> > ---
> >  libavformat/demux.c | 8 +++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/libavformat/demux.c b/libavformat/demux.c
> > index ecd4f40da9..3749ab67a3 100644
> > --- a/libavformat/demux.c
> > +++ b/libavformat/demux.c
> > @@ -1292,9 +1292,15 @@ static int codec_close(FFStream *sti)
> >  {
> >  AVCodecContext *avctx_new = NULL;
> >  AVCodecParameters *par_tmp = NULL;
> > +const AVCodec *new_codec = NULL;
> >  int ret;
> >
> > -avctx_new = avcodec_alloc_context3(sti->avctx->codec);
> > +new_codec =
> > +  (sti->avctx->codec_id != sti->pub.codecpar->codec_id) ?
> > +  avcodec_find_decoder(sti->pub.codecpar->codec_id) :
> > +  sti->avctx->codec;
> > +
> > +avctx_new = avcodec_alloc_context3(new_codec);
> >  if (!avctx_new) {
> >  ret = AVERROR(ENOMEM);
> >  goto fail;
>
> This is not about request_probe
> but about the mpegts demuxer randomly changeing codec id midstream
>


I have several real (not crafted like 1_poc.mp4 is) .ts files where codec
changes from mpeg2video to hevc, from mpeg2audio to eac3 -- while remaining
on the same PIDs.  I also have .ts files where codec switches between
mpeg2video and h264.  VLC was able to play such files, but my ffmpeg based
player (apprenticevideo) could not even see that the codecs changed prior
to 0021484d05f9b0f032fa319399de6e24eea0c04f.  Reverting isn't really an
option for me, not unless there is a better solution presented.

As I am primarily a public ffmpeg API user -- I am well out of my depth
when it comes to making non-trivial changes to ffmpegs internals.





> I belive the patch should be reverted that causes this. I dont think
> applications expect such mid stream changes either
>

I have 2 applications that expect such behavior.


> I hope andreas can take a look and correct me if iam missing something
> but it looks a bit sketchy to me
>
> If a codec changes mid stream i belive a new AVStream
> should be created. It could be a audio stream switches to video
> or data or subtitle.
>

In my player I support video/audio track selection.  MPEG-TS tracks are
associated with a PID.  If the PID did not change but the codec changed --
it's still the same track, and I axpect my player to play it out -- I don't
expect the user to go search for some new track because the codec changed.


> If any stream as detected initially can become any other type later
> this complicates user applications and filter graphs
>

I think this is mostly a issue with the crafted 1_poc.mp4 file.


Also the management of AVPackets is probably rather non trivial
> if the stream_index is not enough to identify which decoder it belongs to
>

In my player I monitor AVCodecParameters for changes, and I attach a
shared_ptr to AVCodecParameters to each packet, so when time comes to
decode a packet I can check if its codecpar matches the current decoder,
and open a new decoder if the codec has changed.  It's not trivial, but not
complicated either.


> thx
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Old school: Use the lowest level language in which you can solve the
> problem
> conveniently.
> New school: Use the highest level language in which the latest
> supercomputer
> can solve the problem without the user falling asleep waiting.
> ___
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] avformat/whip: mark as experimental

2025-06-10 Thread Jack Lau via ffmpeg-devel
--- Begin Message ---
This muxer has been marked AVFMT_EXPERIMENTAL.

Add a note in muxers.texi that WHIP is an experimental feature

This patch doesn't effect WHIP usage command, as WHIP always
needs to be explicitly specified

The details as follows:
https://ffmpeg.org/pipermail/ffmpeg-devel/2025-June/344705.html

Signed-off-by: Jack Lau 
---
 doc/muxers.texi| 2 ++
 libavformat/whip.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 30c95c3d34..d2ee90bf33 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -3885,6 +3885,8 @@ ffmpeg -f webm_dash_manifest -i video1.webm \
 WebRTC (Real-Time Communication) muxer that supports sub-second latency 
streaming according to
 the WHIP (WebRTC-HTTP ingestion protocol) specification.
 
+This is an experimental feature.
+
 It uses HTTP as a signaling protocol to exchange SDP capabilities and ICE lite 
candidates. Then,
 it uses STUN binding requests and responses to establish a session over UDP. 
Subsequently, it
 initiates a DTLS handshake to exchange the SRTP encryption keys. Lastly, it 
splits video and
diff --git a/libavformat/whip.c b/libavformat/whip.c
index 710f24fc5a..bb7b8657dc 100644
--- a/libavformat/whip.c
+++ b/libavformat/whip.c
@@ -1907,7 +1907,7 @@ const FFOutputFormat ff_whip_muxer = {
 .p.long_name= NULL_IF_CONFIG_SMALL("WHIP(WebRTC-HTTP ingestion 
protocol) muxer"),
 .p.audio_codec  = AV_CODEC_ID_OPUS,
 .p.video_codec  = AV_CODEC_ID_H264,
-.p.flags= AVFMT_GLOBALHEADER | AVFMT_NOFILE,
+.p.flags= AVFMT_GLOBALHEADER | AVFMT_NOFILE | 
AVFMT_EXPERIMENTAL,
 .p.priv_class   = &whip_muxer_class,
 .priv_data_size = sizeof(WHIPContext),
 .init   = whip_init,
-- 
2.49.0

--- End Message ---
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".