Commit 13ae02d0 authored by Michael Niedermayer's avatar Michael Niedermayer

imgconvert: add get_pix_fmt_score()

get_pix_fmt_score() returns a score representing the amount
of loss when converting a pixel format
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 969039eb
...@@ -104,24 +104,25 @@ static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) ...@@ -104,24 +104,25 @@ static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
return 0; return 0;
} }
int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
enum AVPixelFormat src_pix_fmt, enum AVPixelFormat src_pix_fmt,
int has_alpha) unsigned *lossp, unsigned consider)
{ {
const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt); const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt); const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
int src_color, dst_color; int src_color, dst_color;
int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
int ret, loss, i, nb_components; int ret, loss, i, nb_components;
int score = INT_MAX;
if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
return ~0; return ~0;
/* compute loss */ /* compute loss */
loss = 0; *lossp = loss = 0;
if (dst_pix_fmt == src_pix_fmt) if (dst_pix_fmt == src_pix_fmt)
return 0; return INT_MAX;
if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
return ret; return ret;
...@@ -133,13 +134,28 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, ...@@ -133,13 +134,28 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);
for (i = 0; i < nb_components; i++) for (i = 0; i < nb_components; i++)
if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1) if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1 && (consider & FF_LOSS_DEPTH)) {
loss |= FF_LOSS_DEPTH; loss |= FF_LOSS_DEPTH;
score -= 65536 >> dst_desc->comp[i].depth_minus1;
}
if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w || if (consider & FF_LOSS_RESOLUTION) {
dst_desc->log2_chroma_h > src_desc->log2_chroma_h) if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
loss |= FF_LOSS_RESOLUTION; loss |= FF_LOSS_RESOLUTION;
score -= 256 << dst_desc->log2_chroma_w;
}
if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {
loss |= FF_LOSS_RESOLUTION;
score -= 256 << dst_desc->log2_chroma_h;
}
// dont favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side
if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&
dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {
score += 512;
}
}
if(consider & FF_LOSS_COLORSPACE)
switch(dst_color) { switch(dst_color) {
case FF_COLOR_RGB: case FF_COLOR_RGB:
if (src_color != FF_COLOR_RGB && if (src_color != FF_COLOR_RGB &&
...@@ -166,15 +182,36 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, ...@@ -166,15 +182,36 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
loss |= FF_LOSS_COLORSPACE; loss |= FF_LOSS_COLORSPACE;
break; break;
} }
if(loss & FF_LOSS_COLORSPACE)
score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1);
if (dst_color == FF_COLOR_GRAY && if (dst_color == FF_COLOR_GRAY &&
src_color != FF_COLOR_GRAY) src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {
loss |= FF_LOSS_CHROMA; loss |= FF_LOSS_CHROMA;
if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && has_alpha)) score -= 2 * 65536;
}
if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {
loss |= FF_LOSS_ALPHA; loss |= FF_LOSS_ALPHA;
if (dst_pix_fmt == AV_PIX_FMT_PAL8 && score -= 65536;
(src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && has_alpha)))) }
if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&
(src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {
loss |= FF_LOSS_COLORQUANT; loss |= FF_LOSS_COLORQUANT;
score -= 65536;
}
*lossp = loss;
return score;
}
int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
enum AVPixelFormat src_pix_fmt,
int has_alpha)
{
int loss;
int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA);
if (ret < 0)
return ret;
return loss; return loss;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment