summaryrefslogtreecommitdiff
path: root/libavcodec/imgconvert.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2013-02-10 01:04:57 +0100
committerMichael Niedermayer <michaelni@gmx.at>2013-02-10 02:14:52 +0100
commit13ae02d03fbb84b22b802609c26aecec285508be (patch)
tree198eb9817f4bd56e945e0fd4e4bf948e7f360ef5 /libavcodec/imgconvert.c
parent969039eb6e10b870811dbd284d807c6aea8a2fcb (diff)
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: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/imgconvert.c')
-rw-r--r--libavcodec/imgconvert.c63
1 files changed, 50 insertions, 13 deletions
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 5c3ec39a1c..e5d5d70a14 100644
--- a/libavcodec/imgconvert.c
+++ b/libavcodec/imgconvert.c
@@ -104,24 +104,25 @@ static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
return 0;
}
-int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
- enum AVPixelFormat src_pix_fmt,
- int has_alpha)
+static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
+ enum AVPixelFormat src_pix_fmt,
+ unsigned *lossp, unsigned consider)
{
const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
int src_color, dst_color;
int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
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)
return ~0;
/* compute loss */
- loss = 0;
+ *lossp = loss = 0;
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)
return ret;
@@ -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);
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;
+ score -= 65536 >> dst_desc->comp[i].depth_minus1;
+ }
- 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;
+ if (consider & FF_LOSS_RESOLUTION) {
+ if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
+ 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) {
case FF_COLOR_RGB:
if (src_color != FF_COLOR_RGB &&
@@ -166,15 +182,36 @@ int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
loss |= FF_LOSS_COLORSPACE;
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 &&
- src_color != FF_COLOR_GRAY)
+ src_color != FF_COLOR_GRAY && (consider & 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;
- if (dst_pix_fmt == AV_PIX_FMT_PAL8 &&
- (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && has_alpha))))
+ score -= 65536;
+ }
+ 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;
+ 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;
}