summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c')
-rw-r--r--chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c135
1 files changed, 77 insertions, 58 deletions
diff --git a/chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c b/chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c
index 79566be8ce6..7c3a7dac152 100644
--- a/chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c
+++ b/chromium/third_party/ffmpeg/libavfilter/vf_lut3d.c
@@ -62,9 +62,7 @@ typedef struct LUT3DContext {
char *file;
uint8_t rgba_map[4];
int step;
- int is16bit;
- struct rgbvec (*interp_8) (const struct LUT3DContext*, uint8_t, uint8_t, uint8_t);
- struct rgbvec (*interp_16)(const struct LUT3DContext*, uint16_t, uint16_t, uint16_t);
+ avfilter_action_func *interp;
struct rgbvec lut[MAX_LEVEL][MAX_LEVEL][MAX_LEVEL];
int lutsize;
#if CONFIG_HALDCLUT_FILTER
@@ -76,6 +74,10 @@ typedef struct LUT3DContext {
#endif
} LUT3DContext;
+typedef struct ThreadData {
+ AVFrame *in, *out;
+} ThreadData;
+
#define OFFSET(x) offsetof(LUT3DContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
#define COMMON_OPTIONS \
@@ -196,15 +198,44 @@ static inline struct rgbvec interp_tetrahedral(const LUT3DContext *lut3d,
return c;
}
-#define DEFINE_INTERP_FUNC(name, nbits) \
-static struct rgbvec interp_##nbits##_##name(const LUT3DContext *lut3d, \
- uint##nbits##_t r, \
- uint##nbits##_t g, \
- uint##nbits##_t b) \
-{ \
- const float scale = (1. / ((1<<nbits) - 1)) * (lut3d->lutsize - 1); \
- const struct rgbvec scaled_rgb = {r * scale, g * scale, b * scale}; \
- return interp_##name(lut3d, &scaled_rgb); \
+#define DEFINE_INTERP_FUNC(name, nbits) \
+static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
+{ \
+ int x, y; \
+ const LUT3DContext *lut3d = ctx->priv; \
+ const ThreadData *td = arg; \
+ const AVFrame *in = td->in; \
+ const AVFrame *out = td->out; \
+ const int direct = out == in; \
+ const int step = lut3d->step; \
+ const uint8_t r = lut3d->rgba_map[R]; \
+ const uint8_t g = lut3d->rgba_map[G]; \
+ const uint8_t b = lut3d->rgba_map[B]; \
+ const uint8_t a = lut3d->rgba_map[A]; \
+ const int slice_start = (in->height * jobnr ) / nb_jobs; \
+ const int slice_end = (in->height * (jobnr+1)) / nb_jobs; \
+ uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; \
+ const uint8_t *srcrow = in ->data[0] + slice_start * in ->linesize[0]; \
+ const float scale = (1. / ((1<<nbits) - 1)) * (lut3d->lutsize - 1); \
+ \
+ for (y = slice_start; y < slice_end; y++) { \
+ uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
+ const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
+ for (x = 0; x < in->width * step; x += step) { \
+ const struct rgbvec scaled_rgb = {src[x + r] * scale, \
+ src[x + g] * scale, \
+ src[x + b] * scale}; \
+ struct rgbvec vec = interp_##name(lut3d, &scaled_rgb); \
+ dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
+ dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
+ dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
+ if (!direct && step == 4) \
+ dst[x + a] = src[x + a]; \
+ } \
+ dstrow += out->linesize[0]; \
+ srcrow += in ->linesize[0]; \
+ } \
+ return 0; \
}
DEFINE_INTERP_FUNC(nearest, 8)
@@ -231,21 +262,34 @@ static int skip_line(const char *p)
} \
} while (loop_cond)
-/* Basically r g and b float values on each line; seems to be generated by
- * Davinci */
+/* Basically r g and b float values on each line, with a facultative 3DLUTSIZE
+ * directive; seems to be generated by Davinci */
static int parse_dat(AVFilterContext *ctx, FILE *f)
{
LUT3DContext *lut3d = ctx->priv;
- const int size = lut3d->lutsize;
- int i, j, k;
+ char line[MAX_LINE_SIZE];
+ int i, j, k, size;
+
+ lut3d->lutsize = size = 33;
+ NEXT_LINE(skip_line(line));
+ if (!strncmp(line, "3DLUTSIZE ", 10)) {
+ size = strtol(line + 10, NULL, 0);
+ if (size < 2 || size > MAX_LEVEL) {
+ av_log(ctx, AV_LOG_ERROR, "Too large or invalid 3D LUT size\n");
+ return AVERROR(EINVAL);
+ }
+ lut3d->lutsize = size;
+ NEXT_LINE(skip_line(line));
+ }
for (k = 0; k < size; k++) {
for (j = 0; j < size; j++) {
for (i = 0; i < size; i++) {
- char line[MAX_LINE_SIZE];
struct rgbvec *vec = &lut3d->lut[k][j][i];
- NEXT_LINE(skip_line(line));
- sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b);
+ if (k != 0 || j != 0 || i != 0)
+ NEXT_LINE(skip_line(line));
+ if (sscanf(line, "%f %f %f", &vec->r, &vec->g, &vec->b) != 3)
+ return AVERROR_INVALIDDATA;
}
}
}
@@ -273,7 +317,7 @@ static int parse_cube(AVFilterContext *ctx, FILE *f)
for (k = 0; k < size; k++) {
for (j = 0; j < size; j++) {
for (i = 0; i < size; i++) {
- struct rgbvec *vec = &lut3d->lut[k][j][i];
+ struct rgbvec *vec = &lut3d->lut[i][j][k];
do {
NEXT_LINE(0);
@@ -433,6 +477,7 @@ static int query_formats(AVFilterContext *ctx)
static int config_input(AVFilterLink *inlink)
{
+ int is16bit = 0;
LUT3DContext *lut3d = inlink->dst->priv;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
@@ -441,15 +486,15 @@ static int config_input(AVFilterLink *inlink)
case AV_PIX_FMT_BGR48:
case AV_PIX_FMT_RGBA64:
case AV_PIX_FMT_BGRA64:
- lut3d->is16bit = 1;
+ is16bit = 1;
}
ff_fill_rgba_map(lut3d->rgba_map, inlink->format);
- lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + lut3d->is16bit);
+ lut3d->step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
-#define SET_FUNC(name) do { \
- if (lut3d->is16bit) lut3d->interp_16 = interp_16_##name; \
- else lut3d->interp_8 = interp_8_##name; \
+#define SET_FUNC(name) do { \
+ if (is16bit) lut3d->interp = interp_16_##name; \
+ else lut3d->interp = interp_8_##name; \
} while (0)
switch (lut3d->interpolation) {
@@ -463,41 +508,15 @@ static int config_input(AVFilterLink *inlink)
return 0;
}
-#define FILTER(nbits) do { \
- uint8_t *dstrow = out->data[0]; \
- const uint8_t *srcrow = in ->data[0]; \
- \
- for (y = 0; y < inlink->h; y++) { \
- uint##nbits##_t *dst = (uint##nbits##_t *)dstrow; \
- const uint##nbits##_t *src = (const uint##nbits##_t *)srcrow; \
- for (x = 0; x < inlink->w * step; x += step) { \
- struct rgbvec vec = lut3d->interp_##nbits(lut3d, src[x + r], src[x + g], src[x + b]); \
- dst[x + r] = av_clip_uint##nbits(vec.r * (float)((1<<nbits) - 1)); \
- dst[x + g] = av_clip_uint##nbits(vec.g * (float)((1<<nbits) - 1)); \
- dst[x + b] = av_clip_uint##nbits(vec.b * (float)((1<<nbits) - 1)); \
- if (!direct && step == 4) \
- dst[x + a] = src[x + a]; \
- } \
- dstrow += out->linesize[0]; \
- srcrow += in ->linesize[0]; \
- } \
-} while (0)
-
static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
{
- int x, y, direct = 0;
AVFilterContext *ctx = inlink->dst;
LUT3DContext *lut3d = ctx->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
AVFrame *out;
- const int step = lut3d->step;
- const uint8_t r = lut3d->rgba_map[R];
- const uint8_t g = lut3d->rgba_map[G];
- const uint8_t b = lut3d->rgba_map[B];
- const uint8_t a = lut3d->rgba_map[A];
+ ThreadData td;
if (av_frame_is_writable(in)) {
- direct = 1;
out = in;
} else {
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
@@ -508,10 +527,11 @@ static AVFrame *apply_lut(AVFilterLink *inlink, AVFrame *in)
av_frame_copy_props(out, in);
}
- if (lut3d->is16bit) FILTER(16);
- else FILTER(8);
+ td.in = in;
+ td.out = out;
+ ctx->internal->execute(ctx, lut3d->interp, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads));
- if (!direct)
+ if (out != in)
av_frame_free(&in);
return out;
@@ -562,7 +582,6 @@ static av_cold int lut3d_init(AVFilterContext *ctx)
ext++;
if (!av_strcasecmp(ext, "dat")) {
- lut3d->lutsize = 33;
ret = parse_dat(ctx, f);
} else if (!av_strcasecmp(ext, "3dl")) {
ret = parse_3dl(ctx, f);
@@ -612,7 +631,7 @@ AVFilter ff_vf_lut3d = {
.inputs = lut3d_inputs,
.outputs = lut3d_outputs,
.priv_class = &lut3d_class,
- .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
};
#endif
@@ -791,6 +810,6 @@ AVFilter ff_vf_haldclut = {
.inputs = haldclut_inputs,
.outputs = haldclut_outputs,
.priv_class = &haldclut_class,
- .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
};
#endif