Showing the changes to libavfilter (1 of 2 files). Show all
Unified · Split
| @@ -30,6 +30,7 @@ · 29 unmodified lines | |||
| 30 | typedef enum AnalyzeMode { | 30 | typedef enum AnalyzeMode { |
| 31 | MANUAL, | 31 | MANUAL, |
| 32 | AVERAGE, | 32 | AVERAGE, |
| 33 | MINMAX, | ||
| 33 | NB_ANALYZE | 34 | 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 | |||
| 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; | ||
| 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 | ||