]> git.sesse.net Git - ffmpeg/blob - libavcodec/imgconvert.c
Merge remote-tracking branch 'qatar/master'
[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 FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
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 "libavutil/colorspace.h"
37 #include "libavutil/common.h"
38 #include "libavutil/pixdesc.h"
39 #include "libavutil/imgutils.h"
40
41 #if HAVE_MMX_EXTERNAL
42 #include "x86/dsputil_mmx.h"
43 #endif
44
45 #define FF_COLOR_RGB      0 /**< RGB color space */
46 #define FF_COLOR_GRAY     1 /**< gray color space */
47 #define FF_COLOR_YUV      2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
48 #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
49
50 #if HAVE_MMX_EXTERNAL
51 #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
52 #define deinterlace_line         ff_deinterlace_line_mmx
53 #else
54 #define deinterlace_line_inplace deinterlace_line_inplace_c
55 #define deinterlace_line         deinterlace_line_c
56 #endif
57
58 #define pixdesc_has_alpha(pixdesc) \
59     ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & PIX_FMT_PAL)
60
61 typedef struct PixFmtInfo {
62     uint8_t color_type;      /**< color type (see FF_COLOR_xxx constants) */
63     uint8_t padded_size;     /**< padded size in bits if different from the non-padded size */
64 } PixFmtInfo;
65
66 /* this table gives more information about formats */
67 static const PixFmtInfo pix_fmt_info[AV_PIX_FMT_NB] = {
68     /* YUV formats */
69     [AV_PIX_FMT_YUV420P] = {
70         .color_type = FF_COLOR_YUV,
71     },
72     [AV_PIX_FMT_YUV422P] = {
73         .color_type = FF_COLOR_YUV,
74     },
75     [AV_PIX_FMT_YUV444P] = {
76         .color_type = FF_COLOR_YUV,
77     },
78     [AV_PIX_FMT_YUYV422] = {
79         .color_type = FF_COLOR_YUV,
80     },
81     [AV_PIX_FMT_UYVY422] = {
82         .color_type = FF_COLOR_YUV,
83     },
84     [AV_PIX_FMT_YUV410P] = {
85         .color_type = FF_COLOR_YUV,
86     },
87     [AV_PIX_FMT_YUV411P] = {
88         .color_type = FF_COLOR_YUV,
89     },
90     [AV_PIX_FMT_YUV440P] = {
91         .color_type = FF_COLOR_YUV,
92     },
93     [AV_PIX_FMT_YUV420P9LE] = {
94         .color_type = FF_COLOR_YUV,
95     },
96     [AV_PIX_FMT_YUV422P9LE] = {
97         .color_type = FF_COLOR_YUV,
98     },
99     [AV_PIX_FMT_YUV444P9LE] = {
100         .color_type = FF_COLOR_YUV,
101     },
102     [AV_PIX_FMT_YUV420P9BE] = {
103         .color_type = FF_COLOR_YUV,
104     },
105     [AV_PIX_FMT_YUV422P9BE] = {
106         .color_type = FF_COLOR_YUV,
107     },
108     [AV_PIX_FMT_YUV444P9BE] = {
109         .color_type = FF_COLOR_YUV,
110     },
111     [AV_PIX_FMT_YUV420P10LE] = {
112         .color_type = FF_COLOR_YUV,
113     },
114     [AV_PIX_FMT_YUV422P10LE] = {
115         .color_type = FF_COLOR_YUV,
116     },
117     [AV_PIX_FMT_YUV444P10LE] = {
118         .color_type = FF_COLOR_YUV,
119     },
120     [AV_PIX_FMT_YUV420P10BE] = {
121         .color_type = FF_COLOR_YUV,
122     },
123     [AV_PIX_FMT_YUV422P10BE] = {
124         .color_type = FF_COLOR_YUV,
125     },
126     [AV_PIX_FMT_YUV444P10BE] = {
127         .color_type = FF_COLOR_YUV,
128     },
129     [AV_PIX_FMT_YUV420P12LE] = {
130         .color_type = FF_COLOR_YUV,
131     },
132     [AV_PIX_FMT_YUV422P12LE] = {
133         .color_type = FF_COLOR_YUV,
134     },
135     [AV_PIX_FMT_YUV444P12LE] = {
136         .color_type = FF_COLOR_YUV,
137     },
138     [AV_PIX_FMT_YUV420P12BE] = {
139         .color_type = FF_COLOR_YUV,
140     },
141     [AV_PIX_FMT_YUV422P12BE] = {
142         .color_type = FF_COLOR_YUV,
143     },
144     [AV_PIX_FMT_YUV444P12BE] = {
145         .color_type = FF_COLOR_YUV,
146     },
147     [AV_PIX_FMT_YUV420P14LE] = {
148         .color_type = FF_COLOR_YUV,
149     },
150     [AV_PIX_FMT_YUV422P14LE] = {
151         .color_type = FF_COLOR_YUV,
152     },
153     [AV_PIX_FMT_YUV444P14LE] = {
154         .color_type = FF_COLOR_YUV,
155     },
156     [AV_PIX_FMT_YUV420P14BE] = {
157         .color_type = FF_COLOR_YUV,
158     },
159     [AV_PIX_FMT_YUV422P14BE] = {
160         .color_type = FF_COLOR_YUV,
161     },
162     [AV_PIX_FMT_YUV444P14BE] = {
163         .color_type = FF_COLOR_YUV,
164     },
165     [AV_PIX_FMT_YUV420P16LE] = {
166         .color_type = FF_COLOR_YUV,
167     },
168     [AV_PIX_FMT_YUV422P16LE] = {
169         .color_type = FF_COLOR_YUV,
170     },
171     [AV_PIX_FMT_YUV444P16LE] = {
172         .color_type = FF_COLOR_YUV,
173     },
174     [AV_PIX_FMT_YUV420P16BE] = {
175         .color_type = FF_COLOR_YUV,
176     },
177     [AV_PIX_FMT_YUV422P16BE] = {
178         .color_type = FF_COLOR_YUV,
179     },
180     [AV_PIX_FMT_YUV444P16BE] = {
181         .color_type = FF_COLOR_YUV,
182     },
183
184     /* YUV formats with alpha plane */
185     [AV_PIX_FMT_YUVA420P] = {
186         .color_type = FF_COLOR_YUV,
187     },
188
189     [AV_PIX_FMT_YUVA422P] = {
190         .color_type = FF_COLOR_YUV,
191     },
192
193     [AV_PIX_FMT_YUVA444P] = {
194         .color_type = FF_COLOR_YUV,
195     },
196     [AV_PIX_FMT_YUVA420P9LE] = {
197         .color_type = FF_COLOR_YUV,
198     },
199     [AV_PIX_FMT_YUVA422P9LE] = {
200         .color_type = FF_COLOR_YUV,
201     },
202     [AV_PIX_FMT_YUVA444P9LE] = {
203         .color_type = FF_COLOR_YUV,
204     },
205     [AV_PIX_FMT_YUVA420P9BE] = {
206         .color_type = FF_COLOR_YUV,
207     },
208     [AV_PIX_FMT_YUVA422P9BE] = {
209         .color_type = FF_COLOR_YUV,
210     },
211     [AV_PIX_FMT_YUVA444P9BE] = {
212         .color_type = FF_COLOR_YUV,
213     },
214     [AV_PIX_FMT_YUVA420P10LE] = {
215         .color_type = FF_COLOR_YUV,
216     },
217     [AV_PIX_FMT_YUVA422P10LE] = {
218         .color_type = FF_COLOR_YUV,
219     },
220     [AV_PIX_FMT_YUVA444P10LE] = {
221         .color_type = FF_COLOR_YUV,
222     },
223     [AV_PIX_FMT_YUVA420P10BE] = {
224         .color_type = FF_COLOR_YUV,
225     },
226     [AV_PIX_FMT_YUVA422P10BE] = {
227         .color_type = FF_COLOR_YUV,
228     },
229     [AV_PIX_FMT_YUVA444P10BE] = {
230         .color_type = FF_COLOR_YUV,
231     },
232
233     /* JPEG YUV */
234     [AV_PIX_FMT_YUVJ420P] = {
235         .color_type = FF_COLOR_YUV_JPEG,
236     },
237     [AV_PIX_FMT_YUVJ422P] = {
238         .color_type = FF_COLOR_YUV_JPEG,
239     },
240     [AV_PIX_FMT_YUVJ444P] = {
241         .color_type = FF_COLOR_YUV_JPEG,
242     },
243     [AV_PIX_FMT_YUVJ440P] = {
244         .color_type = FF_COLOR_YUV_JPEG,
245     },
246
247     /* RGB formats */
248     [AV_PIX_FMT_RGB24] = {
249         .color_type = FF_COLOR_RGB,
250     },
251     [AV_PIX_FMT_BGR24] = {
252         .color_type = FF_COLOR_RGB,
253     },
254     [AV_PIX_FMT_ARGB] = {
255         .color_type = FF_COLOR_RGB,
256     },
257     [AV_PIX_FMT_RGB48BE] = {
258         .color_type = FF_COLOR_RGB,
259     },
260     [AV_PIX_FMT_RGB48LE] = {
261         .color_type = FF_COLOR_RGB,
262     },
263     [AV_PIX_FMT_RGBA64BE] = {
264         .color_type = FF_COLOR_RGB,
265     },
266     [AV_PIX_FMT_RGBA64LE] = {
267         .color_type = FF_COLOR_RGB,
268     },
269     [AV_PIX_FMT_RGB565BE] = {
270         .color_type = FF_COLOR_RGB,
271     },
272     [AV_PIX_FMT_RGB565LE] = {
273         .color_type = FF_COLOR_RGB,
274     },
275     [AV_PIX_FMT_RGB555BE] = {
276         .color_type = FF_COLOR_RGB,
277         .padded_size = 16,
278     },
279     [AV_PIX_FMT_RGB555LE] = {
280         .color_type = FF_COLOR_RGB,
281         .padded_size = 16,
282     },
283     [AV_PIX_FMT_RGB444BE] = {
284         .color_type = FF_COLOR_RGB,
285         .padded_size = 16,
286     },
287     [AV_PIX_FMT_RGB444LE] = {
288         .color_type = FF_COLOR_RGB,
289         .padded_size = 16,
290     },
291
292     /* gray / mono formats */
293     [AV_PIX_FMT_GRAY16BE] = {
294         .color_type = FF_COLOR_GRAY,
295     },
296     [AV_PIX_FMT_GRAY16LE] = {
297         .color_type = FF_COLOR_GRAY,
298     },
299     [AV_PIX_FMT_GRAY8] = {
300         .color_type = FF_COLOR_GRAY,
301     },
302     [AV_PIX_FMT_GRAY8A] = {
303         .color_type = FF_COLOR_GRAY,
304     },
305     [AV_PIX_FMT_MONOWHITE] = {
306         .color_type = FF_COLOR_GRAY,
307     },
308     [AV_PIX_FMT_MONOBLACK] = {
309         .color_type = FF_COLOR_GRAY,
310     },
311
312     /* paletted formats */
313     [AV_PIX_FMT_PAL8] = {
314         .color_type = FF_COLOR_RGB,
315     },
316     [AV_PIX_FMT_UYYVYY411] = {
317         .color_type = FF_COLOR_YUV,
318     },
319     [AV_PIX_FMT_ABGR] = {
320         .color_type = FF_COLOR_RGB,
321     },
322     [AV_PIX_FMT_BGR48BE] = {
323         .color_type = FF_COLOR_RGB,
324     },
325     [AV_PIX_FMT_BGR48LE] = {
326         .color_type = FF_COLOR_RGB,
327     },
328     [AV_PIX_FMT_BGRA64BE] = {
329         .color_type = FF_COLOR_RGB,
330     },
331     [AV_PIX_FMT_BGRA64LE] = {
332         .color_type = FF_COLOR_RGB,
333     },
334     [AV_PIX_FMT_BGR565BE] = {
335         .color_type = FF_COLOR_RGB,
336         .padded_size = 16,
337     },
338     [AV_PIX_FMT_BGR565LE] = {
339         .color_type = FF_COLOR_RGB,
340         .padded_size = 16,
341     },
342     [AV_PIX_FMT_BGR555BE] = {
343         .color_type = FF_COLOR_RGB,
344         .padded_size = 16,
345     },
346     [AV_PIX_FMT_BGR555LE] = {
347         .color_type = FF_COLOR_RGB,
348         .padded_size = 16,
349     },
350     [AV_PIX_FMT_BGR444BE] = {
351         .color_type = FF_COLOR_RGB,
352         .padded_size = 16,
353     },
354     [AV_PIX_FMT_BGR444LE] = {
355         .color_type = FF_COLOR_RGB,
356         .padded_size = 16,
357     },
358     [AV_PIX_FMT_RGB8] = {
359         .color_type = FF_COLOR_RGB,
360     },
361     [AV_PIX_FMT_RGB4] = {
362         .color_type = FF_COLOR_RGB,
363     },
364     [AV_PIX_FMT_RGB4_BYTE] = {
365         .color_type = FF_COLOR_RGB,
366         .padded_size = 8,
367     },
368     [AV_PIX_FMT_BGR8] = {
369         .color_type = FF_COLOR_RGB,
370     },
371     [AV_PIX_FMT_BGR4] = {
372         .color_type = FF_COLOR_RGB,
373     },
374     [AV_PIX_FMT_BGR4_BYTE] = {
375         .color_type = FF_COLOR_RGB,
376         .padded_size = 8,
377     },
378     [AV_PIX_FMT_NV12] = {
379         .color_type = FF_COLOR_YUV,
380     },
381     [AV_PIX_FMT_NV21] = {
382         .color_type = FF_COLOR_YUV,
383     },
384
385     [AV_PIX_FMT_BGRA] = {
386         .color_type = FF_COLOR_RGB,
387     },
388     [AV_PIX_FMT_RGBA] = {
389         .color_type = FF_COLOR_RGB,
390     },
391
392     [AV_PIX_FMT_GBRP] = {
393         .color_type = FF_COLOR_RGB,
394     },
395     [AV_PIX_FMT_GBRP9BE] = {
396         .color_type = FF_COLOR_RGB,
397     },
398     [AV_PIX_FMT_GBRP9LE] = {
399         .color_type = FF_COLOR_RGB,
400     },
401     [AV_PIX_FMT_GBRP10BE] = {
402         .color_type = FF_COLOR_RGB,
403     },
404     [AV_PIX_FMT_GBRP10LE] = {
405         .color_type = FF_COLOR_RGB,
406     },
407     [AV_PIX_FMT_GBRP12BE] = {
408         .color_type = FF_COLOR_RGB,
409     },
410     [AV_PIX_FMT_GBRP12LE] = {
411         .color_type = FF_COLOR_RGB,
412     },
413     [AV_PIX_FMT_GBRP14BE] = {
414         .color_type = FF_COLOR_RGB,
415     },
416     [AV_PIX_FMT_GBRP14LE] = {
417         .color_type = FF_COLOR_RGB,
418     },
419     [AV_PIX_FMT_GBRP16BE] = {
420         .color_type = FF_COLOR_RGB,
421     },
422     [AV_PIX_FMT_GBRP16LE] = {
423         .color_type = FF_COLOR_RGB,
424     },
425 };
426
427 void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
428 {
429     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
430     *h_shift = desc->log2_chroma_w;
431     *v_shift = desc->log2_chroma_h;
432 }
433
434 int ff_is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
435 {
436     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
437     return desc->flags & PIX_FMT_HWACCEL;
438 }
439
440 int avpicture_fill(AVPicture *picture, const uint8_t *ptr,
441                    enum AVPixelFormat pix_fmt, int width, int height)
442 {
443     return av_image_fill_arrays(picture->data, picture->linesize,
444                                 ptr, pix_fmt, width, height, 1);
445 }
446
447 int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, int width, int height,
448                      unsigned char *dest, int dest_size)
449 {
450     return av_image_copy_to_buffer(dest, dest_size,
451                                    (const uint8_t * const*)src->data, src->linesize,
452                                    pix_fmt, width, height, 1);
453 }
454
455 int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height)
456 {
457     return av_image_get_buffer_size(pix_fmt, width, height, 1);
458 }
459
460 static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
461 {
462     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
463     int i;
464
465     if (!desc || !desc->nb_components) {
466         *min = *max = 0;
467         return AVERROR(EINVAL);
468     }
469
470     *min = INT_MAX, *max = -INT_MAX;
471     for (i = 0; i < desc->nb_components; i++) {
472         *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
473         *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
474     }
475     return 0;
476 }
477
478 int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt,
479                              int has_alpha)
480 {
481     const PixFmtInfo *pf, *ps;
482     const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
483     const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
484     int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
485     int ret, loss;
486
487     if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
488         return ~0;
489
490     ps = &pix_fmt_info[src_pix_fmt];
491
492     /* compute loss */
493     loss = 0;
494
495     if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
496         return ret;
497     if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
498         return ret;
499     if (dst_min_depth < src_min_depth ||
500         dst_max_depth < src_max_depth)
501         loss |= FF_LOSS_DEPTH;
502     if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w ||
503         dst_desc->log2_chroma_h > src_desc->log2_chroma_h)
504         loss |= FF_LOSS_RESOLUTION;
505
506     pf = &pix_fmt_info[dst_pix_fmt];
507     switch(pf->color_type) {
508     case FF_COLOR_RGB:
509         if (ps->color_type != FF_COLOR_RGB &&
510             ps->color_type != FF_COLOR_GRAY)
511             loss |= FF_LOSS_COLORSPACE;
512         break;
513     case FF_COLOR_GRAY:
514         if (ps->color_type != FF_COLOR_GRAY)
515             loss |= FF_LOSS_COLORSPACE;
516         break;
517     case FF_COLOR_YUV:
518         if (ps->color_type != FF_COLOR_YUV)
519             loss |= FF_LOSS_COLORSPACE;
520         break;
521     case FF_COLOR_YUV_JPEG:
522         if (ps->color_type != FF_COLOR_YUV_JPEG &&
523             ps->color_type != FF_COLOR_YUV &&
524             ps->color_type != FF_COLOR_GRAY)
525             loss |= FF_LOSS_COLORSPACE;
526         break;
527     default:
528         /* fail safe test */
529         if (ps->color_type != pf->color_type)
530             loss |= FF_LOSS_COLORSPACE;
531         break;
532     }
533     if (pf->color_type == FF_COLOR_GRAY &&
534         ps->color_type != FF_COLOR_GRAY)
535         loss |= FF_LOSS_CHROMA;
536     if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && has_alpha))
537         loss |= FF_LOSS_ALPHA;
538     if (dst_pix_fmt == AV_PIX_FMT_PAL8 &&
539         (src_pix_fmt != AV_PIX_FMT_PAL8 && (ps->color_type != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && has_alpha))))
540         loss |= FF_LOSS_COLORQUANT;
541
542     return loss;
543 }
544
545 static int avg_bits_per_pixel(enum AVPixelFormat pix_fmt)
546 {
547     const PixFmtInfo *info = &pix_fmt_info[pix_fmt];
548     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
549
550     return info->padded_size ?
551         info->padded_size : av_get_bits_per_pixel(desc);
552 }
553
554 #if FF_API_FIND_BEST_PIX_FMT
555 enum AVPixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum AVPixelFormat src_pix_fmt,
556                                             int has_alpha, int *loss_ptr)
557 {
558     enum AVPixelFormat dst_pix_fmt;
559     int i;
560
561     if (loss_ptr) /* all losses count (for backward compatibility) */
562         *loss_ptr = 0;
563
564     dst_pix_fmt = AV_PIX_FMT_NONE; /* so first iteration doesn't have to be treated special */
565     for(i = 0; i< FFMIN(AV_PIX_FMT_NB, 64); i++){
566         if (pix_fmt_mask & (1ULL << i))
567             dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, i, src_pix_fmt, has_alpha, loss_ptr);
568     }
569     return dst_pix_fmt;
570 }
571 #endif /* FF_API_FIND_BEST_PIX_FMT */
572
573 enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
574                                             enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
575 {
576     enum AVPixelFormat dst_pix_fmt;
577     int loss1, loss2, loss_order1, loss_order2, i, loss_mask;
578     static const int loss_mask_order[] = {
579         ~0, /* no loss first */
580         ~FF_LOSS_ALPHA,
581         ~FF_LOSS_RESOLUTION,
582         ~FF_LOSS_COLORSPACE,
583         ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
584         ~FF_LOSS_COLORQUANT,
585         ~FF_LOSS_DEPTH,
586         ~(FF_LOSS_DEPTH|FF_LOSS_COLORSPACE),
587         ~(FF_LOSS_RESOLUTION | FF_LOSS_DEPTH | FF_LOSS_COLORSPACE | FF_LOSS_ALPHA |
588           FF_LOSS_COLORQUANT | FF_LOSS_CHROMA),
589         0x80000, //non zero entry that combines all loss variants including future additions
590         0,
591     };
592
593     loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
594     dst_pix_fmt = AV_PIX_FMT_NONE;
595     loss1 = avcodec_get_pix_fmt_loss(dst_pix_fmt1, src_pix_fmt, has_alpha) & loss_mask;
596     loss2 = avcodec_get_pix_fmt_loss(dst_pix_fmt2, src_pix_fmt, has_alpha) & loss_mask;
597
598     /* try with successive loss */
599     for(i = 0;loss_mask_order[i] != 0 && dst_pix_fmt == AV_PIX_FMT_NONE;i++) {
600         loss_order1 = loss1 & loss_mask_order[i];
601         loss_order2 = loss2 & loss_mask_order[i];
602
603         if (loss_order1 == 0 && loss_order2 == 0 && dst_pix_fmt2 != AV_PIX_FMT_NONE && dst_pix_fmt1 != AV_PIX_FMT_NONE){ /* use format with smallest depth */
604             dst_pix_fmt = avg_bits_per_pixel(dst_pix_fmt2) < avg_bits_per_pixel(dst_pix_fmt1) ? dst_pix_fmt2 : dst_pix_fmt1;
605         } else if (loss_order1 == 0 || loss_order2 == 0) { /* use format with no loss */
606             dst_pix_fmt = loss_order2 ? dst_pix_fmt1 : dst_pix_fmt2;
607         }
608     }
609
610     if (loss_ptr)
611         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
612     return dst_pix_fmt;
613 }
614
615 #if AV_HAVE_INCOMPATIBLE_FORK_ABI
616 enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list,
617                                             enum AVPixelFormat src_pix_fmt,
618                                             int has_alpha, int *loss_ptr){
619     return avcodec_find_best_pix_fmt_of_list(pix_fmt_list, src_pix_fmt, has_alpha, loss_ptr);
620 }
621 #else
622 enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
623                                             enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
624 {
625     return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
626 }
627 #endif
628
629 enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(enum AVPixelFormat *pix_fmt_list,
630                                             enum AVPixelFormat src_pix_fmt,
631                                             int has_alpha, int *loss_ptr){
632     int i;
633
634     enum AVPixelFormat best = AV_PIX_FMT_NONE;
635
636     for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++)
637         best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr);
638
639     return best;
640 }
641
642 void av_picture_copy(AVPicture *dst, const AVPicture *src,
643                      enum AVPixelFormat pix_fmt, int width, int height)
644 {
645     av_image_copy(dst->data, dst->linesize, (const uint8_t **)src->data,
646                   src->linesize, pix_fmt, width, height);
647 }
648
649 /* 2x2 -> 1x1 */
650 void ff_shrink22(uint8_t *dst, int dst_wrap,
651                      const uint8_t *src, int src_wrap,
652                      int width, int height)
653 {
654     int w;
655     const uint8_t *s1, *s2;
656     uint8_t *d;
657
658     for(;height > 0; height--) {
659         s1 = src;
660         s2 = s1 + src_wrap;
661         d = dst;
662         for(w = width;w >= 4; w-=4) {
663             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
664             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
665             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
666             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
667             s1 += 8;
668             s2 += 8;
669             d += 4;
670         }
671         for(;w > 0; w--) {
672             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
673             s1 += 2;
674             s2 += 2;
675             d++;
676         }
677         src += 2 * src_wrap;
678         dst += dst_wrap;
679     }
680 }
681
682 /* 4x4 -> 1x1 */
683 void ff_shrink44(uint8_t *dst, int dst_wrap,
684                      const uint8_t *src, int src_wrap,
685                      int width, int height)
686 {
687     int w;
688     const uint8_t *s1, *s2, *s3, *s4;
689     uint8_t *d;
690
691     for(;height > 0; height--) {
692         s1 = src;
693         s2 = s1 + src_wrap;
694         s3 = s2 + src_wrap;
695         s4 = s3 + src_wrap;
696         d = dst;
697         for(w = width;w > 0; w--) {
698             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
699                     s2[0] + s2[1] + s2[2] + s2[3] +
700                     s3[0] + s3[1] + s3[2] + s3[3] +
701                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
702             s1 += 4;
703             s2 += 4;
704             s3 += 4;
705             s4 += 4;
706             d++;
707         }
708         src += 4 * src_wrap;
709         dst += dst_wrap;
710     }
711 }
712
713 /* 8x8 -> 1x1 */
714 void ff_shrink88(uint8_t *dst, int dst_wrap,
715                      const uint8_t *src, int src_wrap,
716                      int width, int height)
717 {
718     int w, i;
719
720     for(;height > 0; height--) {
721         for(w = width;w > 0; w--) {
722             int tmp=0;
723             for(i=0; i<8; i++){
724                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
725                 src += src_wrap;
726             }
727             *(dst++) = (tmp + 32)>>6;
728             src += 8 - 8*src_wrap;
729         }
730         src += 8*src_wrap - 8*width;
731         dst += dst_wrap - width;
732     }
733 }
734
735
736 int avpicture_alloc(AVPicture *picture,
737                     enum AVPixelFormat pix_fmt, int width, int height)
738 {
739     int ret;
740
741     if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
742         memset(picture, 0, sizeof(AVPicture));
743         return ret;
744     }
745
746     return 0;
747 }
748
749 void avpicture_free(AVPicture *picture)
750 {
751     av_free(picture->data[0]);
752 }
753
754 /* return true if yuv planar */
755 static inline int is_yuv_planar(enum AVPixelFormat fmt)
756 {
757     const PixFmtInfo         *info = &pix_fmt_info[fmt];
758     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
759     int i;
760     int planes[4] = { 0 };
761
762     if (info->color_type != FF_COLOR_YUV &&
763         info->color_type != FF_COLOR_YUV_JPEG)
764         return 0;
765
766     /* set the used planes */
767     for (i = 0; i < desc->nb_components; i++)
768         planes[desc->comp[i].plane] = 1;
769
770     /* if there is an unused plane, the format is not planar */
771     for (i = 0; i < desc->nb_components; i++)
772         if (!planes[i])
773             return 0;
774     return 1;
775 }
776
777 int av_picture_crop(AVPicture *dst, const AVPicture *src,
778                     enum AVPixelFormat pix_fmt, int top_band, int left_band)
779 {
780     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
781     int y_shift;
782     int x_shift;
783
784     if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
785         return -1;
786
787     y_shift = desc->log2_chroma_h;
788     x_shift = desc->log2_chroma_w;
789
790     if (is_yuv_planar(pix_fmt)) {
791     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
792     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
793     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
794     } else{
795         if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
796             return -1;
797         if(left_band) //FIXME add support for this too
798             return -1;
799         dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
800     }
801
802     dst->linesize[0] = src->linesize[0];
803     dst->linesize[1] = src->linesize[1];
804     dst->linesize[2] = src->linesize[2];
805     return 0;
806 }
807
808 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
809                    enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
810             int *color)
811 {
812     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
813     uint8_t *optr;
814     int y_shift;
815     int x_shift;
816     int yheight;
817     int i, y;
818
819     if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB ||
820         !is_yuv_planar(pix_fmt)) return -1;
821
822     for (i = 0; i < 3; i++) {
823         x_shift = i ? desc->log2_chroma_w : 0;
824         y_shift = i ? desc->log2_chroma_h : 0;
825
826         if (padtop || padleft) {
827             memset(dst->data[i], color[i],
828                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
829         }
830
831         if (padleft || padright) {
832             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
833                 (dst->linesize[i] - (padright >> x_shift));
834             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
835             for (y = 0; y < yheight; y++) {
836                 memset(optr, color[i], (padleft + padright) >> x_shift);
837                 optr += dst->linesize[i];
838             }
839         }
840
841         if (src) { /* first line */
842             uint8_t *iptr = src->data[i];
843             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
844                     (padleft >> x_shift);
845             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
846             iptr += src->linesize[i];
847             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
848                 (dst->linesize[i] - (padright >> x_shift));
849             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
850             for (y = 0; y < yheight; y++) {
851                 memset(optr, color[i], (padleft + padright) >> x_shift);
852                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
853                        (width - padleft - padright) >> x_shift);
854                 iptr += src->linesize[i];
855                 optr += dst->linesize[i];
856             }
857         }
858
859         if (padbottom || padright) {
860             optr = dst->data[i] + dst->linesize[i] *
861                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
862             memset(optr, color[i],dst->linesize[i] *
863                 (padbottom >> y_shift) + (padright >> x_shift));
864         }
865     }
866     return 0;
867 }
868
869 #if !HAVE_MMX_EXTERNAL
870 /* filter parameters: [-1 4 2 4 -1] // 8 */
871 static void deinterlace_line_c(uint8_t *dst,
872                              const uint8_t *lum_m4, const uint8_t *lum_m3,
873                              const uint8_t *lum_m2, const uint8_t *lum_m1,
874                              const uint8_t *lum,
875                              int size)
876 {
877     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
878     int sum;
879
880     for(;size > 0;size--) {
881         sum = -lum_m4[0];
882         sum += lum_m3[0] << 2;
883         sum += lum_m2[0] << 1;
884         sum += lum_m1[0] << 2;
885         sum += -lum[0];
886         dst[0] = cm[(sum + 4) >> 3];
887         lum_m4++;
888         lum_m3++;
889         lum_m2++;
890         lum_m1++;
891         lum++;
892         dst++;
893     }
894 }
895
896 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
897                                        uint8_t *lum_m2, uint8_t *lum_m1,
898                                        uint8_t *lum, int size)
899 {
900     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
901     int sum;
902
903     for(;size > 0;size--) {
904         sum = -lum_m4[0];
905         sum += lum_m3[0] << 2;
906         sum += lum_m2[0] << 1;
907         lum_m4[0]=lum_m2[0];
908         sum += lum_m1[0] << 2;
909         sum += -lum[0];
910         lum_m2[0] = cm[(sum + 4) >> 3];
911         lum_m4++;
912         lum_m3++;
913         lum_m2++;
914         lum_m1++;
915         lum++;
916     }
917 }
918 #endif /* !HAVE_MMX_EXTERNAL */
919
920 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
921    top field is copied as is, but the bottom field is deinterlaced
922    against the top field. */
923 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
924                                     const uint8_t *src1, int src_wrap,
925                                     int width, int height)
926 {
927     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
928     int y;
929
930     src_m2 = src1;
931     src_m1 = src1;
932     src_0=&src_m1[src_wrap];
933     src_p1=&src_0[src_wrap];
934     src_p2=&src_p1[src_wrap];
935     for(y=0;y<(height-2);y+=2) {
936         memcpy(dst,src_m1,width);
937         dst += dst_wrap;
938         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
939         src_m2 = src_0;
940         src_m1 = src_p1;
941         src_0 = src_p2;
942         src_p1 += 2*src_wrap;
943         src_p2 += 2*src_wrap;
944         dst += dst_wrap;
945     }
946     memcpy(dst,src_m1,width);
947     dst += dst_wrap;
948     /* do last line */
949     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
950 }
951
952 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
953                                              int width, int height)
954 {
955     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
956     int y;
957     uint8_t *buf;
958     buf = av_malloc(width);
959
960     src_m1 = src1;
961     memcpy(buf,src_m1,width);
962     src_0=&src_m1[src_wrap];
963     src_p1=&src_0[src_wrap];
964     src_p2=&src_p1[src_wrap];
965     for(y=0;y<(height-2);y+=2) {
966         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
967         src_m1 = src_p1;
968         src_0 = src_p2;
969         src_p1 += 2*src_wrap;
970         src_p2 += 2*src_wrap;
971     }
972     /* do last line */
973     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
974     av_free(buf);
975 }
976
977 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
978                           enum AVPixelFormat pix_fmt, int width, int height)
979 {
980     int i;
981
982     if (pix_fmt != AV_PIX_FMT_YUV420P &&
983         pix_fmt != AV_PIX_FMT_YUVJ420P &&
984         pix_fmt != AV_PIX_FMT_YUV422P &&
985         pix_fmt != AV_PIX_FMT_YUVJ422P &&
986         pix_fmt != AV_PIX_FMT_YUV444P &&
987         pix_fmt != AV_PIX_FMT_YUV411P &&
988         pix_fmt != AV_PIX_FMT_GRAY8)
989         return -1;
990     if ((width & 3) != 0 || (height & 3) != 0)
991         return -1;
992
993     for(i=0;i<3;i++) {
994         if (i == 1) {
995             switch(pix_fmt) {
996             case AV_PIX_FMT_YUVJ420P:
997             case AV_PIX_FMT_YUV420P:
998                 width >>= 1;
999                 height >>= 1;
1000                 break;
1001             case AV_PIX_FMT_YUV422P:
1002             case AV_PIX_FMT_YUVJ422P:
1003                 width >>= 1;
1004                 break;
1005             case AV_PIX_FMT_YUV411P:
1006                 width >>= 2;
1007                 break;
1008             default:
1009                 break;
1010             }
1011             if (pix_fmt == AV_PIX_FMT_GRAY8) {
1012                 break;
1013             }
1014         }
1015         if (src == dst) {
1016             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
1017                                  width, height);
1018         } else {
1019             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
1020                                         src->data[i], src->linesize[i],
1021                                         width, height);
1022         }
1023     }
1024     emms_c();
1025     return 0;
1026 }