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

Showing the changes to libavfilter (1 of 2 files). Show all

Unified · Split

libavfilter/vf_colorcorrect.c+91−8
@@ -30,6 +30,7 @@ · 29 unmodified lines
3030 typedef enum AnalyzeMode {
3131 MANUAL,
3232 AVERAGE,
33+ MINMAX,
3334 NB_ANALYZE
3435 } AnalyzeMode;
3536
@@ -48,7 +49,7 @@ typedef struct ColorCorrectContext { · 12 unmodified lines
4849 int planeheight[4];
4950 int planewidth[4];
5051
51− float (*analyzeret)[2];
52+ float (*analyzeret)[4];
5253
5354 int (*do_analyze)(AVFilterContext *s, void *arg,
5455 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
8182 vptr += vlinesize;
8283 }
8384
84− s->analyzeret[jobnr][0] = 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;
85+ s->analyzeret[jobnr][0] = s->analyzeret[jobnr][2] = imax * sum_u / (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;
8687
8788 return 0;
8889 }
@@ -112,8 +113,80 @@ static int average_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 23 unmodified lines
112113 vptr += vlinesize;
113114 }
114115
115− s->analyzeret[jobnr][0] = 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;
116+ s->analyzeret[jobnr][0] = s->analyzeret[jobnr][2] = imax * sum_u / (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+
122+static 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+
158+static 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;
117190
118191 return 0;
119192 }
@@ -215,20 +288,26 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) · 95 unmodified lines
215288 const int nb_threads = FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx));
216289
217290 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;
219292
220293 ff_filter_execute(ctx, s->do_analyze, frame, NULL, nb_threads);
221294
222295 for (int i = 0; i < nb_threads; i++) {
223296 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];
225300 }
226301
227302 bl /= nb_threads;
228303 rl /= nb_threads;
304+ bh /= nb_threads;
305+ rh /= nb_threads;
229306
230307 s->bl = -bl;
231308 s->rl = -rl;
309+ s->bh = -bh;
310+ s->rh = -rh;
232311 }
233312
234313 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
278357 case AVERAGE:
279358 s->do_analyze = s->depth <= 8 ? average_slice8 : average_slice16;
280359 break;
360+ case MINMAX:
361+ s->do_analyze = s->depth <= 8 ? minmax_slice8 : minmax_slice16;
362+ break;
281363 default:
282364 return AVERROR_BUG;
283365 }
@@ -327,9 +409,10 @@ static const AVOption colorcorrect_options[] = { · 43 unmodified lines
327409 { "rh", "set the red highlight spot", OFFSET(rh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },
328410 { "bh", "set the blue highlight spot", OFFSET(bh), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF },
329411 { "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" },
331413 { "manual", "manually set options", 0, AV_OPT_TYPE_CONST, {.i64=MANUAL}, 0, 0, VF, "analyze" },
332414 { "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" },
333416 { NULL }
334417 };
335418

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