Unified · Split
| @@ -44,6 +44,9 @@ typedef struct ColorLevelsContext { · 43 unmodified lines | |||
| 44 | int preserve_color; | 44 | int preserve_color; |
| 45 | 45 | ||
| 46 | int nb_comp; | 46 | int nb_comp; |
| 47 | int depth; | ||
| 48 | int max; | ||
| 49 | int planar; | ||
| 47 | int bpp; | 50 | int bpp; |
| 48 | int step; | 51 | int step; |
| 49 | uint8_t rgba_map[4]; | 52 | uint8_t rgba_map[4]; |
| @@ -85,8 +88,8 @@ static const AVOption colorlevels_options[] = { · 35 unmodified lines | |||
| 85 | AVFILTER_DEFINE_CLASS(colorlevels); | 88 | AVFILTER_DEFINE_CLASS(colorlevels); |
| 86 | 89 | ||
| 87 | typedef struct ThreadData { | 90 | typedef struct ThreadData { |
| 88 | const uint8_t *srcrow; | 91 | const uint8_t *srcrow[4]; |
| 89 | uint8_t *dstrow; | 92 | uint8_t *dstrow[4]; |
| 90 | int dst_linesize; | 93 | int dst_linesize; |
| 91 | int src_linesize; | 94 | int src_linesize; |
| 92 | 95 | ||
| @@ -98,8 +101,7 @@ typedef struct ThreadData { · 5 unmodified lines | |||
| 98 | int omin[4]; | 101 | int omin[4]; |
| 99 | } ThreadData; | 102 | } ThreadData; |
| 100 | 103 | ||
| 101 | #define DO_COMMON(type, clip, preserve) \ | 104 | #define DO_COMMON(type, clip, preserve, planar) \ |
| 102 | ColorLevelsContext *s = ctx->priv; \ | ||
| 103 | const ThreadData *td = arg; \ | 105 | const ThreadData *td = arg; \ |
| 104 | const int linesize = s->linesize; \ | 106 | const int linesize = s->linesize; \ |
| 105 | const int step = s->step; \ | 107 | const int step = s->step; \ |
| @@ -108,12 +110,14 @@ typedef struct ThreadData { · 2 unmodified lines | |||
| 108 | const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ | 110 | const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ |
| 109 | const int src_linesize = td->src_linesize / sizeof(type); \ | 111 | const int src_linesize = td->src_linesize / sizeof(type); \ |
| 110 | const int dst_linesize = td->dst_linesize / sizeof(type); \ | 112 | const int dst_linesize = td->dst_linesize / sizeof(type); \ |
| 111 | const type *srcrow = (const type *)td->srcrow + src_linesize * slice_start; \ | 113 | const type *src_r = (const type *)(td->srcrow[R]) + src_linesize * slice_start; \ |
| 112 | type *dstrow = (type *)td->dstrow + dst_linesize * slice_start; \ | 114 | const type *src_g = (const type *)(td->srcrow[G]) + src_linesize * slice_start; \ |
| 113 | const uint8_t offset_r = s->rgba_map[R]; \ | 115 | const type *src_b = (const type *)(td->srcrow[B]) + src_linesize * slice_start; \ |
| 114 | const uint8_t offset_g = s->rgba_map[G]; \ | 116 | const type *src_a = (const type *)(td->srcrow[A]) + src_linesize * slice_start; \ |
| 115 | const uint8_t offset_b = s->rgba_map[B]; \ | 117 | type *dst_r = (type *)(td->dstrow[R]) + src_linesize * slice_start; \ |
| 116 | const uint8_t offset_a = s->rgba_map[A]; \ | 118 | type *dst_g = (type *)(td->dstrow[G]) + src_linesize * slice_start; \ |
| 119 | type *dst_b = (type *)(td->dstrow[B]) + src_linesize * slice_start; \ | ||
| 120 | type *dst_a = (type *)(td->dstrow[A]) + src_linesize * slice_start; \ | ||
| 117 | const int imin_r = td->imin[R]; \ | 121 | const int imin_r = td->imin[R]; \ |
| 118 | const int imin_g = td->imin[G]; \ | 122 | const int imin_g = td->imin[G]; \ |
| 119 | const int imin_b = td->imin[B]; \ | 123 | const int imin_b = td->imin[B]; \ |
| @@ -126,14 +130,6 @@ typedef struct ThreadData { · 6 unmodified lines | |||
| 126 | const float coeff_g = td->coeff[G]; \ | 130 | const float coeff_g = td->coeff[G]; \ |
| 127 | const float coeff_b = td->coeff[B]; \ | 131 | const float coeff_b = td->coeff[B]; \ |
| 128 | const float coeff_a = td->coeff[A]; \ | 132 | const float coeff_a = td->coeff[A]; \ |
| 129 | const type *src_r = srcrow + offset_r; \ | ||
| 130 | const type *src_g = srcrow + offset_g; \ | ||
| 131 | const type *src_b = srcrow + offset_b; \ | ||
| 132 | const type *src_a = srcrow + offset_a; \ | ||
| 133 | type *dst_r = dstrow + offset_r; \ | ||
| 134 | type *dst_g = dstrow + offset_g; \ | ||
| 135 | type *dst_b = dstrow + offset_b; \ | ||
| 136 | type *dst_a = dstrow + offset_a; \ | ||
| 137 | \ | 133 | \ |
| 138 | for (int y = slice_start; y < slice_end; y++) { \ | 134 | for (int y = slice_start; y < slice_end; y++) { \ |
| 139 | for (int x = 0; x < linesize; x += step) { \ | 135 | for (int x = 0; x < linesize; x += step) { \ |
| @@ -142,7 +138,7 @@ typedef struct ThreadData { · 2 unmodified lines | |||
| 142 | ig = src_g[x]; \ | 138 | ig = src_g[x]; \ |
| 143 | ib = src_b[x]; \ | 139 | ib = src_b[x]; \ |
| 144 | if (preserve) { \ | 140 | if (preserve) { \ |
| 145 | float ratio, icolor, ocolor, max = (1<<(8*sizeof(type)))-1; \ | 141 | float ratio, icolor, ocolor, max = s->max; \ |
| 146 | \ | 142 | \ |
| 147 | or = (ir - imin_r) * coeff_r + omin_r; \ | 143 | or = (ir - imin_r) * coeff_r + omin_r; \ |
| 148 | og = (ig - imin_g) * coeff_g + omin_g; \ | 144 | og = (ig - imin_g) * coeff_g + omin_g; \ |
| @@ -158,18 +154,18 @@ typedef struct ThreadData { · 9 unmodified lines | |||
| 158 | ob *= ratio; \ | 154 | ob *= ratio; \ |
| 159 | } \ | 155 | } \ |
| 160 | \ | 156 | \ |
| 161 | dst_r[x] = clip(or); \ | 157 | dst_r[x] = clip(or, depth); \ |
| 162 | dst_g[x] = clip(og); \ | 158 | dst_g[x] = clip(og, depth); \ |
| 163 | dst_b[x] = clip(ob); \ | 159 | dst_b[x] = clip(ob, depth); \ |
| 164 | } else { \ | 160 | } else { \ |
| 165 | dst_r[x] = clip((ir - imin_r) * coeff_r + omin_r); \ | 161 | dst_r[x] = clip((ir - imin_r) * coeff_r + omin_r, depth); \ |
| 166 | dst_g[x] = clip((ig - imin_g) * coeff_g + omin_g); \ | 162 | dst_g[x] = clip((ig - imin_g) * coeff_g + omin_g, depth); \ |
| 167 | dst_b[x] = clip((ib - imin_b) * coeff_b + omin_b); \ | 163 | dst_b[x] = clip((ib - imin_b) * coeff_b + omin_b, depth); \ |
| 168 | } \ | 164 | } \ |
| 169 | } \ | 165 | } \ |
| 170 | \ | 166 | \ |
| 171 | for (int x = 0; x < linesize && s->nb_comp == 4; x += step) \ | 167 | for (int x = 0; x < linesize && s->nb_comp == 4; x += step) \ |
| 172 | dst_a[x] = clip((src_a[x] - imin_a) * coeff_a + omin_a); \ | 168 | dst_a[x] = clip((src_a[x] - imin_a) * coeff_a + omin_a, depth); \ |
| 173 | \ | 169 | \ |
| 174 | src_r += src_linesize; \ | 170 | src_r += src_linesize; \ |
| 175 | src_g += src_linesize; \ | 171 | src_g += src_linesize; \ |
| @@ -182,31 +178,126 @@ typedef struct ThreadData { · 6 unmodified lines | |||
| 182 | dst_a += dst_linesize; \ | 178 | dst_a += dst_linesize; \ |
| 183 | } | 179 | } |
| 184 | 180 | ||
| 181 | #define CLIP8(x, depth) av_clip_uint8(x) | ||
| 182 | #define CLIP16(x, depth) av_clip_uint16(x) | ||
| 183 | |||
| 185 | static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | 184 | static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
| 186 | { | 185 | { |
| 187 | DO_COMMON(uint8_t, av_clip_uint8, 0) | 186 | ColorLevelsContext *s = ctx->priv; |
| 188 | 187 | DO_COMMON(uint8_t, CLIP8, 0, 0) | |
| 189 | return 0; | 188 | return 0; |
| 190 | } | 189 | } |
| 191 | 190 | ||
| 192 | static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | 191 | static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
| 193 | { | 192 | { |
| 194 | DO_COMMON(uint16_t, av_clip_uint16, 0) | 193 | ColorLevelsContext *s = ctx->priv;\ |
| 195 | 194 | DO_COMMON(uint16_t, CLIP16, 0, 0) | |
| 196 | return 0; | 195 | return 0; |
| 197 | } | 196 | } |
| 198 | 197 | ||
| 199 | static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | 198 | static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
| 200 | { | 199 | { |
| 201 | DO_COMMON(uint8_t, av_clip_uint8, 1) | 200 | ColorLevelsContext *s = ctx->priv; |
| 202 | 201 | DO_COMMON(uint8_t, CLIP8, 1, 0) | |
| 203 | return 0; | 202 | return 0; |
| 204 | } | 203 | } |
| 205 | 204 | ||
| 206 | static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | 205 | static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
| 207 | { | 206 | { |
| 208 | DO_COMMON(uint16_t, av_clip_uint16, 1) | 207 | ColorLevelsContext *s = ctx->priv; |
| 208 | DO_COMMON(uint16_t, CLIP16, 1, 0) | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 213 | { | ||
| 214 | ColorLevelsContext *s = ctx->priv; | ||
| 215 | DO_COMMON(uint8_t, CLIP8, 0, 1) | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 220 | { | ||
| 221 | ColorLevelsContext *s = ctx->priv; | ||
| 222 | const int depth = s->depth; | ||
| 223 | DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) | ||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 228 | { | ||
| 229 | ColorLevelsContext *s = ctx->priv; | ||
| 230 | const int depth = s->depth; | ||
| 231 | DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) | ||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | |||
| 235 | static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 236 | { | ||
| 237 | ColorLevelsContext *s = ctx->priv; | ||
| 238 | const int depth = s->depth; | ||
| 239 | DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) | ||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 244 | { | ||
| 245 | ColorLevelsContext *s = ctx->priv; | ||
| 246 | const int depth = s->depth; | ||
| 247 | DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) | ||
| 248 | return 0; | ||
| 249 | } | ||
| 209 | 250 | ||
| 251 | static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 252 | { | ||
| 253 | ColorLevelsContext *s = ctx->priv; | ||
| 254 | DO_COMMON(uint16_t, CLIP16, 0, 1) | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 259 | { | ||
| 260 | ColorLevelsContext *s = ctx->priv; | ||
| 261 | DO_COMMON(uint8_t, CLIP8, 1, 1) | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 266 | { | ||
| 267 | ColorLevelsContext *s = ctx->priv; | ||
| 268 | const int depth = s->depth; | ||
| 269 | DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 274 | { | ||
| 275 | ColorLevelsContext *s = ctx->priv; | ||
| 276 | const int depth = s->depth; | ||
| 277 | DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 282 | { | ||
| 283 | ColorLevelsContext *s = ctx->priv; | ||
| 284 | const int depth = s->depth; | ||
| 285 | DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) | ||
| 286 | return 0; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 290 | { | ||
| 291 | ColorLevelsContext *s = ctx->priv; | ||
| 292 | const int depth = s->depth; | ||
| 293 | DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | ||
| 298 | { | ||
| 299 | ColorLevelsContext *s = ctx->priv; | ||
| 300 | DO_COMMON(uint16_t, CLIP16, 1, 1) | ||
| 210 | return 0; | 301 | return 0; |
| 211 | } | 302 | } |
| 212 | 303 | ||
| @@ -217,16 +308,48 @@ static int config_input(AVFilterLink *inlink) · 4 unmodified lines | |||
| 217 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | 308 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
| 218 | 309 | ||
| 219 | s->nb_comp = desc->nb_components; | 310 | s->nb_comp = desc->nb_components; |
| 220 | s->bpp = desc->comp[0].depth >> 3; | 311 | s->planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; |
| 221 | s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); | 312 | s->depth = desc->comp[0].depth; |
| 313 | s->max = (1 << s->depth) - 1; | ||
| 314 | s->bpp = (desc->comp[0].depth + 7) >> 3; | ||
| 315 | s->step = s->planar ? 1 : av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); | ||
| 222 | s->linesize = inlink->w * s->step; | 316 | s->linesize = inlink->w * s->step; |
| 223 | ff_fill_rgba_map(s->rgba_map, inlink->format); | 317 | ff_fill_rgba_map(s->rgba_map, inlink->format); |
| 224 | 318 | ||
| 225 | s->colorlevels_slice[0] = colorlevels_slice_8; | 319 | if (!s->planar) { |
| 226 | s->colorlevels_slice[1] = colorlevels_preserve_slice_8; | 320 | s->colorlevels_slice[0] = colorlevels_slice_8; |
| 227 | if (s->bpp == 2) { | 321 | s->colorlevels_slice[1] = colorlevels_preserve_slice_8; |
| 228 | s->colorlevels_slice[0] = colorlevels_slice_16; | 322 | if (s->bpp == 2) { |
| 229 | s->colorlevels_slice[1] = colorlevels_preserve_slice_16; | 323 | s->colorlevels_slice[0] = colorlevels_slice_16; |
| 324 | s->colorlevels_slice[1] = colorlevels_preserve_slice_16; | ||
| 325 | } | ||
| 326 | } else { | ||
| 327 | switch (s->depth) { | ||
| 328 | case 8: | ||
| 329 | s->colorlevels_slice[0] = colorlevels_slice_8_planar; | ||
| 330 | s->colorlevels_slice[1] = colorlevels_preserve_slice_8_planar; | ||
| 331 | break; | ||
| 332 | case 9: | ||
| 333 | s->colorlevels_slice[0] = colorlevels_slice_9_planar; | ||
| 334 | s->colorlevels_slice[1] = colorlevels_preserve_slice_9_planar; | ||
| 335 | break; | ||
| 336 | case 10: | ||
| 337 | s->colorlevels_slice[0] = colorlevels_slice_10_planar; | ||
| 338 | s->colorlevels_slice[1] = colorlevels_preserve_slice_10_planar; | ||
| 339 | break; | ||
| 340 | case 12: | ||
| 341 | s->colorlevels_slice[0] = colorlevels_slice_12_planar; | ||
| 342 | s->colorlevels_slice[1] = colorlevels_preserve_slice_12_planar; | ||
| 343 | break; | ||
| 344 | case 14: | ||
| 345 | s->colorlevels_slice[0] = colorlevels_slice_14_planar; | ||
| 346 | s->colorlevels_slice[1] = colorlevels_preserve_slice_14_planar; | ||
| 347 | break; | ||
| 348 | case 16: | ||
| 349 | s->colorlevels_slice[0] = colorlevels_slice_16_planar; | ||
| 350 | s->colorlevels_slice[1] = colorlevels_preserve_slice_16_planar; | ||
| 351 | break; | ||
| 352 | } | ||
| 230 | } | 353 | } |
| 231 | 354 | ||
| 232 | return 0; | 355 | return 0; |
| @@ -255,8 +378,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 22 unmodified lines | |||
| 255 | td.h = inlink->h; | 378 | td.h = inlink->h; |
| 256 | td.dst_linesize = out->linesize[0]; | 379 | td.dst_linesize = out->linesize[0]; |
| 257 | td.src_linesize = in->linesize[0]; | 380 | td.src_linesize = in->linesize[0]; |
| 258 | td.srcrow = in->data[0]; | 381 | if (s->planar) { |
| 259 | td.dstrow = out->data[0]; | 382 | td.srcrow[R] = in->data[2]; |
| 383 | td.dstrow[R] = out->data[2]; | ||
| 384 | td.srcrow[G] = in->data[0]; | ||
| 385 | td.dstrow[G] = out->data[0]; | ||
| 386 | td.srcrow[B] = in->data[1]; | ||
| 387 | td.dstrow[B] = out->data[1]; | ||
| 388 | td.srcrow[A] = in->data[3]; | ||
| 389 | td.dstrow[A] = out->data[3]; | ||
| 390 | } else { | ||
| 391 | td.srcrow[R] = in->data[0] + s->rgba_map[R] * s->bpp; | ||
| 392 | td.dstrow[R] = out->data[0] + s->rgba_map[R] * s->bpp; | ||
| 393 | td.srcrow[G] = in->data[0] + s->rgba_map[G] * s->bpp; | ||
| 394 | td.dstrow[G] = out->data[0] + s->rgba_map[G] * s->bpp; | ||
| 395 | td.srcrow[B] = in->data[0] + s->rgba_map[B] * s->bpp; | ||
| 396 | td.dstrow[B] = out->data[0] + s->rgba_map[B] * s->bpp; | ||
| 397 | td.srcrow[A] = in->data[0] + s->rgba_map[A] * s->bpp; | ||
| 398 | td.dstrow[A] = out->data[0] + s->rgba_map[A] * s->bpp; | ||
| 399 | } | ||
| 260 | 400 | ||
| 261 | switch (s->bpp) { | 401 | switch (s->bpp) { |
| 262 | case 1: | 402 | case 1: |
| @@ -378,7 +518,13 @@ const AVFilter ff_vf_colorlevels = { · 115 unmodified lines | |||
| 378 | AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, | 518 | AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, |
| 379 | AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, | 519 | AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, |
| 380 | AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, | 520 | AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, |
| 381 | AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA), | 521 | AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, |
| 522 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, | ||
| 523 | AV_PIX_FMT_GBRP9, | ||
| 524 | AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, | ||
| 525 | AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, | ||
| 526 | AV_PIX_FMT_GBRP14, | ||
| 527 | AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16), | ||
| 382 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, | 528 | .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, |
| 383 | .process_command = ff_filter_process_command, | 529 | .process_command = ff_filter_process_command, |
| 384 | }; | 530 | }; |