static int vibrance_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) { VibranceContext *s = avctx->priv; AVFrame *frame = arg; const int depth = s->depth; const float max = (1 << depth) - 1; const float scale = 1.f / max; const float gc = s->lcoeffs[0]; const float bc = s->lcoeffs[1]; const float rc = s->lcoeffs[2]; const int width = frame->width; const int height = frame->height; const float intensity = s->intensity; const float alternate = s->alternate ? 1.f : -1.f; const float gintensity = intensity * s->balance[0]; const float bintensity = intensity * s->balance[1]; const float rintensity = intensity * s->balance[2]; const float sgintensity = alternate * FFSIGN(gintensity); const float sbintensity = alternate * FFSIGN(bintensity); const float srintensity = alternate * FFSIGN(rintensity); const int slice_start = (height * jobnr) / nb_jobs; const int slice_end = (height * (jobnr + 1)) / nb_jobs; const int glinesize = frame->linesize[0] / 2; const int blinesize = frame->linesize[1] / 2; const int rlinesize = frame->linesize[2] / 2; uint16_t *gptr = (uint16_t *)frame->data[0] + slice_start * glinesize; uint16_t *bptr = (uint16_t *)frame->data[1] + slice_start * blinesize; uint16_t *rptr = (uint16_t *)frame->data[2] + slice_start * rlinesize; for (int y = slice_start; y < slice_end; y++) { for (int x = 0; x < width; x++) { float g = gptr[x] * scale; float b = bptr[x] * scale; float r = rptr[x] * scale; float max_color = FFMAX3(r, g, b); float min_color = FFMIN3(r, g, b); float color_saturation = max_color - min_color; float luma = g * gc + r * rc + b * bc; const float cg = 1.f + gintensity * (1.f - sgintensity * color_saturation); const float cb = 1.f + bintensity * (1.f - sbintensity * color_saturation); const float cr = 1.f + rintensity * (1.f - srintensity * color_saturation); g = lerpf(luma, g, cg); b = lerpf(luma, b, cb); r = lerpf(luma, r, cr); gptr[x] = av_clip_uintp2_c(g * max, depth); bptr[x] = av_clip_uintp2_c(b * max, depth); rptr[x] = av_clip_uintp2_c(r * max, depth); } gptr += glinesize; bptr += blinesize; rptr += rlinesize; } return 0; }
static inline void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, uint8_t clip) { int16_t tmp; int i; for (i = 0; i < len; i++) { if (i == 0) { tmp = (11*low[0*low_stride] - 4*low[1*low_stride] + low[2*low_stride] + 4) >> 3; output[(2*i+0)*out_stride] = (tmp + high[0*high_stride]) >> 1; if (clip) output[(2*i+0)*out_stride] = av_clip_uintp2_c(output[(2*i+0)*out_stride], clip); tmp = ( 5*low[0*low_stride] + 4*low[1*low_stride] - low[2*low_stride] + 4) >> 3; output[(2*i+1)*out_stride] = (tmp - high[0*high_stride]) >> 1; if (clip) output[(2*i+1)*out_stride] = av_clip_uintp2_c(output[(2*i+1)*out_stride], clip); } else if (i == len-1) {
static int amplify_frame(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AmplifyContext *s = ctx->priv; ThreadData *td = arg; AVFrame **in = td->in; AVFrame *out = td->out; const int radius = s->radius; const int nb_inputs = s->nb_inputs; const float threshold = s->threshold; const float factor = s->factor; const int llimit = s->llimit; const int hlimit = s->hlimit; const int depth = s->depth; int i, p, x, y; if (s->depth <= 8) { for (p = 0; p < s->nb_planes; p++) { const int slice_start = (s->height[p] * jobnr) / nb_jobs; const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; if (!((1 << p) & s->planes)) { av_image_copy_plane(dst, out->linesize[p], in[radius]->data[p] + slice_start * in[radius]->linesize[p], in[radius]->linesize[p], s->linesize[p], slice_end - slice_start); continue; } for (y = slice_start; y < slice_end; y++) { for (x = 0; x < s->linesize[p]; x++) { int src = in[radius]->data[p][y * in[radius]->linesize[p] + x]; float diff, avg; int sum = 0; for (i = 0; i < nb_inputs; i++) { sum += in[i]->data[p][y * in[i]->linesize[p] + x]; } avg = sum / (float)nb_inputs; diff = src - avg; if (fabsf(diff) < threshold) { int amp; if (diff < 0) { amp = -FFMIN(FFABS(diff * factor), llimit); } else { amp = FFMIN(FFABS(diff * factor), hlimit); } dst[x] = av_clip_uint8(src + amp); } else { dst[x] = src; } } dst += out->linesize[p]; } } } else { for (p = 0; p < s->nb_planes; p++) { const int slice_start = (s->height[p] * jobnr) / nb_jobs; const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]); if (!((1 << p) & s->planes)) { av_image_copy_plane((uint8_t *)dst, out->linesize[p], in[radius]->data[p] + slice_start * in[radius]->linesize[p], in[radius]->linesize[p], s->linesize[p], slice_end - slice_start); continue; } for (y = slice_start; y < slice_end; y++) { for (x = 0; x < s->linesize[p] / 2; x++) { int src = AV_RN16(in[radius]->data[p] + y * in[radius]->linesize[p] + x * 2); float diff, avg; int sum = 0; for (i = 0; i < nb_inputs; i++) { sum += AV_RN16(in[i]->data[p] + y * in[i]->linesize[p] + x * 2); } avg = sum / (float)nb_inputs; diff = src - avg; if (fabsf(diff) < threshold) { int amp; if (diff < 0) { amp = -FFMIN(FFABS(diff * factor), llimit); } else { amp = FFMIN(FFABS(diff * factor), hlimit); } dst[x] = av_clip_uintp2_c(src + amp, depth); } else { dst[x] = src; } } dst += out->linesize[p] / 2; } } } return 0; }