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:
@@ -28092,6 +28092,16 @@ Specify the timebase assumed by the timestamps of the buffered frames.
|
|||||||
@item frame_rate
|
@item frame_rate
|
||||||
Specify the frame rate expected for the video stream.
|
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
|
@item pixel_aspect, sar
|
||||||
The sample (pixel) aspect ratio of the input video.
|
The sample (pixel) aspect ratio of the input video.
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "libavutil/channel_layout.h"
|
#include "libavutil/channel_layout.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
#include "libavutil/frame.h"
|
#include "libavutil/frame.h"
|
||||||
|
#include "libavutil/hwcontext.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
@@ -50,6 +51,8 @@ typedef struct BufferSourceContext {
|
|||||||
/* video only */
|
/* video only */
|
||||||
int w, h;
|
int w, h;
|
||||||
enum AVPixelFormat pix_fmt;
|
enum AVPixelFormat pix_fmt;
|
||||||
|
enum AVColorSpace color_space;
|
||||||
|
enum AVColorRange color_range;
|
||||||
AVRational pixel_aspect;
|
AVRational pixel_aspect;
|
||||||
|
|
||||||
AVBufferRef *hw_frames_ctx;
|
AVBufferRef *hw_frames_ctx;
|
||||||
@@ -65,10 +68,13 @@ typedef struct BufferSourceContext {
|
|||||||
int64_t last_pts;
|
int64_t last_pts;
|
||||||
} BufferSourceContext;
|
} BufferSourceContext;
|
||||||
|
|
||||||
#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, pts)\
|
#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, pts)\
|
||||||
if (c->w != width || c->h != height || c->pix_fmt != format) {\
|
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->color_space != csp || c->color_range != range) {\
|
||||||
c->w, c->h, c->pix_fmt, width, height, format, av_ts2timestr(pts, &s->outputs[0]->time_base));\
|
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");\
|
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;
|
return NULL;
|
||||||
|
|
||||||
par->format = -1;
|
par->format = -1;
|
||||||
|
par->color_range = AVCOL_RANGE_UNSPECIFIED;
|
||||||
|
par->color_space = AVCOL_SPC_UNSPECIFIED;
|
||||||
|
|
||||||
return par;
|
return par;
|
||||||
}
|
}
|
||||||
@@ -119,6 +127,10 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par
|
|||||||
if (!s->hw_frames_ctx)
|
if (!s->hw_frames_ctx)
|
||||||
return AVERROR(ENOMEM);
|
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;
|
break;
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
if (param->format != AV_SAMPLE_FMT_NONE) {
|
if (param->format != AV_SAMPLE_FMT_NONE) {
|
||||||
@@ -206,7 +218,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
|||||||
switch (ctx->outputs[0]->type) {
|
switch (ctx->outputs[0]->type) {
|
||||||
case AVMEDIA_TYPE_VIDEO:
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
|
CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
|
||||||
frame->format, frame->pts);
|
frame->format, frame->colorspace,
|
||||||
|
frame->color_range, frame->pts);
|
||||||
break;
|
break;
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
/* For layouts unknown on input but known on link after negotiation. */
|
/* 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);
|
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->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->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;
|
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 },
|
{ "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 },
|
{ "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 },
|
{ "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 },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -426,14 +464,35 @@ static int query_formats(AVFilterContext *ctx)
|
|||||||
AVFilterChannelLayouts *channel_layouts = NULL;
|
AVFilterChannelLayouts *channel_layouts = NULL;
|
||||||
AVFilterFormats *formats = NULL;
|
AVFilterFormats *formats = NULL;
|
||||||
AVFilterFormats *samplerates = NULL;
|
AVFilterFormats *samplerates = NULL;
|
||||||
|
AVFilterFormats *color_spaces = NULL;
|
||||||
|
AVFilterFormats *color_ranges = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (ctx->outputs[0]->type) {
|
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 ||
|
if ((ret = ff_add_format (&formats, c->pix_fmt)) < 0 ||
|
||||||
(ret = ff_set_common_formats (ctx , formats )) < 0)
|
(ret = ff_set_common_formats (ctx , formats )) < 0)
|
||||||
return ret;
|
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;
|
break;
|
||||||
|
}
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
if ((ret = ff_add_format (&formats , c->sample_fmt )) < 0 ||
|
if ((ret = ff_add_format (&formats , c->sample_fmt )) < 0 ||
|
||||||
(ret = ff_set_common_formats (ctx , formats )) < 0 ||
|
(ret = ff_set_common_formats (ctx , formats )) < 0 ||
|
||||||
|
@@ -123,6 +123,12 @@ typedef struct AVBufferSrcParameters {
|
|||||||
* Audio only, the audio channel layout
|
* Audio only, the audio channel layout
|
||||||
*/
|
*/
|
||||||
AVChannelLayout ch_layout;
|
AVChannelLayout ch_layout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Video only, the YUV colorspace and range.
|
||||||
|
*/
|
||||||
|
enum AVColorSpace color_space;
|
||||||
|
enum AVColorRange color_range;
|
||||||
} AVBufferSrcParameters;
|
} AVBufferSrcParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user