From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <ffmpeg-devel-bounces@ffmpeg.org>
Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100])
	by master.gitmailbox.com (Postfix) with ESMTP id 78B9845201
	for <ffmpegdev@gitmailbox.com>; Wed, 11 Oct 2023 15:09:34 +0000 (UTC)
Received: from [127.0.1.1] (localhost [127.0.0.1])
	by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7413D68CBF5;
	Wed, 11 Oct 2023 18:09:03 +0300 (EEST)
Received: from haasn.dev (haasn.dev [78.46.187.166])
 by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 525EA68CB01
 for <ffmpeg-devel@ffmpeg.org>; Wed, 11 Oct 2023 18:08:54 +0300 (EEST)
Received: from haasn.dev (unknown [10.30.0.2])
 by haasn.dev (Postfix) with ESMTP id 121EA4BBFF;
 Wed, 11 Oct 2023 17:08:54 +0200 (CEST)
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail;
 t=1697036934; bh=Z3TrOqnsv0H6vwRbnP34S8gyRKy56apLqLs1PnD+jfI=;
 h=From:To:Cc:Subject:Date:In-Reply-To:References:From;
 b=UR5157XdrQk6a8ZrQnCaj1aHuDD47yupd76YSa655ojNZO6mZvdH/bpVED09k3sC6
 eixJ1dmJKdlQzRhAdmk2LwrnOytc4IjdEXkHdJiCm6jA1Ob276j0IYx9XEr1odMzJ9
 4DMJ/1BAe05LjDgXzZS6U4WhF9dSe7mfsUE5zwf4=
From: Niklas Haas <ffmpeg@haasn.xyz>
To: ffmpeg-devel@ffmpeg.org
Date: Wed, 11 Oct 2023 16:55:37 +0200
Message-ID: <20231011150848.117897-4-ffmpeg@haasn.xyz>
X-Mailer: git-send-email 2.42.0
In-Reply-To: <20231011150848.117897-1-ffmpeg@haasn.xyz>
References: <20231011150848.117897-1-ffmpeg@haasn.xyz>
MIME-Version: 1.0
Subject: [FFmpeg-devel] [PATCH 3/7] fftools/ffmpeg_filter: auto-insert csp
 conversion filter
X-BeenThere: ffmpeg-devel@ffmpeg.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: FFmpeg development discussions and patches <ffmpeg-devel.ffmpeg.org>
List-Unsubscribe: <https://ffmpeg.org/mailman/options/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=unsubscribe>
List-Archive: <https://ffmpeg.org/pipermail/ffmpeg-devel>
List-Post: <mailto:ffmpeg-devel@ffmpeg.org>
List-Help: <mailto:ffmpeg-devel-request@ffmpeg.org?subject=help>
List-Subscribe: <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=subscribe>
Reply-To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Cc: Niklas Haas <git@haasn.dev>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: ffmpeg-devel-bounces@ffmpeg.org
Sender: "ffmpeg-devel" <ffmpeg-devel-bounces@ffmpeg.org>
Archived-At: <https://master.gitmailbox.com/ffmpegdev/20231011150848.117897-4-ffmpeg@haasn.xyz/>
List-Archive: <https://master.gitmailbox.com/ffmpegdev/>
List-Post: <mailto:ffmpegdev@gitmailbox.com>

From: Niklas Haas <git@haasn.dev>

To convert between color ranges/matrices, if needed by the codec
properties. Swscale can't do this currently, so we fall back to using
zscale. We momentarily duplicate the mjpeg strictness logic to also
enfoce full range. This duplication will be cleaned up in the next
commit.

In theory this scaler can also handle chroma locations, but the
configuration for it is non-trivial due to the split between x/y
offsets, and no codec currently signals a chroma location requirement.
(Though this is subject to change in the future)
---
 fftools/ffmpeg_filter.c | 73 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index c738fc3397..c1bedfda00 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -169,6 +169,8 @@ typedef struct OutputFilterPriv {
     int width, height;
     int sample_rate;
     AVChannelLayout ch_layout;
+    enum AVColorSpace csp;
+    enum AVColorRange color_range;
 
     // time base in which the output is sent to our downstream
     // does not need to match the filtersink's timebase
@@ -184,6 +186,8 @@ typedef struct OutputFilterPriv {
     const int *formats;
     const AVChannelLayout *ch_layouts;
     const int *sample_rates;
+    const enum AVColorSpace *csps;
+    const enum AVColorRange *color_ranges;
 
     AVRational enc_timebase;
     // offset for output timestamps, in AV_TIME_BASE_Q
@@ -368,6 +372,12 @@ DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats,
 DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,
                   "%d", )
 
+DEF_CHOOSE_FORMAT(out_color_matrix, enum AVColorSpace, csp, csps,
+                  AVCOL_SPC_UNSPECIFIED, "%s", av_color_space_name);
+
+DEF_CHOOSE_FORMAT(out_range, enum AVColorRange, color_range, color_ranges,
+                  AVCOL_RANGE_UNSPECIFIED, "%s", av_color_range_name);
+
 static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint)
 {
     if (av_channel_layout_check(&ofp->ch_layout)) {
@@ -594,6 +604,7 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg)
     ofilter           = &ofp->ofilter;
     ofilter->graph    = fg;
     ofp->format       = -1;
+    ofp->csp          = AVCOL_SPC_UNSPECIFIED;
     ofilter->last_pts = AV_NOPTS_VALUE;
 
     return ofilter;
@@ -682,6 +693,37 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost)
     case AVMEDIA_TYPE_VIDEO:
         ofp->width      = ost->enc_ctx->width;
         ofp->height     = ost->enc_ctx->height;
+        if (ost->enc_ctx->colorspace != AVCOL_SPC_UNSPECIFIED) {
+            ofp->csp = ost->enc_ctx->colorspace;
+        } else {
+            ofp->csps = c->csps;
+        }
+        if (ost->enc_ctx->color_range) {
+            ofp->color_range = ost->enc_ctx->color_range;
+        } else {
+            ofp->color_ranges = c->color_ranges;
+
+            // MJPEG encoder exports a full list of supported pixel formats,
+            // but the full-range ones are experimental-only.
+            // Restrict the auto-conversion list unless -strict experimental
+            // has been specified.
+            if (!strcmp(c->name, "mjpeg")) {
+                static const enum AVColorRange mjpeg_ranges[] =
+                    { AVCOL_RANGE_JPEG, AVCOL_RANGE_UNSPECIFIED };
+
+                const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
+                int strict_val = ost->enc_ctx->strict_std_compliance;
+
+                if (strict) {
+                    const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0);
+                    av_assert0(o);
+                    av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val);
+                }
+
+                if (strict_val > FF_COMPLIANCE_UNOFFICIAL)
+                    ofp->color_ranges = mjpeg_ranges;
+            }
+        }
         if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
             ofp->format = ost->enc_ctx->pix_fmt;
         } else {
@@ -1149,6 +1191,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter,
     OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
     OutputStream *ost = ofilter->ost;
     OutputFile    *of = output_files[ost->file_index];
+    FilterGraphPriv *fgp = fgp_from_fg(fg);
     AVFilterContext *last_filter = out->filter_ctx;
     AVBPrint bprint;
     int pad_idx = out->pad_idx;
@@ -1209,6 +1252,36 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter,
         pad_idx     = 0;
     }
 
+    if (!fgp->disable_conversions) {
+        av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
+        choose_out_color_matrix(ofp,    &bprint);
+        choose_out_range(ofp,     &bprint);
+        if (bprint.len) {
+            const AVDictionaryEntry *e = NULL;
+            AVFilterContext *filter;
+
+            while ((e = av_dict_iterate(ost->sws_dict, e)))
+                av_bprintf(&bprint, "%s=%s:", e->key, e->value);
+
+            if (!av_bprint_is_complete(&bprint))
+                return AVERROR(ENOMEM);
+
+            snprintf(name, sizeof(name), "conv_out_%d_%d",
+                     ost->file_index, ost->index);
+            ret = avfilter_graph_create_filter(&filter,
+                                               avfilter_get_by_name("scale"),
+                                               name, bprint.str, NULL, fg->graph);
+            av_bprint_finalize(&bprint, NULL);
+            if (ret < 0)
+                return ret;
+            if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
+                return ret;
+
+            last_filter = filter;
+            pad_idx = 0;
+        }
+    }
+
     snprintf(name, sizeof(name), "trim_out_%d_%d",
              ost->file_index, ost->index);
     ret = insert_trim(of->start_time, of->recording_time,
-- 
2.42.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-request@ffmpeg.org with subject "unsubscribe".