|
|
|
@ -47,7 +47,6 @@ |
|
|
|
|
typedef struct { |
|
|
|
|
int strength; |
|
|
|
|
unsigned flags; |
|
|
|
|
int shiftptr; |
|
|
|
|
AVLFG lfg; |
|
|
|
|
int seed; |
|
|
|
|
int8_t *noise; |
|
|
|
@ -67,6 +66,10 @@ typedef struct { |
|
|
|
|
void (*line_noise_avg)(uint8_t *dst, const uint8_t *src, int len, int8_t **shift); |
|
|
|
|
} NoiseContext; |
|
|
|
|
|
|
|
|
|
typedef struct ThreadData { |
|
|
|
|
AVFrame *in, *out; |
|
|
|
|
} ThreadData; |
|
|
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(NoiseContext, x) |
|
|
|
|
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM |
|
|
|
|
|
|
|
|
@ -161,7 +164,6 @@ static int init_noise(NoiseContext *n, int comp) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fp->noise = noise; |
|
|
|
|
fp->shiftptr = 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -330,46 +332,62 @@ static inline void line_noise_avg_mmx(uint8_t *dst, const uint8_t *src, |
|
|
|
|
|
|
|
|
|
static void noise(uint8_t *dst, const uint8_t *src, |
|
|
|
|
int dst_linesize, int src_linesize, |
|
|
|
|
int width, int height, NoiseContext *n, int comp) |
|
|
|
|
int width, int start, int end, NoiseContext *n, int comp) |
|
|
|
|
{ |
|
|
|
|
int8_t *noise = n->param[comp].noise; |
|
|
|
|
int flags = n->param[comp].flags; |
|
|
|
|
AVLFG *lfg = &n->param[comp].lfg; |
|
|
|
|
FilterParams *p = &n->param[comp]; |
|
|
|
|
int8_t *noise = p->noise; |
|
|
|
|
const int flags = p->flags; |
|
|
|
|
AVLFG *lfg = &p->lfg; |
|
|
|
|
int shift, y; |
|
|
|
|
|
|
|
|
|
if (!noise) { |
|
|
|
|
if (dst != src) |
|
|
|
|
av_image_copy_plane(dst, dst_linesize, src, src_linesize, width, height); |
|
|
|
|
av_image_copy_plane(dst, dst_linesize, src, src_linesize, width, end - start); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) { |
|
|
|
|
for (y = start; y < end; y++) { |
|
|
|
|
if (flags & NOISE_TEMPORAL) |
|
|
|
|
shift = av_lfg_get(lfg) & (MAX_SHIFT - 1); |
|
|
|
|
else |
|
|
|
|
shift = n->rand_shift[y]; |
|
|
|
|
|
|
|
|
|
if (flags & NOISE_AVERAGED) { |
|
|
|
|
n->line_noise_avg(dst, src, width, n->param[comp].prev_shift[y]); |
|
|
|
|
n->param[comp].prev_shift[y][n->param[comp].shiftptr] = noise + shift; |
|
|
|
|
n->line_noise_avg(dst, src, width, p->prev_shift[y]); |
|
|
|
|
p->prev_shift[y][shift & 3] = noise + shift; |
|
|
|
|
} else { |
|
|
|
|
n->line_noise(dst, src, noise, width, shift); |
|
|
|
|
} |
|
|
|
|
dst += dst_linesize; |
|
|
|
|
src += src_linesize; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
n->param[comp].shiftptr++; |
|
|
|
|
if (n->param[comp].shiftptr == 3) |
|
|
|
|
n->param[comp].shiftptr = 0; |
|
|
|
|
static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
|
|
|
|
{ |
|
|
|
|
NoiseContext *s = ctx->priv; |
|
|
|
|
ThreadData *td = arg; |
|
|
|
|
int plane; |
|
|
|
|
|
|
|
|
|
for (plane = 0; plane < s->nb_planes; plane++) { |
|
|
|
|
const int height = s->height[plane]; |
|
|
|
|
const int start = (height * jobnr ) / nb_jobs; |
|
|
|
|
const int end = (height * (jobnr+1)) / nb_jobs; |
|
|
|
|
noise(td->out->data[plane] + start * td->out->linesize[plane], |
|
|
|
|
td->in->data[plane] + start * td->in->linesize[plane], |
|
|
|
|
td->out->linesize[plane], td->in->linesize[plane], |
|
|
|
|
s->linesize[plane], start, end, s, plane); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) |
|
|
|
|
{ |
|
|
|
|
NoiseContext *n = inlink->dst->priv; |
|
|
|
|
AVFilterLink *outlink = inlink->dst->outputs[0]; |
|
|
|
|
AVFilterContext *ctx = inlink->dst; |
|
|
|
|
AVFilterLink *outlink = ctx->outputs[0]; |
|
|
|
|
NoiseContext *n = ctx->priv; |
|
|
|
|
ThreadData td; |
|
|
|
|
AVFrame *out; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (av_frame_is_writable(inpicref)) { |
|
|
|
|
out = inpicref; |
|
|
|
@ -382,9 +400,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) |
|
|
|
|
av_frame_copy_props(out, inpicref); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < n->nb_planes; i++) |
|
|
|
|
noise(out->data[i], inpicref->data[i], out->linesize[i], |
|
|
|
|
inpicref->linesize[i], n->linesize[i], n->height[i], n, i); |
|
|
|
|
td.in = inpicref; td.out = out; |
|
|
|
|
ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(n->height[0], ctx->graph->nb_threads)); |
|
|
|
|
emms_c(); |
|
|
|
|
|
|
|
|
|
if (inpicref != out) |
|
|
|
@ -463,5 +480,5 @@ AVFilter avfilter_vf_noise = { |
|
|
|
|
.inputs = noise_inputs, |
|
|
|
|
.outputs = noise_outputs, |
|
|
|
|
.priv_class = &noise_class, |
|
|
|
|
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, |
|
|
|
|
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, |
|
|
|
|
}; |
|
|
|
|