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