Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 "imgconvert.h"
  36. #include "internal.h"
  37. #include "libavutil/avassert.h"
  38. #include "libavutil/colorspace.h"
  39. #include "libavutil/common.h"
  40. #include "libavutil/pixdesc.h"
  41. #include "libavutil/imgutils.h"
  42.  
  43. #if HAVE_MMX_EXTERNAL
  44. #include "x86/dsputil_x86.h"
  45. #endif
  46.  
  47. #define FF_COLOR_NA      -1
  48. #define FF_COLOR_RGB      0 /**< RGB color space */
  49. #define FF_COLOR_GRAY     1 /**< gray color space */
  50. #define FF_COLOR_YUV      2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
  51. #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
  52.  
  53. #if HAVE_MMX_EXTERNAL
  54. #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
  55. #define deinterlace_line         ff_deinterlace_line_mmx
  56. #else
  57. #define deinterlace_line_inplace deinterlace_line_inplace_c
  58. #define deinterlace_line         deinterlace_line_c
  59. #endif
  60.  
  61. #define pixdesc_has_alpha(pixdesc) \
  62.     ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL)
  63.  
  64.  
  65. void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
  66. {
  67.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  68.     av_assert0(desc);
  69.     *h_shift = desc->log2_chroma_w;
  70.     *v_shift = desc->log2_chroma_h;
  71. }
  72.  
  73. static int get_color_type(const AVPixFmtDescriptor *desc) {
  74.     if (desc->flags & AV_PIX_FMT_FLAG_PAL)
  75.         return FF_COLOR_RGB;
  76.  
  77.     if(desc->nb_components == 1 || desc->nb_components == 2)
  78.         return FF_COLOR_GRAY;
  79.  
  80.     if(desc->name && !strncmp(desc->name, "yuvj", 4))
  81.         return FF_COLOR_YUV_JPEG;
  82.  
  83.     if(desc->flags & AV_PIX_FMT_FLAG_RGB)
  84.         return  FF_COLOR_RGB;
  85.  
  86.     if(desc->nb_components == 0)
  87.         return FF_COLOR_NA;
  88.  
  89.     return FF_COLOR_YUV;
  90. }
  91.  
  92. static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
  93. {
  94.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  95.     int i;
  96.  
  97.     if (!desc || !desc->nb_components) {
  98.         *min = *max = 0;
  99.         return AVERROR(EINVAL);
  100.     }
  101.  
  102.     *min = INT_MAX, *max = -INT_MAX;
  103.     for (i = 0; i < desc->nb_components; i++) {
  104.         *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
  105.         *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
  106.     }
  107.     return 0;
  108. }
  109.  
  110. static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
  111.                               enum AVPixelFormat src_pix_fmt,
  112.                               unsigned *lossp, unsigned consider)
  113. {
  114.     const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
  115.     const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
  116.     int src_color, dst_color;
  117.     int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
  118.     int ret, loss, i, nb_components;
  119.     int score = INT_MAX - 1;
  120.  
  121.     if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
  122.         return ~0;
  123.  
  124.     /* compute loss */
  125.     *lossp = loss = 0;
  126.  
  127.     if (dst_pix_fmt == src_pix_fmt)
  128.         return INT_MAX;
  129.  
  130.     if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
  131.         return ret;
  132.     if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
  133.         return ret;
  134.  
  135.     src_color = get_color_type(src_desc);
  136.     dst_color = get_color_type(dst_desc);
  137.     nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);
  138.  
  139.     for (i = 0; i < nb_components; i++)
  140.         if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1 && (consider & FF_LOSS_DEPTH)) {
  141.             loss |= FF_LOSS_DEPTH;
  142.             score -= 65536 >> dst_desc->comp[i].depth_minus1;
  143.         }
  144.  
  145.     if (consider & FF_LOSS_RESOLUTION) {
  146.         if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
  147.             loss |= FF_LOSS_RESOLUTION;
  148.             score -= 256 << dst_desc->log2_chroma_w;
  149.         }
  150.         if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {
  151.             loss |= FF_LOSS_RESOLUTION;
  152.             score -= 256 << dst_desc->log2_chroma_h;
  153.         }
  154.         // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side
  155.         if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&
  156.             dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {
  157.             score += 512;
  158.         }
  159.     }
  160.  
  161.     if(consider & FF_LOSS_COLORSPACE)
  162.     switch(dst_color) {
  163.     case FF_COLOR_RGB:
  164.         if (src_color != FF_COLOR_RGB &&
  165.             src_color != FF_COLOR_GRAY)
  166.             loss |= FF_LOSS_COLORSPACE;
  167.         break;
  168.     case FF_COLOR_GRAY:
  169.         if (src_color != FF_COLOR_GRAY)
  170.             loss |= FF_LOSS_COLORSPACE;
  171.         break;
  172.     case FF_COLOR_YUV:
  173.         if (src_color != FF_COLOR_YUV)
  174.             loss |= FF_LOSS_COLORSPACE;
  175.         break;
  176.     case FF_COLOR_YUV_JPEG:
  177.         if (src_color != FF_COLOR_YUV_JPEG &&
  178.             src_color != FF_COLOR_YUV &&
  179.             src_color != FF_COLOR_GRAY)
  180.             loss |= FF_LOSS_COLORSPACE;
  181.         break;
  182.     default:
  183.         /* fail safe test */
  184.         if (src_color != dst_color)
  185.             loss |= FF_LOSS_COLORSPACE;
  186.         break;
  187.     }
  188.     if(loss & FF_LOSS_COLORSPACE)
  189.         score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1);
  190.  
  191.     if (dst_color == FF_COLOR_GRAY &&
  192.         src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {
  193.         loss |= FF_LOSS_CHROMA;
  194.         score -= 2 * 65536;
  195.     }
  196.     if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {
  197.         loss |= FF_LOSS_ALPHA;
  198.         score -= 65536;
  199.     }
  200.     if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&
  201.         (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {
  202.         loss |= FF_LOSS_COLORQUANT;
  203.         score -= 65536;
  204.     }
  205.  
  206.     *lossp = loss;
  207.     return score;
  208. }
  209.  
  210. int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
  211.                              enum AVPixelFormat src_pix_fmt,
  212.                              int has_alpha)
  213. {
  214.     int loss;
  215.     int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA);
  216.     if (ret < 0)
  217.         return ret;
  218.     return loss;
  219. }
  220.  
  221. enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
  222.                                             enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
  223. {
  224.     enum AVPixelFormat dst_pix_fmt;
  225.     int loss1, loss2, loss_mask;
  226.     const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1);
  227.     const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2);
  228.     int score1, score2;
  229.  
  230.     loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
  231.     if(!has_alpha)
  232.         loss_mask &= ~FF_LOSS_ALPHA;
  233.  
  234.     dst_pix_fmt = AV_PIX_FMT_NONE;
  235.     score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
  236.     score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
  237.  
  238.     if (score1 == score2) {
  239.         if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
  240.             dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
  241.         } else {
  242.             dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
  243.         }
  244.     } else {
  245.         dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
  246.     }
  247.  
  248.     if (loss_ptr)
  249.         *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
  250.     return dst_pix_fmt;
  251. }
  252.  
  253. #if AV_HAVE_INCOMPATIBLE_LIBAV_ABI
  254. enum AVPixelFormat avcodec_find_best_pix_fmt2(const enum AVPixelFormat *pix_fmt_list,
  255.                                             enum AVPixelFormat src_pix_fmt,
  256.                                             int has_alpha, int *loss_ptr){
  257.     return avcodec_find_best_pix_fmt_of_list(pix_fmt_list, src_pix_fmt, has_alpha, loss_ptr);
  258. }
  259. #else
  260. enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
  261.                                             enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
  262. {
  263.     return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
  264. }
  265. #endif
  266.  
  267. enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *pix_fmt_list,
  268.                                             enum AVPixelFormat src_pix_fmt,
  269.                                             int has_alpha, int *loss_ptr){
  270.     int i;
  271.  
  272.     enum AVPixelFormat best = AV_PIX_FMT_NONE;
  273.  
  274.     for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++)
  275.         best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr);
  276.  
  277.     return best;
  278. }
  279.  
  280. /* 2x2 -> 1x1 */
  281. void ff_shrink22(uint8_t *dst, int dst_wrap,
  282.                      const uint8_t *src, int src_wrap,
  283.                      int width, int height)
  284. {
  285.     int w;
  286.     const uint8_t *s1, *s2;
  287.     uint8_t *d;
  288.  
  289.     for(;height > 0; height--) {
  290.         s1 = src;
  291.         s2 = s1 + src_wrap;
  292.         d = dst;
  293.         for(w = width;w >= 4; w-=4) {
  294.             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
  295.             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
  296.             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
  297.             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
  298.             s1 += 8;
  299.             s2 += 8;
  300.             d += 4;
  301.         }
  302.         for(;w > 0; w--) {
  303.             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
  304.             s1 += 2;
  305.             s2 += 2;
  306.             d++;
  307.         }
  308.         src += 2 * src_wrap;
  309.         dst += dst_wrap;
  310.     }
  311. }
  312.  
  313. /* 4x4 -> 1x1 */
  314. void ff_shrink44(uint8_t *dst, int dst_wrap,
  315.                      const uint8_t *src, int src_wrap,
  316.                      int width, int height)
  317. {
  318.     int w;
  319.     const uint8_t *s1, *s2, *s3, *s4;
  320.     uint8_t *d;
  321.  
  322.     for(;height > 0; height--) {
  323.         s1 = src;
  324.         s2 = s1 + src_wrap;
  325.         s3 = s2 + src_wrap;
  326.         s4 = s3 + src_wrap;
  327.         d = dst;
  328.         for(w = width;w > 0; w--) {
  329.             d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
  330.                     s2[0] + s2[1] + s2[2] + s2[3] +
  331.                     s3[0] + s3[1] + s3[2] + s3[3] +
  332.                     s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
  333.             s1 += 4;
  334.             s2 += 4;
  335.             s3 += 4;
  336.             s4 += 4;
  337.             d++;
  338.         }
  339.         src += 4 * src_wrap;
  340.         dst += dst_wrap;
  341.     }
  342. }
  343.  
  344. /* 8x8 -> 1x1 */
  345. void ff_shrink88(uint8_t *dst, int dst_wrap,
  346.                      const uint8_t *src, int src_wrap,
  347.                      int width, int height)
  348. {
  349.     int w, i;
  350.  
  351.     for(;height > 0; height--) {
  352.         for(w = width;w > 0; w--) {
  353.             int tmp=0;
  354.             for(i=0; i<8; i++){
  355.                 tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7];
  356.                 src += src_wrap;
  357.             }
  358.             *(dst++) = (tmp + 32)>>6;
  359.             src += 8 - 8*src_wrap;
  360.         }
  361.         src += 8*src_wrap - 8*width;
  362.         dst += dst_wrap - width;
  363.     }
  364. }
  365.  
  366. /* return true if yuv planar */
  367. static inline int is_yuv_planar(const AVPixFmtDescriptor *desc)
  368. {
  369.     int i;
  370.     int planes[4] = { 0 };
  371.  
  372.     if (     desc->flags & AV_PIX_FMT_FLAG_RGB
  373.         || !(desc->flags & AV_PIX_FMT_FLAG_PLANAR))
  374.         return 0;
  375.  
  376.     /* set the used planes */
  377.     for (i = 0; i < desc->nb_components; i++)
  378.         planes[desc->comp[i].plane] = 1;
  379.  
  380.     /* if there is an unused plane, the format is not planar */
  381.     for (i = 0; i < desc->nb_components; i++)
  382.         if (!planes[i])
  383.             return 0;
  384.     return 1;
  385. }
  386.  
  387. int av_picture_crop(AVPicture *dst, const AVPicture *src,
  388.                     enum AVPixelFormat pix_fmt, int top_band, int left_band)
  389. {
  390.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  391.     int y_shift;
  392.     int x_shift;
  393.  
  394.     if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
  395.         return -1;
  396.  
  397.     y_shift = desc->log2_chroma_h;
  398.     x_shift = desc->log2_chroma_w;
  399.  
  400.     if (is_yuv_planar(desc)) {
  401.     dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
  402.     dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift);
  403.     dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift);
  404.     } else{
  405.         if(top_band % (1<<y_shift) || left_band % (1<<x_shift))
  406.             return -1;
  407.         if(left_band) //FIXME add support for this too
  408.             return -1;
  409.         dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band;
  410.     }
  411.  
  412.     dst->linesize[0] = src->linesize[0];
  413.     dst->linesize[1] = src->linesize[1];
  414.     dst->linesize[2] = src->linesize[2];
  415.     return 0;
  416. }
  417.  
  418. int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
  419.                    enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright,
  420.             int *color)
  421. {
  422.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
  423.     uint8_t *optr;
  424.     int y_shift;
  425.     int x_shift;
  426.     int yheight;
  427.     int i, y;
  428.  
  429.     if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB ||
  430.         !is_yuv_planar(desc)) return -1;
  431.  
  432.     for (i = 0; i < 3; i++) {
  433.         x_shift = i ? desc->log2_chroma_w : 0;
  434.         y_shift = i ? desc->log2_chroma_h : 0;
  435.  
  436.         if (padtop || padleft) {
  437.             memset(dst->data[i], color[i],
  438.                 dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift));
  439.         }
  440.  
  441.         if (padleft || padright) {
  442.             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
  443.                 (dst->linesize[i] - (padright >> x_shift));
  444.             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
  445.             for (y = 0; y < yheight; y++) {
  446.                 memset(optr, color[i], (padleft + padright) >> x_shift);
  447.                 optr += dst->linesize[i];
  448.             }
  449.         }
  450.  
  451.         if (src) { /* first line */
  452.             uint8_t *iptr = src->data[i];
  453.             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
  454.                     (padleft >> x_shift);
  455.             memcpy(optr, iptr, (width - padleft - padright) >> x_shift);
  456.             iptr += src->linesize[i];
  457.             optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) +
  458.                 (dst->linesize[i] - (padright >> x_shift));
  459.             yheight = (height - 1 - (padtop + padbottom)) >> y_shift;
  460.             for (y = 0; y < yheight; y++) {
  461.                 memset(optr, color[i], (padleft + padright) >> x_shift);
  462.                 memcpy(optr + ((padleft + padright) >> x_shift), iptr,
  463.                        (width - padleft - padright) >> x_shift);
  464.                 iptr += src->linesize[i];
  465.                 optr += dst->linesize[i];
  466.             }
  467.         }
  468.  
  469.         if (padbottom || padright) {
  470.             optr = dst->data[i] + dst->linesize[i] *
  471.                 ((height - padbottom) >> y_shift) - (padright >> x_shift);
  472.             memset(optr, color[i],dst->linesize[i] *
  473.                 (padbottom >> y_shift) + (padright >> x_shift));
  474.         }
  475.     }
  476.     return 0;
  477. }
  478.  
  479. #if FF_API_DEINTERLACE
  480.  
  481. #if !HAVE_MMX_EXTERNAL
  482. /* filter parameters: [-1 4 2 4 -1] // 8 */
  483. static void deinterlace_line_c(uint8_t *dst,
  484.                              const uint8_t *lum_m4, const uint8_t *lum_m3,
  485.                              const uint8_t *lum_m2, const uint8_t *lum_m1,
  486.                              const uint8_t *lum,
  487.                              int size)
  488. {
  489.     const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
  490.     int sum;
  491.  
  492.     for(;size > 0;size--) {
  493.         sum = -lum_m4[0];
  494.         sum += lum_m3[0] << 2;
  495.         sum += lum_m2[0] << 1;
  496.         sum += lum_m1[0] << 2;
  497.         sum += -lum[0];
  498.         dst[0] = cm[(sum + 4) >> 3];
  499.         lum_m4++;
  500.         lum_m3++;
  501.         lum_m2++;
  502.         lum_m1++;
  503.         lum++;
  504.         dst++;
  505.     }
  506. }
  507.  
  508. static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3,
  509.                                        uint8_t *lum_m2, uint8_t *lum_m1,
  510.                                        uint8_t *lum, int size)
  511. {
  512.     const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
  513.     int sum;
  514.  
  515.     for(;size > 0;size--) {
  516.         sum = -lum_m4[0];
  517.         sum += lum_m3[0] << 2;
  518.         sum += lum_m2[0] << 1;
  519.         lum_m4[0]=lum_m2[0];
  520.         sum += lum_m1[0] << 2;
  521.         sum += -lum[0];
  522.         lum_m2[0] = cm[(sum + 4) >> 3];
  523.         lum_m4++;
  524.         lum_m3++;
  525.         lum_m2++;
  526.         lum_m1++;
  527.         lum++;
  528.     }
  529. }
  530. #endif /* !HAVE_MMX_EXTERNAL */
  531.  
  532. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  533.    top field is copied as is, but the bottom field is deinterlaced
  534.    against the top field. */
  535. static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
  536.                                     const uint8_t *src1, int src_wrap,
  537.                                     int width, int height)
  538. {
  539.     const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  540.     int y;
  541.  
  542.     src_m2 = src1;
  543.     src_m1 = src1;
  544.     src_0=&src_m1[src_wrap];
  545.     src_p1=&src_0[src_wrap];
  546.     src_p2=&src_p1[src_wrap];
  547.     for(y=0;y<(height-2);y+=2) {
  548.         memcpy(dst,src_m1,width);
  549.         dst += dst_wrap;
  550.         deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  551.         src_m2 = src_0;
  552.         src_m1 = src_p1;
  553.         src_0 = src_p2;
  554.         src_p1 += 2*src_wrap;
  555.         src_p2 += 2*src_wrap;
  556.         dst += dst_wrap;
  557.     }
  558.     memcpy(dst,src_m1,width);
  559.     dst += dst_wrap;
  560.     /* do last line */
  561.     deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  562. }
  563.  
  564. static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
  565.                                              int width, int height)
  566. {
  567.     uint8_t *src_m1, *src_0, *src_p1, *src_p2;
  568.     int y;
  569.     uint8_t *buf;
  570.     buf = av_malloc(width);
  571.  
  572.     src_m1 = src1;
  573.     memcpy(buf,src_m1,width);
  574.     src_0=&src_m1[src_wrap];
  575.     src_p1=&src_0[src_wrap];
  576.     src_p2=&src_p1[src_wrap];
  577.     for(y=0;y<(height-2);y+=2) {
  578.         deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  579.         src_m1 = src_p1;
  580.         src_0 = src_p2;
  581.         src_p1 += 2*src_wrap;
  582.         src_p2 += 2*src_wrap;
  583.     }
  584.     /* do last line */
  585.     deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  586.     av_free(buf);
  587. }
  588.  
  589. int avpicture_deinterlace(AVPicture *dst, const AVPicture *src,
  590.                           enum AVPixelFormat pix_fmt, int width, int height)
  591. {
  592.     int i;
  593.  
  594.     if (pix_fmt != AV_PIX_FMT_YUV420P &&
  595.         pix_fmt != AV_PIX_FMT_YUVJ420P &&
  596.         pix_fmt != AV_PIX_FMT_YUV422P &&
  597.         pix_fmt != AV_PIX_FMT_YUVJ422P &&
  598.         pix_fmt != AV_PIX_FMT_YUV444P &&
  599.         pix_fmt != AV_PIX_FMT_YUV411P &&
  600.         pix_fmt != AV_PIX_FMT_GRAY8)
  601.         return -1;
  602.     if ((width & 3) != 0 || (height & 3) != 0)
  603.         return -1;
  604.  
  605.     for(i=0;i<3;i++) {
  606.         if (i == 1) {
  607.             switch(pix_fmt) {
  608.             case AV_PIX_FMT_YUVJ420P:
  609.             case AV_PIX_FMT_YUV420P:
  610.                 width >>= 1;
  611.                 height >>= 1;
  612.                 break;
  613.             case AV_PIX_FMT_YUV422P:
  614.             case AV_PIX_FMT_YUVJ422P:
  615.                 width >>= 1;
  616.                 break;
  617.             case AV_PIX_FMT_YUV411P:
  618.                 width >>= 2;
  619.                 break;
  620.             default:
  621.                 break;
  622.             }
  623.             if (pix_fmt == AV_PIX_FMT_GRAY8) {
  624.                 break;
  625.             }
  626.         }
  627.         if (src == dst) {
  628.             deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i],
  629.                                  width, height);
  630.         } else {
  631.             deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  632.                                         src->data[i], src->linesize[i],
  633.                                         width, height);
  634.         }
  635.     }
  636.     emms_c();
  637.     return 0;
  638. }
  639.  
  640. #endif /* FF_API_DEINTERLACE */
  641.  
  642. #ifdef TEST
  643.  
  644. int main(void){
  645.     int i;
  646.     int err=0;
  647.     int skip = 0;
  648.  
  649.     for (i=0; i<AV_PIX_FMT_NB*2; i++) {
  650.         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
  651.         if(!desc || !desc->name) {
  652.             skip ++;
  653.             continue;
  654.         }
  655.         if (skip) {
  656.             av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
  657.             skip = 0;
  658.         }
  659.         av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d colortype:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc), get_color_type(desc));
  660.         if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
  661.             av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
  662.             err = 1;
  663.         }
  664.     }
  665.     return err;
  666. }
  667.  
  668. #endif
  669.