From 39bb27bf79bc4c2d8beaed637a14176264cb1916 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 2 Jul 2012 10:46:39 +0200 Subject: [PATCH 1/5] imgconvert: avoid undefined left shift in avcodec_find_best_pix_fmt CC: libav-stable@libav.org --- libavcodec/imgconvert.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 90c9b7b255..7a6102e08b 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -599,7 +599,8 @@ static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask, /* find exact color match with smallest size */ dst_pix_fmt = PIX_FMT_NONE; min_dist = 0x7fffffff; - for(i = 0;i < PIX_FMT_NB; i++) { + /* test only the first 64 pixel formats to avoid undefined behaviour */ + for (i = 0; i < 64; i++) { if (pix_fmt_mask & (1ULL << i)) { loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask; if (loss == 0) { From ac29054fda1fab73c443b7d6f9dd72a9f25f7aae Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 2 Jul 2012 11:15:06 +0200 Subject: [PATCH 2/5] imgconvert: add avcodec_find_best_pix_fmt2() The number of pixel formats outgrew the number of available bits in the bitmask used in avcodec_find_best_pix_fmt(). avcodec_find_best_pix_fmt2() uses a PIX_FMT_NONE terminated list of pixel formats instead. --- libavcodec/avcodec.h | 21 ++++++++++++++++++ libavcodec/imgconvert.c | 48 ++++++++++++++++++++++++++++++----------- libavcodec/version.h | 2 +- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e397bbca83..9e1aa1c927 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4227,6 +4227,27 @@ int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_ enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat *pix_fmt_list, + enum PixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt); /** diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 7a6102e08b..5b22cab023 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -588,7 +588,7 @@ static int avg_bits_per_pixel(enum PixelFormat pix_fmt) return bits; } -static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask, +static enum PixelFormat avcodec_find_best_pix_fmt1(enum PixelFormat *pix_fmt_list, enum PixelFormat src_pix_fmt, int has_alpha, int loss_mask) @@ -599,24 +599,48 @@ static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t pix_fmt_mask, /* find exact color match with smallest size */ dst_pix_fmt = PIX_FMT_NONE; min_dist = 0x7fffffff; - /* test only the first 64 pixel formats to avoid undefined behaviour */ - for (i = 0; i < 64; 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; - } + i = 0; + while (pix_fmt_list[i] != PIX_FMT_NONE) { + enum PixelFormat pix_fmt = pix_fmt_list[i]; + + if (i > PIX_FMT_NB) { + av_log(NULL, AV_LOG_ERROR, "Pixel format list longer than expected, " + "it is either not properly terminated or contains duplicates\n"); + return PIX_FMT_NONE; + } + + loss = avcodec_get_pix_fmt_loss(pix_fmt, src_pix_fmt, has_alpha) & loss_mask; + if (loss == 0) { + dist = avg_bits_per_pixel(pix_fmt); + if (dist < min_dist) { + min_dist = dist; + dst_pix_fmt = pix_fmt; } } + i++; } 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 list[64]; + int i, j = 0; + + // test only the first 64 pixel formats to avoid undefined behaviour + for (i = 0; i < 64; i++) { + if (pix_fmt_mask & (1ULL << i)) + list[j++] = i; + } + list[j] = PIX_FMT_NONE; + + return avcodec_find_best_pix_fmt2(list, src_pix_fmt, has_alpha, loss_ptr); +} + +enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat *pix_fmt_list, + enum PixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr) { enum PixelFormat dst_pix_fmt; int loss_mask, i; @@ -634,7 +658,7 @@ enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelForma i = 0; for(;;) { loss_mask = loss_mask_order[i++]; - dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt, + dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_list, src_pix_fmt, has_alpha, loss_mask); if (dst_pix_fmt >= 0) goto found; diff --git a/libavcodec/version.h b/libavcodec/version.h index 6cdb92a4ae..ff13f9d22d 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 20 +#define LIBAVCODEC_VERSION_MINOR 21 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ From f30260d32a92c7e12984dd6fb2238da35d6a4c03 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 2 Jul 2012 11:31:26 +0200 Subject: [PATCH 3/5] imgconvert: deprecate avcodec_find_best_pix_fmt() --- libavcodec/avcodec.h | 5 +++++ libavcodec/imgconvert.c | 2 ++ libavcodec/version.h | 3 +++ 3 files changed, 10 insertions(+) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 9e1aa1c927..71f2e7093f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -4202,7 +4202,10 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum PixelFormat pix_fmt); int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_pix_fmt, int has_alpha); +#if FF_API_FIND_BEST_PIX_FMT /** + * @deprecated use avcodec_find_best_pix_fmt2() instead. + * * Find the best pixel format to convert to given a certain source pixel * format. When converting from one pixel format to another, information loss * may occur. For example, when converting from RGB24 to GRAY, the color @@ -4224,8 +4227,10 @@ int avcodec_get_pix_fmt_loss(enum PixelFormat dst_pix_fmt, enum PixelFormat src_ * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. * @return The best pixel format to convert to or -1 if none was found. */ +attribute_deprecated enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +#endif /* FF_API_FIND_BEST_PIX_FMT */ /** * Find the best pixel format to convert to given a certain source pixel diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 5b22cab023..a6c832d5c9 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -622,6 +622,7 @@ static enum PixelFormat avcodec_find_best_pix_fmt1(enum PixelFormat *pix_fmt_lis return dst_pix_fmt; } +#if FF_API_FIND_BEST_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) { @@ -637,6 +638,7 @@ enum PixelFormat avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, enum PixelForma return avcodec_find_best_pix_fmt2(list, src_pix_fmt, has_alpha, loss_ptr); } +#endif /* FF_API_FIND_BEST_PIX_FMT */ enum PixelFormat avcodec_find_best_pix_fmt2(enum PixelFormat *pix_fmt_list, enum PixelFormat src_pix_fmt, diff --git a/libavcodec/version.h b/libavcodec/version.h index ff13f9d22d..87c69aa04e 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -73,5 +73,8 @@ #ifndef FF_API_DSP_MASK #define FF_API_DSP_MASK (LIBAVCODEC_VERSION_MAJOR < 55) #endif +#ifndef FF_API_FIND_BEST_PIX_FMT +#define FF_API_FIND_BEST_PIX_FMT (LIBAVCODEC_VERSION_MAJOR < 55) +#endif #endif /* AVCODEC_VERSION_H */ From caac3ab6efde4fc9769e8a7472269356f262970a Mon Sep 17 00:00:00 2001 From: Max Lazarov Date: Fri, 30 Mar 2012 23:56:56 -0700 Subject: [PATCH 4/5] eval: fix swapping of lt() and lte() CC: libav-stable@libav.org --- libavutil/eval.c | 4 ++-- tests/ref/fate/eval | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavutil/eval.c b/libavutil/eval.c index f2d619f5c9..77af2a371c 100644 --- a/libavutil/eval.c +++ b/libavutil/eval.c @@ -279,8 +279,8 @@ static int parse_primary(AVExpr **e, Parser *p) else if (strmatch(next, "eq" )) d->type = e_eq; else if (strmatch(next, "gte" )) d->type = e_gte; else if (strmatch(next, "gt" )) d->type = e_gt; - else if (strmatch(next, "lte" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } - else if (strmatch(next, "lt" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } + else if (strmatch(next, "lte" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } + else if (strmatch(next, "lt" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } else if (strmatch(next, "ld" )) d->type = e_ld; else if (strmatch(next, "isnan" )) d->type = e_isnan; else if (strmatch(next, "isinf" )) d->type = e_isinf; diff --git a/tests/ref/fate/eval b/tests/ref/fate/eval index b6ca0fa383..13c218c429 100644 --- a/tests/ref/fate/eval +++ b/tests/ref/fate/eval @@ -95,16 +95,16 @@ Evaluating 'st(1, 123); ld(1)' 'st(1, 123); ld(1)' -> 123.000000 Evaluating 'st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)' -'st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)' -> 4950.000000 +'st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)' -> 5050.000000 Evaluating 'st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)' -'st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)' -> 144.000000 +'st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)' -> 233.000000 Evaluating 'while(0, 10)' 'while(0, 10)' -> nan Evaluating 'st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))' -'st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))' -> 100.000000 +'st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))' -> 101.000000 Evaluating 'isnan(1)' 'isnan(1)' -> 0.000000 From 2d497c141d1fb6df290cdf45404b01ea1697d618 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 14 Jul 2012 13:31:14 +0200 Subject: [PATCH 5/5] eval: add gt(), gte(), lt() and lte() fate tests --- libavutil/eval.c | 8 ++++++++ tests/ref/fate/eval | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/libavutil/eval.c b/libavutil/eval.c index 77af2a371c..ff3191de62 100644 --- a/libavutil/eval.c +++ b/libavutil/eval.c @@ -596,6 +596,14 @@ int main(int argc, char **argv) "1Gi", "st(0, 123)", "st(1, 123); ld(1)", + "lte(0, 1)", + "lte(1, 1)", + "lte(1, 0)", + "lt(0, 1)", + "lt(1, 1)", + "gt(1, 0)", + "gt(2, 7)", + "gte(122, 122)", /* compute 1+2+...+N */ "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)", /* compute Fib(N) */ diff --git a/tests/ref/fate/eval b/tests/ref/fate/eval index 13c218c429..dfc5ae463d 100644 --- a/tests/ref/fate/eval +++ b/tests/ref/fate/eval @@ -94,6 +94,30 @@ Evaluating 'st(0, 123)' Evaluating 'st(1, 123); ld(1)' 'st(1, 123); ld(1)' -> 123.000000 +Evaluating 'lte(0, 1)' +'lte(0, 1)' -> 1.000000 + +Evaluating 'lte(1, 1)' +'lte(1, 1)' -> 1.000000 + +Evaluating 'lte(1, 0)' +'lte(1, 0)' -> 0.000000 + +Evaluating 'lt(0, 1)' +'lt(0, 1)' -> 1.000000 + +Evaluating 'lt(1, 1)' +'lt(1, 1)' -> 0.000000 + +Evaluating 'gt(1, 0)' +'gt(1, 0)' -> 1.000000 + +Evaluating 'gt(2, 7)' +'gt(2, 7)' -> 0.000000 + +Evaluating 'gte(122, 122)' +'gte(122, 122)' -> 1.000000 + Evaluating 'st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)' 'st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)' -> 5050.000000