1
0
Fork 0

avfilter/buffersrc: add color_space/range parameters

To allow adding proper negotiation, in particular, to fftools.

These values will simply be negotiated downstream for YUV formats, and
ignored otherwise.
This commit is contained in:
Niklas Haas 2023-10-20 16:55:43 +02:00
parent 9d0f361f7f
commit 2d555dc82d
3 changed files with 83 additions and 8 deletions

View File

@ -28092,6 +28092,16 @@ Specify the timebase assumed by the timestamps of the buffered frames.
@item frame_rate
Specify the frame rate expected for the video stream.
@item colorspace
A string representing the color space of the buffered video frames.
It may be a number corresponding to a color space, or a color space
name.
@item range
A string representing the color range of the buffered video frames.
It may be a number corresponding to a color range, or a color range
name.
@item pixel_aspect, sar
The sample (pixel) aspect ratio of the input video.

View File

@ -28,6 +28,7 @@
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/frame.h"
#include "libavutil/hwcontext.h"
#include "libavutil/imgutils.h"
#include "libavutil/internal.h"
#include "libavutil/opt.h"
@ -50,6 +51,8 @@ typedef struct BufferSourceContext {
/* video only */
int w, h;
enum AVPixelFormat pix_fmt;
enum AVColorSpace color_space;
enum AVColorRange color_range;
AVRational pixel_aspect;
AVBufferRef *hw_frames_ctx;
@ -65,10 +68,13 @@ typedef struct BufferSourceContext {
int64_t last_pts;
} BufferSourceContext;
#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, pts)\
if (c->w != width || c->h != height || c->pix_fmt != format) {\
av_log(s, AV_LOG_INFO, "filter context - w: %d h: %d fmt: %d, incoming frame - w: %d h: %d fmt: %d pts_time: %s\n",\
c->w, c->h, c->pix_fmt, width, height, format, av_ts2timestr(pts, &s->outputs[0]->time_base));\
#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, pts)\
if (c->w != width || c->h != height || c->pix_fmt != format ||\
c->color_space != csp || c->color_range != range) {\
av_log(s, AV_LOG_INFO, "filter context - w: %d h: %d fmt: %d csp: %s range: %s, incoming frame - w: %d h: %d fmt: %d csp: %s range: %s pts_time: %s\n",\
c->w, c->h, c->pix_fmt, av_color_space_name(c->color_space), av_color_range_name(c->color_range),\
width, height, format, av_color_space_name(csp), av_color_range_name(range),\
av_ts2timestr(pts, &s->outputs[0]->time_base));\
av_log(s, AV_LOG_WARNING, "Changing video frame properties on the fly is not supported by all filters.\n");\
}
@ -89,6 +95,8 @@ AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
return NULL;
par->format = -1;
par->color_range = AVCOL_RANGE_UNSPECIFIED;
par->color_space = AVCOL_SPC_UNSPECIFIED;
return par;
}
@ -119,6 +127,10 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par
if (!s->hw_frames_ctx)
return AVERROR(ENOMEM);
}
if (param->color_space != AVCOL_SPC_UNSPECIFIED)
s->color_space = param->color_space;
if (param->color_range != AVCOL_RANGE_UNSPECIFIED)
s->color_range = param->color_range;
break;
case AVMEDIA_TYPE_AUDIO:
if (param->format != AV_SAMPLE_FMT_NONE) {
@ -206,7 +218,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
switch (ctx->outputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
frame->format, frame->pts);
frame->format, frame->colorspace,
frame->color_range, frame->pts);
break;
case AVMEDIA_TYPE_AUDIO:
/* For layouts unknown on input but known on link after negotiation. */
@ -303,10 +316,11 @@ static av_cold int init_video(AVFilterContext *ctx)
return AVERROR(EINVAL);
}
av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d\n",
av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d csp:%s range:%s\n",
c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den,
c->pixel_aspect.num, c->pixel_aspect.den);
c->pixel_aspect.num, c->pixel_aspect.den,
av_color_space_name(c->color_space), av_color_range_name(c->color_range));
return 0;
}
@ -329,6 +343,30 @@ static const AVOption buffer_options[] = {
{ "pixel_aspect", "sample aspect ratio", OFFSET(pixel_aspect), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
{ "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
{ "frame_rate", NULL, OFFSET(frame_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
{ "colorspace", "select colorspace", OFFSET(color_space), AV_OPT_TYPE_INT, {.i64=AVCOL_SPC_UNSPECIFIED}, 0, AVCOL_SPC_NB-1, V, "colorspace"},
{ "gbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_RGB}, INT_MIN, INT_MAX, V, "colorspace"},
{ "bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, INT_MIN, INT_MAX, V, "colorspace"},
{ "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_UNSPECIFIED}, INT_MIN, INT_MAX, V, "colorspace"},
{ "fcc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_FCC}, INT_MIN, INT_MAX, V, "colorspace"},
{ "bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, INT_MIN, INT_MAX, V, "colorspace"},
{ "smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE170M}, INT_MIN, INT_MAX, V, "colorspace"},
{ "smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE240M}, INT_MIN, INT_MAX, V, "colorspace"},
{ "ycgco", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_YCGCO}, INT_MIN, INT_MAX, V, "colorspace"},
{ "bt2020nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, INT_MIN, INT_MAX, V, "colorspace"},
{ "bt2020c", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_CL}, INT_MIN, INT_MAX, V, "colorspace"},
{ "smpte2085", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE2085}, INT_MIN, INT_MAX, V, "colorspace"},
{ "chroma-derived-nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_CHROMA_DERIVED_NCL},INT_MIN, INT_MAX, V, "colorspace"},
{ "chroma-derived-c", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_CHROMA_DERIVED_CL}, INT_MIN, INT_MAX, V, "colorspace"},
{ "ictcp", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_ICTCP}, INT_MIN, INT_MAX, V, "colorspace"},
{ "range", "select color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, AVCOL_RANGE_NB-1, V, "range"},
{ "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, V, "range"},
{ "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, V, "range"},
{ "limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, V, "range"},
{ "tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, V, "range"},
{ "mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, V, "range"},
{ "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, "range"},
{ "pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, "range"},
{ "jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, "range"},
{ NULL },
};
@ -426,14 +464,35 @@ static int query_formats(AVFilterContext *ctx)
AVFilterChannelLayouts *channel_layouts = NULL;
AVFilterFormats *formats = NULL;
AVFilterFormats *samplerates = NULL;
AVFilterFormats *color_spaces = NULL;
AVFilterFormats *color_ranges = NULL;
int ret;
switch (ctx->outputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_VIDEO: {
enum AVPixelFormat swfmt = c->pix_fmt;
if (av_pix_fmt_desc_get(swfmt)->flags & AV_PIX_FMT_FLAG_HWACCEL) {
if (!c->hw_frames_ctx) {
av_log(ctx, AV_LOG_ERROR, "Setting BufferSourceContext.pix_fmt "
"to a HW format requires hw_frames_ctx to be non-NULL!\n");
return AVERROR(EINVAL);
}
swfmt = ((AVHWFramesContext *) c->hw_frames_ctx->data)->sw_format;
}
if ((ret = ff_add_format (&formats, c->pix_fmt)) < 0 ||
(ret = ff_set_common_formats (ctx , formats )) < 0)
return ret;
/* force specific colorspace/range downstream only for ordinary YUV */
if (ff_fmt_is_regular_yuv(swfmt)) {
if ((ret = ff_add_format(&color_spaces, c->color_space)) < 0 ||
(ret = ff_set_common_color_spaces(ctx, color_spaces)) < 0)
return ret;
if ((ret = ff_add_format(&color_ranges, c->color_range)) < 0 ||
(ret = ff_set_common_color_ranges(ctx, color_ranges)) < 0)
return ret;
}
break;
}
case AVMEDIA_TYPE_AUDIO:
if ((ret = ff_add_format (&formats , c->sample_fmt )) < 0 ||
(ret = ff_set_common_formats (ctx , formats )) < 0 ||

View File

@ -123,6 +123,12 @@ typedef struct AVBufferSrcParameters {
* Audio only, the audio channel layout
*/
AVChannelLayout ch_layout;
/**
* Video only, the YUV colorspace and range.
*/
enum AVColorSpace color_space;
enum AVColorRange color_range;
} AVBufferSrcParameters;
/**