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  for(i = 0;i < PIX_FMT_NB; i++) {
616  if (pix_fmt_mask & (1ULL << i)) {
617  loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
618  if (loss == 0) {
619  dist = avg_bits_per_pixel(i);
620  if (dist < min_dist) {
621  min_dist = dist;
622  dst_pix_fmt = i;
623  }
624  }
625  }
626  }
627  return dst_pix_fmt;
628 }
629 
630 enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt,
631  int has_alpha, int *loss_ptr)
632 {
633  enum PixelFormat dst_pix_fmt;
634  int loss_mask, i;
635  static const int loss_mask_order[] = {
636  ~0, /* no loss first */
637  ~FF_LOSS_ALPHA,
641  ~FF_LOSS_DEPTH,
642  0,
643  };
644 
645  /* try with successive loss */
646  i = 0;
647  for(;;) {
648  loss_mask = loss_mask_order[i++];
649  dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
650  has_alpha, loss_mask);
651  if (dst_pix_fmt >= 0)
652  goto found;
653  if (loss_mask == 0)
654  break;
655  }
656  return PIX_FMT_NONE;
657  found:
658  if (loss_ptr)
659  *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
660  return dst_pix_fmt;
661 }
662 
663 void av_picture_copy(AVPicture *dst, const AVPicture *src,
664  enum PixelFormat pix_fmt, int width, int height)
665 {
666  av_image_copy(dst->data, dst->linesize, src->data,
667  src->linesize, pix_fmt, width, height);
668 }
669 
670 /* 2x2 -> 1x1 */
671 void ff_shrink22(uint8_t *dst, int dst_wrap,
672  const uint8_t *src, int src_wrap,
673  int width, int height)
674 {
675  int w;
676  const uint8_t *s1, *s2;
677  uint8_t *d;
678 
679  for(;height > 0; height--) {
680  s1 = src;
681  s2 = s1 + src_wrap;
682  d = dst;
683  for(w = width;w >= 4; w-=4) {
684  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
685  d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
686  d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
687  d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
688  s1 += 8;
689  s2 += 8;
690  d += 4;
691  }
692  for(;w > 0; w--) {
693  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
694  s1 += 2;
695  s2 += 2;
696  d++;
697  }
698  src += 2 * src_wrap;
699  dst += dst_wrap;
700  }
701 }
702 
703 /* 4x4 -> 1x1 */
704 void ff_shrink44(uint8_t *dst, int dst_wrap,
705  const uint8_t *src, int src_wrap,
706  int width, int height)
707 {
708  int w;
709  const uint8_t *s1, *s2, *s3, *s4;
710  uint8_t *d;
711 
712  for(;height > 0; height--) {
713  s1 = src;
714  s2 = s1 + src_wrap;
715  s3 = s2 + src_wrap;
716  s4 = s3 + src_wrap;
717  d = dst;
718  for(w = width;w > 0; w--) {
719  d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
720  s2[0] + s2[1] + s2[2] + s2[3] +
721  s3[0] + s3[1] + s3[2] + s3[3] +
722  s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
723  s1 += 4;
724  s2 += 4;
725  s3 += 4;
726  s4 += 4;
727  d++;
728  }
729  src += 4 * src_wrap;
730  dst += dst_wrap;
731  }
732 }
733 
734 /* 8x8 -> 1x1 */
735 void ff_shrink88(uint8_t *dst, int dst_wrap,
736  const uint8_t *src, int src_wrap,
737  int width, int height)
738 {
739  int w, i;
740 
741  for(;height > 0; height--) {
742  for(w = width;w > 0; w--) {
743  int tmp=0;
744  for(i=0; i<8; i++){
745  tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
746  src += src_wrap;
747  }
748  *(dst++) = (tmp + 32)>>6;
749  src += 8 - 8*src_wrap;
750  }
751  src += 8*src_wrap - 8*width;
752  dst += dst_wrap - width;
753  }
754 }
755 
756 
758  enum PixelFormat pix_fmt, int width, int height)
759 {
760  int ret;
761 
762  if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
763  memset(picture, 0, sizeof(AVPicture));
764  return ret;
765  }
766 
767  return 0;
768 }
769 
771 {
772  av_free(picture->data[0]);
773 }
774 
775 /* return true if yuv planar */
776 static inline int is_yuv_planar(const PixFmtInfo *ps)
777 {
778  return (ps->color_type == FF_COLOR_YUV ||
779  ps->color_type == FF_COLOR_YUV_JPEG) &&
781 }
782 
783 int av_picture_crop(AVPicture *dst, const AVPicture *src,
784  enum PixelFormat pix_fmt, int top_band, int left_band)
785 {
786  int y_shift;
787  int x_shift;
788 
789  if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt]))
790  return -1;
791 
794 
795  dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
796  dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
797  dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
798 
799  dst->linesize[0] = src->linesize[0];
800  dst->linesize[1] = src->linesize[1];
801  dst->linesize[2] = src->linesize[2];
802  return 0;
803 }
804 
805 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
806  enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
807  int *color)
808 {
809  uint8_t *optr;
810  int y_shift;
811  int x_shift;
812  int yheight;
813  int i, y;
814 
815  if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
816  !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1;
817 
818  for (i = 0; i < 3; i++) {
819  x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
820  y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
821 
822  if (padtop || padleft) {
823  memset(dst->data[i], color[i],
824  dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
825  }
826 
827  if (padleft || padright) {
828  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
829  (dst->linesize[i] - (padright >> x_shift));
830  yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
831  for (y = 0; y < yheight; y++) {
832  memset(optr, color[i], (padleft + padright) >> x_shift);
833  optr += dst->linesize[i];
834  }
835  }
836 
837  if (src) { /* first line */
838  uint8_t *iptr = src->data[i];
839  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
840  (padleft >> x_shift);
841  memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
842  iptr += src->linesize[i];
843  optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
844  (dst->linesize[i] - (padright >> x_shift));
845  yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
846  for (y = 0; y < yheight; y++) {
847  memset(optr, color[i], (padleft + padright) >> x_shift);
848  memcpy(optr + ((padleft + padright) >> x_shift), iptr,
849  (width - padleft - padright) >> x_shift);
850  iptr += src->linesize[i];
851  optr += dst->linesize[i];
852  }
853  }
854 
855  if (padbottom || padright) {
856  optr = dst->data[i] + dst->linesize[i] *
857  ((height - padbottom) >> y_shift) - (padright >> x_shift);
858  memset(optr, color[i],dst->linesize[i] *
859  (padbottom >> y_shift) + (padright >> x_shift));
860  }
861  }
862  return 0;
863 }
864 
865 #if FF_API_GET_ALPHA_INFO
866 /* NOTE: we scan all the pixels to have an exact information */
867 static int get_alpha_info_pal8(const AVPicture *src, int width, int height)
868 {
869  const unsigned char *p;
870  int src_wrap, ret, x, y;
871  unsigned int a;
872  uint32_t *palette = (uint32_t *)src->data[1];
873 
874  p = src->data[0];
875  src_wrap = src->linesize[0] - width;
876  ret = 0;
877  for(y=0;y<height;y++) {
878  for(x=0;x<width;x++) {
879  a = palette[p[0]] >> 24;
880  if (a == 0x00) {
881  ret |= FF_ALPHA_TRANSP;
882  } else if (a != 0xff) {
883  ret |= FF_ALPHA_SEMI_TRANSP;
884  }
885  p++;
886  }
887  p += src_wrap;
888  }
889  return ret;
890 }
891 
892 int img_get_alpha_info(const AVPicture *src,
893  enum PixelFormat pix_fmt, int width, int height)
894 {
895  const PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
896  int ret;
897 
898  /* no alpha can be represented in format */
899  if (!pf->is_alpha)
900  return 0;
901  switch(pix_fmt) {
902  case PIX_FMT_PAL8:
903  ret = get_alpha_info_pal8(src, width, height);
904  break;
905  default:
906  /* we do not know, so everything is indicated */
907  ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
908  break;
909  }
910  return ret;
911 }
912 #endif
913 
914 #if !(HAVE_MMX && HAVE_YASM)
915 /* filter parameters: [-1 4 2 4 -1] // 8 */
916 static void deinterlace_line_c(uint8_t *dst,
917  const uint8_t *lum_m4, const uint8_t *lum_m3,
918  const uint8_t *lum_m2, const uint8_t *lum_m1,
919  const uint8_t *lum,
920  int size)
921 {
922  uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
923  int sum;
924 
925  for(;size > 0;size--) {
926  sum = -lum_m4[0];
927  sum += lum_m3[0] << 2;
928  sum += lum_m2[0] << 1;
929  sum += lum_m1[0] << 2;
930  sum += -lum[0];
931  dst[0] = cm[(sum + 4) >> 3];
932  lum_m4++;
933  lum_m3++;
934  lum_m2++;
935  lum_m1++;
936  lum++;
937  dst++;
938  }
939 }
940 
941 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
942  uint8_t *lum_m2, uint8_t *lum_m1,
943  uint8_t *lum, int size)
944 {
945  uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
946  int sum;
947 
948  for(;size > 0;size--) {
949  sum = -lum_m4[0];
950  sum += lum_m3[0] << 2;
951  sum += lum_m2[0] << 1;
952  lum_m4[0]=lum_m2[0];
953  sum += lum_m1[0] << 2;
954  sum += -lum[0];
955  lum_m2[0] = cm[(sum + 4) >> 3];
956  lum_m4++;
957  lum_m3++;
958  lum_m2++;
959  lum_m1++;
960  lum++;
961  }
962 }
963 #endif
964 
965 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
966  top field is copied as is, but the bottom field is deinterlaced
967  against the top field. */
968 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
969  const uint8_t *src1, int src_wrap,
970  int width, int height)
971 {
972  const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
973  int y;
974 
975  src_m2 = src1;
976  src_m1 = src1;
977  src_0=&src_m1[src_wrap];
978  src_p1=&src_0[src_wrap];
979  src_p2=&src_p1[src_wrap];
980  for(y=0;y<(height-2);y+=2) {
981  memcpy(dst,src_m1,width);
982  dst += dst_wrap;
983  deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
984  src_m2 = src_0;
985  src_m1 = src_p1;
986  src_0 = src_p2;
987  src_p1 += 2*src_wrap;
988  src_p2 += 2*src_wrap;
989  dst += dst_wrap;
990  }
991  memcpy(dst,src_m1,width);
992  dst += dst_wrap;
993  /* do last line */
994  deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
995 }
996 
997 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
998  int width, int height)
999 {
1000  uint8_t *src_m1, *src_0, *src_p1, *src_p2;
1001  int y;
1002  uint8_t *buf;
1003  buf = av_malloc(width);
1004 
1005  src_m1 = src1;
1006  memcpy(buf,src_m1,width);
1007  src_0=&src_m1[src_wrap];
1008  src_p1=&src_0[src_wrap];
1009  src_p2=&src_p1[src_wrap];
1010  for(y=0;y<(height-2);y+=2) {
1011  deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
1012  src_m1 = src_p1;
1013  src_0 = src_p2;
1014  src_p1 += 2*src_wrap;
1015  src_p2 += 2*src_wrap;
1016  }
1017  /* do last line */
1018  deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
1019  av_free(buf);
1020 }
1021 
1023  enum PixelFormat pix_fmt, int width, int height)
1024 {
1025  int i;
1026 
1027  if (pix_fmt != PIX_FMT_YUV420P &&
1028  pix_fmt != PIX_FMT_YUVJ420P &&
1029  pix_fmt != PIX_FMT_YUV422P &&
1030  pix_fmt != PIX_FMT_YUVJ422P &&
1031  pix_fmt != PIX_FMT_YUV444P &&
1032  pix_fmt != PIX_FMT_YUV411P &&
1033  pix_fmt != PIX_FMT_GRAY8)
1034  return -1;
1035  if ((width & 3) != 0 || (height & 3) != 0)
1036  return -1;
1037 
1038  for(i=0;i<3;i++) {
1039  if (i == 1) {
1040  switch(pix_fmt) {
1041  case PIX_FMT_YUVJ420P:
1042  case PIX_FMT_YUV420P:
1043  width >>= 1;
1044  height >>= 1;
1045  break;
1046  case PIX_FMT_YUV422P:
1047  case PIX_FMT_YUVJ422P:
1048  width >>= 1;
1049  break;
1050  case PIX_FMT_YUV411P:
1051  width >>= 2;
1052  break;
1053  default:
1054  break;
1055  }
1056  if (pix_fmt == PIX_FMT_GRAY8) {
1057  break;
1058  }
1059  }
1060  if (src == dst) {
1062  width, height);
1063  } else {
1064  deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1065  src->data[i], src->linesize[i],
1066  width, height);
1067  }
1068  }
1069  emms_c();
1070  return 0;
1071 }
1072