From patchwork Fri Jan 12 08:26:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 45582 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bf2f:b0:199:de12:6fa6 with SMTP id gc47csp2204533pzb; Fri, 12 Jan 2024 00:31:28 -0800 (PST) X-Google-Smtp-Source: AGHT+IH0bOZcDLiwuHNjdDC6EskFShtnvuUHBi3dikHjWrW5gtXUGsCTHiZ9TNupsnDAbtmygcnc X-Received: by 2002:a05:6512:304c:b0:50e:690f:ee47 with SMTP id b12-20020a056512304c00b0050e690fee47mr503393lfb.46.1705048287693; Fri, 12 Jan 2024 00:31:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1705048287; cv=none; d=google.com; s=arc-20160816; b=ZqsuqpCcFrkwYNyPioP29KC5PNcl3m/lRCFOXMauk0HgRm5hYwtyHWLVhV1faYD8x2 WipvCatt1HK9RRuiCVV1FhfzVS2MeOiDiNF3jbjquKIR/JEeQKhWRnnRjTo/CNrDUls3 IhYvvQe5OEylltw028G4IuzB4nt76JLorv4hCkFh5YYZtwJbF7i/dNFKcmC4Q+AJgrNX /6vqgu/aE8bhOrH4HMcPObO0w3DROTtOGrxsUIi2wTof+EkBDa2JexEMATaE79o19Rfl MJu56xpxMdYfG/bhWl2nKg1YkU4IUIGbABewajxWuBg2YJ4RSDpzzmYXPnSOeQIeVcLi LHhA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=/OR+8fYQMY+iCqXnnnyyraVQCyqiiNe/seK3k8k5ni4=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=aOB/+B8TwSlIHSmPeCiebe6zY7ydl5ddSsONxWLqjY+9wm2YK62a5oLSSO/YBGFMFb 253vJi7AaJaa5AujAMjy/CICSBsCu7f3uh7TjEI0tYe1eUeOiD3hw1b8VA78CJHM0jDH RDcdqEo+8lW5LS0eyteIMEHrvp0J4DozwEeUfmj4b2px9HGOjaz5F7Xo8HHRnOIyQmjL ZGdbKfbdot7LY5Z5WKgTDu1zreqSo7c5wkZCrY0QoYHJ82cf3YxLNpzKSXrpgxTC/orP pVT+USmU1i+eMM7UuF89kRHh+vboRY3eSqdtZpDyMUd7/coLlVlZgsxcvnjKv+6gJHzk ErhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=ulpDqrWL; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id p3-20020a056402500300b005564f353c64si1230987eda.687.2024.01.12.00.31.24; Fri, 12 Jan 2024 00:31:27 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=ulpDqrWL; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 74CD068D0A0; Fri, 12 Jan 2024 10:30:12 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E80B168D079 for ; Fri, 12 Jan 2024 10:30:01 +0200 (EET) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 571C44065B; Fri, 12 Jan 2024 09:30:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1705048201; bh=SIY7PPT02jI0rnP7p/Nh6/y4wN6nZ4m3w/XXwjlSn3E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ulpDqrWLIbs4lpHWd7peZ5CJ2gsV6aA2l3ccgHMNWLfY5K8K//DKM7e4KEnqsni9h TCwxPtY1e5gWqbdChFYUxmCcK41Ar6pSuzDsaPWZZcCoPiF5XUic1ljNV+7j/AYulk 08qbn/wlrcUzYKlXEtu/SfvKbcbIe7PRquII15MI= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Fri, 12 Jan 2024 09:26:04 +0100 Message-ID: <20240112082950.41637-8-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240112082950.41637-1-ffmpeg@haasn.xyz> References: <20240112082950.41637-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 07/11] fftools/ffmpeg_filter: propagate codec yuv metadata to filters X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: rvitx0oRjJ4k From: Niklas Haas To convert between color spaces/ranges, if needed by the codec properties. We momentarily duplicate the mjpeg strictness logic to also enfoce full range. This duplication will be cleaned up in an upcoming commit. Due to avcodec_open2 being called after ofilter_bind_ost, we need to look up the eventual encoder options from the options dictionary directly, following the same design as the "strict" option. --- fftools/ffmpeg_filter.c | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 39f5cde514..280d80f905 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -206,6 +206,8 @@ typedef struct OutputFilterPriv { int width, height; int sample_rate; AVChannelLayout ch_layout; + enum AVColorSpace color_space; + enum AVColorRange color_range; // time base in which the output is sent to our downstream // does not need to match the filtersink's timebase @@ -221,6 +223,8 @@ typedef struct OutputFilterPriv { const int *formats; const AVChannelLayout *ch_layouts; const int *sample_rates; + const enum AVColorSpace *color_spaces; + const enum AVColorRange *color_ranges; AVRational enc_timebase; // offset for output timestamps, in AV_TIME_BASE_Q @@ -392,6 +396,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(color_spaces, enum AVColorSpace, color_space, color_spaces, + AVCOL_SPC_UNSPECIFIED, "%s", av_color_space_name); + +DEF_CHOOSE_FORMAT(color_ranges, 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)) { @@ -621,6 +631,8 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg) ofilter->graph = fg; ofp->format = -1; ofp->index = fg->nb_outputs - 1; + ofp->color_space = AVCOL_SPC_UNSPECIFIED; + ofp->color_range = AVCOL_RANGE_UNSPECIFIED; return ofilter; } @@ -694,6 +706,17 @@ static int set_channel_layout(OutputFilterPriv *f, OutputStream *ost) return 0; } +static int ost_opt_int(OutputStream *ost, const char *name, int defval) +{ + const AVDictionaryEntry *e = av_dict_get(ost->encoder_opts, name, NULL, 0); + if (e) { + const AVOption *o = av_opt_find(ost->enc_ctx, e->key, NULL, 0, 0); + av_assert0(o); + av_opt_eval_int(ost->enc_ctx, o, e->value, &defval); + } + return defval; +} + int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, unsigned sched_idx_enc) { @@ -702,6 +725,8 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, FilterGraph *fg = ofilter->graph; FilterGraphPriv *fgp = fgp_from_fg(fg); const AVCodec *c = ost->enc_ctx->codec; + enum AVColorSpace color_space; + enum AVColorRange color_range; int ret; av_assert0(!ofilter->ost); @@ -716,6 +741,8 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, case AVMEDIA_TYPE_VIDEO: ofp->width = ost->enc_ctx->width; ofp->height = ost->enc_ctx->height; + color_space = ost_opt_int(ost, "color_space", ost->enc_ctx->colorspace); + color_range = ost_opt_int(ost, "color_range", ost->enc_ctx->color_range); if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { ofp->format = ost->enc_ctx->pix_fmt; } else if (!ost->keep_pix_fmt) { @@ -745,6 +772,30 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, ofp->formats = mjpeg_formats; } } + if (color_space != AVCOL_SPC_UNSPECIFIED) { + ofp->color_space = color_space; + } else { + ofp->color_spaces = c->color_spaces; + } + if (color_range != AVCOL_RANGE_UNSPECIFIED) { + ofp->color_range = 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 }; + + int strict_val = ost->enc_ctx->strict_std_compliance; + strict_val = ost_opt_int(ost, "strict", strict_val); + if (strict_val > FF_COMPLIANCE_UNOFFICIAL) + ofp->color_ranges = mjpeg_ranges; + } + } fgp->disable_conversions |= ost->keep_pix_fmt; @@ -1240,6 +1291,8 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph, av_assert0(!ost->keep_pix_fmt || (!ofp->format && !ofp->formats)); av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); choose_pix_fmts(ofp, &bprint); + choose_color_spaces(ofp, &bprint); + choose_color_ranges(ofp, &bprint); if (!av_bprint_is_complete(&bprint)) return AVERROR(ENOMEM); if (bprint.len) { @@ -1747,6 +1800,8 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt) ofp->width = av_buffersink_get_w(sink); ofp->height = av_buffersink_get_h(sink); + ofp->color_space = av_buffersink_get_colorspace(sink); + ofp->color_range = av_buffersink_get_color_range(sink); // If the timing parameters are not locked yet, get the tentative values // here but don't lock them. They will only be used if no output frames