|
|
@@ -33,6 +33,7 @@ |
|
|
#include "formats.h" |
|
|
#include "formats.h" |
|
|
#include "internal.h" |
|
|
#include "internal.h" |
|
|
#include "video.h" |
|
|
#include "video.h" |
|
|
|
|
|
#include "libavutil/opt.h" |
|
|
#include "libavutil/pixdesc.h" |
|
|
#include "libavutil/pixdesc.h" |
|
|
#include "libavutil/avstring.h" |
|
|
#include "libavutil/avstring.h" |
|
|
|
|
|
|
|
|
@@ -54,15 +55,39 @@ static const double yuv_coeff[4][3][3] = { |
|
|
{ -0.4450, -0.0550, +0.5000 } }, |
|
|
{ -0.4450, -0.0550, +0.5000 } }, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
enum ColorMode { |
|
|
|
|
|
COLOR_MODE_NONE = -1, |
|
|
|
|
|
COLOR_MODE_BT709, |
|
|
|
|
|
COLOR_MODE_FCC, |
|
|
|
|
|
COLOR_MODE_BT601, |
|
|
|
|
|
COLOR_MODE_SMPTE240M, |
|
|
|
|
|
COLOR_MODE_COUNT |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
typedef struct { |
|
|
typedef struct { |
|
|
|
|
|
const AVClass *class; |
|
|
int yuv_convert[16][3][3]; |
|
|
int yuv_convert[16][3][3]; |
|
|
int interlaced; |
|
|
int interlaced; |
|
|
int source, dest, mode; |
|
|
|
|
|
char src[256]; |
|
|
|
|
|
char dst[256]; |
|
|
|
|
|
|
|
|
enum ColorMode source, dest; |
|
|
|
|
|
int mode; |
|
|
int hsub, vsub; |
|
|
int hsub, vsub; |
|
|
} ColorMatrixContext; |
|
|
} ColorMatrixContext; |
|
|
|
|
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(ColorMatrixContext, x) |
|
|
|
|
|
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM |
|
|
|
|
|
|
|
|
|
|
|
static const AVOption colormatrix_options[] = { |
|
|
|
|
|
{ "src", "set source color matrix", OFFSET(source), AV_OPT_TYPE_INT, {.i64=COLOR_MODE_NONE}, COLOR_MODE_NONE, COLOR_MODE_COUNT-1, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ "dst", "set destination color matrix", OFFSET(dest), AV_OPT_TYPE_INT, {.i64=COLOR_MODE_NONE}, COLOR_MODE_NONE, COLOR_MODE_COUNT-1, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ "bt709", "set BT.709 colorspace", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_BT709}, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ "fcc", "set FCC colorspace ", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_FCC}, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ "bt601", "set BT.601 colorspace", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_BT601}, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ "smpte240m", "set SMPTE-240M colorspace", 0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_SMPTE240M}, .flags=FLAGS, .unit="color_mode" }, |
|
|
|
|
|
{ NULL } |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
AVFILTER_DEFINE_CLASS(colormatrix); |
|
|
|
|
|
|
|
|
#define ma m[0][0] |
|
|
#define ma m[0][0] |
|
|
#define mb m[0][1] |
|
|
#define mb m[0][1] |
|
|
#define mc m[0][2] |
|
|
#define mc m[0][2] |
|
|
@@ -133,40 +158,14 @@ static void calc_coefficients(AVFilterContext *ctx) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static const char *color_modes[] = {"bt709", "FCC", "bt601", "smpte240m"}; |
|
|
|
|
|
|
|
|
|
|
|
static int get_color_mode_index(const char *name) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(color_modes); i++) |
|
|
|
|
|
if (!av_strcasecmp(color_modes[i], name)) |
|
|
|
|
|
return i; |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
static const char *color_modes[] = {"bt709", "fcc", "bt601", "smpte240m"}; |
|
|
|
|
|
|
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
static av_cold int init(AVFilterContext *ctx, const char *args) |
|
|
{ |
|
|
{ |
|
|
ColorMatrixContext *color = ctx->priv; |
|
|
ColorMatrixContext *color = ctx->priv; |
|
|
|
|
|
|
|
|
if (!args) |
|
|
|
|
|
goto usage; |
|
|
|
|
|
if (sscanf(args, "%255[^:]:%255[^:]", color->src, color->dst) != 2) { |
|
|
|
|
|
usage: |
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "usage: <src>:<dst>\n"); |
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "possible options: bt709,bt601,smpte240m,fcc\n"); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
color->source = get_color_mode_index(color->src); |
|
|
|
|
|
if (color->source < 0) { |
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "unknown color space %s\n", color->src); |
|
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
color->dest = get_color_mode_index(color->dst); |
|
|
|
|
|
if (color->dest < 0) { |
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "unknown color space %s\n", color->dst); |
|
|
|
|
|
|
|
|
if (color->source == COLOR_MODE_NONE || color->dest == COLOR_MODE_NONE) { |
|
|
|
|
|
av_log(ctx, AV_LOG_ERROR, "Unspecified source or destination color space\n"); |
|
|
return AVERROR(EINVAL); |
|
|
return AVERROR(EINVAL); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -313,7 +312,8 @@ static int config_input(AVFilterLink *inlink) |
|
|
color->hsub = pix_desc->log2_chroma_w; |
|
|
color->hsub = pix_desc->log2_chroma_w; |
|
|
color->vsub = pix_desc->log2_chroma_h; |
|
|
color->vsub = pix_desc->log2_chroma_h; |
|
|
|
|
|
|
|
|
av_log(ctx, AV_LOG_VERBOSE, "%s -> %s\n", color->src, color->dst); |
|
|
|
|
|
|
|
|
av_log(ctx, AV_LOG_VERBOSE, "%s -> %s\n", |
|
|
|
|
|
color_modes[color->source], color_modes[color->dest]); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
@@ -375,13 +375,17 @@ static const AVFilterPad colormatrix_outputs[] = { |
|
|
{ NULL } |
|
|
{ NULL } |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static const char *const shorthand[] = { "src", "dst", NULL }; |
|
|
|
|
|
|
|
|
AVFilter avfilter_vf_colormatrix = { |
|
|
AVFilter avfilter_vf_colormatrix = { |
|
|
.name = "colormatrix", |
|
|
.name = "colormatrix", |
|
|
.description = NULL_IF_CONFIG_SMALL("Color matrix conversion"), |
|
|
|
|
|
|
|
|
.description = NULL_IF_CONFIG_SMALL("Convert color matrix."), |
|
|
|
|
|
|
|
|
.priv_size = sizeof(ColorMatrixContext), |
|
|
.priv_size = sizeof(ColorMatrixContext), |
|
|
.init = init, |
|
|
.init = init, |
|
|
.query_formats = query_formats, |
|
|
.query_formats = query_formats, |
|
|
.inputs = colormatrix_inputs, |
|
|
.inputs = colormatrix_inputs, |
|
|
.outputs = colormatrix_outputs, |
|
|
.outputs = colormatrix_outputs, |
|
|
|
|
|
.priv_class = &colormatrix_class, |
|
|
|
|
|
.shorthand = shorthand, |
|
|
}; |
|
|
}; |