Commit d6e50e07 authored by Paul B Mahol's avatar Paul B Mahol

avfilter/vf_curves: add planar rgb support

parent bb660800
......@@ -70,6 +70,9 @@ typedef struct CurvesContext {
int step;
char *plot_filename;
int is_16bit;
int depth;
int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
} CurvesContext;
typedef struct ThreadData {
......@@ -209,7 +212,7 @@ static int get_nb_points(const struct keypoint *d)
* @see http://people.math.sfu.ca/~stockie/teaching/macm316/notes/splines.pdf
*/
#define CLIP(v) (nbits == 8 ? av_clip_uint8(v) : av_clip_uint16(v))
#define CLIP(v) (nbits == 8 ? av_clip_uint8(v) : av_clip_uintp2_c(v, nbits))
static inline int interpolate(void *log_ctx, uint16_t *y,
const struct keypoint *points, int nbits)
......@@ -341,6 +344,10 @@ static int interpolate##nbits(void *log_ctx, uint16_t *y, \
}
DECLARE_INTERPOLATE_FUNC(8)
DECLARE_INTERPOLATE_FUNC(9)
DECLARE_INTERPOLATE_FUNC(10)
DECLARE_INTERPOLATE_FUNC(12)
DECLARE_INTERPOLATE_FUNC(14)
DECLARE_INTERPOLATE_FUNC(16)
static int parse_psfile(AVFilterContext *ctx, const char *fname)
......@@ -512,6 +519,12 @@ static int query_formats(AVFilterContext *ctx)
AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48,
AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
AV_PIX_FMT_GBRP9,
AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
AV_PIX_FMT_GBRP14,
AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
AV_PIX_FMT_NONE
};
AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
......@@ -520,6 +533,120 @@ static int query_formats(AVFilterContext *ctx)
return ff_set_common_formats(ctx, fmts_list);
}
static int filter_slice_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
int x, y;
const CurvesContext *curves = ctx->priv;
const ThreadData *td = arg;
const AVFrame *in = td->in;
const AVFrame *out = td->out;
const int direct = out == in;
const int step = curves->step;
const uint8_t r = curves->rgba_map[R];
const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A];
const int slice_start = (in->height * jobnr ) / nb_jobs;
const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
if (curves->is_16bit) {
for (y = slice_start; y < slice_end; y++) {
uint16_t *dstp = ( uint16_t *)(out->data[0] + y * out->linesize[0]);
const uint16_t *srcp = (const uint16_t *)(in ->data[0] + y * in->linesize[0]);
for (x = 0; x < in->width * step; x += step) {
dstp[x + r] = curves->graph[R][srcp[x + r]];
dstp[x + g] = curves->graph[G][srcp[x + g]];
dstp[x + b] = curves->graph[B][srcp[x + b]];
if (!direct && step == 4)
dstp[x + a] = srcp[x + a];
}
}
} else {
uint8_t *dst = out->data[0] + slice_start * out->linesize[0];
const uint8_t *src = in->data[0] + slice_start * in->linesize[0];
for (y = slice_start; y < slice_end; y++) {
for (x = 0; x < in->width * step; x += step) {
dst[x + r] = curves->graph[R][src[x + r]];
dst[x + g] = curves->graph[G][src[x + g]];
dst[x + b] = curves->graph[B][src[x + b]];
if (!direct && step == 4)
dst[x + a] = src[x + a];
}
dst += out->linesize[0];
src += in ->linesize[0];
}
}
return 0;
}
static int filter_slice_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
int x, y;
const CurvesContext *curves = ctx->priv;
const ThreadData *td = arg;
const AVFrame *in = td->in;
const AVFrame *out = td->out;
const int direct = out == in;
const int step = curves->step;
const uint8_t r = curves->rgba_map[R];
const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A];
const int slice_start = (in->height * jobnr ) / nb_jobs;
const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
if (curves->is_16bit) {
for (y = slice_start; y < slice_end; y++) {
uint16_t *dstrp = ( uint16_t *)(out->data[r] + y * out->linesize[r]);
uint16_t *dstgp = ( uint16_t *)(out->data[g] + y * out->linesize[g]);
uint16_t *dstbp = ( uint16_t *)(out->data[b] + y * out->linesize[b]);
uint16_t *dstap = ( uint16_t *)(out->data[a] + y * out->linesize[a]);
const uint16_t *srcrp = (const uint16_t *)(in ->data[r] + y * in->linesize[r]);
const uint16_t *srcgp = (const uint16_t *)(in ->data[g] + y * in->linesize[g]);
const uint16_t *srcbp = (const uint16_t *)(in ->data[b] + y * in->linesize[b]);
const uint16_t *srcap = (const uint16_t *)(in ->data[a] + y * in->linesize[a]);
for (x = 0; x < in->width; x++) {
dstrp[x] = curves->graph[R][srcrp[x]];
dstgp[x] = curves->graph[G][srcgp[x]];
dstbp[x] = curves->graph[B][srcbp[x]];
if (!direct && step == 4)
dstap[x] = srcap[x];
}
}
} else {
uint8_t *dstr = out->data[r] + slice_start * out->linesize[r];
uint8_t *dstg = out->data[g] + slice_start * out->linesize[g];
uint8_t *dstb = out->data[b] + slice_start * out->linesize[b];
uint8_t *dsta = out->data[a] + slice_start * out->linesize[a];
const uint8_t *srcr = in->data[r] + slice_start * in->linesize[r];
const uint8_t *srcg = in->data[g] + slice_start * in->linesize[g];
const uint8_t *srcb = in->data[b] + slice_start * in->linesize[b];
const uint8_t *srca = in->data[a] + slice_start * in->linesize[a];
for (y = slice_start; y < slice_end; y++) {
for (x = 0; x < in->width; x++) {
dstr[x] = curves->graph[R][srcr[x]];
dstg[x] = curves->graph[G][srcg[x]];
dstb[x] = curves->graph[B][srcb[x]];
if (!direct && step == 4)
dsta[x] = srca[x];
}
dstr += out->linesize[r];
dstg += out->linesize[g];
dstb += out->linesize[b];
dsta += out->linesize[a];
srcr += in ->linesize[r];
srcg += in ->linesize[g];
srcb += in ->linesize[b];
srca += in ->linesize[a];
}
}
return 0;
}
static int config_input(AVFilterLink *inlink)
{
int i, j, ret;
......@@ -531,8 +658,10 @@ static int config_input(AVFilterLink *inlink)
ff_fill_rgba_map(curves->rgba_map, inlink->format);
curves->is_16bit = desc->comp[0].depth > 8;
curves->lut_size = curves->is_16bit ? 1<<16 : 1<<8;
curves->depth = desc->comp[0].depth;
curves->lut_size = 1 << curves->depth;
curves->step = av_get_padded_bits_per_pixel(desc) >> (3 + curves->is_16bit);
curves->filter_slice = desc->flags & AV_PIX_FMT_FLAG_PLANAR ? filter_slice_planar : filter_slice_packed;
for (i = 0; i < NB_COMP + 1; i++) {
curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0]));
......@@ -541,8 +670,14 @@ static int config_input(AVFilterLink *inlink)
ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i], curves->lut_size);
if (ret < 0)
return ret;
if (curves->is_16bit) ret = interpolate16(ctx, curves->graph[i], comp_points[i]);
else ret = interpolate8(ctx, curves->graph[i], comp_points[i]);
switch (curves->depth) {
case 8: ret = interpolate8 (ctx, curves->graph[i], comp_points[i]); break;
case 9: ret = interpolate9 (ctx, curves->graph[i], comp_points[i]); break;
case 10: ret = interpolate10(ctx, curves->graph[i], comp_points[i]); break;
case 12: ret = interpolate12(ctx, curves->graph[i], comp_points[i]); break;
case 14: ret = interpolate14(ctx, curves->graph[i], comp_points[i]); break;
case 16: ret = interpolate16(ctx, curves->graph[i], comp_points[i]); break;
}
if (ret < 0)
return ret;
}
......@@ -579,57 +714,10 @@ static int config_input(AVFilterLink *inlink)
return 0;
}
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
{
int x, y;
const CurvesContext *curves = ctx->priv;
const ThreadData *td = arg;
const AVFrame *in = td->in;
const AVFrame *out = td->out;
const int direct = out == in;
const int step = curves->step;
const uint8_t r = curves->rgba_map[R];
const uint8_t g = curves->rgba_map[G];
const uint8_t b = curves->rgba_map[B];
const uint8_t a = curves->rgba_map[A];
const int slice_start = (in->height * jobnr ) / nb_jobs;
const int slice_end = (in->height * (jobnr+1)) / nb_jobs;
if (curves->is_16bit) {
for (y = slice_start; y < slice_end; y++) {
uint16_t *dstp = ( uint16_t *)(out->data[0] + y * out->linesize[0]);
const uint16_t *srcp = (const uint16_t *)(in ->data[0] + y * in->linesize[0]);
for (x = 0; x < in->width * step; x += step) {
dstp[x + r] = curves->graph[R][srcp[x + r]];
dstp[x + g] = curves->graph[G][srcp[x + g]];
dstp[x + b] = curves->graph[B][srcp[x + b]];
if (!direct && step == 4)
dstp[x + a] = srcp[x + a];
}
}
} else {
uint8_t *dst = out->data[0] + slice_start * out->linesize[0];
const uint8_t *src = in->data[0] + slice_start * in->linesize[0];
for (y = slice_start; y < slice_end; y++) {
for (x = 0; x < in->width * step; x += step) {
dst[x + r] = curves->graph[R][src[x + r]];
dst[x + g] = curves->graph[G][src[x + g]];
dst[x + b] = curves->graph[B][src[x + b]];
if (!direct && step == 4)
dst[x + a] = src[x + a];
}
dst += out->linesize[0];
src += in ->linesize[0];
}
}
return 0;
}
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{
AVFilterContext *ctx = inlink->dst;
CurvesContext *curves = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
AVFrame *out;
ThreadData td;
......@@ -647,7 +735,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
td.in = in;
td.out = out;
ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
ctx->internal->execute(ctx, curves->filter_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx)));
if (out != in)
av_frame_free(&in);
......
......@@ -3,8 +3,8 @@
#codec_id 0: rawvideo
#dimensions 0: 640x480
#sar 0: 0/1
0, 0, 0, 1, 921600, 0xcf426780
0, 1, 1, 1, 921600, 0x7642892d
0, 2, 2, 1, 921600, 0x13c1ab7e
0, 3, 3, 1, 921600, 0x3eca04bf
0, 4, 4, 1, 921600, 0x61539162
0, 0, 0, 1, 921600, 0x3ed36780
0, 1, 1, 1, 921600, 0x7dbd892d
0, 2, 2, 1, 921600, 0x0894ab7e
0, 3, 3, 1, 921600, 0x471004bf
0, 4, 4, 1, 921600, 0x79c79162
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment