summaryrefslogtreecommitdiff
path: root/libavcodec/imgconvert.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/imgconvert.c')
-rw-r--r--libavcodec/imgconvert.c442
1 files changed, 168 insertions, 274 deletions
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 90c9b7b255..3111418e26 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
@@ -59,352 +55,230 @@
#define deinterlace_line deinterlace_line_c
#endif
+#define pixdesc_has_alpha(pixdesc) \
+ ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & PIX_FMT_PAL)
+
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,
.color_type = FF_COLOR_YUV,
- .pixel_type = FF_PIXEL_PLANAR,
- .depth = 8,
+ },
+
+ [PIX_FMT_YUVA422P] = {
+ .color_type = FF_COLOR_YUV,
+ },
+
+ [PIX_FMT_YUVA444P] = {
+ .color_type = FF_COLOR_YUV,
},
/* 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,
.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] = {
+ .color_type = FF_COLOR_RGB,
+ },
+ [PIX_FMT_RGBA64LE] = {
+ .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] = {
+ .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,
.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,
.color_type = FF_COLOR_RGB,
- .pixel_type = FF_PIXEL_PACKED,
- .depth = 8,
+ },
+ [PIX_FMT_BGR48BE] = {
+ .color_type = FF_COLOR_RGB,
+ },
+ [PIX_FMT_BGR48LE] = {
+ .color_type = FF_COLOR_RGB,
+ },
+ [PIX_FMT_BGRA64BE] = {
+ .color_type = FF_COLOR_RGB,
+ },
+ [PIX_FMT_BGRA64LE] = {
+ .color_type = FF_COLOR_RGB,
},
[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,
.color_type = FF_COLOR_RGB,
- .pixel_type = FF_PIXEL_PACKED,
- .depth = 8,
},
[PIX_FMT_RGBA] = {
- .nb_channels = 4, .is_alpha = 1,
.color_type = FF_COLOR_RGB,
- .pixel_type = FF_PIXEL_PACKED,
- .depth = 8,
},
};
@@ -460,8 +334,21 @@ int avpicture_layout(const AVPicture* src, enum PixelFormat pix_fmt, int width,
}
}
- if (desc->flags & PIX_FMT_PAL)
- memcpy((unsigned char *)(((size_t)dest + 3) & ~3), src->data[1], 256 * 4);
+ 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) {
+ uint32_t *d32 = (unsigned char *)(((size_t)dest + 3) & ~3);
+ for (i = 0; i<256; i++)
+ AV_WL32(d32 + i, AV_RN32(src->data[1] + 4*i));
+ }
return size;
}
@@ -477,28 +364,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 &&
@@ -528,97 +442,46 @@ int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_
if (pf->color_type == FF_COLOR_GRAY &&
ps->color_type != FF_COLOR_GRAY)
loss |= FF_LOSS_CHROMA;
- if (!pf->is_alpha && (ps->is_alpha && has_alpha))
+ if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && 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 || (pixdesc_has_alpha(src_desc) && 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 +489,30 @@ 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_DEPTH|FF_LOSS_COLORSPACE),
+ ~(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 +631,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 +659,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 +694,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;