Re: [FFmpeg-devel] [PATCH v2 2/2] lavc/hevcdec: Update slice index before use it to construct slice RPL

2024-06-21 Thread Anton Khirnov
Quoting fei.w.wang-at-intel@ffmpeg.org (2024-06-19 04:27:22)
> From: Fei Wang 
> 
> Fixes regression from 47d34ba7fbb81

"fix bug" is not a meaningful description of the problem

-- 
Anton Khirnov
___
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/4] avcodec/j2kenc: Merge dwt_norm into lambda

2024-06-21 Thread Andreas Rheinhardt
Michael Niedermayer:
> This moves computations out of a loop
> 
> Fixes: signed integer overflow: 31665934879948800 * 9998 cannot be 
> represented in type 'long'
> Fixes: 
> 69024/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JPEG2000_fuzzer-5949662967169024
> 
> Found-by: continuous fuzzing process 
> https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
> Signed-off-by: Michael Niedermayer 
> ---
>  libavcodec/j2kenc.c | 9 +
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
> index 8cf82f7216c..91e66d81048 100644
> --- a/libavcodec/j2kenc.c
> +++ b/libavcodec/j2kenc.c
> @@ -1349,7 +1349,7 @@ static void makelayers(Jpeg2000EncoderContext *s, 
> Jpeg2000Tile *tile)
>  }
>  }
>  
> -static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda, int dwt_norm)
> +static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda)
>  {
>  int passno, res = 0;
>  for (passno = 0; passno < cblk->npasses; passno++){
> @@ -1361,7 +1361,7 @@ static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda, 
> int dwt_norm)
>  dd = cblk->passes[passno].disto
> - (res ? cblk->passes[res-1].disto : 0);
>  
> -if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda)
> +if (dd  >= dr * lambda)
>  res = passno+1;
>  }
>  return res;
> @@ -1384,11 +1384,12 @@ static void truncpasses(Jpeg2000EncoderContext *s, 
> Jpeg2000Tile *tile)
>  Jpeg2000Band *band = reslevel->band + bandno;
>  Jpeg2000Prec *prec = band->prec + precno;
>  
> +int64_t dwt_norm = dwt_norms[codsty->transform == 
> FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15;
> +int64_t lambda_prime = av_rescale(s->lambda, 1 << 
> WMSEDEC_SHIFT, dwt_norm * dwt_norm);
>  for (cblkno = 0; cblkno < prec->nb_codeblocks_height * 
> prec->nb_codeblocks_width; cblkno++){
>  Jpeg2000Cblk *cblk = prec->cblk + cblkno;
>  
> -cblk->ninclpasses = getcut(cblk, s->lambda,
> -(int64_t)dwt_norms[codsty->transform == 
> FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15);
> +cblk->ninclpasses = getcut(cblk, lambda_prime);
>  cblk->layers[0].data_start = cblk->data;
>  cblk->layers[0].cum_passes = cblk->ninclpasses;
>  cblk->layers[0].npasses = cblk->ninclpasses;

Does this also fix the UB in the vsynth*-jpeg2000-yuva444p16 tests?

- 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 v13 0/8] [WIP] webp: add support for animated WebP decoding

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
Marked WIP because we'd want to introduce private bsf's first; review
welcome before that though

v13
Switched to new ProgressFrame API
Support for pixel format changes in animations
Propagate MIN_DELAY in case of invalid delay in animations
Added more tests for animations with pixel format changes

v12
VP8 decoder decoupled again
The whole animated sequence goes into one packet
The (currently public) bitstream filter splits animations up into 
non-conformant packets
Now with XMP metadata support (as string, like MOV)


Patch 5/8 is still there for making changes in lavc/webp reviewable but shall 
be stashed when pushing.

-Thilo

Josef Zlomek (2):
  libavcodec/webp: add support for animated WebP
  libavformat/webp: add WebP demuxer

Thilo Borgmann via ffmpeg-devel (6):
  avcodec/webp: remove unused definitions
  avcodec/webp: separate VP8 decoding
  avcodec/bsf: Add awebp2webp bitstream filter
  avcodec/webp: make init_canvas_frame static
  fate: add test for animated WebP
  avcodec/webp: export XMP metadata

 Changelog |   2 +
 configure |   1 +
 doc/demuxers.texi |  28 +
 libavcodec/bitstream_filters.c|   1 +
 libavcodec/bsf/Makefile   |   1 +
 libavcodec/bsf/awebp2webp.c   | 353 +++
 libavcodec/codec_desc.c   |   3 +-
 libavcodec/webp.c | 983 --
 libavformat/Makefile  |   1 +
 libavformat/allformats.c  |   1 +
 libavformat/webpdec.c | 384 +++
 tests/fate/image.mak  |   9 +
 tests/ref/fate/exif-image-webp|   4 +-
 tests/ref/fate/webp-anim  |  22 +
 tests/ref/fate/webp-chfmt1|  23 +
 tests/ref/fate/webp-chfmt2| 106 ++
 tests/ref/fate/webp-rgb-lena-lossless |   2 +-
 tests/ref/fate/webp-rgb-lena-lossless-rgb24   |   2 +-
 tests/ref/fate/webp-rgb-lossless  |   2 +-
 .../fate/webp-rgb-lossless-palette-predictor  |   2 +-
 tests/ref/fate/webp-rgb-lossy-q80 |   2 +-
 tests/ref/fate/webp-rgba-lossless |   2 +-
 tests/ref/fate/webp-rgba-lossy-q80|   2 +-
 23 files changed, 1855 insertions(+), 81 deletions(-)
 create mode 100644 libavcodec/bsf/awebp2webp.c
 create mode 100644 libavformat/webpdec.c
 create mode 100644 tests/ref/fate/webp-anim
 create mode 100644 tests/ref/fate/webp-chfmt1
 create mode 100644 tests/ref/fate/webp-chfmt2

-- 
2.39.3 (Apple Git-146)

___
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 v13 2/8] avcodec/webp: separate VP8 decoding

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

---
 libavcodec/webp.c | 50 +--
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index af4ebcec27..c52b9732b4 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -195,6 +195,7 @@ typedef struct WebPContext {
 AVFrame *alpha_frame;   /* AVFrame for alpha data decompressed 
from VP8L */
 AVPacket *pkt;  /* AVPacket to be passed to the 
underlying VP8 decoder */
 AVCodecContext *avctx;  /* parent AVCodecContext */
+AVCodecContext *avctx_vp8;  /* wrapper context for VP8 decoder */
 int initialized;/* set once the VP8 context is 
initialized */
 int has_alpha;  /* has a separate alpha chunk */
 enum AlphaCompression alpha_compression; /* compression type for alpha 
chunk */
@@ -1299,12 +1300,13 @@ static int vp8_lossy_decode_frame(AVCodecContext 
*avctx, AVFrame *p,
 int ret;
 
 if (!s->initialized) {
-ff_vp8_decode_init(avctx);
+VP8Context *s_vp8 = s->avctx_vp8->priv_data;
+s_vp8->actually_webp = 1;
 s->initialized = 1;
-s->v.actually_webp = 1;
 }
 avctx->pix_fmt = s->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
 s->lossless = 0;
+s->avctx_vp8->pix_fmt = avctx->pix_fmt;
 
 if (data_size > INT_MAX) {
 av_log(avctx, AV_LOG_ERROR, "unsupported chunk size\n");
@@ -1315,14 +1317,32 @@ static int vp8_lossy_decode_frame(AVCodecContext 
*avctx, AVFrame *p,
 s->pkt->data = data_start;
 s->pkt->size = data_size;
 
-ret = ff_vp8_decode_frame(avctx, p, got_frame, s->pkt);
-if (ret < 0)
+ret = avcodec_send_packet(s->avctx_vp8, s->pkt);
+if (ret < 0) {
+av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for 
decoding\n");
 return ret;
+}
 
-if (!*got_frame)
+ret = avcodec_receive_frame(s->avctx_vp8, p);
+if (ret < 0) {
+av_log(avctx, AV_LOG_ERROR, "VP8 decoding error: %s.\n", 
av_err2str(ret));
 return AVERROR_INVALIDDATA;
+}
+
+ret = ff_decode_frame_props(avctx, p);
+if (ret < 0) {
+return ret;
+}
+
+if (!p->private_ref) {
+ret = ff_attach_decode_data(p);
+if (ret < 0) {
+return ret;
+}
+}
 
-update_canvas_size(avctx, avctx->width, avctx->height);
+*got_frame = 1;
+update_canvas_size(avctx, s->avctx_vp8->width, s->avctx_vp8->height);
 
 if (s->has_alpha) {
 ret = vp8_lossy_decode_alpha(avctx, p, s->alpha_data,
@@ -1539,11 +1559,28 @@ exif_end:
 static av_cold int webp_decode_init(AVCodecContext *avctx)
 {
 WebPContext *s = avctx->priv_data;
+int ret;
+const AVCodec *codec;
 
 s->pkt = av_packet_alloc();
 if (!s->pkt)
 return AVERROR(ENOMEM);
 
+
+/* Prepare everything needed for VP8 decoding */
+codec = avcodec_find_decoder(AV_CODEC_ID_VP8);
+if (!codec)
+return AVERROR_BUG;
+s->avctx_vp8 = avcodec_alloc_context3(codec);
+if (!s->avctx_vp8)
+return AVERROR(ENOMEM);
+s->avctx_vp8->flags = avctx->flags;
+s->avctx_vp8->flags2 = avctx->flags2;
+s->avctx_vp8->pix_fmt = avctx->pix_fmt;
+ret = avcodec_open2(s->avctx_vp8, codec, NULL);
+if (ret < 0) {
+return ret;
+}
 return 0;
 }
 
@@ -1552,6 +1589,7 @@ static av_cold int webp_decode_close(AVCodecContext 
*avctx)
 WebPContext *s = avctx->priv_data;
 
 av_packet_free(&s->pkt);
+avcodec_free_context(&s->avctx_vp8);
 
 if (s->initialized)
 return ff_vp8_decode_free(avctx);
-- 
2.39.3 (Apple Git-146)

___
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 v13 1/8] avcodec/webp: remove unused definitions

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

---
 libavcodec/webp.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 7c2a5f0111..af4ebcec27 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -60,8 +60,6 @@
 #define VP8X_FLAG_ALPHA 0x10
 #define VP8X_FLAG_ICC   0x20
 
-#define MAX_PALETTE_SIZE256
-#define MAX_CACHE_BITS  11
 #define NUM_CODE_LENGTH_CODES   19
 #define HUFFMAN_CODES_PER_META_CODE 5
 #define NUM_LITERAL_CODES   256
-- 
2.39.3 (Apple Git-146)

___
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 v13 4/8] libavcodec/webp: add support for animated WebP

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Josef Zlomek 

Fixes: 4907

Adds support for decoding of animated WebP.

The WebP decoder adds the animation related features according to the specs:
https://developers.google.com/speed/webp/docs/riff_container#animation
The frames of the animation may be smaller than the image canvas.
Therefore, the frame is decoded to a temporary frame,
then it is blended into the canvas, the canvas is copied to the output frame,
and finally the frame is disposed from the canvas.

The output to AV_PIX_FMT_YUVA420P/AV_PIX_FMT_YUV420P is still supported.
The background color is specified only as BGRA in the WebP file
so it is converted to YUVA if YUV formats are output.

Signed-off-by: Josef Zlomek 
---
 Changelog   |   1 +
 libavcodec/codec_desc.c |   3 +-
 libavcodec/webp.c   | 897 +---
 3 files changed, 840 insertions(+), 61 deletions(-)

diff --git a/Changelog b/Changelog
index 06c00e981a..de6eedfd68 100644
--- a/Changelog
+++ b/Changelog
@@ -101,6 +101,7 @@ version 6.1:
 - ffprobe XML output schema changed to account for multiple
   variable-fields elements within the same parent element
 - ffprobe -output_format option added as an alias of -of
+- animated WebP decoder
 
 
 version 6.0:
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index a28ef68061..ec1dcc327a 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1259,8 +1259,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
 .type  = AVMEDIA_TYPE_VIDEO,
 .name  = "webp",
 .long_name = NULL_IF_CONFIG_SMALL("WebP"),
-.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
- AV_CODEC_PROP_LOSSLESS,
+.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
 .mime_types= MT("image/webp"),
 },
 {
diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index c52b9732b4..146d5cb393 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -35,13 +35,17 @@
  * Exif metadata
  * ICC profile
  *
+ * @author Josef Zlomek, Pexeso Inc. 
+ * Animation
+ *
  * Unimplemented:
- *   - Animation
  *   - XMP metadata
  */
 
+#include "libavutil/common.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/mem.h"
+#include "libavutil/colorspace.h"
 
 #define BITSTREAM_READER_LE
 #include "avcodec.h"
@@ -50,6 +54,7 @@
 #include "decode.h"
 #include "exif.h"
 #include "get_bits.h"
+#include "progressframe.h"
 #include "thread.h"
 #include "tiff_common.h"
 #include "vp8.h"
@@ -68,6 +73,14 @@
 #define NUM_SHORT_DISTANCES 120
 #define MAX_HUFFMAN_CODE_LENGTH 15
 
+#define ANMF_DISPOSAL_METHOD0x01
+#define ANMF_DISPOSAL_METHOD_UNCHANGED  0x00
+#define ANMF_DISPOSAL_METHOD_BACKGROUND 0x01
+
+#define ANMF_BLENDING_METHOD0x02
+#define ANMF_BLENDING_METHOD_ALPHA  0x00
+#define ANMF_BLENDING_METHOD_OVERWRITE  0x02
+
 static const uint16_t alphabet_sizes[HUFFMAN_CODES_PER_META_CODE] = {
 NUM_LITERAL_CODES + NUM_LENGTH_CODES,
 NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
@@ -192,6 +205,8 @@ typedef struct ImageContext {
 typedef struct WebPContext {
 VP8Context v;   /* VP8 Context used for lossy decoding 
*/
 GetBitContext gb;   /* bitstream reader for main image 
chunk */
+ProgressFrame canvas_frame; /* ThreadFrame for canvas */
+AVFrame *frame; /* AVFrame for decoded frame */
 AVFrame *alpha_frame;   /* AVFrame for alpha data decompressed 
from VP8L */
 AVPacket *pkt;  /* AVPacket to be passed to the 
underlying VP8 decoder */
 AVCodecContext *avctx;  /* parent AVCodecContext */
@@ -204,9 +219,25 @@ typedef struct WebPContext {
 int alpha_data_size;/* alpha chunk data size */
 int has_exif;   /* set after an EXIF chunk has been 
processed */
 int has_iccp;   /* set after an ICCP chunk has been 
processed */
+int duration;   /* frame duration in an animation */
 int width;  /* image width */
 int height; /* image height */
-int lossless;   /* indicates lossless or lossy */
+int vp8x_flags; /* global flags from VP8X chunk */
+int canvas_width;   /* canvas width */
+int canvas_height;  /* canvas height */
+int anmf_flags; /* frame flags from ANMF chunk */
+int pos_x;  /* frame position X */
+int pos_y;  /* frame position Y */
+int prev_anmf_flags;/* previous frame flags from ANMF 
chunk */
+int prev_width; /* previous frame width */
+int prev_height;/* previous frame height */
+int prev_pos_x; /* previous frame po

[FFmpeg-devel] [PATCH v13 5/8] avcodec/webp: make init_canvas_frame static

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

---
 libavcodec/webp.c | 146 +++---
 1 file changed, 72 insertions(+), 74 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 146d5cb393..bacf605ff2 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -1383,7 +1383,78 @@ static int vp8_lossy_decode_frame(AVCodecContext *avctx, 
AVFrame *p,
 return ret;
 }
 
-int init_canvas_frame(WebPContext *s, int format, int key_frame);
+static int init_canvas_frame(WebPContext *s, int format, int key_frame)
+{
+AVFrame *canvas = s->canvas_frame.f;
+int height;
+int ret;
+
+// canvas is needed only for animation
+if (!(s->vp8x_flags & VP8X_FLAG_ANIMATION))
+return 0;
+
+// avoid init for non-key frames whose format and size did not change
+if (!key_frame &&
+canvas &&
+canvas->width  == s->canvas_width &&
+canvas->height == s->canvas_height)
+return 0;
+
+// canvas changes within IPPP sequences will lose thread sync
+// because of the ThreadFrame reallocation and will wait forever
+// so if frame-threading is used, forbid canvas changes and unlock
+// previous frames
+if (!key_frame && canvas) {
+if (s->avctx->thread_count > 1) {
+av_log(s->avctx, AV_LOG_WARNING, "Canvas change detected. The 
output will be damaged. Use -threads 1 to try decoding with best effort.\n");
+// unlock previous frames that have sent an _await() call
+ff_progress_frame_report(&s->canvas_frame, INT_MAX);
+return AVERROR_PATCHWELCOME;
+} else {
+// warn for damaged frames
+av_log(s->avctx, AV_LOG_WARNING, "Canvas change detected. The 
output will be damaged.\n");
+}
+}
+
+s->avctx->pix_fmt = format;
+
+// VP8 decoder changed the width and height in AVCodecContext.
+// Change it back to the canvas size.
+ret = ff_set_dimensions(s->avctx, s->canvas_width, s->canvas_height);
+if (ret < 0)
+return ret;
+
+ff_progress_frame_unref(&s->canvas_frame);
+ret = ff_progress_frame_get_buffer(s->avctx, &s->canvas_frame, 
AV_GET_BUFFER_FLAG_REF);
+if (ret < 0)
+return ret;
+
+canvas = s->canvas_frame.f;
+canvas->format= format;
+canvas->duration  = s->duration;
+canvas->width = s->canvas_width;
+canvas->height= s->canvas_height;
+
+if (canvas->format == AV_PIX_FMT_ARGB) {
+height = canvas->height;
+memset(canvas->data[0], 0, height * canvas->linesize[0]);
+} else /* if (canvas->format == AV_PIX_FMT_YUVA420P) */ {
+const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(canvas->format);
+for (int comp = 0; comp < desc->nb_components; comp++) {
+int plane = desc->comp[comp].plane;
+
+if (comp == 1 || comp == 2)
+height = AV_CEIL_RSHIFT(canvas->height, desc->log2_chroma_h);
+else
+height = FFALIGN(canvas->height, 1 << desc->log2_chroma_h);
+
+memset(canvas->data[plane], s->transparent_yuva[plane],
+   height * canvas->linesize[plane]);
+}
+}
+
+return 0;
+}
 
 static int webp_decode_frame_common(AVCodecContext *avctx, uint8_t *data, int 
size,
 int *got_frame, int key_frame, AVFrame *p)
@@ -1629,79 +1700,6 @@ exif_end:
 return size;
 }
 
-int init_canvas_frame(WebPContext *s, int format, int key_frame)
-{
-AVFrame *canvas = s->canvas_frame.f;
-int height;
-int ret;
-
-// canvas is needed only for animation
-if (!(s->vp8x_flags & VP8X_FLAG_ANIMATION))
-return 0;
-
-// avoid init for non-key frames whose format and size did not change
-if (!key_frame &&
-canvas &&
-canvas->width  == s->canvas_width &&
-canvas->height == s->canvas_height)
-return 0;
-
-// canvas changes within IPPP sequences will lose thread sync
-// because of the ThreadFrame reallocation and will wait forever
-// so if frame-threading is used, forbid canvas changes and unlock
-// previous frames
-if (!key_frame && canvas) {
-if (s->avctx->thread_count > 1) {
-av_log(s->avctx, AV_LOG_WARNING, "Canvas change detected. The 
output will be damaged. Use -threads 1 to try decoding with best effort.\n");
-// unlock previous frames that have sent an _await() call
-ff_progress_frame_report(&s->canvas_frame, INT_MAX);
-return AVERROR_PATCHWELCOME;
-} else {
-// warn for damaged frames
-av_log(s->avctx, AV_LOG_WARNING, "Canvas change detected. The 
output will be damaged.\n");
-}
-}
-
-s->avctx->pix_fmt = format;
-
-// VP8 decoder changed the width and height in AVCodecContext.
-// Change it back to the canvas size.
-ret = ff_set_dimensions(s->avctx, s->canvas_width, s->canvas_height);
-if (ret < 0)

[FFmpeg-devel] [PATCH v13 3/8] avcodec/bsf: Add awebp2webp bitstream filter

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

Splits a packet containing a webp animations into
one non-compliant packet per frame of the animation.
Skips RIFF and WEBP chunks for those packets except
for the first. Copyies ICC, EXIF and XMP chunks first
into each of the packets except for the first.
---
 configure  |   1 +
 libavcodec/bitstream_filters.c |   1 +
 libavcodec/bsf/Makefile|   1 +
 libavcodec/bsf/awebp2webp.c| 353 +
 4 files changed, 356 insertions(+)
 create mode 100644 libavcodec/bsf/awebp2webp.c

diff --git a/configure b/configure
index 3bca638459..1b6e56496f 100755
--- a/configure
+++ b/configure
@@ -3437,6 +3437,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
 av1_frame_merge_bsf_select="cbs_av1"
 av1_frame_split_bsf_select="cbs_av1"
 av1_metadata_bsf_select="cbs_av1"
+awebp2webp_bsf_select=""
 dts2pts_bsf_select="cbs_h264 h264parse"
 eac3_core_bsf_select="ac3_parser"
 evc_frame_merge_bsf_select="evcparse"
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 138246c50e..1f6471f4f3 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -28,6 +28,7 @@ extern const FFBitStreamFilter ff_aac_adtstoasc_bsf;
 extern const FFBitStreamFilter ff_av1_frame_merge_bsf;
 extern const FFBitStreamFilter ff_av1_frame_split_bsf;
 extern const FFBitStreamFilter ff_av1_metadata_bsf;
+extern const FFBitStreamFilter ff_awebp2webp_bsf;
 extern const FFBitStreamFilter ff_chomp_bsf;
 extern const FFBitStreamFilter ff_dump_extradata_bsf;
 extern const FFBitStreamFilter ff_dca_core_bsf;
diff --git a/libavcodec/bsf/Makefile b/libavcodec/bsf/Makefile
index fb70ad0c21..48c67dd210 100644
--- a/libavcodec/bsf/Makefile
+++ b/libavcodec/bsf/Makefile
@@ -5,6 +5,7 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF)  += bsf/aac_adtstoasc.o
 OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF)+= bsf/av1_frame_merge.o
 OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF)+= bsf/av1_frame_split.o
 OBJS-$(CONFIG_AV1_METADATA_BSF)   += bsf/av1_metadata.o
+OBJS-$(CONFIG_AWEBP2WEBP_BSF) += bsf/awebp2webp.o
 OBJS-$(CONFIG_CHOMP_BSF)  += bsf/chomp.o
 OBJS-$(CONFIG_DCA_CORE_BSF)   += bsf/dca_core.o
 OBJS-$(CONFIG_DTS2PTS_BSF)+= bsf/dts2pts.o
diff --git a/libavcodec/bsf/awebp2webp.c b/libavcodec/bsf/awebp2webp.c
new file mode 100644
index 00..69a0156167
--- /dev/null
+++ b/libavcodec/bsf/awebp2webp.c
@@ -0,0 +1,353 @@
+/*
+ * Animated WebP into non-compliant WebP bitstream filter
+ * Copyright (c) 2024 Thilo Borgmann 
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * Animated WebP into non-compliant WebP bitstream filter
+ * Splits a packet containing a webp animations into
+ * one non-compliant packet per frame of the animation.
+ * Skips RIFF and WEBP chunks for those packets except
+ * for the first. Copyies ICC, EXIF and XMP chunks first
+ * into each of the packets except for the first.
+ * @author Thilo Borgmann 
+ */
+
+#include 
+#include 
+
+#include "codec_id.h"
+#include "bytestream.h"
+#include "libavutil/error.h"
+#include "libavutil/mem.h"
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "packet.h"
+
+#define VP8X_FLAG_ANIMATION 0x02
+#define VP8X_FLAG_XMP_METADATA  0x04
+#define VP8X_FLAG_EXIF_METADATA 0x08
+#define VP8X_FLAG_ALPHA 0x10
+#define VP8X_FLAG_ICC   0x20
+
+typedef struct WEBPBSFContext {
+const AVClass *class;
+GetByteContext gb;
+
+AVPacket *last_pkt;
+uint8_t *last_iccp;
+uint8_t *last_exif;
+uint8_t *last_xmp;
+
+int iccp_size;
+int exif_size;
+int xmp_size;
+
+int add_iccp;
+int add_exif;
+int add_xmp;
+
+uint64_t last_pts;
+} WEBPBSFContext;
+
+static int save_chunk(WEBPBSFContext *ctx, uint8_t **buf, int *buf_size, 
uint32_t chunk_size)
+{
+if (*buf || !buf_size || !chunk_size)
+return 0;
+
+*buf = av_malloc(chunk_size + 8);
+if (!*buf)
+return AVERROR(ENOMEM);
+
+*buf_size = chunk_size + 8;
+
+bytestream2_seek(&ctx->gb, -8, SEEK_CUR);
+bytestream2_get_buffer(&ctx->gb, *buf, chunk_size + 8);
+
+return 0;
+}
+
+static int awebp2webp_filter(A

[FFmpeg-devel] [PATCH v13 8/8] avcodec/webp: export XMP metadata

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

---
 libavcodec/webp.c | 42 --
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index bacf605ff2..c8be673060 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -38,8 +38,8 @@
  * @author Josef Zlomek, Pexeso Inc. 
  * Animation
  *
- * Unimplemented:
- *   - XMP metadata
+ * @author Thilo Borgmann 
+ * XMP metadata
  */
 
 #include "libavutil/common.h"
@@ -220,6 +220,7 @@ typedef struct WebPContext {
 int has_exif;   /* set after an EXIF chunk has been 
processed */
 int has_iccp;   /* set after an ICCP chunk has been 
processed */
 int duration;   /* frame duration in an animation */
+int has_xmp;/* set after an XMP chunk has been 
processed */
 int width;  /* image width */
 int height; /* image height */
 int vp8x_flags; /* global flags from VP8X chunk */
@@ -1469,6 +1470,7 @@ static int webp_decode_frame_common(AVCodecContext 
*avctx, uint8_t *data, int si
 // reset metadata bit for each packet
 s->has_exif  = 0;
 s->has_iccp  = 0;
+s->has_xmp   = 0;
 
 while (bytestream2_get_bytes_left(&gb) > 8) {
 char chunk_str[5] = { 0 };
@@ -1500,6 +1502,7 @@ static int webp_decode_frame_common(AVCodecContext 
*avctx, uint8_t *data, int si
 s->canvas_height = 0;
 s->has_exif  = 0;
 s->has_iccp  = 0;
+s->has_xmp   = 0;
 ff_progress_frame_unref(&s->canvas_frame);
 break;
 case MKTAG('V', 'P', '8', ' '):
@@ -1682,12 +1685,39 @@ exif_end:
 }
 s->vp8x_flags |= VP8X_FLAG_ANIMATION;
 break;
-case MKTAG('X', 'M', 'P', ' '):
-AV_WL32(chunk_str, chunk_type);
-av_log(avctx, AV_LOG_WARNING, "skipping unsupported chunk: %s\n",
-   chunk_str);
+case MKTAG('X', 'M', 'P', ' '): {
+GetByteContext xmp_gb;
+AVDictionary **xmp_metadata = NULL;
+uint8_t *buffer;
+int xmp_offset = bytestream2_tell(&gb);
+
+if (s->has_xmp) {
+av_log(avctx, AV_LOG_VERBOSE, "Ignoring extra XMP chunk\n");
+goto xmp_end;
+}
+if (!(s->vp8x_flags & VP8X_FLAG_XMP_METADATA))
+av_log(avctx, AV_LOG_WARNING,
+   "XMP chunk present, but XMP bit not set in the "
+   "VP8X header\n");
+
+// there are at least chunk_size bytes left to read
+buffer = av_malloc(chunk_size + 1);
+if (!buffer) {
+return AVERROR(ENOMEM);
+}
+
+s->has_xmp = 1;
+bytestream2_init(&xmp_gb, data + xmp_offset, size - xmp_offset);
+bytestream2_get_buffer(&xmp_gb, buffer, chunk_size);
+buffer[chunk_size] = '\0';
+
+xmp_metadata = (s->vp8x_flags & VP8X_FLAG_ANIMATION) ? 
&p->metadata : &s->frame->metadata;
+av_dict_set(xmp_metadata, "xmp", buffer, AV_DICT_DONT_STRDUP_VAL);
+
+xmp_end:
 bytestream2_skip(&gb, chunk_size);
 break;
+}
 default:
 AV_WL32(chunk_str, chunk_type);
 av_log(avctx, AV_LOG_VERBOSE, "skipping unknown chunk: %s\n",
-- 
2.39.3 (Apple Git-146)

___
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 v13 7/8] fate: add test for animated WebP

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Thilo Borgmann via ffmpeg-devel 

---
 tests/fate/image.mak   |   9 
 tests/ref/fate/webp-anim   |  22 
 tests/ref/fate/webp-chfmt1 |  23 
 tests/ref/fate/webp-chfmt2 | 106 +
 4 files changed, 160 insertions(+)
 create mode 100644 tests/ref/fate/webp-anim
 create mode 100644 tests/ref/fate/webp-chfmt1
 create mode 100644 tests/ref/fate/webp-chfmt2

diff --git a/tests/fate/image.mak b/tests/fate/image.mak
index 753936ec20..37dd0b83d9 100644
--- a/tests/fate/image.mak
+++ b/tests/fate/image.mak
@@ -566,6 +566,15 @@ fate-webp-rgb-lossy-q80: CMD = framecrc -i 
$(TARGET_SAMPLES)/webp/rgb_q80.webp
 FATE_WEBP += fate-webp-rgba-lossy-q80
 fate-webp-rgba-lossy-q80: CMD = framecrc -i 
$(TARGET_SAMPLES)/webp/rgba_q80.webp
 
+FATE_WEBP += fate-webp-anim
+fate-webp-anim: CMD = framecrc -i $(TARGET_SAMPLES)/webp/anim.webp
+
+FATE_WEBP += fate-webp-chfmt1
+fate-webp-chfmt1: CMD = framecrc -i $(TARGET_SAMPLES)/webp/anim_rgb_yuv.webp
+
+FATE_WEBP += fate-webp-chfmt2
+fate-webp-chfmt2: CMD = framecrc -i $(TARGET_SAMPLES)/webp/anim_yuv_rgb.webp
+
 FATE_WEBP-$(call DEMDEC, IMAGE2, WEBP) += $(FATE_WEBP)
 FATE_IMAGE_FRAMECRC += $(FATE_WEBP-yes)
 fate-webp: $(FATE_WEBP-yes)
diff --git a/tests/ref/fate/webp-anim b/tests/ref/fate/webp-anim
new file mode 100644
index 00..f0d3f1a88f
--- /dev/null
+++ b/tests/ref/fate/webp-anim
@@ -0,0 +1,22 @@
+#tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 100x70
+#sar 0: 0/1
+0,  0,  0,   80,28000, 0x2023ba6e
+0, 80, 80,   80,28000, 0x4292b778
+0,160,160,   80,28000, 0x1c972ef1
+0,240,240,   80,28000, 0xa98d8d04
+0,320,320,   80,28000, 0xd323b6af
+0,400,400,   80,28000, 0x508aba99
+0,480,480,   80,28000, 0x5c672dda
+0,560,560,   80,28000, 0xc8961ebb
+0,640,640, 1000,28000, 0x82460e1b
+0,   1640,   1640,   80,28000, 0x3debbfc9
+0,   1720,   1720,   80,28000, 0x427ab31f
+0,   1800,   1800,   80,28000, 0x6bbdec2e
+0,   1880,   1880,   80,28000, 0x5690b56b
+0,   1960,   1960,   80,28000, 0xb62963f3
+0,   2040,   2040,   80,28000, 0x68dd37b2
+0,   2120,   2120,   80,28000, 0x465c47d2
+0,   2200,   2200,1,28000, 0xa92033df
diff --git a/tests/ref/fate/webp-chfmt1 b/tests/ref/fate/webp-chfmt1
new file mode 100644
index 00..bdb0616353
--- /dev/null
+++ b/tests/ref/fate/webp-chfmt1
@@ -0,0 +1,23 @@
+#tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 488x488
+#sar 0: 0/1
+0,  0,  0,   80,   952576, 0x22e300c0
+0, 80, 80,   80,   952576, 0x4e7e9a01
+0,160,160,   80,   952576, 0x01b6a421
+0,240,240,   80,   952576, 0x26f09b88
+0,320,320,   80,   952576, 0xbb1404ac
+0,400,400,  480,   952576, 0x14368b56
+0,880,880,   80,   952576, 0x1843fad6
+0,960,960,   80,   952576, 0xc3c4bb73
+0,   1040,   1040,  160,   952576, 0x9d662364
+0,   1200,   1200,  160,   952576, 0xf8218a9a
+0,   1360,   1360,  160,   952576, 0x5828d888
+0,   1520,   1520,  560,   952576, 0x6a718e32
+0,   2080,   2080,   80,   952576, 0x95b7ff21
+0,   2160,   2160,   80,   952576, 0x84662ce1
+0,   2240,   2240,  720,   952576, 0x11974723
+0,   2960,   2960,   80,   952576, 0xd4a644ef
+0,   3040,   3040,   80,   952576, 0x3d29c6a8
+0,   3120,   3120,  720,   952576, 0x3d3a2d40
diff --git a/tests/ref/fate/webp-chfmt2 b/tests/ref/fate/webp-chfmt2
new file mode 100644
index 00..3d00544390
--- /dev/null
+++ b/tests/ref/fate/webp-chfmt2
@@ -0,0 +1,106 @@
+#tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
+0,  0,  0,   30,   192000, 0x41a50269
+0, 30, 30,   30,   192000, 0xb54a0286
+0, 60, 60,   30,   192000, 0x842c01ab
+0, 90, 90,   30,   192000, 0x19b0fd8f
+0,120,120,   30,   192000, 0x9eb9fb71
+0,150,150,   30,   192000, 0x1e11fb1d
+0,180,180,   30,   192000, 0x4e33fe49
+0,210,210,   30,   192000, 0x2e4fffa4
+0,240,240,   30,   192000, 0xfa74ff7f
+0,270,270,   30,   192000, 0x695ff5dd
+0,300,300,   30,   192000, 0xd263ff87
+0,330,330,   30,   192000, 0x8eb2f958
+0,360,360,   30,   192000, 0x2630f6dd
+0,390,390,   30,   192000, 0xf84af899
+0,420,420,   30, 

[FFmpeg-devel] [PATCH v13 6/8] libavformat/webp: add WebP demuxer

2024-06-21 Thread Thilo Borgmann via ffmpeg-devel
From: Josef Zlomek 

Adds the demuxer of animated WebP files.
It supports non-animated, animated, truncated, and concatenated files.
Reading from a pipe (and other non-seekable inputs) is also supported.

The WebP demuxer splits the input stream into packets containing one frame.
It also marks the key frames properly.
The loop count is ignored by default (same behaviour as animated PNG and GIF),
it may be enabled by the option '-ignore_loop 0'.

The frame rate is set according to the frame delay in the ANMF chunk.
If the delay is too low, or the image is not animated, the default frame rate
is set to 10 fps, similarly to other WebP libraries and browsers.
The fate suite was updated accordingly.

Signed-off-by: Josef Zlomek 
---
 Changelog |   1 +
 doc/demuxers.texi |  28 ++
 libavformat/Makefile  |   1 +
 libavformat/allformats.c  |   1 +
 libavformat/webpdec.c | 384 ++
 tests/ref/fate/exif-image-webp|   4 +-
 tests/ref/fate/webp-rgb-lena-lossless |   2 +-
 tests/ref/fate/webp-rgb-lena-lossless-rgb24   |   2 +-
 tests/ref/fate/webp-rgb-lossless  |   2 +-
 .../fate/webp-rgb-lossless-palette-predictor  |   2 +-
 tests/ref/fate/webp-rgb-lossy-q80 |   2 +-
 tests/ref/fate/webp-rgba-lossless |   2 +-
 tests/ref/fate/webp-rgba-lossy-q80|   2 +-
 13 files changed, 424 insertions(+), 9 deletions(-)
 create mode 100644 libavformat/webpdec.c

diff --git a/Changelog b/Changelog
index de6eedfd68..22a6d16824 100644
--- a/Changelog
+++ b/Changelog
@@ -102,6 +102,7 @@ version 6.1:
   variable-fields elements within the same parent element
 - ffprobe -output_format option added as an alias of -of
 - animated WebP decoder
+- animated WebP demuxer
 
 
 version 6.0:
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 04293c4813..9c9d0fee17 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -1158,4 +1158,32 @@ this is set to 0, which means that a sensible value is 
chosen based on the
 input format.
 @end table
 
+@section webp
+
+Animated WebP demuxer.
+
+It accepts the following options:
+
+@table @option
+@item -min_delay @var{int}
+Set the minimum valid delay between frames in milliseconds.
+Range is 0 to 6. Default value is 10.
+
+@item -max_webp_delay @var{int}
+Set the maximum valid delay between frames in milliseconds.
+Range is 0 to 16777215. Default value is 16777215 (over four hours),
+the maximum value allowed by the specification.
+
+@item -default_delay @var{int}
+Set the default delay between frames in milliseconds.
+Range is 0 to 6. Default value is 100.
+
+@item -ignore_loop @var{bool}
+WebP files can contain information to loop a certain number of times
+(or infinitely). If @option{ignore_loop} is set to true, then the loop
+setting from the input will be ignored and looping will not occur.
+If set to false, then looping will occur and will cycle the number
+of times according to the WebP. Default value is true.
+@end table
+
 @c man end DEMUXERS
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 7ca68a7036..d86e98926d 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -628,6 +628,7 @@ OBJS-$(CONFIG_WEBM_MUXER)+= matroskaenc.o 
matroska.o \
 av1.o avlanguage.o
 OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER)  += webmdashenc.o
 OBJS-$(CONFIG_WEBM_CHUNK_MUXER)  += webm_chunk.o
+OBJS-$(CONFIG_WEBP_DEMUXER)  += webpdec.o
 OBJS-$(CONFIG_WEBP_MUXER)+= webpenc.o
 OBJS-$(CONFIG_WEBVTT_DEMUXER)+= webvttdec.o subtitles.o
 OBJS-$(CONFIG_WEBVTT_MUXER)  += webvttenc.o
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 305fa46532..23f6ef7f7d 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -511,6 +511,7 @@ extern const FFInputFormat  ff_webm_dash_manifest_demuxer;
 extern const FFOutputFormat ff_webm_dash_manifest_muxer;
 extern const FFOutputFormat ff_webm_chunk_muxer;
 extern const FFOutputFormat ff_webp_muxer;
+extern const FFInputFormat  ff_webp_demuxer;
 extern const FFInputFormat  ff_webvtt_demuxer;
 extern const FFOutputFormat ff_webvtt_muxer;
 extern const FFInputFormat  ff_wsaud_demuxer;
diff --git a/libavformat/webpdec.c b/libavformat/webpdec.c
new file mode 100644
index 00..446e181156
--- /dev/null
+++ b/libavformat/webpdec.c
@@ -0,0 +1,384 @@
+/*
+ * WebP demuxer
+ * Copyright (c) 2020 Pexeso Inc.
+ *
+ * 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; with

[FFmpeg-devel] [PATCH 1/2] configure: correct deps assigment for QR libs

2024-06-21 Thread Gyan Doshi
---
 configure | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 3bca638459..1e58c0dbac 100755
--- a/configure
+++ b/configure
@@ -7767,8 +7767,8 @@ enabled mcdeint_filter  && prepend avfilter_deps 
"avcodec"
 enabled movie_filter&& prepend avfilter_deps "avformat avcodec"
 enabled pan_filter  && prepend avfilter_deps "swresample"
 enabled pp_filter   && prepend avfilter_deps "postproc"
-enabled qrencode_filter && prepend_avfilter_deps "swscale"
-enabled qrencodesrc_filter  && prepend_avfilter_deps "swscale"
+enabled qrencode_filter && prepend avfilter_deps "swscale"
+enabled qrencodesrc_filter  && prepend avfilter_deps "swscale"
 enabled removelogo_filter   && prepend avfilter_deps "avformat avcodec swscale"
 enabled sab_filter  && prepend avfilter_deps "swscale"
 enabled scale_filter&& prepend avfilter_deps "swscale"
-- 
2.44.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/2] configure: align conditional library deps assignments

2024-06-21 Thread Gyan Doshi
---
 configure | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 1e58c0dbac..db11a78c74 100755
--- a/configure
+++ b/configure
@@ -7764,14 +7764,14 @@ enabled elbg_filter && prepend avfilter_deps 
"avcodec"
 enabled find_rect_filter&& prepend avfilter_deps "avformat avcodec"
 enabled fsync_filter&& prepend avfilter_deps "avformat"
 enabled mcdeint_filter  && prepend avfilter_deps "avcodec"
-enabled movie_filter&& prepend avfilter_deps "avformat avcodec"
+enabled movie_filter&& prepend avfilter_deps "avformat avcodec"
 enabled pan_filter  && prepend avfilter_deps "swresample"
 enabled pp_filter   && prepend avfilter_deps "postproc"
 enabled qrencode_filter && prepend avfilter_deps "swscale"
 enabled qrencodesrc_filter  && prepend avfilter_deps "swscale"
 enabled removelogo_filter   && prepend avfilter_deps "avformat avcodec swscale"
 enabled sab_filter  && prepend avfilter_deps "swscale"
-enabled scale_filter&& prepend avfilter_deps "swscale"
+enabled scale_filter&& prepend avfilter_deps "swscale"
 enabled scale2ref_filter&& prepend avfilter_deps "swscale"
 enabled showcqt_filter  && prepend avfilter_deps "avformat swscale"
 enabled signature_filter&& prepend avfilter_deps "avcodec avformat"
-- 
2.44.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/3] avutil/ambient_viewing_environment: set a sane default value for AVRational fields

2024-06-21 Thread Jan Ekström
On Thu, Jun 20, 2024 at 6:54 PM James Almer  wrote:
>
> On 6/18/2024 4:20 PM, James Almer wrote:
> > Prevent potential divisions by 0 when using them immediately after 
> > allocation.
> >
> > Signed-off-by: James Almer 
> > ---
> >   libavutil/ambient_viewing_environment.c | 10 ++
> >   1 file changed, 10 insertions(+)
> >
> > diff --git a/libavutil/ambient_viewing_environment.c 
> > b/libavutil/ambient_viewing_environment.c
> > index c47458cfa8..e359727776 100644
> > --- a/libavutil/ambient_viewing_environment.c
> > +++ b/libavutil/ambient_viewing_environment.c
> > @@ -21,6 +21,13 @@
> >   #include "ambient_viewing_environment.h"
> >   #include "mem.h"
> >
> > +static void get_defaults(AVAmbientViewingEnvironment *env)
> > +{
> > +env->ambient_illuminance =
> > +env->ambient_light_x =
> > +env->ambient_light_y = (AVRational) { 0, 1 };
> > +}
> > +
> >   AVAmbientViewingEnvironment *av_ambient_viewing_environment_alloc(size_t 
> > *size)
> >   {
> >   AVAmbientViewingEnvironment *env =
> > @@ -28,6 +35,8 @@ AVAmbientViewingEnvironment 
> > *av_ambient_viewing_environment_alloc(size_t *size)
> >   if (!env)
> >   return NULL;
> >
> > +get_defaults(env);
> > +
> >if (size)
> >   *size = sizeof(*env);
> >
> > @@ -44,6 +53,7 @@ AVAmbientViewingEnvironment 
> > *av_ambient_viewing_environment_create_side_data(AVF
> >   return NULL;
> >
> >   memset(side_data->data, 0, side_data->size);
> > +get_defaults((AVAmbientViewingEnvironment *)side_data->data);
> >
> >   return (AVAmbientViewingEnvironment *)side_data->data;
> >   }
>
> Will apply the set soon if nobody objectx.

In general I guess LGTM as I guess 0/0 is considered bad.

But isn't the function more about setting the defaults to a struct
rather than getting them? I just see that function being closer to
"set_defaults" than "get_defaults".

Jan
___
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 v13 2/8] avcodec/webp: separate VP8 decoding

2024-06-21 Thread Anton Khirnov
Quoting Thilo Borgmann via ffmpeg-devel (2024-06-21 12:43:17)
> From: Thilo Borgmann via ffmpeg-devel 
> 
> ---
>  libavcodec/webp.c | 50 +--
>  1 file changed, 44 insertions(+), 6 deletions(-)
> 
> diff --git a/libavcodec/webp.c b/libavcodec/webp.c
> index af4ebcec27..c52b9732b4 100644
> --- a/libavcodec/webp.c
> +++ b/libavcodec/webp.c
> @@ -195,6 +195,7 @@ typedef struct WebPContext {
>  AVFrame *alpha_frame;   /* AVFrame for alpha data 
> decompressed from VP8L */
>  AVPacket *pkt;  /* AVPacket to be passed to the 
> underlying VP8 decoder */
>  AVCodecContext *avctx;  /* parent AVCodecContext */
> +AVCodecContext *avctx_vp8;  /* wrapper context for VP8 decoder */

As I said before, nested decoders should be avoided whenever possible,
because properly forwarding everything between the caller and the nested
decoder is very tricky and almost never fully correct. For example, this
patch seems to break direct rendering.

And even if a nested decoder is unavoidable for some reason, it need a
lot more justification than none.

-- 
Anton Khirnov
___
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/stereo3d: set a sane default value for AVRational fields

2024-06-21 Thread James Almer

On 6/18/2024 6:13 PM, Michael Niedermayer wrote:

On Tue, Jun 18, 2024 at 04:20:34PM -0300, James Almer wrote:

Prevent potential divisions by 0 when using them immediately after allocation.

Signed-off-by: James Almer 
---
  libavutil/stereo3d.c | 14 +-
  1 file changed, 13 insertions(+), 1 deletion(-)


i must have applied the wrong patches locally but this fails to build

CC  libavutil/stereo3d.o
libavutil/stereo3d.c: In function ‘get_defaults’:
libavutil/stereo3d.c:31:47: error: incompatible types when assigning to type 
‘int32_t’ {aka ‘int’} from type ‘AVRational’ {aka ‘struct AVRational’}


This sounds like you still have Derek's old version in your tree. He has 
since changed it and pushed a different one.



31 | stereo->horizontal_disparity_adjustment = (AVRational) { 0, 1 };
   |   ^
make: *** [ffbuild/common.mak:81: libavutil/stereo3d.o] Error 1

thx

[...]


___
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] avcodec/iirfilter: Move ff_iir_filter() to lavc/tests/iirfilter.c

2024-06-21 Thread Andreas Rheinhardt
Andreas Rheinhardt:
> It is only used by the test.
> 
> Signed-off-by: Andreas Rheinhardt 
> ---
>  libavcodec/iirfilter.c   | 14 --
>  libavcodec/iirfilter.h   | 15 ---
>  libavcodec/tests/iirfilter.c | 17 -
>  3 files changed, 16 insertions(+), 30 deletions(-)
> 
> diff --git a/libavcodec/iirfilter.c b/libavcodec/iirfilter.c
> index 727a370444..cefe35ab6e 100644
> --- a/libavcodec/iirfilter.c
> +++ b/libavcodec/iirfilter.c
> @@ -277,20 +277,6 @@ av_cold struct FFIIRFilterState 
> *ff_iir_filter_init_state(int order)
>  }   \
>  }
>  
> -void ff_iir_filter(const struct FFIIRFilterCoeffs *c,
> -   struct FFIIRFilterState *s, int size,
> -   const int16_t *src, ptrdiff_t sstep,
> -   int16_t *dst, ptrdiff_t dstep)
> -{
> -if (c->order == 2) {
> -FILTER_O2(int16_t, S16)
> -} else if (c->order == 4) {
> -FILTER_BW_O4(int16_t, S16)
> -} else {
> -FILTER_DIRECT_FORM_II(int16_t, S16)
> -}
> -}
> -
>  /**
>   * Perform IIR filtering on floating-point input samples.
>   *
> diff --git a/libavcodec/iirfilter.h b/libavcodec/iirfilter.h
> index d6b8fe2782..8ab8ae68c6 100644
> --- a/libavcodec/iirfilter.h
> +++ b/libavcodec/iirfilter.h
> @@ -28,7 +28,6 @@
>  #define AVCODEC_IIRFILTER_H
>  
>  #include 
> -#include 
>  
>  struct FFIIRFilterCoeffs;
>  struct FFIIRFilterState;
> @@ -114,18 +113,4 @@ void ff_iir_filter_free_coeffsp(struct FFIIRFilterCoeffs 
> **coeffs);
>   */
>  void ff_iir_filter_free_statep(struct FFIIRFilterState **state);
>  
> -/**
> - * Perform IIR filtering on signed 16-bit input samples.
> - *
> - * @param coeffs pointer to filter coefficients
> - * @param state  pointer to filter state
> - * @param size   input length
> - * @param srcsource samples
> - * @param sstep  source stride
> - * @param dstfiltered samples (destination may be the same as input)
> - * @param dstep  destination stride
> - */
> -void ff_iir_filter(const struct FFIIRFilterCoeffs *coeffs, struct 
> FFIIRFilterState *state,
> -   int size, const int16_t *src, ptrdiff_t sstep, int16_t 
> *dst, ptrdiff_t dstep);
> -
>  #endif /* AVCODEC_IIRFILTER_H */
> diff --git a/libavcodec/tests/iirfilter.c b/libavcodec/tests/iirfilter.c
> index 60cc6fc43d..e03e842b85 100644
> --- a/libavcodec/tests/iirfilter.c
> +++ b/libavcodec/tests/iirfilter.c
> @@ -23,10 +23,25 @@
>  #include "libavutil/libm.h"
>  
>  #include "libavcodec/iirfilter.h"
> +#include "libavcodec/iirfilter.c"
>  
>  #define FILT_ORDER 4
>  #define SIZE 1024
>  
> +static void iir_filter_int16(const struct FFIIRFilterCoeffs *c,
> + struct FFIIRFilterState *s, int size,
> + const int16_t *src, ptrdiff_t sstep,
> + int16_t *dst, ptrdiff_t dstep)
> +{
> +if (c->order == 2) {
> +FILTER_O2(int16_t, S16)
> +} else if (c->order == 4) {
> +FILTER_BW_O4(int16_t, S16)
> +} else {
> +FILTER_DIRECT_FORM_II(int16_t, S16)
> +}
> +}
> +
>  int main(void)
>  {
>  struct FFIIRFilterCoeffs *fcoeffs = NULL;
> @@ -43,7 +58,7 @@ int main(void)
>  for (i = 0; i < SIZE; i++)
>  x[i] = lrint(0.75 * INT16_MAX * sin(0.5 * M_PI * i * i / SIZE));
>  
> -ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1);
> +iir_filter_int16(fcoeffs, fstate, SIZE, x, 1, y, 1);
>  
>  for (i = 0; i < SIZE; i++)
>  printf("%6d %6d\n", x[i], y[i]);

Will apply tonight unless there are objections.

- 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] avcodec/osq: avoid signed overflow in downsample path

2024-06-21 Thread Michael Niedermayer
Fixes: signed integer overflow: 865309950 * 256 cannot be represented in type 
'int'
Fixes: 
69191/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_OSQ_fuzzer-6310214413385728

Found-by: continuous fuzzing process 
https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer 
---
 libavcodec/osq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/osq.c b/libavcodec/osq.c
index 8a153330269..42a46b25ce5 100644
--- a/libavcodec/osq.c
+++ b/libavcodec/osq.c
@@ -325,7 +325,7 @@ static int do_decode(AVCodecContext *avctx, AVFrame *frame, 
int decorrelate, int
 cb->prev = prev;
 
 if (downsample)
-dst[n] *= 256;
+dst[n] *= 256U;
 
 dst[E] = dst[D];
 dst[D] = dst[C];
-- 
2.45.2

___
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/4] avcodec/j2kenc: Merge dwt_norm into lambda

2024-06-21 Thread Michael Niedermayer
On Fri, Jun 21, 2024 at 11:38:46AM +0200, Andreas Rheinhardt wrote:
> Michael Niedermayer:
> > This moves computations out of a loop
> > 
> > Fixes: signed integer overflow: 31665934879948800 * 9998 cannot be 
> > represented in type 'long'
> > Fixes: 
> > 69024/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JPEG2000_fuzzer-5949662967169024
> > 
> > Found-by: continuous fuzzing process 
> > https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
> > Signed-off-by: Michael Niedermayer 
> > ---
> >  libavcodec/j2kenc.c | 9 +
> >  1 file changed, 5 insertions(+), 4 deletions(-)
> > 
> > diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
> > index 8cf82f7216c..91e66d81048 100644
> > --- a/libavcodec/j2kenc.c
> > +++ b/libavcodec/j2kenc.c
> > @@ -1349,7 +1349,7 @@ static void makelayers(Jpeg2000EncoderContext *s, 
> > Jpeg2000Tile *tile)
> >  }
> >  }
> >  
> > -static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda, int dwt_norm)
> > +static int getcut(Jpeg2000Cblk *cblk, uint64_t lambda)
> >  {
> >  int passno, res = 0;
> >  for (passno = 0; passno < cblk->npasses; passno++){
> > @@ -1361,7 +1361,7 @@ static int getcut(Jpeg2000Cblk *cblk, uint64_t 
> > lambda, int dwt_norm)
> >  dd = cblk->passes[passno].disto
> > - (res ? cblk->passes[res-1].disto : 0);
> >  
> > -if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda)
> > +if (dd  >= dr * lambda)
> >  res = passno+1;
> >  }
> >  return res;
> > @@ -1384,11 +1384,12 @@ static void truncpasses(Jpeg2000EncoderContext *s, 
> > Jpeg2000Tile *tile)
> >  Jpeg2000Band *band = reslevel->band + bandno;
> >  Jpeg2000Prec *prec = band->prec + precno;
> >  
> > +int64_t dwt_norm = dwt_norms[codsty->transform == 
> > FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15;
> > +int64_t lambda_prime = av_rescale(s->lambda, 1 << 
> > WMSEDEC_SHIFT, dwt_norm * dwt_norm);
> >  for (cblkno = 0; cblkno < prec->nb_codeblocks_height * 
> > prec->nb_codeblocks_width; cblkno++){
> >  Jpeg2000Cblk *cblk = prec->cblk + cblkno;
> >  
> > -cblk->ninclpasses = getcut(cblk, s->lambda,
> > -(int64_t)dwt_norms[codsty->transform == 
> > FF_DWT53][bandpos][lev] * (int64_t)band->i_stepsize >> 15);
> > +cblk->ninclpasses = getcut(cblk, lambda_prime);
> >  cblk->layers[0].data_start = cblk->data;
> >  cblk->layers[0].cum_passes = cblk->ninclpasses;
> >  cblk->layers[0].npasses = cblk->ninclpasses;
> 
> Does this also fix the UB in the vsynth*-jpeg2000-yuva444p16 tests?

we will find out when this is applied, it looks like it might

thx

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

The real ebay dictionary, page 2
"100% positive feedback" - "All either got their money back or didnt complain"
"Best seller ever, very honest" - "Seller refunded buyer after failed scam"


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 3/3] avutil/stereo3d: set a sane default value for AVRational fields

2024-06-21 Thread Michael Niedermayer
On Fri, Jun 21, 2024 at 09:19:36AM -0300, James Almer wrote:
> On 6/18/2024 6:13 PM, Michael Niedermayer wrote:
> > On Tue, Jun 18, 2024 at 04:20:34PM -0300, James Almer wrote:
> > > Prevent potential divisions by 0 when using them immediately after 
> > > allocation.
> > > 
> > > Signed-off-by: James Almer 
> > > ---
> > >   libavutil/stereo3d.c | 14 +-
> > >   1 file changed, 13 insertions(+), 1 deletion(-)
> > 
> > i must have applied the wrong patches locally but this fails to build
> > 
> > CC  libavutil/stereo3d.o
> > libavutil/stereo3d.c: In function ‘get_defaults’:
> > libavutil/stereo3d.c:31:47: error: incompatible types when assigning to 
> > type ‘int32_t’ {aka ‘int’} from type ‘AVRational’ {aka ‘struct AVRational’}
> 
> This sounds like you still have Derek's old version in your tree. He has
> since changed it and pushed a different one.

yes, i realized and fixed that after i sent the mail

thx

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

If you fake or manipulate statistics in a paper in physics you will never
get a job again.
If you fake or manipulate statistics in a paper in medicin you will get
a job for life at the pharma industry.


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 v2] avcodec/aacdec_lpd: remove unused local variables

2024-06-21 Thread Leo Izen
int idx, and int first_tcx_flag are set but not used, so this commit
removes their declarations and assignments.
---
 libavcodec/aac/aacdec_lpd.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/libavcodec/aac/aacdec_lpd.c b/libavcodec/aac/aacdec_lpd.c
index 796edd2ab5..91a3268889 100644
--- a/libavcodec/aac/aacdec_lpd.c
+++ b/libavcodec/aac/aacdec_lpd.c
@@ -99,7 +99,7 @@ static void parse_qn(GetBitContext *gb, int *qn, int nk_mode, 
int no_qn)
 static int parse_codebook_idx(GetBitContext *gb, uint32_t *kv,
   int nk_mode, int no_qn)
 {
-int idx, n, nk;
+int n, nk;
 
 int qn[2];
 parse_qn(gb, qn, nk_mode, no_qn);
@@ -114,7 +114,7 @@ static int parse_codebook_idx(GetBitContext *gb, uint32_t 
*kv,
 }
 }
 
-idx = get_bits(gb, 4*n);
+skip_bits(gb, 4*n);
 
 if (nk > 0)
 for (int i = 0; i < 8; i++)
@@ -145,7 +145,6 @@ int ff_aac_ldp_parse_channel_stream(AACDecContext *ac, 
AACUSACConfig *usac,
 int k;
 const uint8_t *mod;
 int first_ldp_flag;
-int first_tcx_flag;
 
 ce->ldp.acelp_core_mode = get_bits(gb, 3);
 ce->ldp.lpd_mode = get_bits(gb, 5);
@@ -157,7 +156,6 @@ int ff_aac_ldp_parse_channel_stream(AACDecContext *ac, 
AACUSACConfig *usac,
 mod = ff_aac_lpd_mode_tab[ce->ldp.lpd_mode];
 
 first_ldp_flag = !ce->ldp.core_mode_last;
-first_tcx_flag = 1;
 if (first_ldp_flag)
 ce->ldp.last_lpd_mode = -1; /* last_ldp_mode is a **STATEFUL** value */
 
@@ -179,7 +177,6 @@ int ff_aac_ldp_parse_channel_stream(AACDecContext *ac, 
AACUSACConfig *usac,
 //parse_tcx_coding();
 ce->ldp.last_lpd_mode = mod[k];
 k += (1 << (mod[k] - 1));
-first_tcx_flag = 0;
 }
 }
 
-- 
2.45.2

___
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] avutil/stereo3d add Monoscopic View enum value

2024-06-21 Thread James Almer
We need a way to signal the frame has a single view that doesn't map to any
particular eye, and it should be the default one.

Signed-off-by: James Almer 
---
The Stereo spec from Apple, which was used to design this API, states "both
has_left_eye_view and has_right_eye_view can be set to 0 to indicate that the
frame is monoscopic".

Since this API is barely two days old, we can change the enum maped to value 0
as an exception.

 libavutil/stereo3d.h | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index 00a5c3900e..77340f72b2 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -143,9 +143,9 @@ enum AVStereo3DType {
  */
 enum AVStereo3DView {
 /**
- * Frame contains two packed views.
+ * Frame is monoscopic.
  */
-AV_STEREO3D_VIEW_PACKED,
+AV_STEREO3D_VIEW_MONO,
 
 /**
  * Frame contains only the left view.
@@ -156,6 +156,11 @@ enum AVStereo3DView {
  * Frame contains only the right view.
  */
 AV_STEREO3D_VIEW_RIGHT,
+
+/**
+ * Frame contains two packed views.
+ */
+AV_STEREO3D_VIEW_PACKED,
 };
 
 /**
-- 
2.45.2

___
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] avformat/mov: default to Monoscopic view when parsing eyes box

2024-06-21 Thread James Almer
Signed-off-by: James Almer 
---
 libavformat/mov.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 50e171c960..4fa39cf4fd 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6546,7 +6546,7 @@ static int mov_read_eyes(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 int size, flags = 0;
 int64_t remaining;
 uint32_t tag, baseline = 0;
-enum AVStereo3DView view = AV_STEREO3D_VIEW_PACKED;
+enum AVStereo3DView view = AV_STEREO3D_VIEW_MONO;
 enum AVStereo3DPrimaryEye primary_eye = AV_PRIMARY_EYE_NONE;
 AVRational horizontal_disparity_adjustment = { 0, 1 };
 
-- 
2.45.2

___
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] libavformat/vapoursynth: Update to API version 4, load library at runtime

2024-06-21 Thread Stefan Oltmanns via ffmpeg-devel

Hello,

this is my first patch, I hope I got all the formalities correct.

The current VapourSynth implementation is rarely used, as it links the
VapourSynth library at build time, making the resulting build unable to
run when VapourSynth is not installed. Therefore barely anyone compiles
with VapourSynth activated.

I changed it, so that it loads the library at runtime when a VapourSynth
script should be opened, just like AviSynth does.
On Windows the DLL from VapourSynth is not installed in the system
directory, but the location is stored in the Registry. Therefore I added
some code to read that information from the registry.

As the V4 API is designed with dynamic loading in mind (only a single
import), I updated the implementation to V4 (changes are mostly
superficial, no structural changes). The V4 API is already several years
old, fully supported since R55 released in 2021.

I copied the two needed header files directly in a vapoursynth.h,
removing the need to install VapourSynth on the build machine
(VapourSynth is also LGPL 2.1 or later, so no license issue). I updated
the configure so that it checks for the ability to load libraries at
runtime for VapourSynth, just like AviSynth and activate it if not disabled.

make fate runs without any issue. I tested VapourSynth input scripts
with various color formats on different platforms:

Ubuntu 22.04
macOS 13 (x86_64)
macOS 13 (arm64)
Windows 10 (msys2/gcc)

It compiles on these platforms without any warning and runs without any
issues.

Best regards
Stefan
From c13faf46f5d210c676b237f855d56a9b8a0a127d Mon Sep 17 00:00:00 2001
From: John Doe 
Date: Sat, 22 Jun 2024 02:53:07 +0200
Subject: [PATCH] libavformat/vapoursynth: Update to API version 4, load
 library at runtime

The VapourSynth V4 API is designed for loading at runtime instead of linking to it during build time,
this is now done in ffmpeg, similar to how AviSynth support is implemented.
This allows building with VapourSynth support enabled,
but ffmpeg still working fine without VapourSynth installed on target machine.
---
 configure |   7 +-
 libavformat/vapoursynth.c | 167 +++---
 libavformat/vapoursynth.h | 635 ++
 3 files changed, 768 insertions(+), 41 deletions(-)
 create mode 100644 libavformat/vapoursynth.h

diff --git a/configure b/configure
index 3bca638459..a54d2976f5 100755
--- a/configure
+++ b/configure
@@ -333,7 +333,7 @@ External library support:
   --disable-sdl2   disable sdl2 [autodetect]
   --disable-securetransport disable Secure Transport, needed for TLS support
on OSX if openssl and gnutls are not used [autodetect]
-  --enable-vapoursynth enable VapourSynth demuxer [no]
+  --disable-vapoursynthdisable VapourSynth demuxer [autodetect]
   --disable-xlib   disable xlib [autodetect]
   --disable-zlib   disable zlib [autodetect]
 
@@ -1853,6 +1853,7 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST="
 sdl2
 securetransport
 sndio
+vapoursynth
 xlib
 zlib
 "
@@ -1981,7 +1982,6 @@ EXTERNAL_LIBRARY_LIST="
 opengl
 openssl
 pocketsphinx
-vapoursynth
 "
 
 HWACCEL_AUTODETECT_LIBRARY_LIST="
@@ -3572,6 +3572,7 @@ libxevd_decoder_deps="libxevd"
 libxeve_encoder_deps="libxeve"
 libxvid_encoder_deps="libxvid"
 libzvbi_teletext_decoder_deps="libzvbi"
+vapoursynth_deps_any="libdl LoadLibrary"
 vapoursynth_demuxer_deps="vapoursynth"
 videotoolbox_suggest="coreservices"
 videotoolbox_deps="corefoundation coremedia corevideo"
@@ -7068,8 +7069,6 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp  rockchip/r
{ enabled libdrm ||
  die "ERROR: rkmpp requires --enable-libdrm"; }
  }
-enabled vapoursynth   && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init
-
 
 if enabled gcrypt; then
 GCRYPT_CONFIG="${cross_prefix}libgcrypt-config"
diff --git a/libavformat/vapoursynth.c b/libavformat/vapoursynth.c
index 8a2519e19a..8cf309002b 100644
--- a/libavformat/vapoursynth.c
+++ b/libavformat/vapoursynth.c
@@ -25,9 +25,6 @@
 
 #include 
 
-#include 
-#include 
-
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/eval.h"
@@ -39,20 +36,65 @@
 #include "avformat.h"
 #include "demux.h"
 #include "internal.h"
+#include "vapoursynth.h"
+
+/* Platform-specific directives. */
+#ifdef _WIN32
+  #include 
+  #include "compat/w32dlfcn.h"
+  #include "libavutil/wchar_filename.h"
+  static av_cold char* get_vs_script_dll_name(void) {
+   LONG r;
+   WCHAR vss_path[512];
+   char *vss_path_utf8;
+   DWORD buf_size = sizeof(vss_path) - 2;
+   r = RegGetValueW(HKEY_CURRENT_USER, L"SOFTWARE\\VapourSynth",
+L"VSScriptDLL", RRF_RT_REG_SZ, NULL,
+&vss_path, &buf_size);
+   if (r == ERROR_SUCCESS && wchartoutf8(vss_path, &vss_path_

[FFmpeg-devel] [PATCH 3/3] avutil/stereo3d: add a Stereo3D type to signal that the packing is defined by the view field

2024-06-21 Thread James Almer
Given that a video stream/frame may have only one view coded, or both packed in
an undefined way, and as the values of AVStereo3DView and AVStereo3DType may
clash (namely if type is AV_STEREO3D_2D, then AV_STEREO3D_VIEW_PACKED would be
invalid, and if it's anything other than it, then only AV_STEREO3D_VIEW_PACKED
would be valid), this commit adds a new type value AV_STEREO3D_VIEW that
signals the user that AVStereo3D.view contains information about the nature of
the stream, with the added constrain that AVStereo3D.view should be ignored if
AVStereo3D.type is anything other than AV_STEREO3D_VIEW.

Signed-off-by: James Almer 
---
This is the only way i could think of to work around the fact AVStereo3DType
and AVStereo3DView just can't work well together if we want to keep AVStereo
backwards compatible.

 libavutil/stereo3d.c |  1 +
 libavutil/stereo3d.h | 11 ++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c
index 0c0cad127c..e8e5030db9 100644
--- a/libavutil/stereo3d.c
+++ b/libavutil/stereo3d.c
@@ -65,6 +65,7 @@ static const char * const stereo3d_type_names[] = {
 [AV_STEREO3D_SIDEBYSIDE_QUINCUNX] = "side by side (quincunx subsampling)",
 [AV_STEREO3D_LINES]   = "interleaved lines",
 [AV_STEREO3D_COLUMNS] = "interleaved columns",
+[AV_STEREO3D_VIEW]= "view defined",
 };
 
 static const char * const stereo3d_view_names[] = {
diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index 77340f72b2..e3af519e03 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -136,6 +136,14 @@ enum AVStereo3DType {
  * @endcode
  */
 AV_STEREO3D_COLUMNS,
+
+/**
+ * Video may be monoscopic, or stereoscopic where either the
+ * packing is unknown or only one view is present.
+ *
+ * @see AVStereo3DView
+ */
+AV_STEREO3D_VIEW,
 };
 
 /**
@@ -207,7 +215,8 @@ typedef struct AVStereo3D {
 int flags;
 
 /**
- * Determines which views are packed.
+ * Determines which views are packed. This field should be ignored when
+ * @ref type is set to anything other than AV_STEREO3D_VIEW.
  */
 enum AVStereo3DView view;
 
-- 
2.45.2

___
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 4/7] avformat/dump: print Stereo3D view only when type is view defined

2024-06-21 Thread James Almer
Signed-off-by: James Almer 
---
 libavformat/dump.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavformat/dump.c b/libavformat/dump.c
index 61a2c6a29f..33d72b7e18 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -259,9 +259,10 @@ static void dump_stereo3d(void *ctx, const 
AVPacketSideData *sd, int log_level)
 
 stereo = (const AVStereo3D *)sd->data;
 
-av_log(ctx, log_level, "%s, view: %s, primary eye: %s",
-   av_stereo3d_type_name(stereo->type), 
av_stereo3d_view_name(stereo->view),
-   av_stereo3d_primary_eye_name(stereo->primary_eye));
+av_log(ctx, log_level, "%s", av_stereo3d_type_name(stereo->type));
+if (stereo->type == AV_STEREO3D_VIEW)
+av_log(ctx, log_level, ", view: %s", 
av_stereo3d_view_name(stereo->view));
+av_log(ctx, log_level, ", primary eye: %s", 
av_stereo3d_primary_eye_name(stereo->primary_eye));
 if (stereo->baseline)
 av_log(ctx, log_level, ", baseline: %"PRIu32"", stereo->baseline);
 if (stereo->horizontal_disparity_adjustment.num && 
stereo->horizontal_disparity_adjustment.den)
-- 
2.45.2

___
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 5/7] avutil/stereo3d: add a new allocator function that returns a size

2024-06-21 Thread James Almer
av_stereo3d_alloc() is not useful in scenarios where you need to know the
runtime size of AVStereo3D.

Signed-off-by: James Almer 
---
 libavutil/stereo3d.c | 8 
 libavutil/stereo3d.h | 8 
 2 files changed, 16 insertions(+)

diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c
index e8e5030db9..c182b18e52 100644
--- a/libavutil/stereo3d.c
+++ b/libavutil/stereo3d.c
@@ -32,6 +32,11 @@ static void get_defaults(AVStereo3D *stereo)
 }
 
 AVStereo3D *av_stereo3d_alloc(void)
+{
+return av_stereo3d_alloc_size(NULL);
+}
+
+AVStereo3D *av_stereo3d_alloc_size(size_t *size)
 {
 AVStereo3D *stereo = av_mallocz(sizeof(AVStereo3D));
 if (!stereo)
@@ -39,6 +44,9 @@ AVStereo3D *av_stereo3d_alloc(void)
 
 get_defaults(stereo);
 
+if (size)
+*size = sizeof(*stereo);
+
 return stereo;
 }
 
diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index e3af519e03..31167c14fa 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -251,6 +251,14 @@ typedef struct AVStereo3D {
  */
 AVStereo3D *av_stereo3d_alloc(void);
 
+/**
+ * Allocate an AVStereo3D structure and set its fields to default values.
+ * The resulting struct can be freed using av_freep().
+ *
+ * @return An AVStereo3D filled with default values or NULL on failure.
+ */
+AVStereo3D *av_stereo3d_alloc_size(size_t *size);
+
 /**
  * Allocate a complete AVFrameSideData and add it to the frame.
  *
-- 
2.45.2

___
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 6/7] avformat/mov: don't use sizeof(AVStereo3D)

2024-06-21 Thread James Almer
It's not part of the libavutil ABI.

Signed-off-by: James Almer 
---
 libavformat/isom.h |  1 +
 libavformat/mov.c  | 10 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/libavformat/isom.h b/libavformat/isom.h
index 35b767a52c..a0498f45e5 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -247,6 +247,7 @@ typedef struct MOVStreamContext {
 
 int32_t *display_matrix;
 AVStereo3D *stereo3d;
+size_t stereo3d_size;
 AVSphericalMapping *spherical;
 size_t spherical_size;
 AVMasteringDisplayMetadata *mastering;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 9b2ce1f167..07c0ec3ec4 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -6332,7 +6332,7 @@ static int mov_read_st3d(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 return 0;
 }
 
-sc->stereo3d = av_stereo3d_alloc();
+sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
 if (!sc->stereo3d)
 return AVERROR(ENOMEM);
 
@@ -6695,7 +6695,7 @@ static int mov_read_eyes(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 }
 
 if (!sc->stereo3d) {
-sc->stereo3d = av_stereo3d_alloc();
+sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
 if (!sc->stereo3d)
 return AVERROR(ENOMEM);
 }
@@ -6782,7 +6782,7 @@ static int mov_read_hfov(MOVContext *c, AVIOContext *pb, 
MOVAtom atom)
 
 
 if (!sc->stereo3d) {
-sc->stereo3d = av_stereo3d_alloc();
+sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
 if (!sc->stereo3d)
 return AVERROR(ENOMEM);
 }
@@ -6831,7 +6831,7 @@ static int mov_parse_uuid_spherical(MOVStreamContext *sc, 
AVIOContext *pb, size_
 else
 mode = AV_STEREO3D_2D;
 
-sc->stereo3d = av_stereo3d_alloc();
+sc->stereo3d = av_stereo3d_alloc_size(&sc->stereo3d_size);
 if (!sc->stereo3d)
 goto out;
 
@@ -10032,7 +10032,7 @@ static int mov_read_header(AVFormatContext *s)
 if (sc->stereo3d) {
 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, 
&st->codecpar->nb_coded_side_data,
  AV_PKT_DATA_STEREO3D,
- (uint8_t *)sc->stereo3d, 
sizeof(*sc->stereo3d), 0))
+ (uint8_t *)sc->stereo3d, 
sc->stereo3d_size, 0))
 return AVERROR(ENOMEM);
 
 sc->stereo3d = NULL;
-- 
2.45.2

___
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 7/7] avformat/matroskadec: don't use sizeof(AVStereo3D)

2024-06-21 Thread James Almer
It's not part of the libavutil ABI.

Signed-off-by: James Almer 
---
 libavformat/matroskadec.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 6bc5fa621e..d1a135ed63 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2253,8 +2253,9 @@ static int mkv_stereo3d_conv(AVStream *st, 
MatroskaVideoStereoModeType stereo_mo
 STEREOMODE_STEREO3D_MAPPING(STEREO_MODE_CONV, NOTHING)
 };
 AVStereo3D *stereo;
+size_t size;
 
-stereo = av_stereo3d_alloc();
+stereo = av_stereo3d_alloc_size(&size);
 if (!stereo)
 return AVERROR(ENOMEM);
 
@@ -2262,7 +2263,7 @@ static int mkv_stereo3d_conv(AVStream *st, 
MatroskaVideoStereoModeType stereo_mo
 stereo->flags = stereo_mode_conv[stereo_mode].flags;
 
 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, 
&st->codecpar->nb_coded_side_data,
- AV_PKT_DATA_STEREO3D, stereo, 
sizeof(*stereo), 0)) {
+ AV_PKT_DATA_STEREO3D, stereo, size, 0)) {
 av_freep(&stereo);
 return AVERROR(ENOMEM);
 }
-- 
2.45.2

___
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/7 v2] avutil/stereo3d add Monoscopic View enum value

2024-06-21 Thread James Almer
We need a way to signal the frame has a single view that doesn't map to any
particular eye, and it should be the default one.

Signed-off-by: James Almer 
---
Now updating the fate test, to show how type and view clashed as is.

 libavutil/stereo3d.c   | 3 ++-
 libavutil/stereo3d.h   | 9 +++--
 tests/ref/fate/matroska-spherical-mono | 2 +-
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c
index 19e81e4124..0c0cad127c 100644
--- a/libavutil/stereo3d.c
+++ b/libavutil/stereo3d.c
@@ -68,9 +68,10 @@ static const char * const stereo3d_type_names[] = {
 };
 
 static const char * const stereo3d_view_names[] = {
-[AV_STEREO3D_VIEW_PACKED] = "packed",
+[AV_STEREO3D_VIEW_MONO]   = "monoscopic",
 [AV_STEREO3D_VIEW_LEFT]   = "left",
 [AV_STEREO3D_VIEW_RIGHT]  = "right",
+[AV_STEREO3D_VIEW_PACKED] = "packed",
 };
 
 static const char * const stereo3d_primary_eye_names[] = {
diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index 00a5c3900e..77340f72b2 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -143,9 +143,9 @@ enum AVStereo3DType {
  */
 enum AVStereo3DView {
 /**
- * Frame contains two packed views.
+ * Frame is monoscopic.
  */
-AV_STEREO3D_VIEW_PACKED,
+AV_STEREO3D_VIEW_MONO,
 
 /**
  * Frame contains only the left view.
@@ -156,6 +156,11 @@ enum AVStereo3DView {
  * Frame contains only the right view.
  */
 AV_STEREO3D_VIEW_RIGHT,
+
+/**
+ * Frame contains two packed views.
+ */
+AV_STEREO3D_VIEW_PACKED,
 };
 
 /**
diff --git a/tests/ref/fate/matroska-spherical-mono 
b/tests/ref/fate/matroska-spherical-mono
index b108596350..aa17e9c624 100644
--- a/tests/ref/fate/matroska-spherical-mono
+++ b/tests/ref/fate/matroska-spherical-mono
@@ -3,7 +3,7 @@
 side_data_type=Stereo 3D
 type=2D
 inverted=0
-view=packed
+view=monoscopic
 primary_eye=none
 baseline=0
 horizontal_disparity_adjustment=0/1
-- 
2.45.2

___
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 8/8] fftools/ffprobe: only print AVStereo3D.view when it's defined

2024-06-21 Thread James Almer
Signed-off-by: James Almer 
---
 fftools/ffprobe.c  | 3 ++-
 tests/ref/fate/matroska-spherical-mono | 1 -
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index d7ba980ff9..f9124ad5d7 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -2544,7 +2544,8 @@ static void print_pkt_side_data(WriterContext *w,
 const AVStereo3D *stereo = (AVStereo3D *)sd->data;
 print_str("type", av_stereo3d_type_name(stereo->type));
 print_int("inverted", !!(stereo->flags & AV_STEREO3D_FLAG_INVERT));
-print_str("view", av_stereo3d_view_name(stereo->view));
+if (stereo->type == AV_STEREO3D_VIEW)
+print_str("view", av_stereo3d_view_name(stereo->view));
 print_str("primary_eye", 
av_stereo3d_primary_eye_name(stereo->primary_eye));
 print_int("baseline", stereo->baseline);
 print_q("horizontal_disparity_adjustment", 
stereo->horizontal_disparity_adjustment, '/');
diff --git a/tests/ref/fate/matroska-spherical-mono 
b/tests/ref/fate/matroska-spherical-mono
index aa17e9c624..254bb9903f 100644
--- a/tests/ref/fate/matroska-spherical-mono
+++ b/tests/ref/fate/matroska-spherical-mono
@@ -3,7 +3,6 @@
 side_data_type=Stereo 3D
 type=2D
 inverted=0
-view=monoscopic
 primary_eye=none
 baseline=0
 horizontal_disparity_adjustment=0/1
-- 
2.45.2

___
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/4] x86/vvc_alf: avoid overwriting for non-16 aligned widths

2024-06-21 Thread Nuo Mi
Previously, the code allowed overwriting on 16-aligned blocks, which was 
suitable when there were
no picture's virtual boundaries because both CTU sizes and strides were 
16-aligned. However, with
picture's virtual boundaries, each CTU is divided into four ALF blocks, leading 
to potential issues
with overwriting later CTUs.

In cases involving picture virtual boundaries, each ALF block is 8-pixel 
aligned.
For luma, we consistently ensure an 8-aligned width. For chroma in 4:2:0 format,
we need to account for a 4-aligned width.
---
 libavcodec/x86/vvc/vvc_alf.asm | 85 ++
 1 file changed, 75 insertions(+), 10 deletions(-)

diff --git a/libavcodec/x86/vvc/vvc_alf.asm b/libavcodec/x86/vvc/vvc_alf.asm
index b35dd9b0e9..f69a69f05f 100644
--- a/libavcodec/x86/vvc/vvc_alf.asm
+++ b/libavcodec/x86/vvc/vvc_alf.asm
@@ -324,18 +324,69 @@ SECTION .text
 %endif
 %endmacro
 
-; STORE_PIXELS(dst, src)
-%macro STORE_PIXELS 2
+; STORE_PIXELS_W16(dst, src)
+%macro STORE_PIXELS_W16 2
 %if ps == 2
-movu %1, m%2
+movu   [%1],  m%2
 %else
+movu   [%1], xm%2
+%endif
+%endmacro
+
+%macro STORE_PIXELS_W8 2
+%if ps == 2
+movu   [%1], xm%2
+%else
+movq   [%1], xm%2
+%endif
+%endmacro
+
+; STORE_PIXELS_W4(dst, src, offset)
+%macro STORE_PIXELS_W4 3
+%if ps == 2
+movq   [%1 + %3 * ps], xm%2
+%else
+movd[%1 + %3], xm%2
+%endif
+%endmacro
+
+%macro STORE_PIXELS_W8LE 3
+cmp %3, 8
+jl .w4
+STORE_PIXELS_W8 %1, %2
+cmp %3, 12
+%if ps == 2
+vpermq  m%2,  m%2, q0302
+%else
+vpermq  m%2,  m%2, q0101
+%endif
+jl .end
+STORE_PIXELS_W4 %1, %2, 8
+jmp .end
+.w4:
+STORE_PIXELS_W4 %1, %2, 0
+.end:
+%endmacro
+
+; STORE_PIXELS(dst, src, width)
+%macro STORE_PIXELS 3
+%if ps == 1
 packuswbm%2, m%2
 vpermq  m%2, m%2, 0x8
-movu %1, xm%2
+%endif
+
+%ifidn %3, 16
+STORE_PIXELS_W16  %1, %2
+%else
+%if LUMA
+STORE_PIXELS_W8   %1, %2
+%else
+STORE_PIXELS_W8LE %1, %2, %3
+%endif
 %endif
 %endmacro
 
-%macro FILTER_16x4 0
+%macro FILTER_16x4 1
 %if LUMA
 push clipq
 push strideq
@@ -362,7 +413,7 @@ SECTION .text
 ; clip to pixel
 CLIPW m0, m14, m15
 
-STORE_PIXELS  [dstq], 0
+STORE_PIXELSdstq, 0, %1
 
 lea srcq, [srcq + src_strideq]
 lea dstq, [dstq + dst_strideq]
@@ -399,7 +450,7 @@ SECTION .text
 ;  const uint8_t *src, ptrdiff_t src_stride, const ptrdiff_t width, cosnt 
ptr_diff_t height,
 ;  const int16_t *filter, const int16_t *clip, ptrdiff_t stride, ptrdiff_t 
vb_pos, ptrdiff_t pixel_max);
 ; **
-cglobal vvc_alf_filter_%2_%1bpc, 11, 15, 16, 0-0x28, dst, dst_stride, src, 
src_stride, width, height, filter, clip, stride, vb_pos, pixel_max, \
+cglobal vvc_alf_filter_%2_%1bpc, 11, 15, 16, 0-0x30, dst, dst_stride, src, 
src_stride, width, height, filter, clip, stride, vb_pos, pixel_max, \
 offset, x, s5, s6
 %define ps (%1 / 8) ; pixel size
 movdxm15, pixel_maxd
@@ -409,18 +460,32 @@ cglobal vvc_alf_filter_%2_%1bpc, 11, 15, 16, 0-0x28, dst, 
dst_stride, src, src_s
 .loop:
 pushsrcq
 pushdstq
+push  widthq
 xor   xq, xq
 
 .loop_w:
+cmp   widthq, 16
+jl   .loop_w_end
+
 LOAD_PARAMS
-FILTER_16x4
+FILTER_16x4   16
 
 add srcq, 16 * ps
 add dstq, 16 * ps
 add   xq, 16
-cmp   xq, widthq
-jl   .loop_w
+sub   widthq, 16
+jmp  .loop_w
+
+.loop_w_end:
+cmp   widthq, 0
+je.w_end
+
+LOAD_PARAMS
+FILTER_16x4  widthq
+
+.w_end:
 
+pop   widthq
 pop dstq
 pop srcq
 lea srcq, [srcq + 4 * src_strideq]
-- 
2.34.1

___
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 4/4] checkasm/vvc_alf: ensure right and bottom boundaries are not overwritten by asm

2024-06-21 Thread Nuo Mi
---
 tests/checkasm/vvc_alf.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/checkasm/vvc_alf.c b/tests/checkasm/vvc_alf.c
index be8b930810..15e79289cd 100644
--- a/tests/checkasm/vvc_alf.c
+++ b/tests/checkasm/vvc_alf.c
@@ -108,8 +108,8 @@ static void check_alf_filter(VVCDSPContext *c, const int 
bit_depth)
 memset(dst1, 0, DST_BUF_SIZE);
 call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
 call_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
-for (int i = 0; i < h; i++) {
-if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, w * SIZEOF_PIXEL))
+for (int i = 0; i < (h + 1); i++) {
+if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, (w + 1) * SIZEOF_PIXEL))
 fail();
 }
 // Bench only square sizes, and ones with dimensions being 
a power of two.
@@ -125,8 +125,8 @@ static void check_alf_filter(VVCDSPContext *c, const int 
bit_depth)
 memset(dst1, 0, DST_BUF_SIZE);
 call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
 call_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
-for (int i = 0; i < h; i++) {
-if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, w * SIZEOF_PIXEL))
+for (int i = 0; i < (h + 1); i++) {
+if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, (w + 1) * SIZEOF_PIXEL))
 fail();
 }
 if (w == h && (w & (w - 1)) == 0)
-- 
2.34.1

___
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/4] checkasm/vvc_alf: only check the valid filter and classify sizes

2024-06-21 Thread Nuo Mi
---
 tests/checkasm/vvc_alf.c | 61 ++--
 1 file changed, 34 insertions(+), 27 deletions(-)

diff --git a/tests/checkasm/vvc_alf.c b/tests/checkasm/vvc_alf.c
index 84b0f9da15..902757aff1 100644
--- a/tests/checkasm/vvc_alf.c
+++ b/tests/checkasm/vvc_alf.c
@@ -90,35 +90,41 @@ static void check_alf_filter(VVCDSPContext *c, const int 
bit_depth)
 randomize_buffers2(filter, LUMA_PARAMS_SIZE, 1);
 randomize_buffers2(clip, LUMA_PARAMS_SIZE, 0);
 
-for (int h = 4; h <= MAX_CTU_SIZE; h += 8) {
-for (int w = 4; w <= MAX_CTU_SIZE; w += 8) {
+for (int h = 4; h <= MAX_CTU_SIZE; h += 4) {
+for (int w = 4; w <= MAX_CTU_SIZE; w += 4) {
 const int ctu_size = MAX_CTU_SIZE;
-if (check_func(c->alf.filter[LUMA], 
"vvc_alf_filter_luma_%dx%d_%d", w, h, bit_depth)) {
-const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_LUMA;
-memset(dst0, 0, DST_BUF_SIZE);
-memset(dst1, 0, DST_BUF_SIZE);
-call_ref(dst0, dst_stride, src0 + offset, src_stride, w, h, 
filter, clip, vb_pos);
-call_new(dst1, dst_stride, src1 + offset, src_stride, w, h, 
filter, clip, vb_pos);
-for (int i = 0; i < h; i++) {
-if (memcmp(dst0 + i * dst_stride, dst1 + i * dst_stride, w 
* SIZEOF_PIXEL))
-fail();
+//Both picture size and virtual boundaries are 8-aligned. For 
luma, we only need to check 8-aligned sizes.
+if (!(w % 8) && !(h % 8)) {
+if (check_func(c->alf.filter[LUMA], 
"vvc_alf_filter_luma_%dx%d_%d", w, h, bit_depth)) {
+const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_LUMA;
+memset(dst0, 0, DST_BUF_SIZE);
+memset(dst1, 0, DST_BUF_SIZE);
+call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
+call_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
+for (int i = 0; i < h; i++) {
+if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, w * SIZEOF_PIXEL))
+fail();
+}
+// Bench only square sizes, and ones with dimensions being 
a power of two.
+if (w == h && (w & (w - 1)) == 0)
+bench_new(dst1, dst_stride, src1 + offset, src_stride, 
w, h, filter, clip, vb_pos);
 }
-// Bench only square sizes, and ones with dimensions being a 
power of two.
-if (w == h && (w & (w - 1)) == 0)
-bench_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
 }
-if (check_func(c->alf.filter[CHROMA], 
"vvc_alf_filter_chroma_%dx%d_%d", w, h, bit_depth)) {
-const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_CHROMA;
-memset(dst0, 0, DST_BUF_SIZE);
-memset(dst1, 0, DST_BUF_SIZE);
-call_ref(dst0, dst_stride, src0 + offset, src_stride, w, h, 
filter, clip, vb_pos);
-call_new(dst1, dst_stride, src1 + offset, src_stride, w, h, 
filter, clip, vb_pos);
-for (int i = 0; i < h; i++) {
-if (memcmp(dst0 + i * dst_stride, dst1 + i * dst_stride, w 
* SIZEOF_PIXEL))
-fail();
+//For chroma, once it exceeds 64, it's not a 4:2:0 format, so we 
only need to check 8-aligned sizes as well.
+if ((w <= 64 || !(w % 8)) && (h <= 64 || !(h % 8))) {
+if (check_func(c->alf.filter[CHROMA], 
"vvc_alf_filter_chroma_%dx%d_%d", w, h, bit_depth)) {
+const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_CHROMA;
+memset(dst0, 0, DST_BUF_SIZE);
+memset(dst1, 0, DST_BUF_SIZE);
+call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
+call_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
+for (int i = 0; i < h; i++) {
+if (memcmp(dst0 + i * dst_stride, dst1 + i * 
dst_stride, w * SIZEOF_PIXEL))
+fail();
+}
+if (w == h && (w & (w - 1)) == 0)
+bench_new(dst1, dst_stride, src1 + offset, src_stride, 
w, h, filter, clip, vb_pos);
 }
-if (w == h && (w & (w - 1)) == 0)
-bench_new(dst1, dst_stride, src1 + offset, src_stride, w, 
h, filter, clip, vb_pos);
 }
 }
 }
@@ -142,8 +148,9 @@ static void check_alf_classify(VVCDSPContext *c, const int 
bit_depth)
 
 randomize_buffers(src0, src1, SRC_BUF_SIZE);
 
-for (int h = 4; h <= MAX_CTU_SIZE; h += 8) {
-for (int w = 4; w <= MAX_CTU_SIZE; w += 8) {
+//Both 

[FFmpeg-devel] [PATCH 2/4] checkasm/vvc_alf: random select alf virtual boundaries position

2024-06-21 Thread Nuo Mi
A picture's virtual boundaries will split a CTU into 4 ALF blocks.
The ALF virtual boundary may cross or not cross a ALF block.
---
 tests/checkasm/vvc_alf.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/tests/checkasm/vvc_alf.c b/tests/checkasm/vvc_alf.c
index 902757aff1..be8b930810 100644
--- a/tests/checkasm/vvc_alf.c
+++ b/tests/checkasm/vvc_alf.c
@@ -66,6 +66,14 @@ static const uint32_t pixel_mask[3] = { 0x, 
0x03ff03ff, 0x0fff0fff };
 }   \
 } while (0)
 
+static int get_alf_vb_pos(const int h, const int vb_pos_above)
+{
+if (h == MAX_CTU_SIZE)
+return MAX_CTU_SIZE - vb_pos_above;
+// If h < MAX_CTU_SIZE and picture virtual boundaries are involved, ALF 
virtual boundaries can either be within or outside this ALF block.
+return ((rnd() & 1) ? h : MAX_CTU_SIZE) - vb_pos_above;
+}
+
 static void check_alf_filter(VVCDSPContext *c, const int bit_depth)
 {
 LOCAL_ALIGNED_32(uint8_t, dst0, [DST_BUF_SIZE]);
@@ -92,11 +100,10 @@ static void check_alf_filter(VVCDSPContext *c, const int 
bit_depth)
 
 for (int h = 4; h <= MAX_CTU_SIZE; h += 4) {
 for (int w = 4; w <= MAX_CTU_SIZE; w += 4) {
-const int ctu_size = MAX_CTU_SIZE;
 //Both picture size and virtual boundaries are 8-aligned. For 
luma, we only need to check 8-aligned sizes.
 if (!(w % 8) && !(h % 8)) {
 if (check_func(c->alf.filter[LUMA], 
"vvc_alf_filter_luma_%dx%d_%d", w, h, bit_depth)) {
-const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_LUMA;
+const int vb_pos = get_alf_vb_pos(h, 
ALF_VB_POS_ABOVE_LUMA);
 memset(dst0, 0, DST_BUF_SIZE);
 memset(dst1, 0, DST_BUF_SIZE);
 call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
@@ -113,7 +120,7 @@ static void check_alf_filter(VVCDSPContext *c, const int 
bit_depth)
 //For chroma, once it exceeds 64, it's not a 4:2:0 format, so we 
only need to check 8-aligned sizes as well.
 if ((w <= 64 || !(w % 8)) && (h <= 64 || !(h % 8))) {
 if (check_func(c->alf.filter[CHROMA], 
"vvc_alf_filter_chroma_%dx%d_%d", w, h, bit_depth)) {
-const int vb_pos = ctu_size - ALF_VB_POS_ABOVE_CHROMA;
+const int vb_pos = get_alf_vb_pos(h, 
ALF_VB_POS_ABOVE_CHROMA);
 memset(dst0, 0, DST_BUF_SIZE);
 memset(dst1, 0, DST_BUF_SIZE);
 call_ref(dst0, dst_stride, src0 + offset, src_stride, w, 
h, filter, clip, vb_pos);
@@ -152,7 +159,7 @@ static void check_alf_classify(VVCDSPContext *c, const int 
bit_depth)
 for (int h = 8; h <= MAX_CTU_SIZE; h += 8) {
 for (int w = 8; w <= MAX_CTU_SIZE; w += 8) {
 const int id_size = w * h / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE * 
sizeof(int);
-const int vb_pos  = MAX_CTU_SIZE - ALF_BLOCK_SIZE;
+const int vb_pos  = get_alf_vb_pos(h, ALF_VB_POS_ABOVE_LUMA);
 if (check_func(c->alf.classify, "vvc_alf_classify_%dx%d_%d", w, h, 
bit_depth)) {
 memset(class_idx0, 0, id_size);
 memset(class_idx1, 0, id_size);
-- 
2.34.1

___
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 01/18] avcodec/vvcdec: refact, unify vvc_deblock_subblock_bs_{horizontal, vertical}

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 93 ++---
 1 file changed, 32 insertions(+), 61 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 7844d34eac..d4c09b69f3 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -406,30 +406,43 @@ static void derive_max_filter_length_luma(const 
VVCFrameContext *fc, const int q
 *max_len_p = FFMIN(5, *max_len_p);
 }
 
-static void vvc_deblock_subblock_bs_vertical(const VVCLocalContext *lc,
-const int cb_x, const int cb_y, const int x0, const int y0, const int 
width, const int height)
+static void vvc_deblock_subblock_bs(const VVCLocalContext *lc,
+const int cb, int x0, int y0, int width, int height, const int vertical)
 {
 const VVCFrameContext  *fc = lc->fc;
 const MvField *tab_mvf = fc->tab.mvf;
 const RefPicList *rpl  = lc->sc->rpl;
-const int min_pu_width = fc->ps.pps->min_pu_width;
+int stridea= fc->ps.pps->min_pu_width;
+int strideb= 1;
+uint8_t *tab_bs= vertical ? fc->tab.vertical_bs[LUMA] : 
fc->tab.horizontal_bs[LUMA];
+uint8_t *tab_max_len_p = vertical ? fc->tab.vertical_p : 
fc->tab.horizontal_p;
+uint8_t *tab_max_len_q = vertical ? fc->tab.vertical_q : 
fc->tab.horizontal_q;
 const int log2_min_pu_size = MIN_PU_LOG2;
 
+if (!vertical) {
+FFSWAP(int, x0, y0);
+FFSWAP(int, width, height);
+FFSWAP(int, stridea, strideb);
+}
+
 // bs for TU internal vertical PU boundaries
-for (int j = 0; j < height; j += 4) {
-const int y_pu = (y0 + j) >> log2_min_pu_size;
-
-for (int i = 8 - ((x0 - cb_x) % 8); i < width; i += 8) {
-const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
-const int xq_pu = (x0 + i) >> log2_min_pu_size;
-const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
-const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
-const int x = x0 + i;
-const int y = y0 + j;
-const int bs = boundary_strength(lc, curr, left, rpl);
+for (int i = 8 - ((x0 - cb) % 8); i < width; i += 8) {
+const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
+const int xq_pu = (x0 + i) >> log2_min_pu_size;
+
+for (int j = 0; j < height; j += 4) {
+const int y_pu   = (y0 + j) >> log2_min_pu_size;
+const MvField *mvf_p = &tab_mvf[y_pu * stridea + xp_pu * strideb];
+const MvField *mvf_q = &tab_mvf[y_pu * stridea + xq_pu * strideb];
+const int bs = boundary_strength(lc, mvf_q, mvf_p, rpl);
+int x= x0 + i;
+int y= y0 + j;
 uint8_t max_len_p = 0, max_len_q = 0;
 
-TAB_BS(fc->tab.vertical_bs[LUMA], x, y) = bs;
+if (!vertical)
+FFSWAP(int, x, y);
+
+TAB_BS(tab_bs, x, y) = bs;
 
 if (i == 4 || i == width - 4)
 max_len_p = max_len_q = 1;
@@ -438,48 +451,8 @@ static void vvc_deblock_subblock_bs_vertical(const 
VVCLocalContext *lc,
 else
 max_len_p = max_len_q = 3;
 
-TAB_MAX_LEN(fc->tab.vertical_p, x, y) = max_len_p;
-TAB_MAX_LEN(fc->tab.vertical_q, x, y) = max_len_q;
-}
-}
-}
-
-static void vvc_deblock_subblock_bs_horizontal(const VVCLocalContext *lc,
-const int cb_x, const int cb_y, const int x0, const int y0, const int 
width, const int height)
-{
-const VVCFrameContext  *fc = lc->fc;
-const MvField* tab_mvf = fc->tab.mvf;
-const RefPicList* rpl  = lc->sc->rpl;
-const int min_pu_width = fc->ps.pps->min_pu_width;
-const int log2_min_pu_size = MIN_PU_LOG2;
-
-// bs for TU internal horizontal PU boundaries
-for (int j = 8 - ((y0 - cb_y) % 8); j < height; j += 8) {
-int yp_pu = (y0 + j - 1) >> log2_min_pu_size;
-int yq_pu = (y0 + j) >> log2_min_pu_size;
-
-for (int i = 0; i < width; i += 4) {
-const int x_pu = (x0 + i) >> log2_min_pu_size;
-const MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
-const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
-const int x = x0 + i;
-const int y = y0 + j;
-const int bs = boundary_strength(lc, curr, top, rpl);
-uint8_t max_len_p = 0, max_len_q = 0;
-
-TAB_BS(fc->tab.horizontal_bs[LUMA], x, y) = bs;
-
-//fixme:
-//edgeTbFlags[ x − sbW ][ y ] is equal to 1
-//edgeTbFlags[ x + sbW ][ y ] is equal to 1
-if (j == 4 || j == height - 4)
-max_len_p = max_len_q = 1;
-else if (j == 8 || j == height - 8)
-max_len_p = max_len_q = 2;
-else
-max_len_p = max_len_q = 3;
-TAB_MAX_LEN(fc->tab.horizontal_p, x, y) = max_len_p;
-   

[FFmpeg-devel] [PATCH 03/18] avcodec/vvcdec: refact, unify vvc_deblock_bs_chroma_{horizontal, vertical}

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 62 +
 1 file changed, 19 insertions(+), 43 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 996e58dc3e..06e1717b13 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -586,56 +586,33 @@ static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
 }
 }
 
-static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc,
-const int x0, const int y0, const int width, const int height, const int 
rs)
-{
-vvc_deblock_bs_luma(lc, x0, y0, width, height, rs, 1);
-}
-
-static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc,
-const int x0, const int y0, const int width, const int height, const int 
rs)
-{
-vvc_deblock_bs_luma(lc, x0, y0, width, height, rs, 0);
-}
-
-static void vvc_deblock_bs_chroma_vertical(const VVCLocalContext *lc,
-const int x0, const int y0, const int width, const int height, const int 
rs)
+static void vvc_deblock_bs_chroma(const VVCLocalContext *lc,
+const int x0, const int y0, const int width, const int height, const int 
rs, const int vertical)
 {
 const VVCFrameContext *fc = lc->fc;
-const int boundary_left = deblock_is_boundary(lc,
- x0 > 0 && !(x0 & ((CHROMA_GRID << fc->ps.sps->hshift[CHROMA]) - 1)), 
x0, rs, 1);
-
-if (boundary_left) {
-for (int i = 0; i < height; i += 2) {
-for (int c_idx = CB; c_idx <= CR; c_idx++) {
-const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, 
NULL, c_idx, 0, 0);
+const int shift   = (vertical ? fc->ps.sps->hshift : 
fc->ps.sps->vshift)[CHROMA];
+const int mask= (CHROMA_GRID << shift) - 1;
+const int pos = vertical ? x0 : y0;
 
-TAB_BS(fc->tab.vertical_bs[c_idx], x0, (y0 + i)) = bs;
-}
-}
-}
-}
+if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
+const int size = vertical ? height : width;
 
-static void vvc_deblock_bs_chroma_horizontal(const VVCLocalContext *lc,
-const int x0, const int y0, const int width, const int height, const int 
rs)
-{
-const VVCFrameContext *fc = lc->fc;
-const int boundary_upper  = deblock_is_boundary(lc,
-y0 > 0 && !(y0 & ((CHROMA_GRID << fc->ps.sps->vshift[CHROMA]) - 1)), 
y0, rs, 0);
+for (int c_idx = CB; c_idx <= CR; c_idx++) {
+uint8_t *tab_bs = (vertical ? fc->tab.vertical_bs : 
fc->tab.horizontal_bs)[c_idx];
 
-if (boundary_upper) {
-for (int i = 0; i < width; i += 2) {
-for (int c_idx = CB; c_idx <= CR; c_idx++) {
-const int bs = deblock_bs(lc, x0 + i, y0 - 1, x0 + i, y0, 
NULL, c_idx, 0, 0);
+for (int i = 0; i < size; i += 2) {
+const int x  = x0 + i * !vertical;
+const int y  = y0 + i * vertical;
+const int bs = deblock_bs(lc, x - vertical, y - !vertical, x, 
y, NULL, c_idx, 0, 0);
 
-TAB_BS(fc->tab.horizontal_bs[c_idx], x0 + i, y0) = bs;
+TAB_BS(tab_bs, x, y) = bs;
 }
 }
 }
 }
 
 typedef void (*deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const 
int y0,
-const int width, const int height, const int rs);
+const int width, const int height, const int rs, const int vertical);
 
 static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int 
y0, const int rs, const int vertical)
 {
@@ -645,9 +622,8 @@ static void vvc_deblock_bs(const VVCLocalContext *lc, const 
int x0, const int y0
 const int ctb_size = sps->ctb_size_y;
 const int x_end= FFMIN(x0 + ctb_size, pps->width) >> MIN_TU_LOG2;
 const int y_end= FFMIN(y0 + ctb_size, pps->height) >> MIN_TU_LOG2;
-deblock_bs_fn deblock_bs[2][2] = {
-{ vvc_deblock_bs_luma_horizontal, vvc_deblock_bs_chroma_horizontal },
-{ vvc_deblock_bs_luma_vertical,   vvc_deblock_bs_chroma_vertical   }
+deblock_bs_fn deblock_bs[] = {
+vvc_deblock_bs_luma, vvc_deblock_bs_chroma
 };
 
 for (int is_chroma = 0; is_chroma <= 1; is_chroma++) {
@@ -657,8 +633,8 @@ static void vvc_deblock_bs(const VVCLocalContext *lc, const 
int x0, const int y0
 for (int x = x0 >> MIN_TU_LOG2; x < x_end; x++) {
 const int off = y * fc->ps.pps->min_tu_width + x;
 if ((fc->tab.tb_pos_x0[is_chroma][off] >> MIN_TU_LOG2) == x && 
(fc->tab.tb_pos_y0[is_chroma][off] >> MIN_TU_LOG2) == y) {
-deblock_bs[vertical][is_chroma](lc, x << MIN_TU_LOG2, y << 
MIN_TU_LOG2,
-fc->tab.tb_width[is_chroma][off] << hs, 
fc->tab.tb_height[is_chroma][off] << vs, rs);
+deblock_bs[is_chroma](lc, x << MIN_TU_LOG2, y << 
MIN_TU_LOG2,
+fc->tab.tb_width[is_chroma][off] << hs, 
fc->tab.tb_height[is_chroma][off] << vs, rs, vertical);
 }
 }
 }
-- 
2.34.1

___

[FFmpeg-devel] [PATCH 02/18] avcodec/vvcdec: refact, unify vvc_deblock_bs_luma_{horizontal, vertical}

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 108 ++--
 1 file changed, 36 insertions(+), 72 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index d4c09b69f3..996e58dc3e 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -538,100 +538,64 @@ static int deblock_is_boundary(const VVCLocalContext 
*lc, const int boundary,
 return boundary;
 }
 
-static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc,
-const int x0, const int y0, const int width, const int height, const int 
rs)
+static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
+const int x0, const int y0, const int width, const int height, const int 
rs, const int vertical)
 {
 const VVCFrameContext *fc  = lc->fc;
 const MvField *tab_mvf = fc->tab.mvf;
+const int mask = LUMA_GRID - 1;
 const int log2_min_pu_size = MIN_PU_LOG2;
 const int min_pu_width = fc->ps.pps->min_pu_width;
 const int min_cb_log2  = fc->ps.sps->min_cb_log2_size_y;
 const int min_cb_width = fc->ps.pps->min_cb_width;
-const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * 
min_pu_width +
-(x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
-int boundary_left;
-int has_vertical_sb = 0;
-
+const int pos  = vertical ? x0 : y0;
 const int off_q= (y0 >> min_cb_log2) * min_cb_width + (x0 >> 
min_cb_log2);
-const int cb_x = fc->tab.cb_pos_x[LUMA][off_q];
-const int cb_width = fc->tab.cb_width[LUMA][off_q];
-const int off_x= cb_x - x0;
-
-if (!is_intra) {
-if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
-has_vertical_sb = cb_width  > 8;
-}
-
-// bs for vertical TU boundaries
-boundary_left = deblock_is_boundary(lc, x0 > 0 && !(x0 & 3), x0, rs, 1);
-
-if (boundary_left) {
-const RefPicList *rpl_left =
-(lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? 
ff_vvc_get_ref_list(fc, fc->ref, x0 - 1, y0) : lc->sc->rpl;
-for (int i = 0; i < height; i += 4) {
+const int cb   = (vertical ? fc->tab.cb_pos_x : 
fc->tab.cb_pos_y )[LUMA][off_q];
+const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * 
min_pu_width +
+(x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
+
+if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
+const int size  = vertical ? height : width;
+const int off   = cb - pos;
+const int cb_size   = (vertical ? fc->tab.cb_width : 
fc->tab.cb_height)[LUMA][off_q];
+const int has_sb= !is_intra && (fc->tab.msf[off_q] || 
fc->tab.iaf[off_q]) && cb_size > 8;
+const int flag  = vertical ? BOUNDARY_LEFT_SLICE : 
BOUNDARY_UPPER_SLICE;
+const RefPicList *rpl_p =
+(lc->boundary_flags & flag) ? ff_vvc_get_ref_list(fc, fc->ref, x0 
- vertical, y0 - !vertical) : lc->sc->rpl;
+uint8_t *tab_bs = vertical ? fc->tab.vertical_bs[LUMA] : 
fc->tab.horizontal_bs[LUMA];
+uint8_t *tab_max_len_p  = vertical ? fc->tab.vertical_p : 
fc->tab.horizontal_p;
+uint8_t *tab_max_len_q  = vertical ? fc->tab.vertical_q : 
fc->tab.horizontal_q;
+
+for (int i = 0; i < size; i += 4) {
+const int x = x0 + i * !vertical;
+const int y = y0 + i * vertical;
 uint8_t max_len_p, max_len_q;
-const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, 
rpl_left, 0, off_x, has_vertical_sb);
+const int bs = deblock_bs(lc, x - vertical, y - !vertical, x, y, 
rpl_p, LUMA, off, has_sb);
 
-TAB_BS(fc->tab.vertical_bs[LUMA], x0, (y0 + i)) = bs;
+TAB_BS(tab_bs, x, y) = bs;
 
-derive_max_filter_length_luma(fc, x0, y0 + i, is_intra, 
has_vertical_sb, 1, &max_len_p, &max_len_q);
-TAB_MAX_LEN(fc->tab.vertical_p, x0, y0 + i) = max_len_p;
-TAB_MAX_LEN(fc->tab.vertical_q, x0, y0 + i) = max_len_q;
+derive_max_filter_length_luma(fc, x, y, is_intra, has_sb, 
vertical, &max_len_p, &max_len_q);
+TAB_MAX_LEN(tab_max_len_p, x, y) = max_len_p;
+TAB_MAX_LEN(tab_max_len_q, x, y) = max_len_q;
 }
 }
 
 if (!is_intra) {
 if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
-vvc_deblock_subblock_bs(lc, cb_x, x0, y0, width, height, 1);
+vvc_deblock_subblock_bs(lc, cb, x0, y0, width, height, vertical);
 }
 }
 
-static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc,
+static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc,
 const int x0, const int y0, const int width, const int height, const int 
rs)
 {
-const VVCFrameContext *fc  = lc->fc;
-const MvField *tab_mvf = fc->tab.mvf;
-const int log2_min_pu_size = MIN_PU_LOG2;
-const int min_pu_width = fc->ps.pps->min_pu_width;
-const int min_cb_log2  = fc->ps

[FFmpeg-devel] [PATCH 15/18] avcodec/vvcdec: ps, derive virtual boundaries

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/ps.c | 45 +
 libavcodec/vvc/ps.h |  6 ++
 2 files changed, 51 insertions(+)

diff --git a/libavcodec/vvc/ps.c b/libavcodec/vvc/ps.c
index 92368eafc2..58496c9fba 100644
--- a/libavcodec/vvc/ps.c
+++ b/libavcodec/vvc/ps.c
@@ -796,8 +796,49 @@ static int ph_max_num_subblock_merge_cand(const H266RawSPS 
*sps, const H266RawPi
 return sps->sps_sbtmvp_enabled_flag && ph->ph_temporal_mvp_enabled_flag;
 }
 
+static int ph_vb_pos(uint16_t *vbs, uint8_t *num_vbs, const uint16_t 
*pos_minus_1, const uint8_t num_pos, uint16_t max, const int ctb_size_y)
+{
+max = FF_CEIL_RSHIFT(max, 3) - 2;
+for (int i = 0; i < num_pos; i++) {
+if (pos_minus_1[i] > max)
+return AVERROR_INVALIDDATA;
+
+vbs[i] = (pos_minus_1[i] + 1) << 3;
+
+// The distance between any two vertical virtual boundaries shall be 
greater than or equal to CtbSizeY luma samples
+if (i && vbs[i] < vbs[i - 1] + ctb_size_y)
+return AVERROR_INVALIDDATA;
+}
+*num_vbs = num_pos;
+
+return 0;
+}
+
+#define VBF(f) (sps->sps_virtual_boundaries_present_flag ? sps->sps_##f : 
ph->r->ph_##f)
+#define VBFS(c, d) VBF(virtual_boundary_pos_##c##_minus1), 
VBF(num_##d##_virtual_boundaries)
+
+static int ph_vb(VVCPH *ph, const H266RawSPS *sps, const H266RawPPS *pps)
+{
+const int ctb_size_y = 1 << (sps->sps_log2_ctu_size_minus5 + 5);
+int ret;
+
+if (!sps->sps_virtual_boundaries_enabled_flag)
+return 0;
+
+ret = ph_vb_pos(ph->vb_pos_x, &ph->num_ver_vbs, VBFS(x, ver), 
pps->pps_pic_width_in_luma_samples, ctb_size_y);
+if (ret < 0)
+return ret;
+
+ret = ph_vb_pos(ph->vb_pos_y, &ph->num_hor_vbs, VBFS(y, hor), 
pps->pps_pic_height_in_luma_samples, ctb_size_y);
+if (ret < 0)
+return ret;
+
+return 0;
+}
+
 static int ph_derive(VVCPH *ph, const H266RawSPS *sps, const H266RawPPS *pps, 
const int poc_tid0, const int is_clvss)
 {
+int ret;
 ph->max_num_subblock_merge_cand = ph_max_num_subblock_merge_cand(sps, 
ph->r);
 
 ph->poc = ph_compute_poc(ph->r, sps, poc_tid0, is_clvss);
@@ -805,6 +846,10 @@ static int ph_derive(VVCPH *ph, const H266RawSPS *sps, 
const H266RawPPS *pps, co
 if (pps->pps_wp_info_in_ph_flag)
 pred_weight_table(&ph->pwt, &ph->r->ph_pred_weight_table);
 
+ret = ph_vb(ph, sps, pps);
+if (ret < 0)
+return ret;
+
 return 0;
 }
 
diff --git a/libavcodec/vvc/ps.h b/libavcodec/vvc/ps.h
index 6656a06320..9203e2c57f 100644
--- a/libavcodec/vvc/ps.h
+++ b/libavcodec/vvc/ps.h
@@ -151,6 +151,12 @@ typedef struct VVCPH {
 //derived values
 uint32_t max_num_subblock_merge_cand;   ///< 
MaxNumSubblockMergeCand
 int32_t  poc;   ///< PicOrderCntVal
+
+uint8_t  num_ver_vbs;   ///< 
NumVerVirtualBoundaries
+uint16_t vb_pos_x[VVC_MAX_VBS]; ///< VirtualBoundaryPosX
+uint8_t  num_hor_vbs;   ///< 
NumHorVirtualBoundaries
+uint16_t vb_pos_y[VVC_MAX_VBS]; ///< VirtualBoundaryPosY
+
 PredWeightTable pwt;
 } VVCPH;
 
-- 
2.34.1

___
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 04/18] avcodec/vvcdec: refact, unify {horizontal, vertical}_bs, {horizontal, vertical}_p, {horizontal, vertical}_q

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/dec.c| 14 +++---
 libavcodec/vvc/dec.h|  9 +++--
 libavcodec/vvc/filter.c | 32 +++-
 3 files changed, 21 insertions(+), 34 deletions(-)

diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c
index f5603306f3..356ed58e37 100644
--- a/libavcodec/vvc/dec.c
+++ b/libavcodec/vvc/dec.c
@@ -191,14 +191,14 @@ static void bs_tl_init(TabList *l, VVCFrameContext *fc)
 
 tl_init(l, 1, changed);
 
-for (int i = 0; i < VVC_MAX_SAMPLE_ARRAYS; i++) {
-TL_ADD(horizontal_bs[i], bs_count);
-TL_ADD(vertical_bs[i],   bs_count);
+for (int i = 0; i < 2; i++) {
+for (int j = 0; j < VVC_MAX_SAMPLE_ARRAYS; j++) {
+TL_ADD(bs[i][j], bs_count);
+TL_ADD(bs[i][j],   bs_count);
+}
+TL_ADD(max_len_p[i], bs_count);
+TL_ADD(max_len_q[i], bs_count);
 }
-TL_ADD(horizontal_q, bs_count);
-TL_ADD(horizontal_p, bs_count);
-TL_ADD(vertical_p,   bs_count);
-TL_ADD(vertical_q,   bs_count);
 }
 
 static void pixel_buffer_nz_tl_init(TabList *l, VVCFrameContext *fc)
diff --git a/libavcodec/vvc/dec.h b/libavcodec/vvc/dec.h
index 1e0b76f283..a8492f1398 100644
--- a/libavcodec/vvc/dec.h
+++ b/libavcodec/vvc/dec.h
@@ -178,12 +178,9 @@ typedef struct VVCFrameContext {
 uint8_t *tb_height[2];
 uint8_t *pcmf[2];
 
-uint8_t *horizontal_bs[VVC_MAX_SAMPLE_ARRAYS];
-uint8_t *vertical_bs[VVC_MAX_SAMPLE_ARRAYS];
-uint8_t *horizontal_p;  ///< horizontal 
maxFilterLengthPs for luma
-uint8_t *horizontal_q;  ///< horizontal 
maxFilterLengthQs for luma
-uint8_t *vertical_p;///< vertical   
maxFilterLengthPs for luma
-uint8_t *vertical_q;///< vertical   
maxFilterLengthQs for luma
+uint8_t *bs[2][VVC_MAX_SAMPLE_ARRAYS];  ///< horizontal, 
vertical boundary filtering strength
+uint8_t *max_len_p[2];  ///< horizontal, 
vertical maxFilterLengthPs for luma
+uint8_t *max_len_q[2];  ///< horizontal, 
vertical maxFilterLengthQs for luma
 
 uint8_t *sao_pixel_buffer_h[VVC_MAX_SAMPLE_ARRAYS];
 uint8_t *sao_pixel_buffer_v[VVC_MAX_SAMPLE_ARRAYS];
diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 06e1717b13..7ae36b2344 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -414,9 +414,6 @@ static void vvc_deblock_subblock_bs(const VVCLocalContext 
*lc,
 const RefPicList *rpl  = lc->sc->rpl;
 int stridea= fc->ps.pps->min_pu_width;
 int strideb= 1;
-uint8_t *tab_bs= vertical ? fc->tab.vertical_bs[LUMA] : 
fc->tab.horizontal_bs[LUMA];
-uint8_t *tab_max_len_p = vertical ? fc->tab.vertical_p : 
fc->tab.horizontal_p;
-uint8_t *tab_max_len_q = vertical ? fc->tab.vertical_q : 
fc->tab.horizontal_q;
 const int log2_min_pu_size = MIN_PU_LOG2;
 
 if (!vertical) {
@@ -442,7 +439,7 @@ static void vvc_deblock_subblock_bs(const VVCLocalContext 
*lc,
 if (!vertical)
 FFSWAP(int, x, y);
 
-TAB_BS(tab_bs, x, y) = bs;
+TAB_BS(fc->tab.bs[vertical][LUMA], x, y) = bs;
 
 if (i == 4 || i == width - 4)
 max_len_p = max_len_q = 1;
@@ -451,8 +448,8 @@ static void vvc_deblock_subblock_bs(const VVCLocalContext 
*lc,
 else
 max_len_p = max_len_q = 3;
 
-TAB_MAX_LEN(tab_max_len_p, x, y) = max_len_p;
-TAB_MAX_LEN(tab_max_len_q, x, y) = max_len_q;
+TAB_MAX_LEN(fc->tab.max_len_p[vertical], x, y) = max_len_p;
+TAB_MAX_LEN(fc->tab.max_len_q[vertical], x, y) = max_len_q;
 }
 }
 }
@@ -562,9 +559,6 @@ static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
 const int flag  = vertical ? BOUNDARY_LEFT_SLICE : 
BOUNDARY_UPPER_SLICE;
 const RefPicList *rpl_p =
 (lc->boundary_flags & flag) ? ff_vvc_get_ref_list(fc, fc->ref, x0 
- vertical, y0 - !vertical) : lc->sc->rpl;
-uint8_t *tab_bs = vertical ? fc->tab.vertical_bs[LUMA] : 
fc->tab.horizontal_bs[LUMA];
-uint8_t *tab_max_len_p  = vertical ? fc->tab.vertical_p : 
fc->tab.horizontal_p;
-uint8_t *tab_max_len_q  = vertical ? fc->tab.vertical_q : 
fc->tab.horizontal_q;
 
 for (int i = 0; i < size; i += 4) {
 const int x = x0 + i * !vertical;
@@ -572,11 +566,11 @@ static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
 uint8_t max_len_p, max_len_q;
 const int bs = deblock_bs(lc, x - vertical, y - !vertical, x, y, 
rpl_p, LUMA, off, has_sb);
 
-TAB_BS(tab_bs, x, y) = bs;
+TAB_BS(fc->tab.bs[vertical][LUMA], x, y) = bs;
 
 derive_max_filter_length_luma(fc, x, y, is_intra, has_sb, 
vertical, &max_len_p, &max_len_q)

[FFmpeg-devel] [PATCH 05/18] avcodec/vvcdec: misc, use POS to simplify filter code

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 7ae36b2344..82a58a7ea8 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -34,6 +34,10 @@
 
 #define DEFAULT_INTRA_TC_OFFSET 2
 
+#define POS(c_idx, x, y)   
 \
+&fc->frame->data[c_idx][((y) >> fc->ps.sps->vshift[c_idx]) * 
fc->frame->linesize[c_idx] +   \
+(((x) >> fc->ps.sps->hshift[c_idx]) << fc->ps.sps->pixel_shift)]
+
 //Table 43 Derivation of threshold variables beta' and tc' from input Q
 static const uint16_t tctable[66] = {
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
  0,
@@ -135,7 +139,7 @@ static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const 
int rx, const int ry,
 const int ctb_size_v   = ctb_size_y >> fc->ps.sps->vshift[c_idx];
 const int width= FFMIN(ctb_size_h, (fc->ps.pps->width  >> 
fc->ps.sps->hshift[c_idx]) - x);
 const int height   = FFMIN(ctb_size_v, (fc->ps.pps->height >> 
fc->ps.sps->vshift[c_idx]) - y);
-const uint8_t *src  = &fc->frame->data[c_idx][y * src_stride + 
(x << fc->ps.sps->pixel_shift)];
+const uint8_t *src = POS(c_idx, x0, y0);
 copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, c_idx, rx, 
ry, top);
 }
 }
@@ -225,7 +229,7 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 int width= FFMIN(ctb_size_h, (fc->ps.pps->width  >> 
fc->ps.sps->hshift[c_idx]) - x0);
 int height   = FFMIN(ctb_size_v, (fc->ps.pps->height >> 
fc->ps.sps->vshift[c_idx]) - y0);
 int tab  = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
-uint8_t *src = &fc->frame->data[c_idx][y0 * src_stride + (x0 << 
fc->ps.sps->pixel_shift)];
+uint8_t *src = POS(c_idx, x, y);
 ptrdiff_t dst_stride;
 uint8_t *dst;
 
@@ -750,7 +754,7 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, 
const int x0, const int
 const int dy = i << 2;
 bs[i] = (y + dy < y_end) ? TAB_BS(fc->tab.bs[1][c_idx], x, 
y + dy) : 0;
 if (bs[i]) {
-src = &fc->frame->data[c_idx][((y + dy) >> vs) * 
fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
+src = POS(c_idx, x, y + dy);
 qp = get_qp(fc, src, x, y + dy, c_idx, 1);
 
 beta[i] = betatable[av_clip(qp + beta_offset, 0, 
MAX_QP)];
@@ -762,7 +766,7 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, 
const int x0, const int
 }
 
 if (!all_zero_bs) {
-src = &fc->frame->data[c_idx][(y >> vs) * 
fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
+src = POS(c_idx, x, y);
 if (!c_idx) {
 fc->vvcdsp.lf.filter_luma[1](src, 
fc->frame->linesize[c_idx],
 beta, tc, no_p, no_q, max_len_p, max_len_q, 0);
@@ -823,7 +827,7 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, 
const int x0, const in
 
 bs[i] = (x + dx < x_end) ? TAB_BS(fc->tab.bs[0][c_idx], x 
+ dx, y) : 0;
 if (bs[i]) {
-src = &fc->frame->data[c_idx][(y >> vs) * 
fc->frame->linesize[c_idx] + (((x + dx)>> hs) << fc->ps.sps->pixel_shift)];
+src = POS(c_idx, x + dx, y);
 qp = get_qp(fc, src, x + dx, y, c_idx, 0);
 
 beta[i] = betatable[av_clip(qp + beta_offset, 0, 
MAX_QP)];
@@ -834,7 +838,7 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, 
const int x0, const in
 tc[i] = bs[i] ? TC_CALC(qp, bs[i]) : 0;
 }
 if (!all_zero_bs) {
-src = &fc->frame->data[c_idx][(y >> vs) * 
fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
+src = POS(c_idx, x, y);
 if (!c_idx) {
 fc->vvcdsp.lf.filter_luma[0](src, 
fc->frame->linesize[c_idx],
 beta, tc, no_p, no_q, max_len_p, max_len_q, 
horizontal_ctu_edge);
@@ -1079,7 +1083,6 @@ void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const 
int x0, const int y0)
 const int rx = x0 >> fc->ps.sps->ctb_log2_size_y;
 const int ry = y0 >> fc->ps.sps->ctb_log2_size_y;
 const int ctb_size_y = fc->ps.sps->ctb_size_y;
-const int ps = fc->ps.sps->pixel_shift;
 const int c_end  = fc->ps.sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
 
 for (int c_idx = 0; c_idx < c_end; c_idx++) {
@@ -1091,7 +1094,7 @@ void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const 
int x0, const int y0)
 const int height = FF

[FFmpeg-devel] [PATCH 07/18] avcodec/vvcdec: refact out sao_get_edges

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 119 ++--
 1 file changed, 65 insertions(+), 54 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 89b794195e..1326d2c82e 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -155,70 +155,81 @@ void ff_vvc_sao_copy_ctb_to_hv(VVCLocalContext *lc, const 
int rx, const int ry,
 sao_copy_ctb_to_hv(lc, rx, ry, 0);
 }
 
+static int sao_can_cross_slices(const VVCFrameContext *fc, const int rx, const 
int ry, const int dx, const int dy)
+{
+const uint8_t lfase = 
fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
+
+return lfase || CTB(fc->tab.slice_idx, rx, ry) == CTB(fc->tab.slice_idx, 
rx + dx, ry + dy);
+}
+
+static void sao_get_edges(uint8_t vert_edge[2], uint8_t horiz_edge[2], uint8_t 
diag_edge[4], int *restore,
+const VVCLocalContext *lc, const int edges[4], const int rx, const int ry)
+{
+const VVCFrameContext *fc  = lc->fc;
+const VVCSPS *sps  = fc->ps.sps;
+const H266RawSPS *rsps = sps->r;
+const VVCPPS *pps  = fc->ps.pps;
+const int subpic_idx   = lc->sc->sh.r->curr_subpic_idx;
+const uint8_t lfase= 
fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
+const uint8_t no_tile_filter   = pps->r->num_tiles_in_pic > 1 && 
!pps->r->pps_loop_filter_across_tiles_enabled_flag;
+const uint8_t no_subpic_filter = rsps->sps_num_subpics_minus1 && 
!rsps->sps_loop_filter_across_subpic_enabled_flag[subpic_idx];
+uint8_t lf_edge[] = { 0, 0, 0, 0 };
+
+*restore = no_subpic_filter || no_tile_filter || !lfase;
+
+if (!*restore)
+return;
+
+if (!edges[LEFT]) {
+lf_edge[LEFT]  = no_tile_filter && pps->ctb_to_col_bd[rx] == rx;
+lf_edge[LEFT] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_x[subpic_idx] == rx;
+vert_edge[0]   = !sao_can_cross_slices(fc, rx, ry, -1, 0) || 
lf_edge[LEFT];
+}
+if (!edges[RIGHT]) {
+lf_edge[RIGHT]  = no_tile_filter && pps->ctb_to_col_bd[rx] != 
pps->ctb_to_col_bd[rx + 1];
+lf_edge[RIGHT] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_x[subpic_idx] + 
rsps->sps_subpic_width_minus1[subpic_idx] == rx;
+vert_edge[1]= !sao_can_cross_slices(fc, rx, ry, 1, 0) || 
lf_edge[RIGHT];
+}
+if (!edges[TOP]) {
+lf_edge[TOP]   = no_tile_filter && pps->ctb_to_row_bd[ry] == ry;
+lf_edge[TOP]  |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_y[subpic_idx] == ry;
+horiz_edge[0]  = !sao_can_cross_slices(fc, rx, ry, 0, -1) || 
lf_edge[TOP];
+}
+if (!edges[BOTTOM]) {
+lf_edge[BOTTOM]  = no_tile_filter && pps->ctb_to_row_bd[ry] != 
pps->ctb_to_row_bd[ry + 1];
+lf_edge[BOTTOM] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_y[subpic_idx] + 
rsps->sps_subpic_height_minus1[subpic_idx] == ry;
+horiz_edge[1]= !sao_can_cross_slices(fc, rx, ry, 0, 1) || 
lf_edge[BOTTOM];
+}
+
+if (!edges[LEFT] && !edges[TOP])
+diag_edge[0] = !sao_can_cross_slices(fc, rx, ry, -1, -1) || 
lf_edge[LEFT] || lf_edge[TOP];
+
+if (!edges[TOP] && !edges[RIGHT])
+diag_edge[1] = !sao_can_cross_slices(fc, rx, ry,  1, -1) || 
lf_edge[RIGHT] || lf_edge[TOP];
+
+if (!edges[RIGHT] && !edges[BOTTOM])
+diag_edge[2] = !sao_can_cross_slices(fc, rx, ry,  1,  1) || 
lf_edge[RIGHT] || lf_edge[BOTTOM];
+
+if (!edges[LEFT] && !edges[BOTTOM])
+diag_edge[3] = !sao_can_cross_slices(fc, rx, ry, -1,  1) || 
lf_edge[LEFT] || lf_edge[BOTTOM];
+}
+
 void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 {
 VVCFrameContext *fc  = lc->fc;
 const int ctb_size_y = fc->ps.sps->ctb_size_y;
 static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 
7, 7, 8, 8 };
-int c_idx;
+int c_idx, restore;
 const int rx = x >> fc->ps.sps->ctb_log2_size_y;
 const int ry = y >> fc->ps.sps->ctb_log2_size_y;
 int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == 
fc->ps.pps->ctb_height - 1 };
 const SAOParams *sao = &CTB(fc->tab.sao, rx, ry);
 // flags indicating unfilterable edges
-uint8_t vert_edge[]  = { 0, 0 };
-uint8_t horiz_edge[] = { 0, 0 };
-uint8_t diag_edge[]  = { 0, 0, 0, 0 };
-uint8_t tile_edge[]  = { 0, 0, 0, 0 };
-uint8_t subpic_edge[]= { 0, 0, 0, 0 };
-const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
-const uint8_t lfase  = 
fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
-const uint8_t no_tile_filter = fc->ps.pps->r->num_tiles_in_pic > 1 &&
-   
!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag;
-const uint8_t no_subpic_filter = fc->ps.sps->r->sps_num_subpics_minus1 &&
-!fc->ps.sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx];
-const uint8_t restore= no_sub

[FFmpeg-devel] [PATCH 06/18] avcodec/vvcdec: refact, unify ff_vvc_deblock_{horizontal, vertical}

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 153 
 1 file changed, 44 insertions(+), 109 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 82a58a7ea8..89b794195e 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -712,144 +712,79 @@ static int get_qp(const VVCFrameContext *fc, const 
uint8_t *src, const int x, co
 return get_qp_c(fc, x, y, c_idx, vertical);
 }
 
-void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const 
int y0, const int rs)
+static void vvc_deblock(const VVCLocalContext *lc, int x0, int y0, const int 
rs, const int vertical)
 {
-VVCFrameContext *fc = lc->fc;
-const VVCSPS *sps   = fc->ps.sps;
-const int c_end = sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
-uint8_t *src;
-int x, y, qp;
+VVCFrameContext *fc= lc->fc;
+const VVCSPS *sps  = fc->ps.sps;
+const int c_end= sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
+const int ctb_size = fc->ps.sps->ctb_size_y;
+const DBParams *params = fc->tab.deblock + rs;
+int x_end  = FFMIN(x0 + ctb_size, fc->ps.pps->width);
+int y_end  = FFMIN(y0 + ctb_size, fc->ps.pps->height);
 
 //not use this yet, may needed by plt.
-const uint8_t no_p[4] = { 0 };
-const uint8_t no_q[4] = { 0 } ;
-
-const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y;
-int x_end, y_end;
-const int ctb_size = 1 << ctb_log2_size_y;
-const DBParams *params = fc->tab.deblock + rs;
+const uint8_t no_p[4]  = { 0 };
+const uint8_t no_q[4]  = { 0 } ;
 
-vvc_deblock_bs(lc, x0, y0, rs, 1);
+vvc_deblock_bs(lc, x0, y0, rs, vertical);
 
-x_end = x0 + ctb_size;
-if (x_end > fc->ps.pps->width)
-x_end = fc->ps.pps->width;
-y_end = y0 + ctb_size;
-if (y_end > fc->ps.pps->height)
-y_end = fc->ps.pps->height;
+if (!vertical) {
+FFSWAP(int, x_end, y_end);
+FFSWAP(int, x0, y0);
+}
 
 for (int c_idx = 0; c_idx < c_end; c_idx++) {
-const int hs  = sps->hshift[c_idx];
-const int vs  = sps->vshift[c_idx];
+const int hs  = (vertical ? sps->hshift : sps->vshift)[c_idx];
+const int vs  = (vertical ? sps->vshift : sps->hshift)[c_idx];
 const int grid= c_idx ? (CHROMA_GRID << hs) : LUMA_GRID;
 const int tc_offset   = params->tc_offset[c_idx];
 const int beta_offset = params->beta_offset[c_idx];
+const int src_stride  = fc->frame->linesize[c_idx];
 
-for (y = y0; y < y_end; y += (DEBLOCK_STEP << vs)) {
-for (x = x0 ? x0 : grid; x < x_end; x += grid) {
-int32_t bs[4], beta[4], tc[4], all_zero_bs = 1;
+for (int y = y0; y < y_end; y += (DEBLOCK_STEP << vs)) {
+for (int x = x0 ? x0 : grid; x < x_end; x += grid) {
+const uint8_t horizontal_ctu_edge = !vertical && !(x % 
ctb_size);
+int32_t bs[4], beta[4], tc[4] = { }, all_zero_bs = 1;
 uint8_t max_len_p[4], max_len_q[4];
 
 for (int i = 0; i < DEBLOCK_STEP >> (2 - vs); i++) {
-const int dy = i << 2;
-bs[i] = (y + dy < y_end) ? TAB_BS(fc->tab.bs[1][c_idx], x, 
y + dy) : 0;
-if (bs[i]) {
-src = POS(c_idx, x, y + dy);
-qp = get_qp(fc, src, x, y + dy, c_idx, 1);
+int tx = x;
+int ty = y + (i << 2);
+const int end  = ty >= y_end;
 
-beta[i] = betatable[av_clip(qp + beta_offset, 0, 
MAX_QP)];
+if (!vertical)
+FFSWAP(int, tx, ty);
 
-max_filter_length(fc, x, y + dy, c_idx, 1, 0, bs[i], 
&max_len_p[i], &max_len_q[i]);
+bs[i] = end ? 0 : TAB_BS(fc->tab.bs[vertical][c_idx], tx, 
ty);
+if (bs[i]) {
+const int qp = get_qp(fc, POS(c_idx, tx, ty), tx, ty, 
c_idx, vertical);
+beta[i] = betatable[av_clip(qp + beta_offset, 0, 
MAX_QP)];
+tc[i] = TC_CALC(qp, bs[i]) ;
+max_filter_length(fc, tx, ty, c_idx, vertical, 
horizontal_ctu_edge, bs[i], &max_len_p[i], &max_len_q[i]);
 all_zero_bs = 0;
 }
-tc[i] = bs[i] ? TC_CALC(qp, bs[i]) : 0;
 }
 
 if (!all_zero_bs) {
-src = POS(c_idx, x, y);
-if (!c_idx) {
-fc->vvcdsp.lf.filter_luma[1](src, 
fc->frame->linesize[c_idx],
-beta, tc, no_p, no_q, max_len_p, max_len_q, 0);
-} else {
-fc->vvcdsp.lf.filter_chroma[1](src, 
fc->frame->linesize[c_idx],
- 

[FFmpeg-devel] [PATCH 09/18] avcodec/vvcdec: refact, fix naming convention of x0, y0 for sao

2024-06-21 Thread Nuo Mi
it's mismatched with the ff_vvc_sao_filter function declaration
---
 libavcodec/vvc/filter.c | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 534ba57205..10d11ce31f 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -237,10 +237,12 @@ static void sao_copy_hor(uint8_t *dst, const ptrdiff_t 
dst_stride,
 
 static void sao_extends_edges(uint8_t *dst, const ptrdiff_t dst_stride,
 const uint8_t *src, const ptrdiff_t src_stride, const int width, const int 
height,
-const VVCFrameContext *fc, const int x, const int y, const int rx, const 
int ry, const int edges[4], const int c_idx)
+const VVCFrameContext *fc, const int x0, const int y0, const int rx, const 
int ry, const int edges[4], const int c_idx)
 {
 const uint8_t *sao_h = fc->tab.sao_pixel_buffer_h[c_idx];
 const uint8_t *sao_v = fc->tab.sao_pixel_buffer_v[c_idx];
+const int x  = x0 >> fc->ps.sps->hshift[c_idx];
+const int y  = y0 >> fc->ps.sps->vshift[c_idx];
 const int w  = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
 const int h  = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
 const int ps = fc->ps.sps->pixel_shift;
@@ -260,14 +262,14 @@ static void sao_extends_edges(uint8_t *dst, const 
ptrdiff_t dst_stride,
 copy_ctb(dst, src, width << ps, height, dst_stride, src_stride);
 }
 
-void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
+void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
 {
 VVCFrameContext *fc  = lc->fc;
-const int ctb_size_y = fc->ps.sps->ctb_size_y;
+const VVCSPS *sps= fc->ps.sps;
 static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 
7, 7, 8, 8 };
 int c_idx, restore;
-const int rx = x >> fc->ps.sps->ctb_log2_size_y;
-const int ry = y >> fc->ps.sps->ctb_log2_size_y;
+const int rx = x0 >> sps->ctb_log2_size_y;
+const int ry = y0 >> sps->ctb_log2_size_y;
 int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == 
fc->ps.pps->ctb_height - 1 };
 const SAOParams *sao = &CTB(fc->tab.sao, rx, ry);
 // flags indicating unfilterable edges
@@ -277,16 +279,12 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 
 sao_get_edges(vert_edge, horiz_edge, diag_edge, &restore, lc, edges, rx, 
ry);
 
-for (c_idx = 0; c_idx < (fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1); 
c_idx++) {
-int x0   = x >> fc->ps.sps->hshift[c_idx];
-int y0   = y >> fc->ps.sps->vshift[c_idx];
+for (c_idx = 0; c_idx < (sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
 ptrdiff_t src_stride = fc->frame->linesize[c_idx];
-int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
-int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
-int width= FFMIN(ctb_size_h, (fc->ps.pps->width  >> 
fc->ps.sps->hshift[c_idx]) - x0);
-int height   = FFMIN(ctb_size_v, (fc->ps.pps->height >> 
fc->ps.sps->vshift[c_idx]) - y0);
+const int width  = FFMIN(sps->ctb_size_y, fc->ps.pps->width - x0) >> 
sps->hshift[c_idx];
+const int height = FFMIN(sps->ctb_size_y, fc->ps.pps->height - y0) >> 
sps->vshift[c_idx];
 int tab  = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
-uint8_t *src = POS(c_idx, x, y);
+uint8_t *src = POS(c_idx, x0, y0);
 
 switch (sao->type_idx[c_idx]) {
 case SAO_BAND:
-- 
2.34.1

___
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 08/18] avcodec/vvcdec: refact out sao_extends_edges

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 108 +++-
 1 file changed, 50 insertions(+), 58 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 1326d2c82e..534ba57205 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -214,6 +214,52 @@ static void sao_get_edges(uint8_t vert_edge[2], uint8_t 
horiz_edge[2], uint8_t d
 diag_edge[3] = !sao_can_cross_slices(fc, rx, ry, -1,  1) || 
lf_edge[LEFT] || lf_edge[BOTTOM];
 }
 
+static void sao_copy_hor(uint8_t *dst, const ptrdiff_t dst_stride,
+const uint8_t *src, const ptrdiff_t src_stride, const int width, const int 
edges[4], const int ps)
+{
+const int left  = 1 - edges[LEFT];
+const int right = 1 - edges[RIGHT];
+int pos = 0;
+
+src -= left << ps;
+dst -= left << ps;
+
+if (left) {
+copy_pixel(dst, src, ps);
+pos += (1 << ps);
+}
+memcpy(dst + pos, src + pos, width << ps);
+if (right) {
+pos += width << ps;
+copy_pixel(dst + pos, src + pos, ps);
+}
+}
+
+static void sao_extends_edges(uint8_t *dst, const ptrdiff_t dst_stride,
+const uint8_t *src, const ptrdiff_t src_stride, const int width, const int 
height,
+const VVCFrameContext *fc, const int x, const int y, const int rx, const 
int ry, const int edges[4], const int c_idx)
+{
+const uint8_t *sao_h = fc->tab.sao_pixel_buffer_h[c_idx];
+const uint8_t *sao_v = fc->tab.sao_pixel_buffer_v[c_idx];
+const int w  = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
+const int h  = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
+const int ps = fc->ps.sps->pixel_shift;
+
+if (!edges[TOP])
+sao_copy_hor(dst - dst_stride, dst_stride, sao_h + (((2 * ry - 1) * w 
+ x) << ps), src_stride, width, edges, ps);
+
+if (!edges[BOTTOM])
+sao_copy_hor(dst + height * dst_stride, dst_stride, sao_h + (((2 * ry 
+ 2) * w + x) << ps), src_stride, width, edges, ps);
+
+if (!edges[LEFT])
+copy_vert(dst - (1 << ps), sao_v + (((2 * rx - 1) * h + y) << ps), ps, 
height, dst_stride, 1 << ps);
+
+if (!edges[RIGHT])
+copy_vert(dst + (width << ps), sao_v + (((2 * rx + 2) * h + y) << ps), 
 ps, height, dst_stride, 1 << ps);
+
+copy_ctb(dst, src, width << ps, height, dst_stride, src_stride);
+}
+
 void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 {
 VVCFrameContext *fc  = lc->fc;
@@ -241,8 +287,6 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 int height   = FFMIN(ctb_size_v, (fc->ps.pps->height >> 
fc->ps.sps->vshift[c_idx]) - y0);
 int tab  = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
 uint8_t *src = POS(c_idx, x, y);
-ptrdiff_t dst_stride;
-uint8_t *dst;
 
 switch (sao->type_idx[c_idx]) {
 case SAO_BAND:
@@ -251,63 +295,11 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
 break;
 case SAO_EDGE:
 {
-const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
-const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
-const int sh = fc->ps.sps->pixel_shift;
-
-dst_stride = 2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE;
-dst = lc->sao_buffer + dst_stride + AV_INPUT_BUFFER_PADDING_SIZE;
-
-if (!edges[TOP]) {
-const int left = 1 - edges[LEFT];
-const int right = 1 - edges[RIGHT];
-const uint8_t *src1;
-uint8_t *dst1;
-int pos = 0;
-
-dst1 = dst - dst_stride - (left << sh);
-src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry - 1) * w 
+ x0 - left) << sh);
-if (left) {
-copy_pixel(dst1, src1, sh);
-pos += (1 << sh);
-}
-memcpy(dst1 + pos, src1 + pos, width << sh);
-if (right) {
-pos += width << sh;
-copy_pixel(dst1 + pos, src1 + pos, sh);
-}
-}
-if (!edges[BOTTOM]) {
-const int left = 1 - edges[LEFT];
-const int right = 1 - edges[RIGHT];
-const uint8_t *src1;
-uint8_t *dst1;
-int pos = 0;
-
-dst1 = dst + height * dst_stride - (left << sh);
-src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 2) * w 
+ x0 - left) << sh);
-if (left) {
-copy_pixel(dst1, src1, sh);
-pos += (1 << sh);
-}
-memcpy(dst1 + pos, src1 + pos, width << sh);
-if (right) {
-pos += width << sh;
-copy_pixel(dst1 + pos, src1 + pos, sh);
-}
-}
-if (!edges[LEFT]) {
-copy_vert(dst - (1 << sh),
-fc-

[FFmpeg-devel] [PATCH 10/18] avcodec/vvcdec: misc, reformat ff_vvc_sao_filter

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 52 -
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 10d11ce31f..3aa241ad90 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -266,44 +266,44 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int 
y0)
 {
 VVCFrameContext *fc  = lc->fc;
 const VVCSPS *sps= fc->ps.sps;
-static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 
7, 7, 8, 8 };
-int c_idx, restore;
 const int rx = x0 >> sps->ctb_log2_size_y;
 const int ry = y0 >> sps->ctb_log2_size_y;
-int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == 
fc->ps.pps->ctb_height - 1 };
+const int edges[4]   = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == 
fc->ps.pps->ctb_height - 1 };
 const SAOParams *sao = &CTB(fc->tab.sao, rx, ry);
 // flags indicating unfilterable edges
 uint8_t vert_edge[]  = { 0, 0 };
 uint8_t horiz_edge[] = { 0, 0 };
 uint8_t diag_edge[]  = { 0, 0, 0, 0 };
+int restore;
 
 sao_get_edges(vert_edge, horiz_edge, diag_edge, &restore, lc, edges, rx, 
ry);
 
-for (c_idx = 0; c_idx < (sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
-ptrdiff_t src_stride = fc->frame->linesize[c_idx];
-const int width  = FFMIN(sps->ctb_size_y, fc->ps.pps->width - x0) >> 
sps->hshift[c_idx];
-const int height = FFMIN(sps->ctb_size_y, fc->ps.pps->height - y0) >> 
sps->vshift[c_idx];
-int tab  = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
-uint8_t *src = POS(c_idx, x0, y0);
+for (int c_idx = 0; c_idx < (sps->r->sps_chroma_format_idc ? 3 : 1); 
c_idx++) {
+static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 
6, 7, 7, 8, 8 };
+const ptrdiff_t src_stride   = fc->frame->linesize[c_idx];
+uint8_t *src = POS(c_idx, x0, y0);
+const int width  = FFMIN(sps->ctb_size_y, 
fc->ps.pps->width - x0) >> sps->hshift[c_idx];
+const int height = FFMIN(sps->ctb_size_y, 
fc->ps.pps->height - y0) >> sps->vshift[c_idx];
+const int tab= sao_tab[(FFALIGN(width, 8) >> 3) - 
1];
 
 switch (sao->type_idx[c_idx]) {
-case SAO_BAND:
-fc->vvcdsp.sao.band_filter[tab](src, src, src_stride, src_stride,
-sao->offset_val[c_idx], sao->band_position[c_idx], width, 
height);
-break;
-case SAO_EDGE:
-{
-const ptrdiff_t dst_stride = 2 * MAX_PB_SIZE + 
AV_INPUT_BUFFER_PADDING_SIZE;
-uint8_t *dst   = lc->sao_buffer + dst_stride + 
AV_INPUT_BUFFER_PADDING_SIZE;
-
-sao_extends_edges(dst, dst_stride, src, src_stride, width, height, 
fc, x0, y0, rx, ry, edges, c_idx);
-
-fc->vvcdsp.sao.edge_filter[tab](src, dst, src_stride, 
sao->offset_val[c_idx],
-sao->eo_class[c_idx], width, height);
-fc->vvcdsp.sao.edge_restore[restore](src, dst, src_stride, 
dst_stride,
-sao, edges, width, height, c_idx, vert_edge, horiz_edge, 
diag_edge);
-break;
-}
+case SAO_BAND:
+fc->vvcdsp.sao.band_filter[tab](src, src, src_stride, 
src_stride,
+sao->offset_val[c_idx], sao->band_position[c_idx], width, 
height);
+break;
+case SAO_EDGE:
+{
+const ptrdiff_t dst_stride = 2 * MAX_PB_SIZE + 
AV_INPUT_BUFFER_PADDING_SIZE;
+uint8_t *dst   = lc->sao_buffer + dst_stride + 
AV_INPUT_BUFFER_PADDING_SIZE;
+
+sao_extends_edges(dst, dst_stride, src, src_stride, width, 
height, fc, x0, y0, rx, ry, edges, c_idx);
+
+fc->vvcdsp.sao.edge_filter[tab](src, dst, src_stride, 
sao->offset_val[c_idx],
+sao->eo_class[c_idx], width, height);
+fc->vvcdsp.sao.edge_restore[restore](src, dst, src_stride, 
dst_stride,
+sao, edges, width, height, c_idx, vert_edge, horiz_edge, 
diag_edge);
+break;
+}
 }
 }
 }
-- 
2.34.1

___
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 11/18] avcodec/vvcdec: refact out alf_get_edges

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 53 -
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 3aa241ad90..671e599dab 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -1036,6 +1036,35 @@ void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, 
const int x0, const int y0)
 }
 }
 
+static void alf_get_edges(const VVCLocalContext *lc, int edges[MAX_EDGES], 
const int rx, const int ry)
+{
+VVCFrameContext *fc  = lc->fc;
+const VVCSPS *sps= fc->ps.sps;
+const VVCPPS *pps= fc->ps.pps;
+const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
+
+if (!pps->r->pps_loop_filter_across_tiles_enabled_flag) {
+edges[LEFT]   |= !!(lc->boundary_flags & BOUNDARY_LEFT_TILE);
+edges[TOP]|= !!(lc->boundary_flags & BOUNDARY_UPPER_TILE);
+edges[RIGHT]  |= pps->ctb_to_col_bd[rx] != pps->ctb_to_col_bd[rx + 1];
+edges[BOTTOM] |= pps->ctb_to_row_bd[ry] != pps->ctb_to_row_bd[ry + 1];
+}
+
+if (!pps->r->pps_loop_filter_across_slices_enabled_flag) {
+edges[LEFT]   |= !!(lc->boundary_flags & BOUNDARY_LEFT_SLICE);
+edges[TOP]|= !!(lc->boundary_flags & BOUNDARY_UPPER_SLICE);
+edges[RIGHT]  |= CTB(fc->tab.slice_idx, rx, ry) != 
CTB(fc->tab.slice_idx, rx + 1, ry);
+edges[BOTTOM] |= CTB(fc->tab.slice_idx, rx, ry) != 
CTB(fc->tab.slice_idx, rx, ry + 1);
+}
+
+if (!sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]) {
+edges[LEFT]   |= !!(lc->boundary_flags & BOUNDARY_LEFT_SUBPIC);
+edges[TOP]|= !!(lc->boundary_flags & BOUNDARY_UPPER_SUBPIC);
+edges[RIGHT]  |= fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] 
+ fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
+edges[BOTTOM] |= fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] 
+ fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
+}
+}
+
 void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
 {
 VVCFrameContext *fc = lc->fc;
@@ -1047,31 +1076,11 @@ void ff_vvc_alf_filter(VVCLocalContext *lc, const int 
x0, const int y0)
 const int ps= fc->ps.sps->pixel_shift;
 const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
 const int padded_offset = padded_stride * ALF_PADDING_SIZE + 
(ALF_PADDING_SIZE << ps);
-const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
-const int subpic_idx= lc->sc->sh.r->curr_subpic_idx;
+const int c_end = sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
 ALFParams *alf  = &CTB(fc->tab.alf, rx, ry);
 int edges[MAX_EDGES]= { rx == 0, ry == 0, rx == pps->ctb_width - 1, ry 
== pps->ctb_height - 1 };
 
-if (!pps->r->pps_loop_filter_across_tiles_enabled_flag) {
-edges[LEFT]   = edges[LEFT] || (lc->boundary_flags & 
BOUNDARY_LEFT_TILE);
-edges[TOP]= edges[TOP] || (lc->boundary_flags & 
BOUNDARY_UPPER_TILE);
-edges[RIGHT]  = edges[RIGHT] || pps->ctb_to_col_bd[rx] != 
pps->ctb_to_col_bd[rx + 1];
-edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[ry] != 
pps->ctb_to_row_bd[ry + 1];
-}
-
-if (!pps->r->pps_loop_filter_across_slices_enabled_flag) {
-edges[LEFT]   = edges[LEFT] || (lc->boundary_flags & 
BOUNDARY_LEFT_SLICE);
-edges[TOP]= edges[TOP] || (lc->boundary_flags & 
BOUNDARY_UPPER_SLICE);
-edges[RIGHT]  = edges[RIGHT] || CTB(fc->tab.slice_idx, rx, ry) != 
CTB(fc->tab.slice_idx, rx + 1, ry);
-edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, rx, ry) != 
CTB(fc->tab.slice_idx, rx, ry + 1);
-}
-
-if (!sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]) {
-edges[LEFT]   = edges[LEFT] || (lc->boundary_flags & 
BOUNDARY_LEFT_SUBPIC);
-edges[TOP]= edges[TOP] || (lc->boundary_flags & 
BOUNDARY_UPPER_SUBPIC);
-edges[RIGHT]  = edges[RIGHT] || 
fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + 
fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
-edges[BOTTOM] = edges[BOTTOM] || 
fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + 
fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
-}
+alf_get_edges(lc, edges, rx, ry);
 
 for (int c_idx = 0; c_idx < c_end; c_idx++) {
 const int hs = fc->ps.sps->hshift[c_idx];
-- 
2.34.1

___
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 12/18] avcodec/vvcdec: misc, remove unused ALFParams.applied

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/ctu.h| 2 --
 libavcodec/vvc/filter.c | 2 --
 2 files changed, 4 deletions(-)

diff --git a/libavcodec/vvc/ctu.h b/libavcodec/vvc/ctu.h
index a987328d81..432dbc5ade 100644
--- a/libavcodec/vvc/ctu.h
+++ b/libavcodec/vvc/ctu.h
@@ -461,8 +461,6 @@ typedef struct ALFParams {
 uint8_t ctb_filt_set_idx_y; ///< AlfCtbFiltSetIdxY
 uint8_t alf_ctb_filter_alt_idx[2];  ///< alf_ctb_filter_alt_idx[]
 uint8_t ctb_cc_idc[2];  ///< alf_ctb_cc_cb_idc, 
alf_ctb_cc_cr_idc
-
-uint8_t applied[3];
 } ALFParams;
 
 /**
diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 671e599dab..457e2b99c2 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -1116,8 +1116,6 @@ void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, 
const int y0)
 alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
 width, height, hs, vs, (ctb_size_v << vs) - 
ALF_VB_POS_ABOVE_LUMA, alf);
 }
-
-alf->applied[c_idx] = 1;
 }
 }
 
-- 
2.34.1

___
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 13/18] avcodec/vvcdec: misc, constify ALFParams

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 457e2b99c2..a5635c60df 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -926,7 +926,7 @@ static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t 
*_dst, const uint8_t
 #define ALF_MAX_FILTER_SIZE (ALF_MAX_BLOCKS_IN_CTU * ALF_NUM_COEFF_LUMA)
 
 static void alf_get_coeff_and_clip(VVCLocalContext *lc, int16_t *coeff, 
int16_t *clip,
-const uint8_t *src, ptrdiff_t src_stride, int width, int height, int 
vb_pos, ALFParams *alf)
+const uint8_t *src, ptrdiff_t src_stride, int width, int height, int 
vb_pos, const ALFParams *alf)
 {
 const VVCFrameContext *fc = lc->fc;
 const H266RawSliceHeader *rsh = lc->sc->sh.r;
@@ -957,7 +957,7 @@ static void alf_get_coeff_and_clip(VVCLocalContext *lc, 
int16_t *coeff, int16_t
 
 static void alf_filter_luma(VVCLocalContext *lc, uint8_t *dst, const uint8_t 
*src,
 const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int x0, 
const int y0,
-const int width, const int height, const int _vb_pos, ALFParams *alf)
+const int width, const int height, const int _vb_pos, const ALFParams *alf)
 {
 const VVCFrameContext *fc = lc->fc;
 int vb_pos= _vb_pos - y0;
@@ -981,7 +981,7 @@ static int alf_clip_from_idx(const VVCFrameContext *fc, 
const int idx)
 
 static void alf_filter_chroma(VVCLocalContext *lc, uint8_t *dst, const uint8_t 
*src,
 const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx,
-const int width, const int height, const int vb_pos, ALFParams *alf)
+const int width, const int height, const int vb_pos, const ALFParams *alf)
 {
 VVCFrameContext *fc   = lc->fc;
 const H266RawSliceHeader *rsh = lc->sc->sh.r;
@@ -998,7 +998,7 @@ static void alf_filter_chroma(VVCLocalContext *lc, uint8_t 
*dst, const uint8_t *
 
 static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t 
*luma,
 const ptrdiff_t dst_stride, const ptrdiff_t luma_stride, const int c_idx,
-const int width, const int height, const int hs, const int vs, const int 
vb_pos, ALFParams *alf)
+const int width, const int height, const int hs, const int vs, const int 
vb_pos, const ALFParams *alf)
 {
 const VVCFrameContext *fc = lc->fc;
 const H266RawSliceHeader *rsh = lc->sc->sh.r;
@@ -1077,7 +1077,7 @@ void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, 
const int y0)
 const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
 const int padded_offset = padded_stride * ALF_PADDING_SIZE + 
(ALF_PADDING_SIZE << ps);
 const int c_end = sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
-ALFParams *alf  = &CTB(fc->tab.alf, rx, ry);
+const ALFParams *alf= &CTB(fc->tab.alf, rx, ry);
 int edges[MAX_EDGES]= { rx == 0, ry == 0, rx == pps->ctb_width - 1, ry 
== pps->ctb_height - 1 };
 
 alf_get_edges(lc, edges, rx, ry);
-- 
2.34.1

___
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 14/18] cbs_h266: add VVC_MAX_VBS for max num of virtual boundaries

2024-06-21 Thread Nuo Mi
---
 libavcodec/cbs_h266.h | 8 
 libavcodec/cbs_h266_syntax_template.c | 8 
 libavcodec/vvc.h  | 3 +++
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/libavcodec/cbs_h266.h b/libavcodec/cbs_h266.h
index 21b9a4196c..5f12915b65 100644
--- a/libavcodec/cbs_h266.h
+++ b/libavcodec/cbs_h266.h
@@ -464,9 +464,9 @@ typedef struct H266RawSPS {
 uint8_t  sps_virtual_boundaries_enabled_flag;
 uint8_t  sps_virtual_boundaries_present_flag;
 uint8_t  sps_num_ver_virtual_boundaries;
-uint16_t sps_virtual_boundary_pos_x_minus1[3];
+uint16_t sps_virtual_boundary_pos_x_minus1[VVC_MAX_VBS];
 uint8_t  sps_num_hor_virtual_boundaries;
-uint16_t sps_virtual_boundary_pos_y_minus1[3];
+uint16_t sps_virtual_boundary_pos_y_minus1[VVC_MAX_VBS];
 
 uint8_t  sps_timing_hrd_params_present_flag;
 uint8_t  sps_sublayer_cpb_params_present_flag;
@@ -703,9 +703,9 @@ typedef struct  H266RawPictureHeader {
 
 uint8_t  ph_virtual_boundaries_present_flag;
 uint8_t  ph_num_ver_virtual_boundaries;
-uint16_t ph_virtual_boundary_pos_x_minus1[3];
+uint16_t ph_virtual_boundary_pos_x_minus1[VVC_MAX_VBS];
 uint8_t  ph_num_hor_virtual_boundaries;
-uint16_t ph_virtual_boundary_pos_y_minus1[3];
+uint16_t ph_virtual_boundary_pos_y_minus1[VVC_MAX_VBS];
 
 uint8_t  ph_pic_output_flag;
 H266RefPicLists ph_ref_pic_lists;
diff --git a/libavcodec/cbs_h266_syntax_template.c 
b/libavcodec/cbs_h266_syntax_template.c
index 53c4b60b0d..34b766c7af 100644
--- a/libavcodec/cbs_h266_syntax_template.c
+++ b/libavcodec/cbs_h266_syntax_template.c
@@ -1562,13 +1562,13 @@ static int FUNC(sps)(CodedBitstreamContext *ctx, 
RWContext *rw,
 flag(sps_virtual_boundaries_present_flag);
 if (current->sps_virtual_boundaries_present_flag) {
 ue(sps_num_ver_virtual_boundaries,
-   0, current->sps_pic_width_max_in_luma_samples <= 8 ? 0 : 3);
+   0, current->sps_pic_width_max_in_luma_samples <= 8 ? 0 : 
VVC_MAX_VBS);
 for (i = 0; i < current->sps_num_ver_virtual_boundaries; i++)
 ues(sps_virtual_boundary_pos_x_minus1[i],
 0, (current->sps_pic_width_max_in_luma_samples + 7) / 8 - 
2,
 1, i);
 ue(sps_num_hor_virtual_boundaries,
-   0, current->sps_pic_height_max_in_luma_samples <= 8 ? 0 : 3);
+   0, current->sps_pic_height_max_in_luma_samples <= 8 ? 0 : 
VVC_MAX_VBS);
 for (i = 0; i < current->sps_num_hor_virtual_boundaries; i++)
 ues(sps_virtual_boundary_pos_y_minus1[i],
 0, (current->sps_pic_height_max_in_luma_samples + 7) /
@@ -2714,13 +2714,13 @@ static int FUNC(picture_header) (CodedBitstreamContext 
*ctx, RWContext *rw,
 flag(ph_virtual_boundaries_present_flag);
 if (current->ph_virtual_boundaries_present_flag) {
 ue(ph_num_ver_virtual_boundaries,
-   0, pps->pps_pic_width_in_luma_samples <= 8 ? 0 : 3);
+   0, pps->pps_pic_width_in_luma_samples <= 8 ? 0 : VVC_MAX_VBS);
 for (i = 0; i < current->ph_num_ver_virtual_boundaries; i++) {
 ues(ph_virtual_boundary_pos_x_minus1[i],
 0, (pps->pps_pic_width_in_luma_samples + 7) / 8 - 2, 1, i);
 }
 ue(ph_num_hor_virtual_boundaries,
-   0, pps->pps_pic_height_in_luma_samples <= 8 ? 0 : 3);
+   0, pps->pps_pic_height_in_luma_samples <= 8 ? 0 : VVC_MAX_VBS);
 for (i = 0; i < current->ph_num_hor_virtual_boundaries; i++) {
 ues(ph_virtual_boundary_pos_y_minus1[i],
 0, (pps->pps_pic_height_in_luma_samples + 7) / 8 - 2, 1, 
i);
diff --git a/libavcodec/vvc.h b/libavcodec/vvc.h
index c4cec1eb8f..92639779c1 100644
--- a/libavcodec/vvc.h
+++ b/libavcodec/vvc.h
@@ -151,6 +151,9 @@ enum {
 // get near that, though, so set a lower limit here with the maximum
 // possible value for 8K video (at most 135 32x32 Ctb rows).
 VVC_MAX_ENTRY_POINTS = VVC_MAX_TILE_COLUMNS * 135,
+
+// {sps, ph}_num_{ver, hor}_virtual_boundaries should in [0, 3]
+VVC_MAX_VBS = 3,
 };
 
 #endif /* AVCODEC_VVC_H */
-- 
2.34.1

___
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 17/18] avcodec/vvcdec: sao, support virtual boundaries

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 46 +
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 69d67cb7f6..44dd895d7d 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "libavutil/frame.h"
+#include "libavutil/imgutils.h"
 
 #include "ctu.h"
 #include "data.h"
@@ -198,7 +199,7 @@ static void sao_get_edges(uint8_t vert_edge[2], uint8_t 
horiz_edge[2], uint8_t d
 const uint8_t no_subpic_filter = rsps->sps_num_subpics_minus1 && 
!rsps->sps_loop_filter_across_subpic_enabled_flag[subpic_idx];
 uint8_t lf_edge[] = { 0, 0, 0, 0 };
 
-*restore = no_subpic_filter || no_tile_filter || !lfase;
+*restore = no_subpic_filter || no_tile_filter || !lfase || 
rsps->sps_virtual_boundaries_enabled_flag;
 
 if (!*restore)
 return;
@@ -206,21 +207,25 @@ static void sao_get_edges(uint8_t vert_edge[2], uint8_t 
horiz_edge[2], uint8_t d
 if (!edges[LEFT]) {
 lf_edge[LEFT]  = no_tile_filter && pps->ctb_to_col_bd[rx] == rx;
 lf_edge[LEFT] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_x[subpic_idx] == rx;
+lf_edge[LEFT] |= is_virtual_boundary(fc, rx << sps->ctb_log2_size_y, 
1);
 vert_edge[0]   = !sao_can_cross_slices(fc, rx, ry, -1, 0) || 
lf_edge[LEFT];
 }
 if (!edges[RIGHT]) {
 lf_edge[RIGHT]  = no_tile_filter && pps->ctb_to_col_bd[rx] != 
pps->ctb_to_col_bd[rx + 1];
 lf_edge[RIGHT] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_x[subpic_idx] + 
rsps->sps_subpic_width_minus1[subpic_idx] == rx;
+lf_edge[RIGHT] |= is_virtual_boundary(fc, (rx + 1) << 
sps->ctb_log2_size_y, 1);
 vert_edge[1]= !sao_can_cross_slices(fc, rx, ry, 1, 0) || 
lf_edge[RIGHT];
 }
 if (!edges[TOP]) {
 lf_edge[TOP]   = no_tile_filter && pps->ctb_to_row_bd[ry] == ry;
 lf_edge[TOP]  |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_y[subpic_idx] == ry;
+lf_edge[TOP]  |= is_virtual_boundary(fc, ry << sps->ctb_log2_size_y, 
0);
 horiz_edge[0]  = !sao_can_cross_slices(fc, rx, ry, 0, -1) || 
lf_edge[TOP];
 }
 if (!edges[BOTTOM]) {
 lf_edge[BOTTOM]  = no_tile_filter && pps->ctb_to_row_bd[ry] != 
pps->ctb_to_row_bd[ry + 1];
 lf_edge[BOTTOM] |= no_subpic_filter && 
rsps->sps_subpic_ctu_top_left_y[subpic_idx] + 
rsps->sps_subpic_height_minus1[subpic_idx] == ry;
+lf_edge[BOTTOM] |= is_virtual_boundary(fc, (ry + 1) << 
sps->ctb_log2_size_y, 0);
 horiz_edge[1]= !sao_can_cross_slices(fc, rx, ry, 0, 1) || 
lf_edge[BOTTOM];
 }
 
@@ -285,6 +290,24 @@ static void sao_extends_edges(uint8_t *dst, const 
ptrdiff_t dst_stride,
 copy_ctb(dst, src, width << ps, height, dst_stride, src_stride);
 }
 
+static void sao_restore_vb(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t 
*src, ptrdiff_t src_stride,
+const int width, const int height, const int vb_pos, const int ps, const 
int vertical)
+{
+int w = 2;
+int h = (vertical ? height : width);
+int dx = vb_pos - 1;
+int dy = 0;
+
+if (!vertical) {
+FFSWAP(int, w, h);
+FFSWAP(int, dx, dy);
+}
+dst += dy * dst_stride +(dx << ps);
+src += dy * src_stride +(dx << ps);
+
+av_image_copy_plane(dst, dst_stride, src, src_stride, w << ps, h);
+}
+
 void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
 {
 VVCFrameContext *fc  = lc->fc;
@@ -297,7 +320,12 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
 uint8_t vert_edge[]  = { 0, 0 };
 uint8_t horiz_edge[] = { 0, 0 };
 uint8_t diag_edge[]  = { 0, 0, 0, 0 };
-int restore;
+int restore, vb_x = 0, vb_y = 0;;
+
+if (sps->r->sps_virtual_boundaries_enabled_flag) {
+vb_x = get_virtual_boundary(fc, rx, 1);
+vb_y = get_virtual_boundary(fc, ry, 0);
+}
 
 sao_get_edges(vert_edge, horiz_edge, diag_edge, &restore, lc, edges, rx, 
ry);
 
@@ -305,9 +333,13 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
 static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 
6, 7, 7, 8, 8 };
 const ptrdiff_t src_stride   = fc->frame->linesize[c_idx];
 uint8_t *src = POS(c_idx, x0, y0);
-const int width  = FFMIN(sps->ctb_size_y, 
fc->ps.pps->width - x0) >> sps->hshift[c_idx];
-const int height = FFMIN(sps->ctb_size_y, 
fc->ps.pps->height - y0) >> sps->vshift[c_idx];
+const int hs = sps->hshift[c_idx];
+const int vs = sps->vshift[c_idx];
+const int ps = sps->pixel_shift;
+const int width  = FFMIN(sps->ctb_size_y, 
fc->ps.pps->width  - x0) >> hs;
+const int height = FFMIN(sps->ctb_size_y, 
fc->ps.pps->height 

[FFmpeg-devel] [PATCH 16/18] avcodec/vvcdec: deblock, support virtual boundaries

2024-06-21 Thread Nuo Mi
---
 libavcodec/vvc/filter.c | 34 ++
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index a5635c60df..69d67cb7f6 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -55,6 +55,29 @@ static const uint8_t betatable[64] = {
  58,  60,  62,  64,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86, 
 88,
 };
 
+static int get_virtual_boundary(const VVCFrameContext *fc, const int ctu_pos, 
const int vertical)
+{
+const VVCSPS *sps= fc->ps.sps;
+const VVCPH *ph  = &fc->ps.ph;
+const uint16_t *vbs  = vertical ? ph->vb_pos_x: ph->vb_pos_y;
+const uint8_t nb_vbs = vertical ? ph->num_ver_vbs : ph->num_hor_vbs;
+const int pos= ctu_pos << sps->ctb_log2_size_y;
+
+if (sps->r->sps_virtual_boundaries_enabled_flag) {
+for (int i = 0; i < nb_vbs; i++) {
+const int o = vbs[i] - pos;
+if (o >= 0 && o < sps->ctb_size_y)
+return vbs[i];
+}
+}
+return 0;
+}
+
+static int is_virtual_boundary(const VVCFrameContext *fc, const int pos, const 
int vertical)
+{
+return get_virtual_boundary(fc, pos >> fc->ps.sps->ctb_log2_size_y, 
vertical) == pos;
+}
+
 static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, 
const int chroma)
 {
 const int x= x0 >> MIN_TU_LOG2;
@@ -429,6 +452,7 @@ static void vvc_deblock_subblock_bs(const VVCLocalContext 
*lc,
 
 // bs for TU internal vertical PU boundaries
 for (int i = 8 - ((x0 - cb) % 8); i < width; i += 8) {
+const int is_vb = is_virtual_boundary(fc, x0 + i, vertical);
 const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
 const int xq_pu = (x0 + i) >> log2_min_pu_size;
 
@@ -436,7 +460,7 @@ static void vvc_deblock_subblock_bs(const VVCLocalContext 
*lc,
 const int y_pu   = (y0 + j) >> log2_min_pu_size;
 const MvField *mvf_p = &tab_mvf[y_pu * stridea + xp_pu * strideb];
 const MvField *mvf_q = &tab_mvf[y_pu * stridea + xq_pu * strideb];
-const int bs = boundary_strength(lc, mvf_q, mvf_p, rpl);
+const int bs = is_vb ? 0 : boundary_strength(lc, mvf_q, 
mvf_p, rpl);
 int x= x0 + i;
 int y= y0 + j;
 uint8_t max_len_p = 0, max_len_q = 0;
@@ -557,6 +581,7 @@ static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
 (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
 
 if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
+const int is_vb = is_virtual_boundary(fc, pos, vertical);
 const int size  = vertical ? height : width;
 const int off   = cb - pos;
 const int cb_size   = (vertical ? fc->tab.cb_width : 
fc->tab.cb_height)[LUMA][off_q];
@@ -569,7 +594,7 @@ static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
 const int x = x0 + i * !vertical;
 const int y = y0 + i * vertical;
 uint8_t max_len_p, max_len_q;
-const int bs = deblock_bs(lc, x - vertical, y - !vertical, x, y, 
rpl_p, LUMA, off, has_sb);
+const int bs = is_vb ? 0 : deblock_bs(lc, x - vertical, y - 
!vertical, x, y, rpl_p, LUMA, off, has_sb);
 
 TAB_BS(fc->tab.bs[vertical][LUMA], x, y) = bs;
 
@@ -594,13 +619,14 @@ static void vvc_deblock_bs_chroma(const VVCLocalContext 
*lc,
 const int pos = vertical ? x0 : y0;
 
 if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
-const int size = vertical ? height : width;
+const int is_vb = is_virtual_boundary(fc, pos, vertical);
+const int size  = vertical ? height : width;
 
 for (int c_idx = CB; c_idx <= CR; c_idx++) {
 for (int i = 0; i < size; i += 2) {
 const int x  = x0 + i * !vertical;
 const int y  = y0 + i * vertical;
-const int bs = deblock_bs(lc, x - vertical, y - !vertical, x, 
y, NULL, c_idx, 0, 0);
+const int bs = is_vb ? 0 : deblock_bs(lc, x - vertical, y - 
!vertical, x, y, NULL, c_idx, 0, 0);
 
 TAB_BS(fc->tab.bs[vertical][c_idx], x, y) = bs;
 }
-- 
2.34.1

___
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 18/18] avcodec/vvcdec: alf, support virtual boundaries

2024-06-21 Thread Nuo Mi
see https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=9503377

passed files:
GDR_A_ERICSSON_2.bit
GDR_B_NOKIA_2.bit
GDR_C_NOKIA_2.bit
VIRTUAL_A_MediaTek_3.bit
VIRTUAL_B_MediaTek_3.bit
---
 libavcodec/vvc/ctu.h|   7 +++
 libavcodec/vvc/filter.c | 134 
 libavcodec/vvc/inter.c  |   7 ---
 3 files changed, 100 insertions(+), 48 deletions(-)

diff --git a/libavcodec/vvc/ctu.h b/libavcodec/vvc/ctu.h
index 432dbc5ade..d5c3e8d96f 100644
--- a/libavcodec/vvc/ctu.h
+++ b/libavcodec/vvc/ctu.h
@@ -463,6 +463,13 @@ typedef struct ALFParams {
 uint8_t ctb_cc_idc[2];  ///< alf_ctb_cc_cb_idc, 
alf_ctb_cc_cr_idc
 } ALFParams;
 
+typedef struct VVCRect {
+int l;  // left
+int t;  // top
+int r;  // right
+int b;  // bottom
+} VVCRect;
+
 /**
  * parse a CTU
  * @param lc local context for CTU
diff --git a/libavcodec/vvc/filter.c b/libavcodec/vvc/filter.c
index 44dd895d7d..19b69f078e 100644
--- a/libavcodec/vvc/filter.c
+++ b/libavcodec/vvc/filter.c
@@ -56,6 +56,9 @@ static const uint8_t betatable[64] = {
  58,  60,  62,  64,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86, 
 88,
 };
 
+// One vertical and one horizontal virtual boundary in a CTU at most. The CTU 
will be divided into 4 subblocks.
+#define MAX_VBBS 4
+
 static int get_virtual_boundary(const VVCFrameContext *fc, const int ctu_pos, 
const int vertical)
 {
 const VVCSPS *sps= fc->ps.sps;
@@ -1127,58 +1130,107 @@ static void alf_get_edges(const VVCLocalContext *lc, 
int edges[MAX_EDGES], const
 edges[RIGHT]  |= fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] 
+ fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
 edges[BOTTOM] |= fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] 
+ fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
 }
+
+if (sps->r->sps_virtual_boundaries_enabled_flag) {
+edges[LEFT]   |= is_virtual_boundary(fc, rx << sps->ctb_log2_size_y, 
1);
+edges[TOP]|= is_virtual_boundary(fc, ry << sps->ctb_log2_size_y, 
0);
+edges[RIGHT]  |= is_virtual_boundary(fc, (rx + 1) << 
sps->ctb_log2_size_y, 1);
+edges[BOTTOM] |= is_virtual_boundary(fc, (ry + 1) << 
sps->ctb_log2_size_y, 0);
+}
+}
+
+static void alf_init_subblock(VVCRect *sb, int sb_edges[MAX_EDGES], const 
VVCRect *b, const int edges[MAX_EDGES])
+{
+*sb = *b;
+memcpy(sb_edges, edges, sizeof(int) * MAX_EDGES);
+}
+
+static void alf_get_subblock(VVCRect *sb, int edges[MAX_EDGES], const int bx, 
const int by, const int vb_pos[2], const int has_vb[2])
+{
+int *pos[] = { &sb->l, &sb->t, &sb->r, &sb->b };
+
+for (int vertical = 0; vertical <= 1; vertical++) {
+if (has_vb[vertical]) {
+const int c = vertical ? (bx ? LEFT : RIGHT) : (by ? TOP : BOTTOM);
+*pos[c] = vb_pos[vertical];
+edges[c]  = 1;
+}
+}
+}
+
+static void alf_get_subblocks(const VVCLocalContext *lc, VVCRect 
sbs[MAX_VBBS], int sb_edges[MAX_VBBS][MAX_EDGES], int *nb_sbs,
+const int x0, const int y0, const int rx, const int ry)
+{
+VVCFrameContext *fc  = lc->fc;
+const VVCSPS *sps= fc->ps.sps;
+const VVCPPS *pps= fc->ps.pps;
+const int ctu_size_y = sps->ctb_size_y;
+const int vb_pos[]   = { get_virtual_boundary(fc, ry, 0),  
get_virtual_boundary(fc, rx, 1) };
+const int has_vb[]   = { vb_pos[0] > y0, vb_pos[1] > x0 };
+const VVCRect b  = { x0, y0, FFMIN(x0 + ctu_size_y, pps->width), 
FFMIN(y0 + ctu_size_y, pps->height) };
+int edges[MAX_EDGES] = { !rx, !ry, rx == pps->ctb_width - 1, ry == 
pps->ctb_height - 1 };
+int i= 0;
+
+alf_get_edges(lc, edges, rx, ry);
+
+for (int by = 0; by <= has_vb[0]; by++) {
+for (int bx = 0; bx <= has_vb[1]; bx++, i++) {
+alf_init_subblock(sbs + i, sb_edges[i], &b, edges);
+alf_get_subblock(sbs + i, sb_edges[i], bx, by, vb_pos, has_vb);
+}
+}
+*nb_sbs = i;
 }
 
 void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
 {
 VVCFrameContext *fc = lc->fc;
 const VVCSPS *sps   = fc->ps.sps;
-const VVCPPS *pps   = fc->ps.pps;
-const int rx= x0 >> fc->ps.sps->ctb_log2_size_y;
-const int ry= y0 >> fc->ps.sps->ctb_log2_size_y;
-const int ctb_size_y= fc->ps.sps->ctb_size_y;
-const int ps= fc->ps.sps->pixel_shift;
+const int rx= x0 >> sps->ctb_log2_size_y;
+const int ry= y0 >> sps->ctb_log2_size_y;
+const int ps= sps->pixel_shift;
 const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
 const int padded_offset = padded_stride * ALF_PADDING_SIZE + 
(ALF_PADDING_SIZE << ps);
 const int c_end = sps->r->sps_chroma_format_idc ? 
VVC_MAX_SAMPLE_ARRAYS : 1;
+const int ctu_end   = y0 + sps->ctb_size_y;

Re: [FFmpeg-devel] [PATCH] libavformat/vapoursynth: Update to API version 4, load library at runtime

2024-06-21 Thread Stephen Hutchinson

On 6/21/24 9:37 PM, Stefan Oltmanns via ffmpeg-devel wrote:

The current VapourSynth implementation is rarely used, as it links the
VapourSynth library at build time, making the resulting build unable to
run when VapourSynth is not installed. Therefore barely anyone compiles
with VapourSynth activated.



How many distros package VapourSynth yet don't enable it in FFmpeg vs.
both not packaging it and not enabling it?  VapourSynth not being
available as a package in the distro's repository is a far more likely
reason than linking is.

Switching to dynamic loading would absolutely make the experience on or
building for Windows smoother, and would remove the need to rebuild
FFmpeg when VapourSynth updates, outside of future API changes the
demuxer would need to actively account for.


I changed it, so that it loads the library at runtime when a VapourSynth
script should be opened, just like AviSynth does.
On Windows the DLL from VapourSynth is not installed in the system
directory, but the location is stored in the Registry. Therefore I added
some code to read that information from the registry.



That function is in the wrong place.


I copied the two needed header files directly in a vapoursynth.h,
removing the need to install VapourSynth on the build machine
(VapourSynth is also LGPL 2.1 or later, so no license issue). I updated
the configure so that it checks for the ability to load libraries at
runtime for VapourSynth, just like AviSynth and activate it if not 
disabled.




Including local copies of the headers in compat/ wasn't acceptable for
AviSynth (and were removed as soon as it was no longer necessary for 
there to be an OS distinction between what headers were being used),

it's not going to be acceptable for this either.

And setting it up as autodetect seems like overreach.  I don't know if
there's any actual written rule about which libraries to autodetect and
which ones require explicit enabling, but most of the autodetected ones
thus far appear to be OS-level or otherwise foundational libraries, not
libraries for a singular media format.
___
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".