diff options
author | Niklas Haas <git@haasn.dev> | 2024-04-08 13:58:19 +0200 |
---|---|---|
committer | Niklas Haas <git@haasn.dev> | 2024-09-08 13:59:29 +0200 |
commit | a850f80e2c1fdd7dcac536cce773ddb2bfad7265 (patch) | |
tree | e0ed61ca006a3bc63ee0c7de68a2f8e6c98426fb | |
parent | 33d5a4ec4eaf3d206eb229faf7276e0d0e543b34 (diff) | |
download | ffmpeg-a850f80e2c1fdd7dcac536cce773ddb2bfad7265.tar.gz |
fftools/ffmpeg_filter: propagate codec yuv metadata to filters
To convert between color spaces/ranges, if needed by the codec
properties.
Signed-off-by: Anton Khirnov <anton@khirnov.net>
-rw-r--r-- | fftools/ffmpeg.h | 4 | ||||
-rw-r--r-- | fftools/ffmpeg_filter.c | 26 | ||||
-rw-r--r-- | fftools/ffmpeg_mux_init.c | 12 |
3 files changed, 42 insertions, 0 deletions
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index ca24b20640..f4a10b2a66 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -304,6 +304,8 @@ typedef struct OutputFilterOptions { int format; int width; int height; + enum AVColorSpace color_space; + enum AVColorRange color_range; enum VideoSyncMethod vsync_method; @@ -314,6 +316,8 @@ typedef struct OutputFilterOptions { const int *sample_rates; const AVChannelLayout *ch_layouts; const AVRational *frame_rates; + const enum AVColorSpace *color_spaces; + const enum AVColorRange *color_ranges; } OutputFilterOptions; typedef struct InputFilter { diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 9effa96aac..8b420e68ab 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -202,6 +202,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 @@ -220,6 +222,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; int64_t trim_start_us; @@ -395,6 +399,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)) { @@ -639,6 +649,8 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type) ofilter->graph = fg; ofilter->type = type; ofp->format = -1; + ofp->color_space = AVCOL_SPC_UNSPECIFIED; + ofp->color_range = AVCOL_RANGE_UNSPECIFIED; ofp->index = fg->nb_outputs - 1; snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d", @@ -822,6 +834,16 @@ int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, } else ofp->formats = opts->formats; + if (opts->color_space != AVCOL_SPC_UNSPECIFIED) + ofp->color_space = opts->color_space; + else + ofp->color_spaces = opts->color_spaces; + + if (opts->color_range != AVCOL_RANGE_UNSPECIFIED) + ofp->color_range = opts->color_range; + else + ofp->color_ranges = opts->color_ranges; + fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT); ofp->fps.last_frame = av_frame_alloc(); @@ -1485,6 +1507,8 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph, ofp->format != AV_PIX_FMT_NONE || !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); @@ -1907,6 +1931,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 diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c index a2cb0ba294..452889233d 100644 --- a/fftools/ffmpeg_mux_init.c +++ b/fftools/ffmpeg_mux_init.c @@ -934,6 +934,8 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter, enc_ctx->pix_fmt : enc_ctx->sample_fmt, .width = enc_ctx->width, .height = enc_ctx->height, + .color_space = enc_ctx->colorspace, + .color_range = enc_ctx->color_range, .vsync_method = vsync_method, .sample_rate = enc_ctx->sample_rate, .ch_layout = enc_ctx->ch_layout, @@ -967,6 +969,16 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter, if (ret < 0) return ret; } + ret = avcodec_get_supported_config(enc_ctx, NULL, + AV_CODEC_CONFIG_COLOR_SPACE, 0, + (const void **) &opts.color_spaces, NULL); + if (ret < 0) + return ret; + ret = avcodec_get_supported_config(enc_ctx, NULL, + AV_CODEC_CONFIG_COLOR_RANGE, 0, + (const void **) &opts.color_ranges, NULL); + if (ret < 0) + return ret; } else { ret = avcodec_get_supported_config(enc_ctx, NULL, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, |