PR #24860 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24860
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24860.patch

Mixed bag of changes.


>From 8af0a63b378326e18f8eb244e36a98f5809ac4b0 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Sun, 26 Jul 2026 13:53:42 +0800
Subject: [PATCH 1/3] avutil: add AV_PIX_FMT_XYZP12

Planar 12-bit XYZ, the natural planar layout for DCI JPEG2000 content.
Also wire it into the Vulkan format table and shader format helpers.
---
 doc/APIchanges                   |  3 +++
 libavutil/hwcontext_vulkan.c     |  3 +++
 libavutil/pixdesc.c              | 24 ++++++++++++++++++++++++
 libavutil/pixfmt.h               |  5 +++++
 libavutil/version.h              |  2 +-
 libavutil/vulkan.c               |  2 ++
 tests/ref/fate/imgutils          |  4 ++++
 tests/ref/fate/sws-pixdesc-query | 11 +++++++++++
 8 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 7d83410b6b..c7f3f7a253 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2026-06-23.
 
 API changes, most recent first:
 
+2026-10-03 - xxxxxxxxxx - lavu 61.11.100 - pixfmt.h
+  Add AV_PIX_FMT_XYZP12LE, AV_PIX_FMT_XYZP12BE, and AV_PIX_FMT_XYZP12.
+
 2026-09-xx - xxxxxxxxxx - lavfi 12.5.100 - avfilter.h buffersrc.h buffersink.h
   Add AVFilterLink.chroma_location, AVBufferSrcParameters.chroma_location and
   av_buffersink_get_chroma_location().
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index fab3532df9..63d2ab5c43 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -514,6 +514,9 @@ static const struct FFVkFormatEntry {
     { VK_FORMAT_R16_SFLOAT, AV_PIX_FMT_GBRPF16,  VK_IMAGE_ASPECT_COLOR_BIT, 3, 
3, 3, { VK_FORMAT_R16_SFLOAT,  VK_FORMAT_R16_SFLOAT,  VK_FORMAT_R16_SFLOAT  } },
     { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32,  VK_IMAGE_ASPECT_COLOR_BIT, 3, 
3, 3, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
 
+    /* XYZ */
+    { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_XYZP12,   VK_IMAGE_ASPECT_COLOR_BIT, 3, 
3, 3, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM  } },
+
     /* Planar RGB + Alpha */
     { VK_FORMAT_R8_UNORM,   AV_PIX_FMT_GBRAP,    VK_IMAGE_ASPECT_COLOR_BIT, 4, 
4, 4, { VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   VK_FORMAT_R8_UNORM,   
VK_FORMAT_R8_UNORM   } },
     { VK_FORMAT_R16_UNORM,  AV_PIX_FMT_GBRAP10,  VK_IMAGE_ASPECT_COLOR_BIT, 4, 
4, 4, { VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  VK_FORMAT_R16_UNORM,  
VK_FORMAT_R16_UNORM  } },
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index f1e80cb31c..c7cbfa8658 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -2145,6 +2145,30 @@ static const AVPixFmtDescriptor 
av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
        },
         .flags = AV_PIX_FMT_FLAG_XYZ | AV_PIX_FMT_FLAG_BE,
     },
+    [AV_PIX_FMT_XYZP12LE] = {
+        .name = "xyzp12le",
+        .nb_components = 3,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 0, 2, 0, 4, 12 },       /* X */
+            { 1, 2, 0, 4, 12 },       /* Y */
+            { 2, 2, 0, 4, 12 },       /* Z */
+        },
+        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_XYZ,
+    },
+    [AV_PIX_FMT_XYZP12BE] = {
+        .name = "xyzp12be",
+        .nb_components = 3,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 0, 2, 0, 4, 12 },       /* X */
+            { 1, 2, 0, 4, 12 },       /* Y */
+            { 2, 2, 0, 4, 12 },       /* Z */
+        },
+        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_XYZ | 
AV_PIX_FMT_FLAG_BE,
+    },
 
 #define BAYER8_DESC_COMMON \
         .nb_components= 3, \
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index b08881cc1f..750e05b644 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -505,6 +505,9 @@ enum AVPixelFormat {
      */
     AV_PIX_FMT_CUARRAY,
 
+    AV_PIX_FMT_XYZP12LE,       ///< planar XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 
12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 
lower bits are set to 0
+    AV_PIX_FMT_XYZP12BE,       ///< planar XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 
12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower 
bits are set to 0
+
     AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS if you 
want to link with shared libav* because the number of formats might differ 
between versions
 };
 
@@ -603,6 +606,8 @@ enum AVPixelFormat {
 #define AV_PIX_FMT_YUVA444P16 AV_PIX_FMT_NE(YUVA444P16BE, YUVA444P16LE)
 
 #define AV_PIX_FMT_XYZ12      AV_PIX_FMT_NE(XYZ12BE, XYZ12LE)
+#define AV_PIX_FMT_XYZP12     AV_PIX_FMT_NE(XYZP12BE, XYZP12LE)
+
 #define AV_PIX_FMT_NV20       AV_PIX_FMT_NE(NV20BE,  NV20LE)
 #define AV_PIX_FMT_AYUV64     AV_PIX_FMT_NE(AYUV64BE, AYUV64LE)
 #define AV_PIX_FMT_P010       AV_PIX_FMT_NE(P010BE,  P010LE)
diff --git a/libavutil/version.h b/libavutil/version.h
index 1a2406e75e..edc3fa5832 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  61
-#define LIBAVUTIL_VERSION_MINOR   10
+#define LIBAVUTIL_VERSION_MINOR   11
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
index fd8f939c55..3987c33080 100644
--- a/libavutil/vulkan.c
+++ b/libavutil/vulkan.c
@@ -1707,6 +1707,7 @@ int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
         pix_fmt == AV_PIX_FMT_X2RGB10 || pix_fmt == AV_PIX_FMT_X2BGR10 ||
         pix_fmt == AV_PIX_FMT_RGBAF32 || pix_fmt == AV_PIX_FMT_RGBF32 ||
         pix_fmt == AV_PIX_FMT_RGBA128 || pix_fmt == AV_PIX_FMT_RGB96 ||
+        pix_fmt == AV_PIX_FMT_XYZP12 ||
         pix_fmt == AV_PIX_FMT_GBRP || pix_fmt == AV_PIX_FMT_BAYER_RGGB16)
         return 1;
     return 0;
@@ -1875,6 +1876,7 @@ const char *ff_vk_shader_rep_fmt(enum AVPixelFormat 
pix_fmt,
     case AV_PIX_FMT_GBRP14:
     case AV_PIX_FMT_GBRP16:
     case AV_PIX_FMT_GBRPF16:
+    case AV_PIX_FMT_XYZP12:
     case AV_PIX_FMT_YUV420P10:
     case AV_PIX_FMT_YUV420P12:
     case AV_PIX_FMT_YUV420P16:
diff --git a/tests/ref/fate/imgutils b/tests/ref/fate/imgutils
index ccd1522ef2..1d104b7476 100644
--- a/tests/ref/fate/imgutils
+++ b/tests/ref/fate/imgutils
@@ -306,6 +306,8 @@ gbrp10msbbe     planes: 3, linesizes: 128 128 128   0, 
plane_sizes:  6144  6144
 gbrp10msble     planes: 3, linesizes: 128 128 128   0, plane_sizes:  6144  
6144  6144     0, plane_offsets:  6144  6144     0, total_size: 18432
 gbrp12msbbe     planes: 3, linesizes: 128 128 128   0, plane_sizes:  6144  
6144  6144     0, plane_offsets:  6144  6144     0, total_size: 18432
 gbrp12msble     planes: 3, linesizes: 128 128 128   0, plane_sizes:  6144  
6144  6144     0, plane_offsets:  6144  6144     0, total_size: 18432
+xyzp12le        planes: 3, linesizes: 128 128 128   0, plane_sizes:  6144  
6144  6144     0, plane_offsets:  6144  6144     0, total_size: 18432
+xyzp12be        planes: 3, linesizes: 128 128 128   0, plane_sizes:  6144  
6144  6144     0, plane_offsets:  6144  6144     0, total_size: 18432
 
 image_fill_black tests
 yuv420p         total_size:   4608,  black_unknown_crc: 0xd00f6cc6,  
black_tv_crc: 0xd00f6cc6,  black_pc_crc: 0x234969af
@@ -559,3 +561,5 @@ gbrp10msbbe     total_size:  18432,  black_unknown_crc: 
0x00000000,  black_tv_cr
 gbrp10msble     total_size:  18432,  black_unknown_crc: 0x00000000,  
black_tv_crc: 0x00000000,  black_pc_crc: 0x00000000
 gbrp12msbbe     total_size:  18432,  black_unknown_crc: 0x00000000,  
black_tv_crc: 0x00000000,  black_pc_crc: 0x00000000
 gbrp12msble     total_size:  18432,  black_unknown_crc: 0x00000000,  
black_tv_crc: 0x00000000,  black_pc_crc: 0x00000000
+xyzp12le        total_size:  18432,  black_unknown_crc: 0x00000000,  
black_tv_crc: 0x00000000,  black_pc_crc: 0x00000000
+xyzp12be        total_size:  18432,  black_unknown_crc: 0x00000000,  
black_tv_crc: 0x00000000,  black_pc_crc: 0x00000000
diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query
index a062088d54..92a2430ca4 100644
--- a/tests/ref/fate/sws-pixdesc-query
+++ b/tests/ref/fate/sws-pixdesc-query
@@ -105,6 +105,8 @@ isNBPS:
   xv36le
   xyz12be
   xyz12le
+  xyzp12be
+  xyzp12le
   y210be
   y210le
   y212be
@@ -221,6 +223,7 @@ isBE:
   xv36be
   xv48be
   xyz12be
+  xyzp12be
   y210be
   y212be
   y216be
@@ -303,6 +306,8 @@ isYUV:
   xv48le
   xyz12be
   xyz12le
+  xyzp12be
+  xyzp12le
   y210be
   y210le
   y212be
@@ -419,6 +424,8 @@ isPlanarYUV:
   p412le
   p416be
   p416le
+  xyzp12be
+  xyzp12le
   yuv410p
   yuv411p
   yuv420p
@@ -1035,6 +1042,8 @@ Planar:
   p412le
   p416be
   p416le
+  xyzp12be
+  xyzp12le
   yuv410p
   yuv411p
   yuv420p
@@ -1241,6 +1250,8 @@ DataInHighBits:
   xv36le
   xyz12be
   xyz12le
+  xyzp12be
+  xyzp12le
   y210be
   y210le
   y212be
-- 
2.52.0


>From e382640440b6761a0e5cf457ff69d2bab0186042 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Sun, 26 Jul 2026 13:53:52 +0800
Subject: [PATCH 2/3] swscale: treat XYZ formats as colorspace-less in color
 (de|en)coding

XYZ formats carry no colorspace matrix; their transfer and primaries
are handled by the color mapping layer, so treat them like RGB when
decoding and encoding colors.
---
 libswscale/format.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index 631719fa8e..5484e8180c 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1522,8 +1522,10 @@ int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType 
type,
         .lin  = fmt_decode_range(fmt, incomplete),
     }));
 
-    /* Final step, decode colorspace */
-    switch (fmt->csp) {
+    /* Final step, decode colorspace. XYZ formats carry no colorspace
+     * matrix; their transfer/primaries are handled by the color mapping
+     * layer, so treat them like RGB here. */
+    switch (fmt->desc->flags & AV_PIX_FMT_FLAG_XYZ ? AVCOL_SPC_RGB : fmt->csp) 
{
     case AVCOL_SPC_RGB:
         return 0;
     case AVCOL_SPC_UNSPECIFIED:
@@ -1595,7 +1597,8 @@ int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType 
type,
     if (!pixel_type)
          return AVERROR(ENOTSUP);
 
-    switch (dst->csp) {
+    /* See ff_sws_decode_colors(): XYZ formats have no colorspace matrix */
+    switch (dst->desc->flags & AV_PIX_FMT_FLAG_XYZ ? AVCOL_SPC_RGB : dst->csp) 
{
     case AVCOL_SPC_RGB:
         break;
     case AVCOL_SPC_UNSPECIFIED:
-- 
2.52.0


>From c0c3c7298353843497ceec877c74a16054a118f0 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Sun, 26 Jul 2026 13:55:17 +0800
Subject: [PATCH 3/3] jpeg2000dec: convert the decoder to the receive_frame API

Convert the decoder to the receive_frame API (one codestream per
packet; skipped frames pull the next packet instead of returning
empty-handed), finish threading setup before the tile decode, and do
not leave a partially initialized frame on the output on error.

Move the tag-tree size, exp2fi and band stepsize helpers into the
shared header as ff_-prefixed inlines so code outside jpeg2000.c can
derive the same geometry and quantization parameters.

Co-Authored-By: Claude Fable 5 <[email protected]>
---
 libavcodec/jpeg2000.c    | 89 ++++++++++++++++++----------------------
 libavcodec/jpeg2000.h    | 36 ++++++++++++++++
 libavcodec/jpeg2000dec.c | 40 ++++++++++++++----
 3 files changed, 108 insertions(+), 57 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 6433e13892..a21f9c2a82 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -39,18 +39,6 @@
 
 /* tag tree routines */
 
-static int32_t tag_tree_size(int w, int h)
-{
-    int64_t res = 0;
-    while (w > 1 || h > 1) {
-        res += w * (int64_t)h;
-        av_assert0(res + 1 < INT32_MAX);
-        w = (w + 1) >> 1;
-        h = (h + 1) >> 1;
-    }
-    return (int32_t)(res + 1);
-}
-
 /* allocate the memory for tag tree */
 static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int h)
 {
@@ -58,7 +46,7 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int 
h)
     Jpeg2000TgtNode *res, *t, *t2;
     int32_t tt_size;
 
-    tt_size = tag_tree_size(w, h);
+    tt_size = ff_jpeg2000_tag_tree_size(w, h);
 
     t = res = av_calloc(tt_size, sizeof(*t));
     if (!res)
@@ -85,7 +73,7 @@ static Jpeg2000TgtNode *ff_jpeg2000_tag_tree_init(int w, int 
h)
 
 void ff_tag_tree_zero(Jpeg2000TgtNode *t, int w, int h, int val)
 {
-    int i, siz = tag_tree_size(w, h);
+    int i, siz = ff_jpeg2000_tag_tree_size(w, h);
 
     for (i = 0; i < siz; i++) {
         t[i].val = val;
@@ -199,33 +187,22 @@ void ff_jpeg2000_set_significance(Jpeg2000T1Context *t1, 
int x, int y,
     t1->flags[(y - 1) * t1->stride + x - 1] |= JPEG2000_T1_SIG_SE;
 }
 
+/* TODO: Implementation of quantization step not finished, see
+ * ISO/IEC 15444-1:2002 E.1 and A.6.4. */
 // static const uint8_t lut_gain[2][4] = { { 0, 0, 0, 0 }, { 0, 1, 1, 2 } }; 
(unused)
-
-/**
- * 2^(x) for integer x in the range -126..128.
- * @return correctly rounded float
- */
-static av_always_inline float exp2fi(int x)
+float ff_jpeg2000_band_stepsize(AVCodecContext *avctx,
+                                              Jpeg2000CodingStyle *codsty,
+                                              Jpeg2000QuantStyle *qntsty,
+                                              int bandno, int gbandno,
+                                              int reslevelno, int cbps)
 {
-    av_assert2(-126 <= x && x <= 128);
-    /* Normal range */
-    return av_int2float((x+127) << 23);
-}
+    float fss;
 
-static void init_band_stepsize(AVCodecContext *avctx,
-                               Jpeg2000Band *band,
-                               Jpeg2000CodingStyle *codsty,
-                               Jpeg2000QuantStyle *qntsty,
-                               int bandno, int gbandno, int reslevelno,
-                               int cbps)
-{
-    /* TODO: Implementation of quantization step not finished,
-     * see ISO/IEC 15444-1:2002 E.1 and A.6.4. */
     switch (qntsty->quantsty) {
         uint8_t gain;
     case JPEG2000_QSTY_NONE:
         /* TODO: to verify. No quantization in this case */
-        band->f_stepsize = 1;
+        fss = 1;
         break;
     case JPEG2000_QSTY_SI:
         /*TODO: Compute formula to implement. */
@@ -240,35 +217,47 @@ static void init_band_stepsize(AVCodecContext *avctx,
          * delta_b = 2 ^ (R_b - expn_b) * (1 + (mant_b / 2 ^ 11))
          * R_b = R_I + log2 (gain_b )
          * see ISO/IEC 15444-1:2002 E.1.1 eqn. E-3 and E-4 */
-        gain            = cbps;
-        band->f_stepsize  = exp2fi(gain - qntsty->expn[gbandno]);
-        band->f_stepsize *= qntsty->mant[gbandno] / 2048.0 + 1.0;
+        gain = cbps;
+        fss  = ff_jpeg2000_exp2fi(gain - qntsty->expn[gbandno]);
+        fss *= qntsty->mant[gbandno] / 2048.0 + 1.0;
         break;
     default:
-        band->f_stepsize = 0;
         av_log(avctx, AV_LOG_ERROR, "Unknown quantization format\n");
-        break;
+        return 0;
     }
     if (codsty->transform != FF_DWT53) {
         int lband = 0;
         switch (bandno + (reslevelno > 0)) {
-            case 1:
-            case 2:
-                band->f_stepsize *= F_LFTG_X * 2;
-                lband = 1;
-                break;
-            case 3:
-                band->f_stepsize *= F_LFTG_X * F_LFTG_X * 4;
-                break;
+        case 1:
+        case 2:
+            fss *= F_LFTG_X * 2;
+            lband = 1;
+            break;
+        case 3:
+            fss *= F_LFTG_X * F_LFTG_X * 4;
+            break;
         }
-        band->f_stepsize *= pow(F_LFTG_K, 2*(codsty->nreslevels2decode - 
reslevelno) + lband - 2);
+        fss *= pow(F_LFTG_K, 2 * (codsty->nreslevels2decode - reslevelno) +
+                             lband - 2);
     }
 
-    if (band->f_stepsize > (INT_MAX >> 15)) {
-        band->f_stepsize = 0;
+    if (fss > (INT_MAX >> 15)) {
         av_log(avctx, AV_LOG_ERROR, "stepsize out of range\n");
+        return 0;
     }
+    return fss;
+}
 
+static void init_band_stepsize(AVCodecContext *avctx,
+                               Jpeg2000Band *band,
+                               Jpeg2000CodingStyle *codsty,
+                               Jpeg2000QuantStyle *qntsty,
+                               int bandno, int gbandno, int reslevelno,
+                               int cbps)
+{
+    band->f_stepsize = ff_jpeg2000_band_stepsize(avctx, codsty, qntsty,
+                                                 bandno, gbandno, reslevelno,
+                                                 cbps);
     band->i_stepsize = (int)floorf(band->f_stepsize * (1 << 15));
 }
 
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index 93221d90ca..52c00f4268 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -31,6 +31,9 @@
 
 #include <stdint.h>
 
+#include "libavutil/avassert.h"
+#include "libavutil/intfloat.h"
+
 #include "avcodec.h"
 #include "mqc.h"
 #include "jpeg2000dwt.h"
@@ -289,6 +292,39 @@ static inline int ff_jpeg2000_getsgnctxno(int flag, int 
*xorbit)
     return ff_jpeg2000_sgnctxno_lut[flag & 15][(flag >> 8) & 15];
 }
 
+/* Node count of the tag-tree pyramid over a (w, h) leaf grid. */
+static inline int32_t ff_jpeg2000_tag_tree_size(int w, int h)
+{
+    int64_t res = 0;
+    while (w > 1 || h > 1) {
+        res += w * (int64_t)h;
+        av_assert0(res + 1 < INT32_MAX);
+        w = (w + 1) >> 1;
+        h = (h + 1) >> 1;
+    }
+    return (int32_t)(res + 1);
+}
+
+/**
+ * 2^(x) for integer x in the range -126..128.
+ * @return correctly rounded float
+ */
+static av_always_inline float ff_jpeg2000_exp2fi(int x)
+{
+    av_assert2(-126 <= x && x <= 128);
+    /* Normal range */
+    return av_int2float((x + 127) << 23);
+}
+
+/* Band dequantization step size (ISO/IEC 15444-1:2002 E.1), shared between
+ * the software decoder's band setup and the Vulkan hwaccel's inline
+ * geometry. */
+float ff_jpeg2000_band_stepsize(AVCodecContext *avctx,
+                                Jpeg2000CodingStyle *codsty,
+                                Jpeg2000QuantStyle *qntsty,
+                                int bandno, int gbandno,
+                                int reslevelno, int cbps);
+
 int ff_jpeg2000_init_component(Jpeg2000Component *comp,
                                Jpeg2000CodingStyle *codsty,
                                Jpeg2000QuantStyle *qntsty,
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 369377e4fc..870678f0b0 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -39,6 +39,7 @@
 #include "bytestream.h"
 #include "codec_internal.h"
 #include "decode.h"
+#include "internal.h"
 #include "thread.h"
 #include "jpeg2000.h"
 #include "jpeg2000dsp.h"
@@ -2855,7 +2856,7 @@ static av_cold int jpeg2000_decode_init(AVCodecContext 
*avctx)
 }
 
 static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture,
-                                 int *got_frame, AVPacket *avpkt)
+                                 const AVPacket *avpkt)
 {
     Jpeg2000DecoderContext *s = avctx->priv_data;
     int ret;
@@ -2902,7 +2903,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, 
AVFrame *picture,
 
     if (avctx->skip_frame >= AVDISCARD_ALL) {
         jpeg2000_dec_cleanup(s);
-        return avpkt->size;
+        return 0;
     }
 
     /* get picture buffer */
@@ -2916,22 +2917,47 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, 
AVFrame *picture,
         if (++x == s->ncomponents)
             picture->flags |= AV_FRAME_FLAG_LOSSLESS;
 
-    avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, s->numXtiles * 
s->numYtiles);
+    ff_thread_finish_setup(avctx);
+
+    avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL,
+                    s->numXtiles * s->numYtiles);
 
     jpeg2000_dec_cleanup(s);
 
-    *got_frame = 1;
-
     if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
         memcpy(picture->data[1], s->palette, 256 * sizeof(uint32_t));
 
-    return bytestream2_tell(&s->g);
+    return 0;
 
 end:
+    /* Do not leave a partially initialized frame on the output. */
+    av_frame_unref(picture);
     jpeg2000_dec_cleanup(s);
     return ret;
 }
 
+static int jpeg2000_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+    AVPacket *const avpkt = avctx->internal->in_pkt;
+    int ret;
+
+    /* One codestream per packet. Loop so that skipped frames (produce no
+     * output) transparently pull the next packet instead of returning to the
+     * caller empty-handed. */
+    do {
+        ret = ff_decode_get_packet(avctx, avpkt);
+        if (ret < 0)
+            return ret;
+
+        ret = jpeg2000_decode_frame(avctx, frame, avpkt);
+        av_packet_unref(avpkt);
+        if (ret < 0)
+            return ret;
+    } while (!frame->buf[0]);
+
+    return 0;
+}
+
 #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x)
 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
 
@@ -2956,7 +2982,7 @@ const FFCodec ff_jpeg2000_decoder = {
     .p.capabilities   = AV_CODEC_CAP_SLICE_THREADS | 
AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1,
     .priv_data_size   = sizeof(Jpeg2000DecoderContext),
     .init             = jpeg2000_decode_init,
-    FF_CODEC_DECODE_CB(jpeg2000_decode_frame),
+    FF_CODEC_RECEIVE_FRAME_CB(jpeg2000_receive_frame),
     .p.priv_class     = &jpeg2000_class,
     .p.max_lowres     = 5,
     .p.profiles       = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles),
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to