]> 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 "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 && HAVE_YASM
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 && HAVE_YASM
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_fmt2(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_fmt2(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 enum PixelFormat avcodec_find_best_pix_fmt_of_list(enum PixelFormat *pix_fmt_list,
581                                             enum PixelFormat src_pix_fmt,
582                                             int has_alpha, int *loss_ptr){
583     int i;
584
585     enum PixelFormat best = PIX_FMT_NONE;
586
587     for(i=0; pix_fmt_list[i] != PIX_FMT_NONE; i++)
588         best = avcodec_find_best_pix_fmt2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr);
589
590     return best;
591 }
592
593 void av_picture_copy(AVPicture *dst, const AVPicture *src,
594                      enum PixelFormat pix_fmt, int width, int height)
595 {
596     av_image_copy(dst->data, dst->linesize, src->data,
597                   src->linesize, pix_fmt, width, height);
598 }
599
600 /* 2x2 -> 1x1 */
601 void ff_shrink22(uint8_t *dst, int dst_wrap,
602                      const uint8_t *src, int src_wrap,
603                      int width, int height)
604 {
605     int w;
606     const uint8_t *s1, *s2;
607     uint8_t *d;
608
609     for(;height > 0; height--) {
610         s1 = src;
611         s2 = s1 + src_wrap;
612         d = dst;
613         for(w = width;w >= 4; w-=4) {
614             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
615             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
616             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
617             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
618             s1 += 8;
619             s2 += 8;
620             d += 4;
621         }
622         for(;w > 0; w--) {
623             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
624             s1 += 2;
625             s2 += 2;
626             d++;
627         }
628         src += 2 * src_wrap;
629         dst += dst_wrap;
630     }
631 }
632
633 /* 4x4 -> 1x1 */
634 void ff_shrink44(uint8_t *dst, int dst_wrap,
635                      const uint8_t *src, int src_wrap,
636                      int width, int height)
637 {
638     int w;
639     const uint8_t *s1, *s2, *s3, *s4;
640     uint8_t *d;
641
642     for(;height > 0; height--) {
643         s1 = src;
644         s2 = s1 + src_wrap;
645         s3 = s2 + src_wrap;
646         s4 = s3 + src_wrap;
647         d = dst;
648         for(w = width;w > 0; w--) {
649             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
650                     s2[0] + s2[1] + s2[2] + s2[3] +
651                     s3[0] + s3[1] + s3[2] + s3[3] +
652                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
653             s1 += 4;
654             s2 += 4;
655             s3 += 4;
656             s4 += 4;
657             d++;
658         }
659         src += 4 * src_wrap;
660         dst += dst_wrap;
661     }
662 }
663
664 /* 8x8 -> 1x1 */
665 void ff_shrink88(uint8_t *dst, int dst_wrap,
666                      const uint8_t *src, int src_wrap,
667                      int width, int height)
668 {
669     int w, i;
670
671     for(;height > 0; height--) {
672         for(w = width;w > 0; w--) {
673             int tmp=0;
674             for(i=0; i<8; i++){
675                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
676                 src += src_wrap;
677             }
678             *(dst++) = (tmp + 32)>>6;
679             src += 8 - 8*src_wrap;
680         }
681         src += 8*src_wrap - 8*width;
682         dst += dst_wrap - width;
683     }
684 }
685
686
687 int avpicture_alloc(AVPicture *picture,
688                     enum PixelFormat pix_fmt, int width, int height)
689 {
690     int ret;
691
692     if ((ret = av_image_alloc(picture->data, picture->linesize, width, height, pix_fmt, 1)) < 0) {
693         memset(picture, 0, sizeof(AVPicture));
694         return ret;
695     }
696
697     return 0;
698 }
699
700 void avpicture_free(AVPicture *picture)
701 {
702     av_free(picture->data[0]);
703 }
704
705 /* return true if yuv planar */
706 static inline int is_yuv_planar(enum PixelFormat fmt)
707 {
708     const PixFmtInfo         *info = &pix_fmt_info[fmt];
709     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[fmt];
710     int i;
711     int planes[4] = { 0 };
712
713     if (info->color_type != FF_COLOR_YUV &&
714         info->color_type != FF_COLOR_YUV_JPEG)
715         return 0;
716
717     /* set the used planes */
718     for (i = 0; i < desc->nb_components; i++)
719         planes[desc->comp[i].plane] = 1;
720
721     /* if there is an unused plane, the format is not planar */
722     for (i = 0; i < desc->nb_components; i++)
723         if (!planes[i])
724             return 0;
725     return 1;
726 }
727
728 int av_picture_crop(AVPicture *dst, const AVPicture *src,
729                     enum PixelFormat pix_fmt, int top_band, int left_band)
730 {
731     int y_shift;
732     int x_shift;
733
734     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
735         return -1;
736
737     y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h;
738     x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w;
739
740     if (is_yuv_planar(pix_fmt)) {
741     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
742     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
743     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
744     } else{
745         if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
746             return -1;
747         if(left_band) //FIXME add support for this too
748             return -1;
749         dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
750     }
751
752     dst->linesize[0] = src->linesize[0];
753     dst->linesize[1] = src->linesize[1];
754     dst->linesize[2] = src->linesize[2];
755     return 0;
756 }
757
758 int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
759                    enum PixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
760             int *color)
761 {
762     uint8_t *optr;
763     int y_shift;
764     int x_shift;
765     int yheight;
766     int i, y;
767
768     if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB ||
769         !is_yuv_planar(pix_fmt)) return -1;
770
771     for (i = 0; i < 3; i++) {
772         x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0;
773         y_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_h : 0;
774
775         if (padtop || padleft) {
776             memset(dst->data[i], color[i],
777                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
778         }
779
780         if (padleft || padright) {
781             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
782                 (dst->linesize[i] - (padright >> x_shift));
783             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
784             for (y = 0; y < yheight; y++) {
785                 memset(optr, color[i], (padleft + padright) >> x_shift);
786                 optr += dst->linesize[i];
787             }
788         }
789
790         if (src) { /* first line */
791             uint8_t *iptr = src->data[i];
792             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
793                     (padleft >> x_shift);
794             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
795             iptr += src->linesize[i];
796             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
797                 (dst->linesize[i] - (padright >> x_shift));
798             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
799             for (y = 0; y < yheight; y++) {
800                 memset(optr, color[i], (padleft + padright) >> x_shift);
801                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
802                        (width - padleft - padright) >> x_shift);
803                 iptr += src->linesize[i];
804                 optr += dst->linesize[i];
805             }
806         }
807
808         if (padbottom || padright) {
809             optr = dst->data[i] + dst->linesize[i] *
810                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
811             memset(optr, color[i],dst->linesize[i] *
812                 (padbottom >> y_shift) + (padright >> x_shift));
813         }
814     }
815     return 0;
816 }
817
818 #if !(HAVE_MMX && HAVE_YASM)
819 /* filter parameters: [-1 4 2 4 -1] // 8 */
820 static void deinterlace_line_c(uint8_t *dst,
821                              const uint8_t *lum_m4, const uint8_t *lum_m3,
822                              const uint8_t *lum_m2, const uint8_t *lum_m1,
823                              const uint8_t *lum,
824                              int size)
825 {
826     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
827     int sum;
828
829     for(;size > 0;size--) {
830         sum = -lum_m4[0];
831         sum += lum_m3[0] << 2;
832         sum += lum_m2[0] << 1;
833         sum += lum_m1[0] << 2;
834         sum += -lum[0];
835         dst[0] = cm[(sum + 4) >> 3];
836         lum_m4++;
837         lum_m3++;
838         lum_m2++;
839         lum_m1++;
840         lum++;
841         dst++;
842     }
843 }
844
845 static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
846                                        uint8_t *lum_m2, uint8_t *lum_m1,
847                                        uint8_t *lum, int size)
848 {
849     uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
850     int sum;
851
852     for(;size > 0;size--) {
853         sum = -lum_m4[0];
854         sum += lum_m3[0] << 2;
855         sum += lum_m2[0] << 1;
856         lum_m4[0]=lum_m2[0];
857         sum += lum_m1[0] << 2;
858         sum += -lum[0];
859         lum_m2[0] = cm[(sum + 4) >> 3];
860         lum_m4++;
861         lum_m3++;
862         lum_m2++;
863         lum_m1++;
864         lum++;
865     }
866 }
867 #endif
868
869 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
870    top field is copied as is, but the bottom field is deinterlaced
871    against the top field. */
872 static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
873                                     const uint8_t *src1, int src_wrap,
874                                     int width, int height)
875 {
876     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
877     int y;
878
879     src_m2 = src1;
880     src_m1 = src1;
881     src_0=&src_m1[src_wrap];
882     src_p1=&src_0[src_wrap];
883     src_p2=&src_p1[src_wrap];
884     for(y=0;y<(height-2);y+=2) {
885         memcpy(dst,src_m1,width);
886         dst += dst_wrap;
887         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
888         src_m2 = src_0;
889         src_m1 = src_p1;
890         src_0 = src_p2;
891         src_p1 += 2*src_wrap;
892         src_p2 += 2*src_wrap;
893         dst += dst_wrap;
894     }
895     memcpy(dst,src_m1,width);
896     dst += dst_wrap;
897     /* do last line */
898     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
899 }
900
901 static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
902                                              int width, int height)
903 {
904     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
905     int y;
906     uint8_t *buf;
907     buf = av_malloc(width);
908
909     src_m1 = src1;
910     memcpy(buf,src_m1,width);
911     src_0=&src_m1[src_wrap];
912     src_p1=&src_0[src_wrap];
913     src_p2=&src_p1[src_wrap];
914     for(y=0;y<(height-2);y+=2) {
915         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
916         src_m1 = src_p1;
917         src_0 = src_p2;
918         src_p1 += 2*src_wrap;
919         src_p2 += 2*src_wrap;
920     }
921     /* do last line */
922     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
923     av_free(buf);
924 }
925
926 int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
927                           enum PixelFormat pix_fmt, int width, int height)
928 {
929     int i;
930
931     if (pix_fmt != PIX_FMT_YUV420P &&
932         pix_fmt != PIX_FMT_YUVJ420P &&
933         pix_fmt != PIX_FMT_YUV422P &&
934         pix_fmt != PIX_FMT_YUVJ422P &&
935         pix_fmt != PIX_FMT_YUV444P &&
936         pix_fmt != PIX_FMT_YUV411P &&
937         pix_fmt != PIX_FMT_GRAY8)
938         return -1;
939     if ((width & 3) != 0 || (height & 3) != 0)
940         return -1;
941
942     for(i=0;i<3;i++) {
943         if (i == 1) {
944             switch(pix_fmt) {
945             case PIX_FMT_YUVJ420P:
946             case PIX_FMT_YUV420P:
947                 width >>= 1;
948                 height >>= 1;
949                 break;
950             case PIX_FMT_YUV422P:
951             case PIX_FMT_YUVJ422P:
952                 width >>= 1;
953                 break;
954             case PIX_FMT_YUV411P:
955                 width >>= 2;
956                 break;
957             default:
958                 break;
959             }
960             if (pix_fmt == PIX_FMT_GRAY8) {
961                 break;
962             }
963         }
964         if (src == dst) {
965             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
966                                  width, height);
967         } else {
968             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
969                                         src->data[i], src->linesize[i],
970                                         width, height);
971         }
972     }
973     emms_c();
974     return 0;
975 }