diff options
Diffstat (limited to 'libavcodec/imgconvert.c')
-rw-r--r-- | libavcodec/imgconvert.c | 436 |
1 files changed, 166 insertions, 270 deletions
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 90c9b7b..058a0d5 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -2,20 +2,20 @@ * Misc image conversion routines * Copyright (c) 2001, 2002, 2003 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -47,10 +47,6 @@ #define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ -#define FF_PIXEL_PLANAR 0 /**< each channel has one component in AVPicture */ -#define FF_PIXEL_PACKED 1 /**< only one components containing all the channels */ -#define FF_PIXEL_PALETTE 2 /**< one components containing indexes for a palette */ - #if HAVE_MMX && HAVE_YASM #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx #define deinterlace_line ff_deinterlace_line_mmx @@ -60,351 +56,235 @@ #endif typedef struct PixFmtInfo { - uint8_t nb_channels; /**< number of channels (including alpha) */ uint8_t color_type; /**< color type (see FF_COLOR_xxx constants) */ - uint8_t pixel_type; /**< pixel storage type (see FF_PIXEL_xxx constants) */ uint8_t is_alpha : 1; /**< true if alpha can be specified */ - uint8_t depth; /**< bit depth of the color components */ + uint8_t padded_size; /**< padded size in bits if different from the non-padded size */ } PixFmtInfo; /* this table gives more information about formats */ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { /* YUV formats */ [PIX_FMT_YUV420P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUV422P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUV444P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUYV422] = { - .nb_channels = 1, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_UYVY422] = { - .nb_channels = 1, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_YUV410P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUV411P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUV440P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUV420P16LE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_YUV422P16LE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_YUV444P16LE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_YUV420P16BE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_YUV422P16BE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_YUV444P16BE] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, - /* YUV formats with alpha plane */ [PIX_FMT_YUVA420P] = { - .nb_channels = 4, + .is_alpha = 1, + .color_type = FF_COLOR_YUV, + }, + + [PIX_FMT_YUVA444P] = { + .is_alpha = 1, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, /* JPEG YUV */ [PIX_FMT_YUVJ420P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV_JPEG, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUVJ422P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV_JPEG, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUVJ444P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV_JPEG, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_YUVJ440P] = { - .nb_channels = 3, .color_type = FF_COLOR_YUV_JPEG, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, /* RGB formats */ [PIX_FMT_RGB24] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_BGR24] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_ARGB] = { - .nb_channels = 4, .is_alpha = 1, + .is_alpha = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_RGB48BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 16, }, [PIX_FMT_RGB48LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 16, + }, + [PIX_FMT_RGBA64BE] = { + .is_alpha = 1, + .color_type = FF_COLOR_RGB, + }, + [PIX_FMT_RGBA64LE] = { + .is_alpha = 1, + .color_type = FF_COLOR_RGB, }, [PIX_FMT_RGB565BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, }, [PIX_FMT_RGB565LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, }, [PIX_FMT_RGB555BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_RGB555LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_RGB444BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, + .padded_size = 16, }, [PIX_FMT_RGB444LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, + .padded_size = 16, }, /* gray / mono formats */ [PIX_FMT_GRAY16BE] = { - .nb_channels = 1, .color_type = FF_COLOR_GRAY, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_GRAY16LE] = { - .nb_channels = 1, .color_type = FF_COLOR_GRAY, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 16, }, [PIX_FMT_GRAY8] = { - .nb_channels = 1, .color_type = FF_COLOR_GRAY, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, + }, + [PIX_FMT_GRAY8A] = { + .is_alpha = 1, + .color_type = FF_COLOR_GRAY, }, [PIX_FMT_MONOWHITE] = { - .nb_channels = 1, .color_type = FF_COLOR_GRAY, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 1, }, [PIX_FMT_MONOBLACK] = { - .nb_channels = 1, .color_type = FF_COLOR_GRAY, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 1, }, /* paletted formats */ [PIX_FMT_PAL8] = { - .nb_channels = 4, .is_alpha = 1, + .is_alpha = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PALETTE, - .depth = 8, }, [PIX_FMT_UYYVYY411] = { - .nb_channels = 1, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_ABGR] = { - .nb_channels = 4, .is_alpha = 1, + .is_alpha = 1, + .color_type = FF_COLOR_RGB, + }, + [PIX_FMT_BGR48BE] = { + .color_type = FF_COLOR_RGB, + }, + [PIX_FMT_BGR48LE] = { + .color_type = FF_COLOR_RGB, + }, + [PIX_FMT_BGRA64BE] = { + .is_alpha = 1, + .color_type = FF_COLOR_RGB, + }, + [PIX_FMT_BGRA64LE] = { + .is_alpha = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_BGR565BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_BGR565LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_BGR555BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_BGR555LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 5, + .padded_size = 16, }, [PIX_FMT_BGR444BE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, + .padded_size = 16, }, [PIX_FMT_BGR444LE] = { - .nb_channels = 3, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, + .padded_size = 16, }, [PIX_FMT_RGB8] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_RGB4] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, }, [PIX_FMT_RGB4_BYTE] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, + .padded_size = 8, }, [PIX_FMT_BGR8] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_BGR4] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 4, }, [PIX_FMT_BGR4_BYTE] = { - .nb_channels = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, + .padded_size = 8, }, [PIX_FMT_NV12] = { - .nb_channels = 2, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_NV21] = { - .nb_channels = 2, .color_type = FF_COLOR_YUV, - .pixel_type = FF_PIXEL_PLANAR, - .depth = 8, }, [PIX_FMT_BGRA] = { - .nb_channels = 4, .is_alpha = 1, + .is_alpha = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, [PIX_FMT_RGBA] = { - .nb_channels = 4, .is_alpha = 1, + .is_alpha = 1, .color_type = FF_COLOR_RGB, - .pixel_type = FF_PIXEL_PACKED, - .depth = 8, }, }; @@ -460,6 +340,16 @@ int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width, } } + switch (pix_fmt) { + case PIX_FMT_RGB8: + case PIX_FMT_BGR8: + case PIX_FMT_RGB4_BYTE: + case PIX_FMT_BGR4_BYTE: + case PIX_FMT_GRAY8: + // do not include palette for these pseudo-paletted formats + return size; + } + if (desc->flags & PIX_FMT_PAL) memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4); @@ -477,28 +367,55 @@ int avpicture_get_size(enum PixelFormat pix_fmt, int width, int height) return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height); } +static int get_pix_fmt_depth(int *min, int *max, enum PixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; + int i; + + if (!desc->nb_components) { + *min = *max = 0; + return AVERROR(EINVAL); + } + + *min = INT_MAX, *max = -INT_MAX; + for (i = 0; i < desc->nb_components; i++) { + *min = FFMIN(desc->comp[i].depth_minus1+1, *min); + *max = FFMAX(desc->comp[i].depth_minus1+1, *max); + } + return 0; +} + int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt, int has_alpha) { const PixFmtInfo *pf, *ps; - const AVPixFmtDescriptor *src_desc = &av_pix_fmt_descriptors[src_pix_fmt]; - const AVPixFmtDescriptor *dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt]; - int loss; + const AVPixFmtDescriptor *src_desc; + const AVPixFmtDescriptor *dst_desc; + int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; + int ret, loss; + + if (dst_pix_fmt >= PIX_FMT_NB || dst_pix_fmt <= PIX_FMT_NONE) + return ~0; + src_desc = &av_pix_fmt_descriptors[src_pix_fmt]; + dst_desc = &av_pix_fmt_descriptors[dst_pix_fmt]; ps = &pix_fmt_info[src_pix_fmt]; /* compute loss */ loss = 0; - pf = &pix_fmt_info[dst_pix_fmt]; - if (pf->depth < ps->depth || - ((dst_pix_fmt == PIX_FMT_RGB555BE || dst_pix_fmt == PIX_FMT_RGB555LE || - dst_pix_fmt == PIX_FMT_BGR555BE || dst_pix_fmt == PIX_FMT_BGR555LE) && - (src_pix_fmt == PIX_FMT_RGB565BE || src_pix_fmt == PIX_FMT_RGB565LE || - src_pix_fmt == PIX_FMT_BGR565BE || src_pix_fmt == PIX_FMT_BGR565LE))) + + if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) + return ret; + if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) + return ret; + if (dst_min_depth < src_min_depth || + dst_max_depth < src_max_depth) loss |= FF_LOSS_DEPTH; if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w || dst_desc->log2_chroma_h > src_desc->log2_chroma_h) loss |= FF_LOSS_RESOLUTION; + + pf = &pix_fmt_info[dst_pix_fmt]; switch(pf->color_type) { case FF_COLOR_RGB: if (ps->color_type != FF_COLOR_RGB && @@ -530,95 +447,44 @@ int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_ loss |= FF_LOSS_CHROMA; if (!pf->is_alpha && (ps->is_alpha && has_alpha)) loss |= FF_LOSS_ALPHA; - if (pf->pixel_type == FF_PIXEL_PALETTE && - (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY)) + if (dst_pix_fmt == PIX_FMT_PAL8 && + (src_pix_fmt != PIX_FMT_PAL8 && (ps->color_type != FF_COLOR_GRAY || (ps->is_alpha && has_alpha)))) loss |= FF_LOSS_COLORQUANT; + return loss; } static int avg_bits_per_pixel(enum PixelFormat pix_fmt) { - int bits; - const PixFmtInfo *pf; + const PixFmtInfo *info = &pix_fmt_info[pix_fmt]; const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; - pf = &pix_fmt_info[pix_fmt]; - switch(pf->pixel_type) { - case FF_PIXEL_PACKED: - switch(pix_fmt) { - case PIX_FMT_YUYV422: - case PIX_FMT_UYVY422: - case PIX_FMT_RGB565BE: - case PIX_FMT_RGB565LE: - case PIX_FMT_RGB555BE: - case PIX_FMT_RGB555LE: - case PIX_FMT_RGB444BE: - case PIX_FMT_RGB444LE: - case PIX_FMT_BGR565BE: - case PIX_FMT_BGR565LE: - case PIX_FMT_BGR555BE: - case PIX_FMT_BGR555LE: - case PIX_FMT_BGR444BE: - case PIX_FMT_BGR444LE: - bits = 16; - break; - case PIX_FMT_UYYVYY411: - bits = 12; - break; - default: - bits = pf->depth * pf->nb_channels; - break; - } - break; - case FF_PIXEL_PLANAR: - if (desc->log2_chroma_w == 0 && desc->log2_chroma_h == 0) { - bits = pf->depth * pf->nb_channels; - } else { - bits = pf->depth + ((2 * pf->depth) >> - (desc->log2_chroma_w + desc->log2_chroma_h)); - } - break; - case FF_PIXEL_PALETTE: - bits = 8; - break; - default: - bits = -1; - break; - } - return bits; + return info->padded_size ? + info->padded_size : av_get_bits_per_pixel(desc); } -static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask, - enum PixelFormat src_pix_fmt, - int has_alpha, - int loss_mask) +enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr) { - int dist, i, loss, min_dist; enum PixelFormat dst_pix_fmt; + int i; - /* find exact color match with smallest size */ - dst_pix_fmt = PIX_FMT_NONE; - min_dist = 0x7fffffff; - for(i = 0;i < PIX_FMT_NB; i++) { - if (pix_fmt_mask & (1ULL << i)) { - loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask; - if (loss == 0) { - dist = avg_bits_per_pixel(i); - if (dist < min_dist) { - min_dist = dist; - dst_pix_fmt = i; - } - } - } + if (loss_ptr) /* all losses count (for backward compatibility) */ + *loss_ptr = 0; + + dst_pix_fmt = PIX_FMT_NONE; /* so first iteration doesn't have to be treated special */ + for(i = 0; i< FFMIN(PIX_FMT_NB, 64); i++){ + if (pix_fmt_mask & (1ULL << i)) + dst_pix_fmt = avcodec_find_best_pix_fmt2(dst_pix_fmt, i, src_pix_fmt, has_alpha, loss_ptr); } return dst_pix_fmt; } -enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, - int has_alpha, int *loss_ptr) +enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat dst_pix_fmt1, enum PixelFormat dst_pix_fmt2, + enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) { enum PixelFormat dst_pix_fmt; - int loss_mask, i; + int loss1, loss2, loss_order1, loss_order2, i, loss_mask; static const int loss_mask_order[] = { ~0, /* no loss first */ ~FF_LOSS_ALPHA, @@ -626,22 +492,29 @@ enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelForma ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), ~FF_LOSS_COLORQUANT, ~FF_LOSS_DEPTH, + ~(FF_LOSS_RESOLUTION | FF_LOSS_DEPTH | FF_LOSS_COLORSPACE | FF_LOSS_ALPHA | + FF_LOSS_COLORQUANT | FF_LOSS_CHROMA), + 0x80000, //non zero entry that combines all loss variants including future additions 0, }; + loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ + dst_pix_fmt = PIX_FMT_NONE; + loss1 = avcodec_get_pix_fmt_loss(dst_pix_fmt1, src_pix_fmt, has_alpha) & loss_mask; + loss2 = avcodec_get_pix_fmt_loss(dst_pix_fmt2, src_pix_fmt, has_alpha) & loss_mask; + /* try with successive loss */ - i = 0; - for(;;) { - loss_mask = loss_mask_order[i++]; - dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt, - has_alpha, loss_mask); - if (dst_pix_fmt >= 0) - goto found; - if (loss_mask == 0) - break; + for(i = 0;loss_mask_order[i] != 0 && dst_pix_fmt == PIX_FMT_NONE;i++) { + loss_order1 = loss1 & loss_mask_order[i]; + loss_order2 = loss2 & loss_mask_order[i]; + + if (loss_order1 == 0 && loss_order2 == 0){ /* use format with smallest depth */ + dst_pix_fmt = avg_bits_per_pixel(dst_pix_fmt2) < avg_bits_per_pixel(dst_pix_fmt1) ? dst_pix_fmt2 : dst_pix_fmt1; + } else if (loss_order1 == 0 || loss_order2 == 0) { /* use format with no loss */ + dst_pix_fmt = loss_order2 ? dst_pix_fmt1 : dst_pix_fmt2; + } } - return PIX_FMT_NONE; - found: + if (loss_ptr) *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); return dst_pix_fmt; @@ -760,11 +633,26 @@ void avpicture_free(AVPicture *picture) } /* return true if yuv planar */ -static inline int is_yuv_planar(const PixFmtInfo *ps) +static inline int is_yuv_planar(enum PixelFormat fmt) { - return (ps->color_type == FF_COLOR_YUV || - ps->color_type == FF_COLOR_YUV_JPEG) && - ps->pixel_type == FF_PIXEL_PLANAR; + const PixFmtInfo *info = &pix_fmt_info[fmt]; + const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[fmt]; + int i; + int planes[4] = { 0 }; + + if (info->color_type != FF_COLOR_YUV && + info->color_type != FF_COLOR_YUV_JPEG) + return 0; + + /* set the used planes */ + for (i = 0; i < desc->nb_components; i++) + planes[desc->comp[i].plane] = 1; + + /* if there is an unused plane, the format is not planar */ + for (i = 0; i < desc->nb_components; i++) + if (!planes[i]) + return 0; + return 1; } int av_picture_crop(AVPicture *dst, const AVPicture *src, @@ -773,15 +661,23 @@ int av_picture_crop(AVPicture *dst, const AVPicture *src, int y_shift; int x_shift; - if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || !is_yuv_planar(&pix_fmt_info[pix_fmt])) + if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) return -1; y_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_h; x_shift = av_pix_fmt_descriptors[pix_fmt].log2_chroma_w; + if (is_yuv_planar(pix_fmt)) { dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift); dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift); + } else{ + if(top_band % (1<<y_shift) || left_band % (1<<x_shift)) + return -1; + if(left_band) //FIXME add support for this too + return -1; + dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; + } dst->linesize[0] = src->linesize[0]; dst->linesize[1] = src->linesize[1]; @@ -800,7 +696,7 @@ int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, int i, y; if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB || - !is_yuv_planar(&pix_fmt_info[pix_fmt])) return -1; + !is_yuv_planar(pix_fmt)) return -1; for (i = 0; i < 3; i++) { x_shift = i ? av_pix_fmt_descriptors[pix_fmt].log2_chroma_w : 0; |