History

avfilter/vf_colorlevels: add planar rgb formats support

Paul B Mahol committed 4 years ago

Commit 10c2ef11 parent 47c3b341 file · +189 −43Browse files

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

Unified · Split

libavfilter/vf_colorlevels.c+189−43
@@ -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
85AVFILTER_DEFINE_CLASS(colorlevels);88AVFILTER_DEFINE_CLASS(colorlevels);
86 89
87typedef struct ThreadData {90typedef 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
185static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)184static 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
192static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)191static 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
199static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)198static 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
206static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)205static 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
212static 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
219static 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
227static 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
235static 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
243static 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
251static 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
258static 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
265static 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
273static 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
281static 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
289static 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
297static 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};

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