1 /*
2 * Copyright 2011 Stefano Sabatini <stefano.sabatini-lala poste it>
3 * Copyright 2012 Nicolas George <nicolas.george normalesup org>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <string.h>
23
30
32
34 {
35 switch (pix_fmt) {
56 default: /* unsupported */
58 }
59 return 0;
60 }
61
64 int *is_packed_rgba,
uint8_t rgba_map_ptr[4])
65 {
67 int i;
70
72
73 if (*is_packed_rgba) {
75 for (i = 0; i < 4; i++)
76 dst_color[rgba_map[i]] = rgba_color[i];
77
79 for (i = 0; i < w; i++)
80 memcpy(line[0] + i * pixel_step[0], dst_color, pixel_step[0]);
81 if (rgba_map_ptr)
82 memcpy(rgba_map_ptr, rgba_map, sizeof(rgba_map[0]) * 4);
83 } else {
84 int plane;
85
86 dst_color[0] =
RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]);
87 dst_color[1] =
RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
88 dst_color[2] =
RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
89 dst_color[3] = rgba_color[3];
90
91 for (plane = 0; plane < 4; plane++) {
92 int line_size;
93 int hsub1 = (plane == 1 || plane == 2) ? hsub : 0;
94
95 pixel_step[plane] = 1;
98 memset(line[plane], dst_color[plane], line_size);
99 }
100 }
101
102 return 0;
103 }
104
107 int hsub,
int vsub,
int x,
int y,
int w,
int h)
108 {
109 int i, plane;
111
112 for (plane = 0; plane < 4 && dst[plane]; plane++) {
113 int hsub1 = plane == 1 || plane == 2 ? hsub : 0;
114 int vsub1 = plane == 1 || plane == 2 ? vsub : 0;
117
118 p = dst[plane] + (y >> vsub1) * dst_linesize[plane];
119 for (i = 0; i <
height; i++) {
120 memcpy(p + (x >> hsub1) * pixelstep[plane],
121 src[plane], width * pixelstep[plane]);
122 p += dst_linesize[plane];
123 }
124 }
125 }
126
128 uint8_t *
src[4],
int src_linesize[4],
int pixelstep[4],
129 int hsub,
int vsub,
int x,
int y,
int y2,
int w,
int h)
130 {
131 int i, plane;
133
134 for (plane = 0; plane < 4 && dst[plane]; plane++) {
135 int hsub1 = plane == 1 || plane == 2 ? hsub : 0;
136 int vsub1 = plane == 1 || plane == 2 ? vsub : 0;
139
140 p = dst[plane] + (y >> vsub1) * dst_linesize[plane];
141 for (i = 0; i <
height; i++) {
142 memcpy(p + (x >> hsub1) * pixelstep[plane],
143 src[plane] + src_linesize[plane]*(i+(y2>>vsub1)), width * pixelstep[plane]);
144 p += dst_linesize[plane];
145 }
146 }
147 }
148
150 {
153 unsigned i, nb_planes = 0;
155
162 /* for now, only 8-bits formats */
167 /* strange interleaving */
168 if (pixelstep[c->
plane] != 0 &&
172 if (pixelstep[c->
plane] >= 8)
175 }
177 return AVERROR(ENOSYS);
/* exclude NV12 and NV21 */
178 memset(draw, 0, sizeof(*draw));
186 }
190 return 0;
191 }
192
194 {
195 unsigned i;
197
198 if (rgba != color->
rgba)
199 memcpy(color->
rgba, rgba,
sizeof(color->
rgba));
203 for (i = 0; i < 4; i++)
204 color->
comp[0].
u8[rgba_map[i]] = rgba[i];
205 } else {
206 for (i = 0; i < 4; i++)
207 color->
comp[rgba_map[i]].
u8[0] = rgba[i];
208 }
210 /* assume YUV */
214 color->
comp[3].
u8[0] = rgba[3];
217 color->
comp[1].
u8[0] = rgba[3];
218 } else {
220 "Color conversion not implemented for %s\n", draw->
desc->
name);
221 memset(color, 128, sizeof(*color));
222 }
223 }
224
226 int plane,
int x,
int y)
227 {
228 return data[plane] +
229 (y >> draw->
vsub[plane]) * linesize[plane] +
231 }
232
234 uint8_t *dst[],
int dst_linesize[],
236 int dst_x, int dst_y, int src_x, int src_y,
237 int w, int h)
238 {
239 int plane,
y, wp, hp;
241
242 for (plane = 0; plane < draw->
nb_planes; plane++) {
243 p =
pointer_at(draw, src, src_linesize, plane, src_x, src_y);
244 q =
pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
247 for (y = 0; y < hp; y++) {
248 memcpy(q, p, wp);
249 p += src_linesize[plane];
250 q += dst_linesize[plane];
251 }
252 }
253 }
254
256 uint8_t *dst[],
int dst_linesize[],
257 int dst_x, int dst_y, int w, int h)
258 {
259 int plane, x,
y, wp, hp;
261
262 for (plane = 0; plane < draw->
nb_planes; plane++) {
263 p0 =
pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
266 if (!hp)
267 return;
268 p = p0;
269 /* copy first line from color */
270 for (x = 0; x < wp; x++) {
273 }
275 /* copy next lines from first line */
276 p = p0 + dst_linesize[plane];
277 for (y = 1; y < hp; y++) {
278 memcpy(p, p0, wp);
279 p += dst_linesize[plane];
280 }
281 }
282 }
283
284 /**
285 * Clip interval [x; x+w[ within [0; wmax[.
286 * The resulting w may be negative if the final interval is empty.
287 * dx, if not null, return the difference between in and out value of x.
288 */
290 {
291 if (dx)
292 *dx = 0;
293 if (*x < 0) {
294 if (dx)
295 *dx = -*x;
296 *w += *x;
297 *x = 0;
298 }
299 if (*x + *w > wmax)
300 *w = wmax - *x;
301 }
302
303 /**
304 * Decompose w pixels starting at x
305 * into start + (w starting at x) + end
306 * with x and w aligned on multiples of 1<<sub.
307 */
309 {
310 int mask = (1 << sub) - 1;
311
312 *start = (-*x) & mask;
314 *start =
FFMIN(*start, *w);
317 *w >>= sub;
318 }
319
321 {
322 return (draw->
comp_mask[plane] >> comp) & 1;
323 }
324
325 /* If alpha is in the [ 0 ; 0x1010101 ] range,
326 then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range,
327 and >> 24 gives a correct rounding. */
329 int dx, int w, unsigned hsub, int left, int right)
330 {
331 unsigned asrc = alpha *
src;
332 unsigned tau = 0x1010101 -
alpha;
333 int x;
334
335 if (left) {
336 unsigned suba = (left *
alpha) >> hsub;
337 *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
338 dst += dx;
339 }
340 for (x = 0; x < w; x++) {
341 *dst = (*dst * tau + asrc) >> 24;
342 dst += dx;
343 }
344 if (right) {
345 unsigned suba = (right *
alpha) >> hsub;
346 *dst = (*dst * (0x1010101 - suba) + src * suba) >> 24;
347 }
348 }
349
351 uint8_t *dst[],
int dst_linesize[],
352 int dst_w, int dst_h,
353 int x0, int y0, int w, int h)
354 {
355 unsigned alpha, nb_planes, nb_comp, plane,
comp;
356 int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom,
y;
358
359 /* TODO optimize if alpha = 0xFF */
362 if (w <= 0 || h <= 0 || !color->rgba[3])
363 return;
364 /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
365 alpha = 0x10203 * color->
rgba[3] + 0x2;
366 nb_planes = (draw->
nb_planes - 1) | 1;
/* eliminate alpha */
367 for (plane = 0; plane < nb_planes; plane++) {
369 p0 =
pointer_at(draw, dst, dst_linesize, plane, x0, y0);
370 w_sub = w;
371 h_sub = h;
372 x_sub = x0;
373 y_sub = y0;
376 for (comp = 0; comp < nb_comp; comp++) {
378 continue;
380 if (top) {
383 draw->
hsub[plane], left, right);
384 p += dst_linesize[plane];
385 }
386 for (y = 0; y < h_sub; y++) {
389 draw->
hsub[plane], left, right);
390 p += dst_linesize[plane];
391 }
392 if (bottom)
395 draw->
hsub[plane], left, right);
396 }
397 }
398 }
399
402 unsigned w,
unsigned h,
unsigned shift,
unsigned xm0)
403 {
404 unsigned xm, x,
y,
t = 0;
405 unsigned xmshf = 3 - l2depth;
406 unsigned xmmod = 7 >> l2depth;
407 unsigned mbits = (1 << (1 << l2depth)) - 1;
408 unsigned mmult = 255 / mbits;
409
410 for (y = 0; y < h; y++) {
411 xm = xm0;
412 for (x = 0; x < w; x++) {
413 t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
414 * mmult;
415 xm++;
416 }
417 mask += mask_linesize;
418 }
419 alpha = (t >>
shift) * alpha;
420 *dst = ((0x1010101 -
alpha) * *dst + alpha * src) >> 24;
421 }
422
425 uint8_t *
mask,
int mask_linesize,
int l2depth,
int w,
426 unsigned hsub, unsigned vsub,
427 int xm, int left, int right, int hband)
428 {
429 int x;
430
431 if (left) {
432 blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
433 left, hband, hsub + vsub, xm);
434 dst += dst_delta;
435 xm += left;
436 }
437 for (x = 0; x < w; x++) {
438 blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
439 1 << hsub, hband, hsub + vsub, xm);
440 dst += dst_delta;
441 xm += 1 << hsub;
442 }
443 if (right)
444 blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
445 right, hband, hsub + vsub, xm);
446 }
447
449 uint8_t *dst[],
int dst_linesize[],
int dst_w,
int dst_h,
450 uint8_t *
mask,
int mask_linesize,
int mask_w,
int mask_h,
451 int l2depth, unsigned endianness, int x0, int y0)
452 {
453 unsigned alpha, nb_planes, nb_comp, plane,
comp;
454 int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom,
y;
456
459 mask += ym0 * mask_linesize;
460 if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
461 return;
462 /* alpha is in the [ 0 ; 0x10203 ] range,
463 alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
464 alpha = (0x10307 * color->
rgba[3] + 0x3) >> 8;
465 nb_planes = (draw->
nb_planes - 1) | 1;
/* eliminate alpha */
466 for (plane = 0; plane < nb_planes; plane++) {
468 p0 =
pointer_at(draw, dst, dst_linesize, plane, x0, y0);
469 w_sub = mask_w;
470 h_sub = mask_h;
471 x_sub = x0;
472 y_sub = y0;
475 for (comp = 0; comp < nb_comp; comp++) {
477 continue;
480 if (top) {
482 color->
comp[plane].
u8[comp], alpha,
483 m, mask_linesize, l2depth, w_sub,
484 draw->
hsub[plane], draw->
vsub[plane],
485 xm0, left, right, top);
486 p += dst_linesize[plane];
487 m += top * mask_linesize;
488 }
489 for (y = 0; y < h_sub; y++) {
491 color->
comp[plane].
u8[comp], alpha,
492 m, mask_linesize, l2depth, w_sub,
493 draw->
hsub[plane], draw->
vsub[plane],
494 xm0, left, right, 1 << draw->
vsub[plane]);
495 p += dst_linesize[plane];
496 m += mask_linesize << draw->
vsub[plane];
497 }
498 if (bottom)
500 color->
comp[plane].
u8[comp], alpha,
501 m, mask_linesize, l2depth, w_sub,
502 draw->
hsub[plane], draw->
vsub[plane],
503 xm0, left, right, bottom);
504 }
505 }
506 }
507
510 {
512
513 if (!shift)
515 if (round_dir >= 0)
516 value += round_dir ? (1 <<
shift) - 1 : 1 << (shift - 1);
517 return (value >> shift) <<
shift;
518 }
519
521 {
525
528 pix_fmts[n++] = i;
531 }
532
533 #ifdef TEST
534
535 #undef printf
536
538 {
544
548 continue;
549 printf(
"Testing %s...%*s", desc->
name,
550 (
int)(16 - strlen(desc->
name)),
"");
552 if (r < 0) {
555 printf("no: %s\n", buf);
556 continue;
557 }
559 for (i = 0; i <
sizeof(
color); i++)
560 if (((
uint8_t *)&color)[i] != 128)
561 break;
562 if (i == sizeof(color)) {
563 printf("fallback color\n");
564 continue;
565 }
566 printf("ok\n");
567 }
568 return 0;
569 }
570
571 #endif