Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust default knee_offset for bt2390 tonemapper #473

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
# We just wrap `build` so this is really it
name: "jellyfin-ffmpeg"
version: "7.0.2-3"
version: "7.0.2-4"
packages:
- bullseye-amd64
- bullseye-armhf
Expand Down
2 changes: 1 addition & 1 deletion builder/scripts.d/50-x265.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

SCRIPT_REPO="https://bitbucket.org/multicoreware/x265_git.git"
SCRIPT_COMMIT="a009ec07721b1e7fcf5289619a3cd5dd6b67a546"
SCRIPT_COMMIT="26d2bab0063cee453b7d8012e76539a7786c032f"

ffbuild_enabled() {
[[ $VARIANT == lgpl* ]] && return -1
Expand Down
8 changes: 8 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
jellyfin-ffmpeg (7.0.2-4) unstable; urgency=medium

* Use more stable range and peak handling in tonemap filters
* Adjust default knee_offset for bt2390 tonemapper
* Respect bl_video_full_range_flag for DoVi video

-- nyanmisaka <[email protected]> Sun, 6 Oct 2024 21:13:39 +0800

jellyfin-ffmpeg (7.0.2-3) unstable; urgency=medium

* Allow VPL QSV to init with the legacy MSDK path
Expand Down
14 changes: 11 additions & 3 deletions debian/patches/0004-add-cuda-tonemap-impl.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ Index: FFmpeg/libavfilter/cuda/tonemap.cu
+ float s_pq = s * scale;
+ float max_lum = inverse_eotf_st2084(dst_peak) * scale;
+
+ float ks = 1.5f * max_lum - 0.5f;
+ float ks = (1.0f + tone_param) * max_lum - tone_param;
+ float tb = (s_pq - ks) / (1.0f - ks);
+ float tb2 = tb * tb;
+ float tb3 = tb2 * tb;
Expand Down Expand Up @@ -1775,7 +1775,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c
===================================================================
--- /dev/null
+++ FFmpeg/libavfilter/vf_tonemap_cuda.c
@@ -0,0 +1,1123 @@
@@ -0,0 +1,1131 @@
+/*
+ * This file is part of FFmpeg.
+ *
Expand Down Expand Up @@ -2313,6 +2313,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c
+ if (isnan(s->param))
+ s->param = 0.3f;
+ break;
+ case TONEMAP_BT2390:
+ if (isnan(s->param))
+ s->param = 1.0f; // diff from the spec-defined 0.5f
+ else
+ s->param = FFMIN(FFMAX(s->param, 0.5f), 2.0f);
+ break;
+ }
+
+ if (isnan(s->param))
Expand Down Expand Up @@ -2735,6 +2741,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c
+ in->color_trc = AVCOL_TRC_SMPTE2084;
+ in->colorspace = AVCOL_SPC_UNSPECIFIED;
+ in->color_primaries = AVCOL_PRI_BT2020;
+ if (rpu->bl_video_full_range_flag)
+ in->color_range = AVCOL_RANGE_JPEG;
+ }
+ }
+
Expand Down Expand Up @@ -2812,7 +2820,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c
+#define OFFSET(x) offsetof(TonemapCUDAContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption options[] = {
+ { "tonemap", "Tonemap algorithm selection", OFFSET(tonemap), AV_OPT_TYPE_INT, {.i64 = TONEMAP_NONE}, TONEMAP_NONE, TONEMAP_COUNT - 1, FLAGS, .unit = "tonemap" },
+ { "tonemap", "Tonemap algorithm selection", OFFSET(tonemap), AV_OPT_TYPE_INT, {.i64 = TONEMAP_BT2390}, TONEMAP_NONE, TONEMAP_COUNT - 1, FLAGS, .unit = "tonemap" },
+ { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_NONE}, 0, 0, FLAGS, .unit = "tonemap" },
+ { "linear", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_LINEAR}, 0, 0, FLAGS, .unit = "tonemap" },
+ { "gamma", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_GAMMA}, 0, 0, FLAGS, .unit = "tonemap" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl
+ float s_pq = s * scale;
+ float max_lum = target_peak_inv_pq * scale;
+
+ float ks = 1.5f * max_lum - 0.5f;
+ float ks = (1.0f + tone_param) * max_lum - tone_param;
+ float tb = (s_pq - ks) / (1.0f - ks);
+ float tb2 = tb * tb;
+ float tb3 = tb2 * tb;
Expand Down Expand Up @@ -1240,15 +1240,15 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
[TONEMAP_HABLE] = "hable",
[TONEMAP_MOBIUS] = "mobius",
+ [TONEMAP_BT2390] = "bt2390",
+};
+
};
+static const double dovi_lms2rgb_matrix[3][3] =
+{
+ { 3.06441879, -2.16597676, 0.10155818},
+ {-0.65612108, 1.78554118, -0.12943749},
+ { 0.01736321, -0.04725154, 1.03004253},
};
+};
+
+static float linearize(float x, float ref_white, enum AVColorTransferCharacteristic trc_in)
+{
+ if (trc_in == AVCOL_TRC_SMPTE2084)
Expand Down Expand Up @@ -1450,7 +1450,18 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c

switch(ctx->tonemap) {
case TONEMAP_GAMMA:
@@ -144,48 +358,167 @@ static int tonemap_opencl_init(AVFilterC
@@ -139,53 +353,178 @@ static int tonemap_opencl_init(AVFilterC
if (isnan(ctx->param))
ctx->param = 0.3f;
break;
+ case TONEMAP_BT2390:
+ if (isnan(ctx->param))
+ ctx->param = 1.0f; // diff from the spec-defined 0.5f
+ else
+ ctx->param = FFMIN(FFMAX(ctx->param, 0.5f), 2.0f);
+ break;
}

if (isnan(ctx->param))
ctx->param = 1.0f;

Expand Down Expand Up @@ -1633,7 +1644,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
if (ctx->range_in == AVCOL_RANGE_JPEG)
av_bprintf(&header, "#define FULL_RANGE_IN\n");

@@ -199,19 +532,41 @@ static int tonemap_opencl_init(AVFilterC
@@ -199,19 +538,41 @@ static int tonemap_opencl_init(AVFilterC
else
ff_opencl_print_const_matrix_3x3(&header, "rgb2rgb", rgb2rgb);

Expand Down Expand Up @@ -1682,7 +1693,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
ctx->colorspace_out, av_color_space_name(ctx->colorspace_out));
goto fail;
}
@@ -219,24 +574,23 @@ static int tonemap_opencl_init(AVFilterC
@@ -219,24 +580,23 @@ static int tonemap_opencl_init(AVFilterC
ff_fill_rgb2yuv_table(luma_dst, rgb2yuv);
ff_opencl_print_const_matrix_3x3(&header, "yuv_matrix", rgb2yuv);

Expand Down Expand Up @@ -1722,7 +1733,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c

av_log(avctx, AV_LOG_DEBUG, "Generated OpenCL header:\n%s\n", header.str);
opencl_sources[0] = header.str;
@@ -254,46 +608,171 @@ static int tonemap_opencl_init(AVFilterC
@@ -254,46 +614,171 @@ static int tonemap_opencl_init(AVFilterC
CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL "
"command queue %d.\n", cle);

Expand Down Expand Up @@ -1888,12 +1899,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
+ av_log(ctx, AV_LOG_ERROR, "Unsupported input format: %s\n",
+ av_get_pix_fmt_name(in_format));
+ return AVERROR(ENOSYS);
}
+ }
+ if (!format_is_supported(out_format)) {
+ av_log(ctx, AV_LOG_ERROR, "Unsupported output format: %s\n",
+ av_get_pix_fmt_name(out_format));
+ return AVERROR(ENOSYS);
+ }
}
+ if (in_desc->comp[0].depth != 10 && in_desc->comp[0].depth != 16) {
+ av_log(ctx, AV_LOG_ERROR, "Unsupported input format depth: %d\n",
+ in_desc->comp[0].depth);
Expand All @@ -1912,7 +1923,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
ret = ff_opencl_filter_config_output(outlink);
if (ret < 0)
return ret;
@@ -308,13 +787,46 @@ static int launch_kernel(AVFilterContext
@@ -308,13 +793,46 @@ static int launch_kernel(AVFilterContext
size_t global_work[2];
size_t local_work[2];
cl_int cle;
Expand Down Expand Up @@ -1961,7 +1972,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c

local_work[0] = 16;
local_work[1] = 16;
@@ -338,13 +850,10 @@ static int tonemap_opencl_filter_frame(A
@@ -338,13 +856,10 @@ static int tonemap_opencl_filter_frame(A
AVFilterContext *avctx = inlink->dst;
AVFilterLink *outlink = avctx->outputs[0];
TonemapOpenCLContext *ctx = avctx->priv;
Expand All @@ -1976,24 +1987,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c

av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
av_get_pix_fmt_name(input->format),
@@ -363,9 +872,6 @@ static int tonemap_opencl_filter_frame(A
@@ -363,8 +878,49 @@ static int tonemap_opencl_filter_frame(A
if (err < 0)
goto fail;

- if (!peak)
- peak = ff_determine_signal_peak(input);
-
if (ctx->trc != -1)
output->color_trc = ctx->trc;
if (ctx->primaries != -1)
@@ -385,72 +891,92 @@ static int tonemap_opencl_filter_frame(A
ctx->range_out = output->color_range;
ctx->chroma_loc = output->chroma_location;

- if (!ctx->initialised) {
- if (!(input->color_trc == AVCOL_TRC_SMPTE2084 ||
- input->color_trc == AVCOL_TRC_ARIB_STD_B67)) {
- av_log(ctx, AV_LOG_ERROR, "unsupported transfer function characteristic.\n");
+ if (ctx->apply_dovi)
+ dovi_sd = av_frame_get_side_data(input, AV_FRAME_DATA_DOVI_METADATA);
+
Expand All @@ -2004,25 +2003,21 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
+ av_log(ctx, AV_LOG_ERROR, "No DOVI metadata and "
+ "unsupported transfer function characteristic: %s\n",
+ av_color_transfer_name(input->color_trc));
err = AVERROR(ENOSYS);
goto fail;
}
+ err = AVERROR(ENOSYS);
+ goto fail;
+ }
+ }

- if (input_frames_ctx->sw_format != AV_PIX_FMT_P010) {
- av_log(ctx, AV_LOG_ERROR, "unsupported format in tonemap_opencl.\n");
- err = AVERROR(ENOSYS);
- goto fail;
+
+ if (!ctx->peak) {
+ if (dovi_sd) {
+ const AVDOVIMetadata *metadata = (AVDOVIMetadata *) dovi_sd->data;
+ ctx->peak = ff_determine_dovi_signal_peak(metadata);
+ } else {
+ ctx->peak = ff_determine_signal_peak(input);
}
+ }
+ av_log(ctx, AV_LOG_DEBUG, "Computed signal peak: %f\n", ctx->peak);
+ }
+
+ if (dovi_sd) {
+ const AVDOVIMetadata *metadata = (AVDOVIMetadata *) dovi_sd->data;
+ const AVDOVIRpuDataHeader *rpu = av_dovi_get_header(metadata);
Expand All @@ -2034,15 +2029,36 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
+ goto fail;
+
+ ff_map_dovi_metadata(ctx->dovi, metadata);
+ ctx->trc_in = AVCOL_TRC_SMPTE2084;
+ ctx->colorspace_in = AVCOL_SPC_UNSPECIFIED;
+ ctx->primaries_in = AVCOL_PRI_BT2020;
+ output->color_trc = input->color_trc = AVCOL_TRC_SMPTE2084;
+ output->colorspace = input->colorspace = AVCOL_SPC_BT2020_NCL;
+ output->color_primaries = input->color_primaries = AVCOL_PRI_BT2020;
+ if (rpu->bl_video_full_range_flag)
+ output->color_range = input->color_range = AVCOL_RANGE_JPEG;
+ }
+ }
+

if (ctx->trc != -1)
output->color_trc = ctx->trc;
@@ -385,72 +941,50 @@ static int tonemap_opencl_filter_frame(A
ctx->range_out = output->color_range;
ctx->chroma_loc = output->chroma_location;

- if (!ctx->initialised) {
- if (!(input->color_trc == AVCOL_TRC_SMPTE2084 ||
- input->color_trc == AVCOL_TRC_ARIB_STD_B67)) {
- av_log(ctx, AV_LOG_ERROR, "unsupported transfer function characteristic.\n");
- err = AVERROR(ENOSYS);
- goto fail;
- }
-
- if (input_frames_ctx->sw_format != AV_PIX_FMT_P010) {
- av_log(ctx, AV_LOG_ERROR, "unsupported format in tonemap_opencl.\n");
- err = AVERROR(ENOSYS);
- goto fail;
- }
+ if (!ctx->init_with_dovi && ctx->dovi && ctx->initialised)
+ tonemap_opencl_uninit_common(avctx);
+
+ if (!ctx->initialised) {
err = tonemap_opencl_init(avctx);
if (err < 0)
Expand Down Expand Up @@ -2119,7 +2135,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
av_frame_free(&input);
av_frame_free(&output);
return err;
@@ -458,24 +984,9 @@ fail:
@@ -458,24 +992,9 @@ fail:

static av_cold void tonemap_opencl_uninit(AVFilterContext *avctx)
{
Expand All @@ -2146,7 +2162,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c

ff_opencl_filter_uninit(avctx);
}
@@ -483,37 +994,50 @@ static av_cold void tonemap_opencl_unini
@@ -483,37 +1002,50 @@ static av_cold void tonemap_opencl_unini
#define OFFSET(x) offsetof(TonemapOpenCLContext, x)
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
static const AVOption tonemap_opencl_options[] = {
Expand Down Expand Up @@ -2181,7 +2197,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c
- { "param", "tonemap parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl = NAN}, DBL_MIN, DBL_MAX, FLAGS },
- { "desat", "desaturation parameter", OFFSET(desat_param), AV_OPT_TYPE_DOUBLE, {.dbl = 0.5}, 0, DBL_MAX, FLAGS },
- { "threshold", "scene detection threshold", OFFSET(scene_threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.2}, 0, DBL_MAX, FLAGS },
+ { "tonemap", "Tonemap algorithm selection", OFFSET(tonemap), AV_OPT_TYPE_INT, { .i64 = TONEMAP_NONE }, TONEMAP_NONE, TONEMAP_COUNT - 1, FLAGS, "tonemap" },
+ { "tonemap", "Tonemap algorithm selection", OFFSET(tonemap), AV_OPT_TYPE_INT, { .i64 = TONEMAP_BT2390 }, TONEMAP_NONE, TONEMAP_COUNT - 1, FLAGS, "tonemap" },
+ { "none", 0, 0, AV_OPT_TYPE_CONST, { .i64 = TONEMAP_NONE }, 0, 0, FLAGS, "tonemap" },
+ { "linear", 0, 0, AV_OPT_TYPE_CONST, { .i64 = TONEMAP_LINEAR }, 0, 0, FLAGS, "tonemap" },
+ { "gamma", 0, 0, AV_OPT_TYPE_CONST, { .i64 = TONEMAP_GAMMA }, 0, 0, FLAGS, "tonemap" },
Expand Down
Loading
Loading