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 | return 0; | 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 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) | 170 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
| 109 | { | 171 | { |
| 110 | AVFilterContext *ctx = inlink->dst; | 172 | AVFilterContext *ctx = inlink->dst; |
| @@ -137,6 +199,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 26 unmodified lines | |||
| 137 | int omin = lrint(r->out_min * UINT8_MAX); | 199 | int omin = lrint(r->out_min * UINT8_MAX); |
| 138 | int omax = lrint(r->out_max * UINT8_MAX); | 200 | int omax = lrint(r->out_max * UINT8_MAX); |
| 139 | double coeff; | 201 | double coeff; |
| 202 | struct thread_data td; | ||
| 140 | 203 | ||
| 141 | if (imin < 0) { | 204 | if (imin < 0) { |
| 142 | imin = UINT8_MAX; | 205 | imin = UINT8_MAX; |
| @@ -162,15 +225,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 19 unmodified lines | |||
| 162 | 225 | ||
| 163 | srcrow = in->data[0]; | 226 | srcrow = in->data[0]; |
| 164 | coeff = (omax - omin) / (double)(imax - imin); | 227 | coeff = (omax - omin) / (double)(imax - imin); |
| 165 | for (y = 0; y < inlink->h; y++) { | 228 | |
| 166 | const uint8_t *src = srcrow; | 229 | td.srcrow = srcrow; |
| 167 | uint8_t *dst = dstrow; | 230 | td.dstrow = dstrow; |
| 168 | 231 | td.dst_linesize = out->linesize[0]; | |
| 169 | for (x = 0; x < s->linesize; x += step) | 232 | td.src_linesize = in->linesize[0]; |
| 170 | dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin); | 233 | td.coeff = coeff; |
| 171 | dstrow += out->linesize[0]; | 234 | td.offset = offset; |
| 172 | srcrow += in->linesize[0]; | 235 | td.h = inlink->h; |
| 173 | } | 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 | break; | 242 | break; |
| 176 | case 2: | 243 | case 2: |
| @@ -184,6 +251,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 7 unmodified lines | |||
| 184 | int omin = lrint(r->out_min * UINT16_MAX); | 251 | int omin = lrint(r->out_min * UINT16_MAX); |
| 185 | int omax = lrint(r->out_max * UINT16_MAX); | 252 | int omax = lrint(r->out_max * UINT16_MAX); |
| 186 | double coeff; | 253 | double coeff; |
| 254 | struct thread_data td; | ||
| 187 | 255 | ||
| 188 | if (imin < 0) { | 256 | if (imin < 0) { |
| 189 | imin = UINT16_MAX; | 257 | imin = UINT16_MAX; |
| @@ -209,15 +277,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 19 unmodified lines | |||
| 209 | 277 | ||
| 210 | srcrow = in->data[0]; | 278 | srcrow = in->data[0]; |
| 211 | coeff = (omax - omin) / (double)(imax - imin); | 279 | coeff = (omax - omin) / (double)(imax - imin); |
| 212 | for (y = 0; y < inlink->h; y++) { | 280 | |
| 213 | const uint16_t *src = (const uint16_t*)srcrow; | 281 | td.srcrow = srcrow; |
| 214 | uint16_t *dst = (uint16_t *)dstrow; | 282 | td.dstrow = dstrow; |
| 215 | 283 | td.dst_linesize = out->linesize[0]; | |
| 216 | for (x = 0; x < s->linesize; x += step) | 284 | td.src_linesize = in->linesize[0]; |
| 217 | dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin); | 285 | td.coeff = coeff; |
| 218 | dstrow += out->linesize[0]; | 286 | td.offset = offset; |
| 219 | srcrow += in->linesize[0]; | 287 | td.h = inlink->h; |
| 220 | } | 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 | .query_formats = query_formats, | 324 | .query_formats = query_formats, |
| 253 | .inputs = colorlevels_inputs, | 325 | .inputs = colorlevels_inputs, |
| 254 | .outputs = colorlevels_outputs, | 326 | .outputs = colorlevels_outputs, |
| 255 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, | 327 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, |
| 256 | }; | 328 | }; |