Files
jellyfin-ffmpeg/builder/patches/libplacebo/0001-libav-utils-fix-non-multiplane-fmt-bit_shift-in-pl_m.patch
T
2026-05-28 10:57:06 +08:00

118 lines
4.2 KiB
Diff

From 1d687149fcfc2caca536c168ba2068e7816844ac Mon Sep 17 00:00:00 2001
From: nyanmisaka <nst799610810@gmail.com>
Date: Fri, 1 May 2026 19:45:21 +0800
Subject: [PATCH] libav/utils: fix non-multiplane fmt bit_shift in
pl_map_avframe*
Fixes: https://github.com/haasn/libplacebo/issues/349
Signed-off-by: nyanmisaka <nst799610810@gmail.com>
---
src/include/libplacebo/utils/libav_internal.h | 58 +++++++++++++++++--
1 file changed, 52 insertions(+), 6 deletions(-)
diff --git a/src/include/libplacebo/utils/libav_internal.h b/src/include/libplacebo/utils/libav_internal.h
index cc954dc9..ca298c1f 100644
--- a/src/include/libplacebo/utils/libav_internal.h
+++ b/src/include/libplacebo/utils/libav_internal.h
@@ -1040,6 +1040,44 @@ struct pl_avframe_priv {
pl_tex planar; // for planar vulkan textures
};
+#define COMP_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define COMP_MIN(x, y) ((x) < (y) ? (x) : (y))
+#define COMP_ABS(x) ((x) < 0 ? -(x) : (x))
+
+static void pl_map_hwframe_bit_encoding(struct pl_bit_encoding *out_bits,
+ enum AVPixelFormat pix_fmt)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+ struct pl_bit_encoding bits = {0};
+ bool is_supported = true;
+ if (!out_bits || !desc)
+ return;
+
+ // Calculate bit encoding from all components (excluding alpha)
+ for (int c = 0; c < COMP_MIN(desc->nb_components, 3); c++) {
+ const AVComponentDescriptor *comp = &desc->comp[c];
+ struct pl_bit_encoding cbits = {
+ .sample_depth = comp->depth + COMP_ABS(comp->shift),
+ .color_depth = comp->depth,
+ .bit_shift = COMP_MAX(comp->shift, 0),
+ };
+
+ if (bits.sample_depth && !pl_bit_encoding_equal(&bits, &cbits)) {
+ // Bit encoding differs between components, cannot handle this
+ is_supported = false;
+ break;
+ }
+
+ bits = cbits;
+ }
+ if (is_supported)
+ *out_bits = bits;
+}
+
+#undef COMP_MAX
+#undef COMP_MIN
+#undef COMP_ABS
+
static void pl_fix_hwframe_sample_depth(struct pl_frame *out)
{
pl_fmt fmt = out->planes[0].texture->params.format;
@@ -1088,13 +1126,9 @@ static bool pl_map_avframe_drm(pl_gpu gpu, struct pl_frame *out,
return false;
}
+ pl_map_hwframe_bit_encoding(&out->repr.bits, hwfc->sw_format);
pl_fix_hwframe_sample_depth(out);
- switch (hwfc->sw_format) {
- case AV_PIX_FMT_P010: out->repr.bits.bit_shift = 6; break;
- default: break;
- }
-
return true;
}
@@ -1234,8 +1268,11 @@ static bool pl_map_avframe_vulkan(pl_gpu gpu, struct pl_frame *out,
if (!vk)
return false;
+ pl_map_hwframe_bit_encoding(&out->repr.bits, hwfc->sw_format);
+
for (int n = 0; n < out->num_planes; n++) {
struct pl_plane *plane = &out->planes[n];
+ struct pl_bit_encoding bits = {0};
bool chroma = n == 1 || n == 2;
int num_subplanes;
assert(vk_fmt[n]);
@@ -1244,7 +1281,7 @@ static bool pl_map_avframe_vulkan(pl_gpu gpu, struct pl_frame *out,
.image = vkf->img[n],
.width = AV_CEIL_RSHIFT(hwfc->width, chroma ? desc->log2_chroma_w : 0),
.height = AV_CEIL_RSHIFT(hwfc->height, chroma ? desc->log2_chroma_h : 0),
- .format = map_vk_fmt(vkfc, vk_fmt[n], &out->repr.bits),
+ .format = map_vk_fmt(vkfc, vk_fmt[n], &bits),
.usage = vkfc->usage,
));
if (!plane->texture)
@@ -1253,6 +1290,15 @@ static bool pl_map_avframe_vulkan(pl_gpu gpu, struct pl_frame *out,
num_subplanes = plane->texture->params.format->num_planes;
if (num_subplanes) {
assert(num_subplanes == out->num_planes);
+
+ // Cannot shift on non-mutable multiplane vk image
+ if (!n && num_subplanes > 1 && out->repr.bits.bit_shift) {
+ if (vkfc->img_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT)
+ assert(out->repr.bits.bit_shift == bits.bit_shift);
+ else
+ out->repr.bits.bit_shift = 0;
+ }
+
priv->planar = plane->texture;
for (int i = 0; i < num_subplanes; i++)
out->planes[i].texture = priv->planar->planes[i];
--
2.34.1