Add slice threading support, use the command like: ./ffmpeg -i input -vf colorlevels -f null /dev/null with 1080p h264 clip, the fps from 39 fps to 79 fps in the local(Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz)
Unified · Split
| @@ -105,6 +105,68 @@ static int config_input(AVFilterLink *inlink) · 104 unmodified lines | ||
| 105 | 105 | return 0; |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | +struct thread_data { | |
| 109 | + const uint8_t *srcrow; | |
| 110 | + uint8_t *dstrow; | |
| 111 | + int dst_linesize; | |
| 112 | + int src_linesize; | |
| 113 | + | |
| 114 | + double coeff; | |
| 115 | + uint8_t offset; | |
| 116 | + | |
| 117 | + int h; | |
| 118 | + | |
| 119 | + int imin; | |
| 120 | + int omin; | |
| 121 | +}; | |
| 122 | + | |
| 123 | +#define LOAD_COMMON\ | |
| 124 | + ColorLevelsContext *s = ctx->priv;\ | |
| 125 | + const struct thread_data *td = arg;\ | |
| 126 | +\ | |
| 127 | + int process_h = td->h;\ | |
| 128 | + const int slice_start = (process_h * jobnr ) / nb_jobs;\ | |
| 129 | + const int slice_end = (process_h * (jobnr+1)) / nb_jobs;\ | |
| 130 | + int x, y;\ | |
| 131 | + const uint8_t *srcrow = td->srcrow;\ | |
| 132 | + uint8_t *dstrow = td->dstrow;\ | |
| 133 | + const int step = s->step;\ | |
| 134 | + const uint8_t offset = td->offset;\ | |
| 135 | +\ | |
| 136 | + int imin = td->imin;\ | |
| 137 | + int omin = td->omin;\ | |
| 138 | + double coeff = td->coeff;\ | |
| 139 | + | |
| 140 | +static int colorlevel_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
| 141 | +{ | |
| 142 | + LOAD_COMMON | |
| 143 | + | |
| 144 | + for (y = slice_start; y < slice_end; y++) { | |
| 145 | + const uint8_t *src = srcrow + y * td->src_linesize; | |
| 146 | + uint8_t *dst = dstrow + y * td->dst_linesize; | |
| 147 | + | |
| 148 | + for (x = 0; x < s->linesize; x += step) | |
| 149 | + dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); | |
| 150 | + } | |
| 151 | + | |
| 152 | + return 0; | |
| 153 | +} | |
| 154 | + | |
| 155 | +static int colorlevel_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
| 156 | +{ | |
| 157 | + LOAD_COMMON | |
| 158 | + | |
| 159 | + for (y = slice_start; y < slice_end; y++) { | |
| 160 | + const uint16_t *src = (const uint16_t *)(srcrow + y * td->src_linesize); | |
| 161 | + uint16_t *dst = (uint16_t *)(dstrow + y * td->dst_linesize); | |
| 162 | + | |
| 163 | + for (x = 0; x < s->linesize; x += step) | |
| 164 | + dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); | |
| 165 | + } | |
| 166 | + | |
| 167 | + return 0; | |
| 168 | +} | |
| 169 | + | |
| 108 | 170 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
| 109 | 171 | { |
| 110 | 172 | AVFilterContext *ctx = inlink->dst; |
| @@ -137,6 +199,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 26 unmodified lines | ||
| 137 | 199 | int omin = lrint(r->out_min * UINT8_MAX); |
| 138 | 200 | int omax = lrint(r->out_max * UINT8_MAX); |
| 139 | 201 | double coeff; |
| 202 | + struct thread_data td; | |
| 140 | 203 | |
| 141 | 204 | if (imin < 0) { |
| 142 | 205 | imin = UINT8_MAX; |
| @@ -162,15 +225,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 19 unmodified lines | ||
| 162 | 225 | |
| 163 | 226 | srcrow = in->data[0]; |
| 164 | 227 | coeff = (omax - omin) / (double)(imax - imin); |
| 165 | − for (y = 0; y < inlink->h; y++) { | |
| 166 | − const uint8_t *src = srcrow; | |
| 167 | − uint8_t *dst = dstrow; | |
| 168 | − | |
| 169 | − for (x = 0; x < s->linesize; x += step) | |
| 170 | − dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); | |
| 171 | − dstrow += out->linesize[0]; | |
| 172 | − srcrow += in->linesize[0]; | |
| 173 | − } | |
| 228 | + | |
| 229 | + td.srcrow = srcrow; | |
| 230 | + td.dstrow = dstrow; | |
| 231 | + td.dst_linesize = out->linesize[0]; | |
| 232 | + td.src_linesize = in->linesize[0]; | |
| 233 | + td.coeff = coeff; | |
| 234 | + td.offset = offset; | |
| 235 | + td.h = inlink->h; | |
| 236 | + td.imin = imin; | |
| 237 | + td.omin = omin; | |
| 238 | + | |
| 239 | + ctx->internal->execute(ctx, colorlevel_slice_8, &td, NULL, | |
| 240 | + FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); | |
| 174 | 241 | } |
| 175 | 242 | break; |
| 176 | 243 | case 2: |
| @@ -184,6 +251,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 7 unmodified lines | ||
| 184 | 251 | int omin = lrint(r->out_min * UINT16_MAX); |
| 185 | 252 | int omax = lrint(r->out_max * UINT16_MAX); |
| 186 | 253 | double coeff; |
| 254 | + struct thread_data td; | |
| 187 | 255 | |
| 188 | 256 | if (imin < 0) { |
| 189 | 257 | imin = UINT16_MAX; |
| @@ -209,15 +277,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 19 unmodified lines | ||
| 209 | 277 | |
| 210 | 278 | srcrow = in->data[0]; |
| 211 | 279 | coeff = (omax - omin) / (double)(imax - imin); |
| 212 | − for (y = 0; y < inlink->h; y++) { | |
| 213 | − const uint16_t *src = (const uint16_t*)srcrow; | |
| 214 | − uint16_t *dst = (uint16_t *)dstrow; | |
| 215 | − | |
| 216 | − for (x = 0; x < s->linesize; x += step) | |
| 217 | − dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); | |
| 218 | − dstrow += out->linesize[0]; | |
| 219 | − srcrow += in->linesize[0]; | |
| 220 | − } | |
| 280 | + | |
| 281 | + td.srcrow = srcrow; | |
| 282 | + td.dstrow = dstrow; | |
| 283 | + td.dst_linesize = out->linesize[0]; | |
| 284 | + td.src_linesize = in->linesize[0]; | |
| 285 | + td.coeff = coeff; | |
| 286 | + td.offset = offset; | |
| 287 | + td.h = inlink->h; | |
| 288 | + td.imin = imin; | |
| 289 | + td.omin = omin; | |
| 290 | + | |
| 291 | + ctx->internal->execute(ctx, colorlevel_slice_16, &td, NULL, | |
| 292 | + FFMIN(inlink->h, ff_filter_get_nb_threads(ctx))); | |
| 221 | 293 | } |
| 222 | 294 | } |
| 223 | 295 | |
| @@ -252,5 +324,5 @@ AVFilter ff_vf_colorlevels = { · 28 unmodified lines | ||
| 252 | 324 | .query_formats = query_formats, |
| 253 | 325 | .inputs = colorlevels_inputs, |
| 254 | 326 | .outputs = colorlevels_outputs, |
| 255 | − .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, | |
| 327 | + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, | |
| 256 | 328 | }; |