History

avfilter/vf_colorcorrect: fix average analyze mode and add minmax mode

Paul B Mahol committed 5 years ago

Commit d5b3e041 parent b06f12b2 files · +92 −9Browse files

Unified · Split

2 files
  1. doc/filters.texi +1 −1
  2. libavfilter/vf_colorcorrect.c +91 −8
doc/filters.texi+1−1
@@ -8227,7 +8227,7 @@ Default value is 1. · 8226 unmodified lines
8227 8227
8228@item analyze8228@item analyze
8229If set to anything other than @code{manual} it will analyze every frame and use derived8229If set to anything other than @code{manual} it will analyze every frame and use derived
8230parameters for filtering output frame. Can be @code{manual} or @code{average}.8230parameters for filtering output frame. Can be @code{manual} or @code{average} or @code{minmax}.
8231Default value is @code{manual}.8231Default value is @code{manual}.
8232@end table8232@end table
8233 8233
libavfilter/vf_colorcorrect.c+91−8
@@ -30,6 +30,7 @@ · 29 unmodified lines
30typedef enum AnalyzeMode {30typedef enum AnalyzeMode {
31 MANUAL,31 MANUAL,
32 AVERAGE,32 AVERAGE,
33 MINMAX,
33 NB_ANALYZE34 NB_ANALYZE
34} AnalyzeMode;35} AnalyzeMode;
35 36
@@ -48,7 +49,7 @@ typedef struct ColorCorrectContext { · 12 unmodified lines
48 int planeheight[4];49 int planeheight[4];
49 int planewidth[4];50 int planewidth[4];
50 51
51 float (*analyzeret)[2];52 float (*analyzeret)[4];
52 53
53 int (*do_analyze)(AVFilterContext *s, void *arg,54 int (*do_analyze)(AVFilterContext *s, void *arg,
54 int jobnr, int nb_jobs);55 int jobnr, int nb_jobs);
@@ -81,8 +82,8 @@ static int average_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 26 unmodified lines
81 vptr += vlinesize;82 vptr += vlinesize;
82 }83 }
83 84
84 s->analyzeret[jobnr][0] = imax * sum_u / (float)((slice_end - slice_start) * width) - 0.5f;85 s->analyzeret[jobnr][0] = s->analyzeret[jobnr][2] = imax * sum_u / (float)((slice_end - slice_start) * width) - 0.5f;
85 s->analyzeret[jobnr][1] = imax * sum_v / (float)((slice_end - slice_start) * width) - 0.5f;86 s->analyzeret[jobnr][1] = s->analyzeret[jobnr][3] = imax * sum_v / (float)((slice_end - slice_start) * width) - 0.5f;
86 87
87 return 0;88 return 0;
88}89}
@@ -112,8 +113,80 @@ static int average_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 23 unmodified lines
112 vptr += vlinesize;113 vptr += vlinesize;
113 }114 }
114 115
115 s->analyzeret[jobnr][0] = imax * sum_u / (float)((slice_end - slice_start) * width) - 0.5f;116 s->analyzeret[jobnr][0] = s->analyzeret[jobnr][2] = imax * sum_u / (float)((slice_end - slice_start) * width) - 0.5f;
116 s->analyzeret[jobnr][1] = imax * sum_v / (float)((slice_end - slice_start) * width) - 0.5f;117 s->analyzeret[jobnr][1] = s->analyzeret[jobnr][3] = imax * sum_v / (float)((slice_end - slice_start) * width) - 0.5f;
118
119 return 0;
120}
121
122static int minmax_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
123{
124 ColorCorrectContext *s = ctx->priv;
125 AVFrame *frame = arg;
126 const float imax = s->imax;
127 const int width = s->planewidth[1];
128 const int height = s->planeheight[1];
129 const int slice_start = (height * jobnr) / nb_jobs;
130 const int slice_end = (height * (jobnr + 1)) / nb_jobs;
131 const int ulinesize = frame->linesize[1];
132 const int vlinesize = frame->linesize[2];
133 const uint8_t *uptr = (const uint8_t *)frame->data[1] + slice_start * ulinesize;
134 const uint8_t *vptr = (const uint8_t *)frame->data[2] + slice_start * vlinesize;
135 int min_u = 255, min_v = 255;
136 int max_u = 0, max_v = 0;
137
138 for (int y = slice_start; y < slice_end; y++) {
139 for (int x = 0; x < width; x++) {
140 min_u = FFMIN(min_u, uptr[x]);
141 min_v = FFMIN(min_v, vptr[x]);
142 max_u = FFMAX(max_u, uptr[x]);
143 max_v = FFMAX(max_v, vptr[x]);
144 }
145
146 uptr += ulinesize;
147 vptr += vlinesize;
148 }
149
150 s->analyzeret[jobnr][0] = imax * min_u - 0.5f;
151 s->analyzeret[jobnr][1] = imax * min_v - 0.5f;
152 s->analyzeret[jobnr][2] = imax * max_u - 0.5f;
153 s->analyzeret[jobnr][3] = imax * max_v - 0.5f;
154
155 return 0;
156}
157
158static int minmax_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
159{
160 ColorCorrectContext *s = ctx->priv;
161 AVFrame *frame = arg;
162 const float imax = s->imax;
163 const int width = s->planewidth[1];
164 const int height = s->planeheight[1];
165 const int slice_start = (height * jobnr) / nb_jobs;
166 const int slice_end = (height * (jobnr + 1)) / nb_jobs;
167 const int ulinesize = frame->linesize[1] / 2;
168 const int vlinesize = frame->linesize[2] / 2;
169 const uint16_t *uptr = (const uint16_t *)frame->data[1] + slice_start * ulinesize;
170 const uint16_t *vptr = (const uint16_t *)frame->data[2] + slice_start * vlinesize;
171 int min_u = INT_MAX, min_v = INT_MAX;
172 int max_u = INT_MIN, max_v = INT_MIN;
173
174 for (int y = slice_start; y < slice_end; y++) {
175 for (int x = 0; x < width; x++) {
176 min_u = FFMIN(min_u, uptr[x]);
177 min_v = FFMIN(min_v, vptr[x]);
178 max_u = FFMAX(max_u, uptr[x]);
179 max_v = FFMAX(max_v, vptr[x]);
180 }
181
182 uptr += ulinesize;
183 vptr += vlinesize;
184 }
185
186 s->analyzeret[jobnr][0] = imax * min_u - 0.5f;
187 s->analyzeret[jobnr][1] = imax * min_v - 0.5f;
188 s->analyzeret[jobnr][2] = imax * max_u - 0.5f;
189 s->analyzeret[jobnr][3] = imax * max_v - 0.5f;
117 190
118 return 0;191 return 0;
119}192}
@@ -215,20 +288,26 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 95 unmodified lines
215 const int nb_threads = FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx));288 const int nb_threads = FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx));
216 289
217 if (s->analyze) {290 if (s->analyze) {
218 float bl = 0.f, rl = 0.f;291 float bl = 0.f, rl = 0.f, bh = 0.f, rh = 0.f;
219 292
220 ff_filter_execute(ctx, s->do_analyze, frame, NULL, nb_threads);293 ff_filter_execute(ctx, s->do_analyze, frame, NULL, nb_threads);
221 294
222 for (int i = 0; i < nb_threads; i++) {295 for (int i = 0; i < nb_threads; i++) {
223 bl += s->analyzeret[i][0];296 bl += s->analyzeret[i][0];
224 rl += s->analyzeret[i][0];297 rl += s->analyzeret[i][1];
298 bh += s->analyzeret[i][2];
299 rh += s->analyzeret[i][3];
225 }300 }
226 301
227 bl /= nb_threads;302 bl /= nb_threads;
228 rl /= nb_threads;303 rl /= nb_threads;
304 bh /= nb_threads;
305 rh /= nb_threads;
229 306
230 s->bl = -bl;307 s->bl = -bl;
231 s->rl = -rl;308 s->rl = -rl;
309 s->bh = -bh;
310 s->rh = -rh;
232 }311 }
233 312
234 ff_filter_execute(ctx, s->do_slice, frame, NULL, nb_threads);313 ff_filter_execute(ctx, s->do_slice, frame, NULL, nb_threads);
@@ -278,6 +357,9 @@ static av_cold int config_input(AVFilterLink *inlink) · 43 unmodified lines
278 case AVERAGE:357 case AVERAGE:
279 s->do_analyze = s->depth <= 8 ? average_slice8 : average_slice16;358 s->do_analyze = s->depth <= 8 ? average_slice8 : average_slice16;
280 break;359 break;
360 case MINMAX:
361 s->do_analyze = s->depth <= 8 ? minmax_slice8 : minmax_slice16;
362 break;
281 default:363 default:
282 return AVERROR_BUG;364 return AVERROR_BUG;
283 }365 }
@@ -327,9 +409,10 @@ static const AVOption colorcorrect_options[] = { · 43 unmodified lines
327 { "rh", "set the red highlight spot", OFFSET(rh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },409 { "rh", "set the red highlight spot", OFFSET(rh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },
328 { "bh", "set the blue highlight spot", OFFSET(bh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },410 { "bh", "set the blue highlight spot", OFFSET(bh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },
329 { "saturation", "set the amount of saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=1}, -3, 3, VF },411 { "saturation", "set the amount of saturation", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=1}, -3, 3, VF },
330 { "analyze", "set the analyze mode", OFFSET(analyze), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_ANALYZE, VF, "analyze" },412 { "analyze", "set the analyze mode", OFFSET(analyze), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_ANALYZE-1, VF, "analyze" },
331 { "manual", "manually set options", 0, AV_OPT_TYPE_CONST, {.i64=MANUAL}, 0, 0, VF, "analyze" },413 { "manual", "manually set options", 0, AV_OPT_TYPE_CONST, {.i64=MANUAL}, 0, 0, VF, "analyze" },
332 { "average", "use average pixels", 0, AV_OPT_TYPE_CONST, {.i64=AVERAGE}, 0, 0, VF, "analyze" },414 { "average", "use average pixels", 0, AV_OPT_TYPE_CONST, {.i64=AVERAGE}, 0, 0, VF, "analyze" },
415 { "minmax", "use minmax pixels", 0, AV_OPT_TYPE_CONST, {.i64=MINMAX}, 0, 0, VF, "analyze" },
333 { NULL }416 { NULL }
334};417};
335 418

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