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