History

lavfi/colorlevels: Add slice threading support

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)

Jun Zhao committed 7 years ago

Commit 360bee81 parent 468f0031 file · +91 −19Browse files

Unified · Split

libavfilter/vf_colorlevels.c+91−19
@@ -105,6 +105,68 @@ static int config_input(AVFilterLink *inlink) · 104 unmodified lines
105 return 0;105 return 0;
106}106}
107 107
108struct 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
140static 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
155static 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
108static int filter_frame(AVFilterLink *inlink, AVFrame *in)170static 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};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t