imgconvert.c
Go to the documentation of this file.
1 /*
2  * Misc image conversion routines
3  * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
27 /* TODO:
28  * - write 'ffimg' program to test all the image related stuff
29  * - move all api to slice based system
30  * - integrate deinterlacing, postprocessing and scaling in the conversion process
31  */
32 
33 #include "avcodec.h"
34 #include "dsputil.h"
35 #include "internal.h"
36 #include "imgconvert.h"
37 #include "libavutil/colorspace.h"
38 #include "libavutil/pixdesc.h"
39 #include "libavutil/imgutils.h"
40 
41 #if HAVE_MMX && HAVE_YASM
42 #include "x86/dsputil_mmx.h"
43 #endif
44 
45 #define FF_COLOR_RGB 0
46 #define FF_COLOR_GRAY 1
47 #define FF_COLOR_YUV 2
48 #define FF_COLOR_YUV_JPEG 3
50 #define FF_PIXEL_PLANAR 0
51 #define FF_PIXEL_PACKED 1
52 #define FF_PIXEL_PALETTE 2
54 #if HAVE_MMX && HAVE_YASM
55 #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
56 #define deinterlace_line ff_deinterlace_line_mmx
57 #else
58 #define deinterlace_line_inplace deinterlace_line_inplace_c
59 #define deinterlace_line deinterlace_line_c
60 #endif
61 
62 typedef struct PixFmtInfo {
63  uint8_t nb_channels;
64  uint8_t color_type;
65  uint8_t pixel_type;
66  uint8_t is_alpha : 1;
67  uint8_t depth;
68 } PixFmtInfo;
69 
70 /* this table gives more information about formats */
72  /* YUV formats */
73  [PIX_FMT_YUV420P] = {
74  .nb_channels = 3,
75  .color_type = FF_COLOR_YUV,
76  .pixel_type = FF_PIXEL_PLANAR,
77  .depth = 8,
78  },
79  [PIX_FMT_YUV422P] = {
80  .nb_channels = 3,
81  .color_type = FF_COLOR_YUV,
82  .pixel_type = FF_PIXEL_PLANAR,
83  .depth = 8,
84  },
85  [PIX_FMT_YUV444P] = {
86  .nb_channels = 3,
87  .color_type = FF_COLOR_YUV,
88  .pixel_type = FF_PIXEL_PLANAR,
89  .depth = 8,
90  },
91  [PIX_FMT_YUYV422] = {
92  .nb_channels = 1,
93  .color_type = FF_COLOR_YUV,
94  .pixel_type = FF_PIXEL_PACKED,
95  .depth = 8,
96  },
97  [PIX_FMT_UYVY422] = {
98  .nb_channels = 1,
99  .color_type = FF_COLOR_YUV,
100  .pixel_type = FF_PIXEL_PACKED,
101  .depth = 8,
102  },
103  [PIX_FMT_YUV410P] = {
104  .nb_channels = 3,
105  .color_type = FF_COLOR_YUV,
106  .pixel_type = FF_PIXEL_PLANAR,
107  .depth = 8,
108  },
109  [PIX_FMT_YUV411P] = {
110  .nb_channels = 3,
111  .color_type = FF_COLOR_YUV,
112  .pixel_type = FF_PIXEL_PLANAR,
113  .depth = 8,
114  },
115  [PIX_FMT_YUV440P] = {
116  .nb_channels = 3,
117  .color_type = FF_COLOR_YUV,
118  .pixel_type = FF_PIXEL_PLANAR,
119  .depth = 8,
120  },
121  [PIX_FMT_YUV420P16LE] = {
122  .nb_channels = 3,
123  .color_type = FF_COLOR_YUV,
124  .pixel_type = FF_PIXEL_PLANAR,
125  .depth = 16,
126  },
127  [PIX_FMT_YUV422P16LE] = {
128  .nb_channels = 3,
129  .color_type = FF_COLOR_YUV,
130  .pixel_type = FF_PIXEL_PLANAR,
131  .depth = 16,
132  },
133  [PIX_FMT_YUV444P16LE] = {
134  .nb_channels = 3,
135  .color_type = FF_COLOR_YUV,
136  .pixel_type = FF_PIXEL_PLANAR,
137  .depth = 16,
138  },
139  [PIX_FMT_YUV420P16BE] = {
140  .nb_channels = 3,
141  .color_type = FF_COLOR_YUV,
142  .pixel_type = FF_PIXEL_PLANAR,
143  .depth = 16,
144  },
145  [PIX_FMT_YUV422P16BE] = {
146  .nb_channels = 3,
147  .color_type = FF_COLOR_YUV,
148  .pixel_type = FF_PIXEL_PLANAR,
149  .depth = 16,
150  },
151  [PIX_FMT_YUV444P16BE] = {
152  .nb_channels = 3,
153  .color_type = FF_COLOR_YUV,
154  .pixel_type = FF_PIXEL_PLANAR,
155  .depth = 16,
156  },
157 
158 
159  /* YUV formats with alpha plane */
160  [PIX_FMT_YUVA420P] = {
161  .nb_channels = 4,
162  .color_type = FF_COLOR_YUV,
163  .pixel_type = FF_PIXEL_PLANAR,
164  .depth = 8,
165  },
166 
167  /* JPEG YUV */
168  [PIX_FMT_YUVJ420P] = {
169  .nb_channels = 3,
170  .color_type = FF_COLOR_YUV_JPEG,
171  .pixel_type = FF_PIXEL_PLANAR,
172  .depth = 8,
173  },
174  [PIX_FMT_YUVJ422P] = {
175  .nb_channels = 3,
176  .color_type = FF_COLOR_YUV_JPEG,
177  .pixel_type = FF_PIXEL_PLANAR,
178  .depth = 8,
179  },
180  [PIX_FMT_YUVJ444P] = {
181  .nb_channels = 3,
182  .color_type = FF_COLOR_YUV_JPEG,
183  .pixel_type = FF_PIXEL_PLANAR,
184  .depth = 8,
185  },
186  [PIX_FMT_YUVJ440P] = {
187  .nb_channels = 3,
188  .color_type = FF_COLOR_YUV_JPEG,
189  .pixel_type = FF_PIXEL_PLANAR,
190  .depth = 8,
191  },
192 
193  /* RGB formats */
194  [PIX_FMT_RGB24] = {
195  .nb_channels = 3,
196  .color_type = FF_COLOR_RGB,
197  .pixel_type = FF_PIXEL_PACKED,
198  .depth = 8,
199  },
200  [PIX_FMT_BGR24] = {
201  .nb_channels = 3,
202  .color_type = FF_COLOR_RGB,
203  .pixel_type = FF_PIXEL_PACKED,
204  .depth = 8,
205  },
206  [PIX_FMT_ARGB] = {
207  .nb_channels = 4, .is_alpha = 1,
208  .color_type = FF_COLOR_RGB,
209  .pixel_type = FF_PIXEL_PACKED,
210  .depth = 8,
211  },
212  [PIX_FMT_RGB48BE] = {
213  .nb_channels = 3,
214  .color_type = FF_COLOR_RGB,
215  .pixel_type = FF_PIXEL_PACKED,
216  .depth = 16,
217  },
218  [PIX_FMT_RGB48LE] = {
219  .nb_channels = 3,
220  .color_type = FF_COLOR_RGB,
221  .pixel_type = FF_PIXEL_PACKED,
222  .depth = 16,
223  },
224  [PIX_FMT_RGB565BE] = {
225  .nb_channels = 3,
226  .color_type = FF_COLOR_RGB,
227  .pixel_type = FF_PIXEL_PACKED,
228  .depth = 5,
229  },
230  [PIX_FMT_RGB565LE] = {
231  .nb_channels = 3,
232  .color_type = FF_COLOR_RGB,
233  .pixel_type = FF_PIXEL_PACKED,
234  .depth = 5,
235  },
236  [PIX_FMT_RGB555BE] = {
237  .nb_channels = 3,
238  .color_type = FF_COLOR_RGB,
239  .pixel_type = FF_PIXEL_PACKED,
240  .depth = 5,
241  },
242  [PIX_FMT_RGB555LE] = {
243  .nb_channels = 3,
244  .color_type = FF_COLOR_RGB,
245  .pixel_type = FF_PIXEL_PACKED,
246  .depth = 5,
247  },
248  [PIX_FMT_RGB444BE] = {
249  .nb_channels = 3,
250  .color_type = FF_COLOR_RGB,
251  .pixel_type = FF_PIXEL_PACKED,
252  .depth = 4,
253  },
254  [PIX_FMT_RGB444LE] = {
255  .nb_channels = 3,
256  .color_type = FF_COLOR_RGB,
257  .pixel_type = FF_PIXEL_PACKED,
258  .depth = 4,
259  },
260 
261  /* gray / mono formats */
262  [PIX_FMT_GRAY16BE] = {
263  .nb_channels = 1,
264  .color_type = FF_COLOR_GRAY,
265  .pixel_type = FF_PIXEL_PLANAR,
266  .depth = 16,
267  },
268  [PIX_FMT_GRAY16LE] = {
269  .nb_channels = 1,
270  .color_type = FF_COLOR_GRAY,
271  .pixel_type = FF_PIXEL_PLANAR,
272  .depth = 16,
273  },
274  [PIX_FMT_GRAY8] = {
275  .nb_channels = 1,
276  .color_type = FF_COLOR_GRAY,
277  .pixel_type = FF_PIXEL_PLANAR,
278  .depth = 8,
279  },
280  [PIX_FMT_MONOWHITE] = {
281  .nb_channels = 1,
282  .color_type = FF_COLOR_GRAY,
283  .pixel_type = FF_PIXEL_PLANAR,
284  .depth = 1,
285  },
286  [PIX_FMT_MONOBLACK] = {
287  .nb_channels = 1,
288  .color_type = FF_COLOR_GRAY,
289  .pixel_type = FF_PIXEL_PLANAR,
290  .depth = 1,
291  },
292 
293  /* paletted formats */
294  [PIX_FMT_PAL8] = {
295  .nb_channels = 4, .is_alpha = 1,
296  .color_type = FF_COLOR_RGB,
297  .pixel_type = FF_PIXEL_PALETTE,
298  .depth = 8,
299  },
300  [PIX_FMT_UYYVYY411] = {
301  .nb_channels = 1,
302  .color_type = FF_COLOR_YUV,
303  .pixel_type = FF_PIXEL_PACKED,
304  .depth = 8,
305  },
306  [PIX_FMT_ABGR] = {
307  .nb_channels = 4, .is_alpha = 1,
308  .color_type = FF_COLOR_RGB,
309  .pixel_type = FF_PIXEL_PACKED,
310  .depth = 8,
311  },
312  [PIX_FMT_BGR565BE] = {
313  .nb_channels = 3,
314  .color_type = FF_COLOR_RGB,
315  .pixel_type = FF_PIXEL_PACKED,
316  .depth = 5,
317  },
318  [PIX_FMT_BGR565LE] = {
319  .nb_channels = 3,
320  .color_type = FF_COLOR_RGB,
321  .pixel_type = FF_PIXEL_PACKED,
322  .depth = 5,
323  },
324  [PIX_FMT_BGR555BE] = {
325  .nb_channels = 3,
326  .color_type = FF_COLOR_RGB,
327  .pixel_type = FF_PIXEL_PACKED,
328  .depth = 5,
329  },
330  [PIX_FMT_BGR555LE] = {
331  .nb_channels = 3,
332  .color_type = FF_COLOR_RGB,
333  .pixel_type = FF_PIXEL_PACKED,
334  .depth = 5,
335  },
336  [PIX_FMT_BGR444BE] = {
337  .nb_channels = 3,
338  .color_type = FF_COLOR_RGB,
339  .pixel_type = FF_PIXEL_PACKED,
340  .depth = 4,
341  },
342  [PIX_FMT_BGR444LE] = {
343  .nb_channels = 3,
344  .color_type = FF_COLOR_RGB,
345  .pixel_type = FF_PIXEL_PACKED,
346  .depth = 4,
347  },
348  [PIX_FMT_RGB8] = {
349  .nb_channels = 1,
350  .color_type = FF_COLOR_RGB,
351  .pixel_type = FF_PIXEL_PACKED,
352  .depth = 8,
353  },
354  [PIX_FMT_RGB4] = {
355  .nb_channels = 1,
356  .color_type = FF_COLOR_RGB,
357  .pixel_type = FF_PIXEL_PACKED,
358  .depth = 4,
359  },
360  [PIX_FMT_RGB4_BYTE] = {
361  .nb_channels = 1,
362  .color_type = FF_COLOR_RGB,
363  .pixel_type = FF_PIXEL_PACKED,
364  .depth = 8,
365  },
366  [PIX_FMT_BGR8] = {
367  .nb_channels = 1,
368  .color_type = FF_COLOR_RGB,
369  .pixel_type = FF_PIXEL_PACKED,
370  .depth = 8,
371  },
372  [PIX_FMT_BGR4] = {
373  .nb_channels = 1,
374  .color_type = FF_COLOR_RGB,
375  .pixel_type = FF_PIXEL_PACKED,
376  .depth = 4,
377  },
378  [PIX_FMT_BGR4_BYTE] = {
379  .nb_channels = 1,
380  .color_type = FF_COLOR_RGB,
381  .pixel_type = FF_PIXEL_PACKED,
382  .depth = 8,
383  },
384  [PIX_FMT_NV12] = {
385  .nb_channels = 2,
386  .color_type = FF_COLOR_YUV,
387  .pixel_type = FF_PIXEL_PLANAR,
388  .depth = 8,
389  },
390  [PIX_FMT_NV21] = {
391  .nb_channels = 2,
392  .color_type = FF_COLOR_YUV,
393  .pixel_type = FF_PIXEL_PLANAR,
394  .depth = 8,
395  },
396 
397  [PIX_FMT_BGRA] = {
398  .nb_channels = 4, .is_alpha = 1,
399  .color_type = FF_COLOR_RGB,
400  .pixel_type = FF_PIXEL_PACKED,
401  .depth = 8,
402  },
403  [PIX_FMT_RGBA] = {
404  .nb_channels = 4, .is_alpha = 1,
405  .color_type = FF_COLOR_RGB,
406  .pixel_type = FF_PIXEL_PACKED,
407  .depth = 8,
408  },
409 };
410 
411 void avcodec_get_chroma_sub_sample(enum PixelFormat pix_fmt, int *h_shift, int *v_shift)
412 {
415 }
416 
417 #if FF_API_GET_PIX_FMT_NAME
418 const char *avcodec_get_pix_fmt_name(enum PixelFormat pix_fmt)
419 {
420  return av_get_pix_fmt_name(pix_fmt);
421 }
422 #endif
423 
425 {
427 }
428 
429 int avpicture_fill(AVPicture *picture, uint8_t *ptr,
430  enum PixelFormat pix_fmt, int width, int height)
431 {
432  int ret;
433 
434  if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
435  return ret;
436 
437  if ((ret = av_image_fill_linesizes(picture->linesize, pix_fmt, width)) < 0)
438  return ret;
439 
440  return av_image_fill_pointers(picture->data, pix_fmt, height, ptr, picture->linesize);
441 }
442 
443 int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, int height,
444  unsigned char *dest, int dest_size)
445 {
446  int i, j, nb_planes = 0, linesizes[4];
448  int size = avpicture_get_size(pix_fmt, width, height);
449 
450  if (size > dest_size || size < 0)
451  return AVERROR(EINVAL);
452 
453  for (i = 0; i < desc->nb_components; i++)
454  nb_planes = FFMAX(desc->comp[i].plane, nb_planes);
455  nb_planes++;
456 
457  av_image_fill_linesizes(linesizes, pix_fmt, width);
458  for (i = 0; i < nb_planes; i++) {
459  int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
460  const unsigned char *s = src->data[i];
461  h = (height + (1 << shift) - 1) >> shift;
462 
463  for (j = 0; j < h; j++) {
464  memcpy(dest, s, linesizes[i]);
465  dest += linesizes[i];
466  s += src->linesize[i];
467  }
468  }
469 
470  if (desc->flags & PIX_FMT_PAL)
471  memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
472 
473  return size;
474 }
475 
477 {
478  AVPicture dummy_pict;
479  if(av_image_check_size(width, height, 0, NULL))
480  return -1;
481  switch (pix_fmt) {
482  case PIX_FMT_RGB8:
483  case PIX_FMT_BGR8:
484  case PIX_FMT_RGB4_BYTE:
485  case PIX_FMT_BGR4_BYTE:
486  case PIX_FMT_GRAY8:
487  // do not include palette for these pseudo-paletted formats
488  return width * height;
489  }
490  return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
491 }
492 
493 int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt,
494  int has_alpha)
495 {
496  const PixFmtInfo *pf, *ps;
497  const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt];
498  const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt];
499  int loss;
500 
501  ps = &pix_fmt_info[src_pix_fmt];
502 
503  /* compute loss */
504  loss = 0;
505  pf = &pix_fmt_info[dst_pix_fmt];
506  if (pf->depth < ps->depth ||
507  ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE ||
508  dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) &&
509  (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE ||
510  src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE)))
511  loss |= FF_LOSS_DEPTH;
512  if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
513  dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
514  loss |= FF_LOSS_RESOLUTION;
515  switch(pf->color_type) {
516  case FF_COLOR_RGB:
517  if (ps->color_type != FF_COLOR_RGB &&
518  ps->color_type != FF_COLOR_GRAY)
519  loss |= FF_LOSS_COLORSPACE;
520  break;
521  case FF_COLOR_GRAY:
522  if (ps->color_type != FF_COLOR_GRAY)
523  loss |= FF_LOSS_COLORSPACE;
524  break;
525  case FF_COLOR_YUV:
526  if (ps->color_type != FF_COLOR_YUV)
527  loss |= FF_LOSS_COLORSPACE;
528  break;
529  case FF_COLOR_YUV_JPEG:
530  if (ps->color_type != FF_COLOR_YUV_JPEG &&
531  ps->color_type != FF_COLOR_YUV &&
532  ps->color_type != FF_COLOR_GRAY)
533  loss |= FF_LOSS_COLORSPACE;
534  break;
535  default:
536  /* fail safe test */
537  if (ps->color_type != pf->color_type)
538  loss |= FF_LOSS_COLORSPACE;
539  break;
540  }
541  if (pf->color_type == FF_COLOR_GRAY &&
542  ps->color_type != FF_COLOR_GRAY)
543  loss |= FF_LOSS_CHROMA;
544  if (!pf->is_alpha && (ps->is_alpha && has_alpha))
545  loss |= FF_LOSS_ALPHA;
546  if (pf->pixel_type == FF_PIXEL_PALETTE &&
548  loss |= FF_LOSS_COLORQUANT;
549  return loss;
550 }
551 
553 {
554  int bits;
555  const PixFmtInfo *pf;
557 
558  pf = &pix_fmt_info[pix_fmt];
559  switch(pf->pixel_type) {
560  case FF_PIXEL_PACKED:
561  switch(pix_fmt) {
562  case PIX_FMT_YUYV422:
563  case PIX_FMT_UYVY422:
564  case PIX_FMT_RGB565BE:
565  case PIX_FMT_RGB565LE:
566  case PIX_FMT_RGB555BE:
567  case PIX_FMT_RGB555LE:
568  case PIX_FMT_RGB444BE:
569  case PIX_FMT_RGB444LE:
570  case PIX_FMT_BGR565BE:
571  case PIX_FMT_BGR565LE:
572  case PIX_FMT_BGR555BE:
573  case PIX_FMT_BGR555LE:
574  case PIX_FMT_BGR444BE:
575  case PIX_FMT_BGR444LE:
576  bits = 16;
577  break;
578  case PIX_FMT_UYYVYY411:
579  bits = 12;
580  break;
581  default:
582  bits = pf->depth * pf->nb_channels;
583  break;
584  }
585  break;
586  case FF_PIXEL_PLANAR:
587  if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) {
588  bits = pf->depth * pf->nb_channels;
589  } else {
590  bits = pf->depth + ((2 * pf->depth) >>
591  (desc->log2_chroma_w + desc->log2_chroma_h));
592  }
593  break;
594  case FF_PIXEL_PALETTE:
595  bits = 8;
596  break;
597  default:
598  bits = -1;
599  break;
600  }
601  return bits;
602 }
603 
604 static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask,
605  enum PixelFormat src_pix_fmt,
606  int has_alpha,
607  int loss_mask)
608 {
609  int dist, i, loss, min_dist;
610  enum PixelFormat dst_pix_fmt;
611 
612  /* find exact color match with smallest size */
613  dst_pix_fmt = PIX_FMT_NONE;
614  min_dist = 0x7fffffff;
615  /* test only the first 64 pixel formats to avoid undefined behaviour */
616  for (i = 0; i < 64; i++) {
617  if (pix_fmt_mask & (1ULL << i)) {
618  loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
619  if (loss == 0) {
620  dist = avg_bits_per_pixel(i);
621  if (dist < min_dist) {
622  min_dist = dist;
623  dst_pix_fmt = i;
624  }
625  }
626  }
627  }
628  return dst_pix_fmt;
629 }
630 
631 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
632  int has_alpha, int *loss_ptr)
633 {
634  enum PixelFormat dst_pix_fmt;
635  int loss_mask, i;
636  static const int loss_mask_order[] = {
637  ~0, /* no loss first */
638  ~FF_LOSS_ALPHA,
642  ~FF_LOSS_DEPTH,
643  0,
644  };
645 
646  /* try with successive loss */
647  i = 0;
648  for(;;) {
649  loss_mask = loss_mask_order[i++];
650  dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
651  has_alpha, loss_mask);
652  if (dst_pix_fmt >= 0)
653  goto found;
654  if (loss_mask == 0)
655  break;
656  }
657  return PIX_FMT_NONE;
658  found:
659  if (loss_ptr)
660  *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
661  return dst_pix_fmt;
662 }
663 
664 void av_picture_copy(AVPicture *dst, const AVPicture *src,
665  enum PixelFormat pix_fmt, int width, int height)
666 {
667  av_image_copy(dst->data, dst->linesize, src->data,
668  src->linesize, pix_fmt, width, height);
669 }
670 
671 /* 2x2 -> 1x1 */
672 void ff_shrink22(uint8_t *dst, int dst_wrap,
673  const uint8_t *src, int src_wrap,
674  int width, int height)
675 {
676  int w;
677  const uint8_t *s1, *s2;
678  uint8_t *d;
679 
680  for(;height > 0; height--) {
681  s1 = src;
682  s2 = s1 + src_wrap;
683  d = dst;
684  for(w = width;w >= 4; w-=4) {
685  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
686  d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
687  d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
688  d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
689  s1 += 8;
690  s2 += 8;
691  d += 4;
692  }
693  for(;w > 0; w--) {
694  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
695  s1 += 2;
696  s2 += 2;
697  d++;
698  }
699  src += 2 * src_wrap;
700  dst += dst_wrap;
701  }
702 }
703 
704 /* 4x4 -> 1x1 */
705 void ff_shrink44(uint8_t *dst, int dst_wrap,
706  const uint8_t *src, int src_wrap,
707  int width, int height)
708 {
709  int w;
710  const uint8_t *s1, *s2, *s3, *s4;
711  uint8_t *d;
712 
713  for(;height > 0; height--) {
714  s1 = src;
715  s2 = s1 + src_wrap;
716  s3 = s2 + src_wrap;
717  s4 = s3 + src_wrap;
718  d = dst;
719  for(w = width;w > 0; w--) {
720  d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
721  s2[0] + s2[1] + s2[2] + s2[3] +
722  s3[0] + s3[1] + s3[2] + s3[3] +
723  s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
724  s1 += 4;
725  s2 += 4;
726  s3 += 4;
727  s4 += 4;
728  d++;
729  }
730  src += 4 * src_wrap;
731  dst += dst_wrap;
732  }
733 }
734 
735 /* 8x8 -> 1x1 */
736 void ff_shrink88(uint8_t *dst, int dst_wrap,
737  const uint8_t *src, int src_wrap,
738  int width, int height)
739 {
740  int w, i;
741 
742  for(;height > 0; height--) {
743  for(w = width;w > 0; w--) {
744  int tmp=0;
745  for(i=0; i<8; i++){
746  tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
747  src += src_wrap;
748  }
749  *(dst++) = (tmp + 32)>>6;
750  src += 8 - 8*src_wrap;
751  }
752  src += 8*src_wrap - 8*width;
753  dst += dst_wrap - width;
754  }
755 }
756 
757 
759  enum PixelFormat pix_fmt, int width, int height)
760 {
761  int ret;
762 
763  if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
764  memset(picture, 0, sizeof(AVPicture));
765  return ret;
766  }
767 
768  return 0;
769 }
770 
772 {
773  av_free(picture->data[0]);
774 }
775 
776 /* return true if yuv planar */
777 static inline int is_yuv_planar(const PixFmtInfo *ps)
778 {
779  return (ps->color_type == FF_COLOR_YUV ||
780  ps->color_type == FF_COLOR_YUV_JPEG) &&
782 }
783 
784 int av_picture_crop(AVPicture *dst, const AVPicture *src,
785  enum PixelFormat pix_fmt, int top_band, int left_band)
786 {
787  int y_shift;
788  int x_shift;
789 
790  if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
791  return -1;
792 
795 
796  dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
797  dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
798  dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
799 
800  dst->linesize[0] = src->linesize[0];
801  dst->linesize[1] = src->linesize[1];
802  dst->linesize[2] = src->linesize[2];
803  return 0;
804 }
805 
806 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
807  enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
808  int *color)
809 {
810  uint8_t *optr;
811  int y_shift;
812  int x_shift;
813  int yheight;
814  int i, y;
815 
816  if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
817  !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
818 
819  for (i = 0; i < 3; i++) {
820  x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
821  y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
822 
823  if (padtop || padleft) {
824  memset(dst->data[i], color[i],
825  dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
826  }
827 
828  if (padleft || padright) {
829  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
830  (dst->linesize[i] - (padright >> x_shift));
831  yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
832  for (y = 0; y < yheight; y++) {
833  memset(optr, color[i], (padleft + padright) >> x_shift);
834  optr += dst->linesize[i];
835  }
836  }
837 
838  if (src) { /* first line */
839  uint8_t *iptr = src->data[i];
840  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
841  (padleft >> x_shift);
842  memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
843  iptr += src->linesize[i];
844  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
845  (dst->linesize[i] - (padright >> x_shift));
846  yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
847  for (y = 0; y < yheight; y++) {
848  memset(optr, color[i], (padleft + padright) >> x_shift);
849  memcpy(optr + ((padleft + padright) >> x_shift), iptr,
850  (width - padleft - padright) >> x_shift);
851  iptr += src->linesize[i];
852  optr += dst->linesize[i];
853  }
854  }
855 
856  if (padbottom || padright) {
857  optr = dst->data[i] + dst->linesize[i] *
858  ((height - padbottom) >> y_shift) - (padright >> x_shift);
859  memset(optr, color[i],dst->linesize[i] *
860  (padbottom >> y_shift) + (padright >> x_shift));
861  }
862  }
863  return 0;
864 }
865 
866 #if FF_API_GET_ALPHA_INFO
867 /* NOTE: we scan all the pixels to have an exact information */
868 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
869 {
870  const unsigned char *p;
871  int src_wrap, ret, x, y;
872  unsigned int a;
873  uint32_t *palette = (uint32_t *)src->data[1];
874 
875  p = src->data[0];
876  src_wrap = src->linesize[0] - width;
877  ret = 0;
878  for(y=0;y<height;y++) {
879  for(x=0;x<width;x++) {
880  a = palette[p[0]] >> 24;
881  if (a == 0x00) {
882  ret |= FF_ALPHA_TRANSP;
883  } else if (a != 0xff) {
884  ret |= FF_ALPHA_SEMI_TRANSP;
885  }
886  p++;
887  }
888  p += src_wrap;
889  }
890  return ret;
891 }
892 
893 int img_get_alpha_info(const AVPicture *src,
894  enum PixelFormat pix_fmt, int width, int height)
895 {
896  const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
897  int ret;
898 
899  /* no alpha can be represented in format */
900  if (!pf->is_alpha)
901  return 0;
902  switch(pix_fmt) {
903  case PIX_FMT_PAL8:
904  ret = get_alpha_info_pal8(src, width, height);
905  break;
906  default:
907  /* we do not know, so everything is indicated */
908  ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
909  break;
910  }
911  return ret;
912 }
913 #endif
914 
915 #if !(HAVE_MMX && HAVE_YASM)
916 /* filter parameters: [-1 4 2 4 -1] // 8 */
917 static void deinterlace_line_c(uint8_t *dst,
918  const uint8_t *lum_m4, const uint8_t *lum_m3,
919  const uint8_t *lum_m2, const uint8_t *lum_m1,
920  const uint8_t *lum,
921  int size)
922 {
923  uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
924  int sum;
925 
926  for(;size > 0;size--) {
927  sum = -lum_m4[0];
928  sum += lum_m3[0] << 2;
929  sum += lum_m2[0] << 1;
930  sum += lum_m1[0] << 2;
931  sum += -lum[0];
932  dst[0] = cm[(sum + 4) >> 3];
933  lum_m4++;
934  lum_m3++;
935  lum_m2++;
936  lum_m1++;
937  lum++;
938  dst++;
939  }
940 }
941 
942 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
943  uint8_t *lum_m2, uint8_t *lum_m1,
944  uint8_t *lum, int size)
945 {
946  uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
947  int sum;
948 
949  for(;size > 0;size--) {
950  sum = -lum_m4[0];
951  sum += lum_m3[0] << 2;
952  sum += lum_m2[0] << 1;
953  lum_m4[0]=lum_m2[0];
954  sum += lum_m1[0] << 2;
955  sum += -lum[0];
956  lum_m2[0] = cm[(sum + 4) >> 3];
957  lum_m4++;
958  lum_m3++;
959  lum_m2++;
960  lum_m1++;
961  lum++;
962  }
963 }
964 #endif
965 
966 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
967  top field is copied as is, but the bottom field is deinterlaced
968  against the top field. */
969 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
970  const uint8_t *src1, int src_wrap,
971  int width, int height)
972 {
973  const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
974  int y;
975 
976  src_m2 = src1;
977  src_m1 = src1;
978  src_0=&src_m1[src_wrap];
979  src_p1=&src_0[src_wrap];
980  src_p2=&src_p1[src_wrap];
981  for(y=0;y<(height-2);y+=2) {
982  memcpy(dst,src_m1,width);
983  dst += dst_wrap;
984  deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
985  src_m2 = src_0;
986  src_m1 = src_p1;
987  src_0 = src_p2;
988  src_p1 += 2*src_wrap;
989  src_p2 += 2*src_wrap;
990  dst += dst_wrap;
991  }
992  memcpy(dst,src_m1,width);
993  dst += dst_wrap;
994  /* do last line */
995  deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
996 }
997 
998 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
999  int width, int height)
1000 {
1001  uint8_t *src_m1, *src_0, *src_p1, *src_p2;
1002  int y;
1003  uint8_t *buf;
1004  buf = av_malloc(width);
1005 
1006  src_m1 = src1;
1007  memcpy(buf,src_m1,width);
1008  src_0=&src_m1[src_wrap];
1009  src_p1=&src_0[src_wrap];
1010  src_p2=&src_p1[src_wrap];
1011  for(y=0;y<(height-2);y+=2) {
1012  deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1013  src_m1 = src_p1;
1014  src_0 = src_p2;
1015  src_p1 += 2*src_wrap;
1016  src_p2 += 2*src_wrap;
1017  }
1018  /* do last line */
1019  deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
1020  av_free(buf);
1021 }
1022 
1024  enum PixelFormat pix_fmt, int width, int height)
1025 {
1026  int i;
1027 
1028  if (pix_fmt != PIX_FMT_YUV420P &&
1029  pix_fmt != PIX_FMT_YUVJ420P &&
1030  pix_fmt != PIX_FMT_YUV422P &&
1031  pix_fmt != PIX_FMT_YUVJ422P &&
1032  pix_fmt != PIX_FMT_YUV444P &&
1033  pix_fmt != PIX_FMT_YUV411P &&
1034  pix_fmt != PIX_FMT_GRAY8)
1035  return -1;
1036  if ((width & 3) != 0 || (height & 3) != 0)
1037  return -1;
1038 
1039  for(i=0;i<3;i++) {
1040  if (i == 1) {
1041  switch(pix_fmt) {
1042  case PIX_FMT_YUVJ420P:
1043  case PIX_FMT_YUV420P:
1044  width >>= 1;
1045  height >>= 1;
1046  break;
1047  case PIX_FMT_YUV422P:
1048  case PIX_FMT_YUVJ422P:
1049  width >>= 1;
1050  break;
1051  case PIX_FMT_YUV411P:
1052  width >>= 2;
1053  break;
1054  default:
1055  break;
1056  }
1057  if (pix_fmt == PIX_FMT_GRAY8) {
1058  break;
1059  }
1060  }
1061  if (src == dst) {
1063  width, height);
1064  } else {
1065  deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1066  src->data[i], src->linesize[i],
1067  width, height);
1068  }
1069  }
1070  emms_c();
1071  return 0;
1072 }
1073