1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * misc image utilities
22 */
23
34
37 {
39 memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0]));
40 if (max_pixstep_comps)
41 memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0]));
42
43 for (
i = 0;
i < 4;
i++) {
45 if (
comp->step > max_pixsteps[
comp->plane]) {
46 max_pixsteps[
comp->plane] =
comp->step;
47 if (max_pixstep_comps)
48 max_pixstep_comps[
comp->plane] =
i;
49 }
50 }
51 }
52
53 static inline
55 int max_step, int max_step_comp,
57 {
58 int s, shifted_w, linesize;
59
62
65 s = (max_step_comp == 1 || max_step_comp == 2) ?
desc->log2_chroma_w : 0;
66 shifted_w = ((
width + (1 <<
s) - 1)) >>
s;
67 if (shifted_w && max_step > INT_MAX / shifted_w)
69 linesize = max_step * shifted_w;
70
72 linesize = (linesize + 7) >> 3;
73 return linesize;
74 }
75
77 {
79 int max_step [4]; /* max pixel step for each plane */
80 int max_step_comp[4]; /* the component for each plane which has the max pixel step */
81
84
87 }
88
90 {
93 int max_step [4]; /* max pixel step for each plane */
94 int max_step_comp[4]; /* the component for each plane which has the max pixel step */
95
96 memset(linesizes, 0, 4*sizeof(linesizes[0]));
97
100
102 for (
i = 0;
i < 4;
i++) {
106 }
107
108 return 0;
109 }
110
112 int height,
const ptrdiff_t linesizes[4])
113 {
114 int i, has_plane[4] = { 0 };
115
118
121
122 if (linesizes[0] > SIZE_MAX /
height)
125
127 sizes[1] = 256 * 4;
/* palette is stored here as 256 32 bits words */
128 return 0;
129 }
130
131 for (
i = 0;
i < 4;
i++)
132 has_plane[
desc->comp[
i].plane] = 1;
133
134 for (
i = 1;
i < 4 && has_plane[
i];
i++) {
135 int h,
s = (
i == 1 ||
i == 2) ?
desc->log2_chroma_h : 0;
137 if (linesizes[
i] > SIZE_MAX /
h)
139 sizes[
i] = (size_t)
h * linesizes[
i];
140 }
141
142 return 0;
143 }
144
146 uint8_t *ptr, const int linesizes[4])
147 {
149 ptrdiff_t linesizes1[4];
151
152 memset(
data , 0,
sizeof(
data[0])*4);
153
154 for (
i = 0;
i < 4;
i++)
155 linesizes1[
i] = linesizes[
i];
156
160
162 for (
i = 0;
i < 4;
i++) {
166 }
167
168 if (!ptr)
170
174
176 }
177
179 {
181
182 for (
i = 0;
i < 256;
i++) {
184
190 break;
195 break;
200 break;
205 break;
208 break;
209 default:
211 }
212 pal[
i] =
b + (
g << 8) + (
r << 16) + (0xFF
U << 24);
213 }
214
215 return 0;
216 }
217
220 {
223 ptrdiff_t linesizes1[4];
224 size_t total_size,
sizes[4];
225 uint8_t *buf;
226
229
234
235 for (
i = 0;
i < 4;
i++) {
237 linesizes1[
i] = linesizes[
i];
238 }
239
243 for (
i = 0;
i < 4;
i++) {
244 if (total_size > SIZE_MAX -
sizes[
i])
247 }
249 if (!buf)
254 }
261 }
262 }
263
266 /* zero-initialize the padding before the palette */
267 memset(
pointers[0] + linesizes[0] *
h, 0,
269 }
270
272 }
273
279
285 .log_level_offset_offset = offsetof(
ImgUtils, log_offset),
286 .parent_log_context_offset = offsetof(
ImgUtils, log_ctx),
287 };
288
290 {
293 .log_offset = log_offset,
294 .log_ctx = log_ctx,
295 };
300
301 if ((
int)
w<=0 || (
int)h<=0 || stride >= INT_MAX ||
stride*(uint64_t)(
h+128) >= INT_MAX) {
304 }
305
306 if (max_pixels < INT64_MAX) {
307 if (
w*(int64_t)
h > max_pixels) {
309 "Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",
312 }
313 }
314
315 return 0;
316 }
317
319 {
321 }
322
324 {
325 int64_t scaled_dim;
326
327 if (sar.
den <= 0 || sar.
num < 0)
329
331 return 0;
332
335 else
337
338 if (scaled_dim > 0)
339 return 0;
340
342 }
343
345 const uint8_t *
src, ptrdiff_t src_linesize,
346 ptrdiff_t bytewidth,
int height)
347 {
349 return;
353 memcpy(dst,
src, bytewidth);
354 dst += dst_linesize;
356 }
357 }
358
360 const uint8_t *
src, ptrdiff_t src_linesize,
361 ptrdiff_t bytewidth,
int height)
362 {
364
365 #if ARCH_X86
368 #endif
369
372 }
373
375 const uint8_t *
src,
int src_linesize,
376 int bytewidth,
int height)
377 {
379 }
380
381 static void image_copy(uint8_t *dst_data[4],
const ptrdiff_t dst_linesizes[4],
382 const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
384 void (*
copy_plane)(uint8_t *, ptrdiff_t,
const uint8_t *,
385 ptrdiff_t, ptrdiff_t, int))
386 {
388
390 return;
391
394 src_data[0], src_linesizes[0],
396 /* copy the palette */
398 memcpy(dst_data[1], src_data[1], 4*256);
399 } else {
400 int i, planes_nb = 0;
401
402 for (
i = 0;
i <
desc->nb_components;
i++)
403 planes_nb =
FFMAX(planes_nb,
desc->comp[
i].plane + 1);
404
405 for (
i = 0;
i < planes_nb;
i++) {
408 if (bwidth < 0) {
410 return;
411 }
412 if (
i == 1 ||
i == 2) {
414 }
416 src_data[
i], src_linesizes[
i],
418 }
419 }
420 }
421
423 const uint8_t *src_data[4], const int src_linesizes[4],
425 {
426 ptrdiff_t dst_linesizes1[4], src_linesizes1[4];
428
429 for (
i = 0;
i < 4;
i++) {
430 dst_linesizes1[
i] = dst_linesizes[
i];
431 src_linesizes1[
i] = src_linesizes[
i];
432 }
433
436 }
437
439 const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4],
441 {
444 }
445
449 {
451
455
459
460 for (
i = 0;
i < 4;
i++)
462
464 }
465
468 {
470 int linesize[4];
471 ptrdiff_t aligned_linesize[4];
476
480
484
485 for (
i = 0;
i < 4;
i++)
487
491
493 for (
i = 0;
i < 4;
i++) {
497 }
499 }
500
502 const uint8_t * const src_data[4],
503 const int src_linesize[4],
506 {
507 int i, j, nb_planes = 0, linesize[4];
511
514
515 for (
i = 0;
i <
desc->nb_components;
i++)
516 nb_planes =
FFMAX(
desc->comp[
i].plane, nb_planes);
517
518 nb_planes++;
519
522
523 for (
i = 0;
i < nb_planes;
i++) {
524 int h,
shift = (
i == 1 ||
i == 2) ?
desc->log2_chroma_h : 0;
525 const uint8_t *
src = src_data[
i];
527
528 for (j = 0; j <
h; j++) {
529 memcpy(dst,
src, linesize[
i]);
531 src += src_linesize[
i];
532 }
533 }
534
536 uint32_t *
d32 = (uint32_t *)dst;
537
538 for (
i = 0;
i<256;
i++)
540 }
541
543 }
544
545 // Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear
546 // bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e.
547 // dst_size%clear_size!=0), the remaining data will be filled with the beginning
548 // of the clear data only.
549 static void memset_bytes(uint8_t *dst,
size_t dst_size, uint8_t *clear,
550 size_t clear_size)
551 {
552 int same = 1;
554
555 if (!clear_size)
556 return;
557
558 // Reduce to memset() if possible.
559 for (
i = 0;
i < clear_size;
i++) {
560 if (clear[
i] != clear[0]) {
561 same = 0;
562 break;
563 }
564 }
565 if (same)
566 clear_size = 1;
567
568 if (clear_size == 1) {
569 memset(dst, clear[0], dst_size);
570 } else {
571 if (clear_size > dst_size)
572 clear_size = dst_size;
573 memcpy(dst, clear, clear_size);
575 }
576 }
577
578 // Maximum size in bytes of a plane element (usually a pixel, or multiple pixels
579 // if it's a subsampled packed format).
580 #define MAX_BLOCK_SIZE 32
581
585 {
588 // A pixel or a group of pixels on each plane, with a value that represents black.
589 // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases.
590 uint8_t clear_block[4][
MAX_BLOCK_SIZE] = {{0}};
// clear padding with 0
591 int clear_block_size[4] = {0};
592 ptrdiff_t plane_line_bytes[4] = {0};
595
598
601
607 if (nb_planes != 1 || !(
rgb || mono) || bytewidth < 1)
609
610 if (!dst_data)
611 return 0;
612
614
615 // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.)
617 memset(
data, fill, bytewidth);
618 data += dst_linesize[0];
619 }
620 return 0;
621 }
622
623 for (
c = 0;
c <
desc->nb_components;
c++) {
625
626 // We try to operate on entire non-subsampled pixel groups (for
627 // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels).
629
632 }
633
634 // Create a byte array for clearing 1 pixel (sometimes several pixels).
635 for (
c = 0;
c <
desc->nb_components;
c++) {
637 // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.)
638 int w = clear_block_size[
comp.plane] /
comp.step;
639 uint8_t *c_data[4];
640 const int c_linesize[4] = {0};
643 int x;
644
651
652 if (
c == 0 && limited) {
654 }
else if ((
c == 1 ||
c == 2) && !
rgb) {
657 // (Assume even limited YUV uses full range alpha.)
659 }
660
661 for (x = 0; x <
w; x++)
663
664 for (x = 0; x < 4; x++)
665 c_data[x] = &clear_block[x][0];
666
668 }
669
670 for (plane = 0; plane < nb_planes; plane++) {
672 if (plane_line_bytes[plane] < 0)
674 }
675
676 if (!dst_data)
677 return 0;
678
679 for (plane = 0; plane < nb_planes; plane++) {
680 size_t bytewidth = plane_line_bytes[plane];
681 uint8_t *
data = dst_data[plane];
682 int chroma_div = plane == 1 || plane == 2 ?
desc->log2_chroma_h : 0;
683 int plane_h = ((
height + ( 1 << chroma_div) - 1)) >> chroma_div;
684
685 for (; plane_h > 0; plane_h--) {
686 memset_bytes(
data, bytewidth, &clear_block[plane][0], clear_block_size[plane]);
687 data += dst_linesize[plane];
688 }
689 }
690
691 return 0;
692 }