[FFmpeg-devel] [PATCH] avfilter/vf_rotate: support slice threading
Stefano Sabatini
stefasab at gmail.com
Mon Sep 30 11:38:00 CEST 2013
On date Sunday 2013-09-29 19:46:38 +0000, Paul B Mahol encoded:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> libavfilter/vf_rotate.c | 155 +++++++++++++++++++++++++++++-------------------
> 1 file changed, 94 insertions(+), 61 deletions(-)
>
> diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c
> index f70a8ef..710c4db 100644
> --- a/libavfilter/vf_rotate.c
> +++ b/libavfilter/vf_rotate.c
> @@ -77,6 +77,16 @@ typedef struct {
> FFDrawColor color;
> } RotContext;
>
> +typedef struct ThreadData {
> + AVFrame *in, *out;
> + int inw, inh;
> + int outw, outh;
> + int plane;
> + int xi, yi;
> + int xprime, yprime;
> + int c, s;
> +} ThreadData;
> +
> #define OFFSET(x) offsetof(RotContext, x)
> #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
>
> @@ -299,6 +309,76 @@ static uint8_t *interpolate_bilinear(uint8_t *dst_color,
>
> #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
>
> +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
nit: jobnr and nb_jobs are inconsistent in several ways
> +{
> + ThreadData *td = arg;
> + AVFrame *in = td->in;
> + AVFrame *out = td->out;
> + RotContext *rot = ctx->priv;
> + const int outw = td->outw, outh = td->outh;
> + const int inw = td->inw, inh = td->inh;
> + const int plane = td->plane;
> + const int xi = td->xi, yi = td->yi;
> + const int c = td->c, s = td->s;
> + const int start = (outh * jobnr ) / nb_jobs;
> + const int end = (outh * (jobnr+1)) / nb_jobs;
> + int xprime = td->xprime + start * s;
> + int yprime = td->yprime + start * c;
> + int i, j, x, y;
> +
> + for (j = start; j < end; j++) {
> + x = xprime + xi + FIXP*inw/2;
> + y = yprime + yi + FIXP*inh/2;
> +
> + for (i = 0; i < outw; i++) {
> + int32_t v;
> + int x1, y1;
> + uint8_t *pin, *pout;
> + x += c;
> + y -= s;
> + x1 = x>>16;
> + y1 = y>>16;
> +
> + /* the out-of-range values avoid border artifacts */
> + if (x1 >= -1 && x1 <= inw && y1 >= -1 && y1 <= inh) {
> + uint8_t inp_inv[4]; /* interpolated input value */
> + pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane];
> + if (rot->use_bilinear) {
> + pin = interpolate_bilinear(inp_inv,
> + in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane],
> + x, y, inw-1, inh-1);
> + } else {
> + int x2 = av_clip(x1, 0, inw-1);
> + int y2 = av_clip(y1, 0, inh-1);
> + pin = in->data[plane] + y2 * in->linesize[plane] + x2 * rot->draw.pixelstep[plane];
> + }
> + switch (rot->draw.pixelstep[plane]) {
> + case 1:
> + *pout = *pin;
> + break;
> + case 2:
> + *((uint16_t *)pout) = *((uint16_t *)pin);
> + break;
> + case 3:
> + v = AV_RB24(pin);
> + AV_WB24(pout, v);
> + break;
> + case 4:
> + *((uint32_t *)pout) = *((uint32_t *)pin);
> + break;
> + default:
> + memcpy(pout, pin, rot->draw.pixelstep[plane]);
> + break;
> + }
> + }
> + }
> + xprime += s;
> + yprime += c;
> + }
> +
> + return 0;
> +}
> +
> static int filter_frame(AVFilterLink *inlink, AVFrame *in)
> {
> AVFilterContext *ctx = inlink->dst;
> @@ -334,66 +414,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
> for (plane = 0; plane < rot->nb_planes; plane++) {
> int hsub = plane == 1 || plane == 2 ? rot->hsub : 0;
> int vsub = plane == 1 || plane == 2 ? rot->vsub : 0;
> - int inw = FF_CEIL_RSHIFT(inlink->w, hsub);
> - int inh = FF_CEIL_RSHIFT(inlink->h, vsub);
> - int outw = FF_CEIL_RSHIFT(outlink->w, hsub);
> - int outh = FF_CEIL_RSHIFT(outlink->h, vsub);
> -
> - const int xi = -outw/2 * c;
> - const int yi = outw/2 * s;
> - int xprime = -outh/2 * s;
> - int yprime = -outh/2 * c;
> - int i, j, x, y;
> -
> - for (j = 0; j < outh; j++) {
> - x = xprime + xi + FIXP*inw/2;
> - y = yprime + yi + FIXP*inh/2;
> -
> - for (i = 0; i < outw; i++) {
> - int32_t v;
> - int x1, y1;
> - uint8_t *pin, *pout;
> - x += c;
> - y -= s;
> - x1 = x>>16;
> - y1 = y>>16;
> -
> - /* the out-of-range values avoid border artifacts */
> - if (x1 >= -1 && x1 <= inw && y1 >= -1 && y1 <= inh) {
> - uint8_t inp_inv[4]; /* interpolated input value */
> - pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane];
> - if (rot->use_bilinear) {
> - pin = interpolate_bilinear(inp_inv,
> - in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane],
> - x, y, inw-1, inh-1);
> - } else {
> - int x2 = av_clip(x1, 0, inw-1);
> - int y2 = av_clip(y1, 0, inh-1);
> - pin = in->data[plane] + y2 * in->linesize[plane] + x2 * rot->draw.pixelstep[plane];
> - }
> - switch (rot->draw.pixelstep[plane]) {
> - case 1:
> - *pout = *pin;
> - break;
> - case 2:
> - *((uint16_t *)pout) = *((uint16_t *)pin);
> - break;
> - case 3:
> - v = AV_RB24(pin);
> - AV_WB24(pout, v);
> - break;
> - case 4:
> - *((uint32_t *)pout) = *((uint32_t *)pin);
> - break;
> - default:
> - memcpy(pout, pin, rot->draw.pixelstep[plane]);
> - break;
> - }
> - }
> - }
> - xprime += s;
> - yprime += c;
> - }
> + const int outw = FF_CEIL_RSHIFT(outlink->w, hsub);
> + const int outh = FF_CEIL_RSHIFT(outlink->h, vsub);
> + ThreadData td = { .in = in, .out = out,
> + .inw = FF_CEIL_RSHIFT(inlink->w, hsub),
> + .inh = FF_CEIL_RSHIFT(inlink->h, vsub),
> + .outh = outh, .outw = outw,
> + .xi = -outw/2 * c, .yi = outw/2 * s,
> + .xprime = -outh/2 * s,
> + .yprime = -outh/2 * c,
> + .plane = plane, .c = c, .s = s };
> +
> +
> + ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outh, ctx->graph->nb_threads));
> }
>
> av_frame_free(&in);
> @@ -452,5 +485,5 @@ AVFilter avfilter_vf_rotate = {
> .inputs = rotate_inputs,
> .outputs = rotate_outputs,
> .priv_class = &rotate_class,
> - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
> + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
> };
LGTM, assuming it passes tests. Thanks.
--
FFmpeg = Fantastic and Fundamental Moronic Problematic Elected Gadget
More information about the ffmpeg-devel
mailing list