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 |   46 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index a1103e9..75ff116 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4222,6 +4222,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 8e3003d..79940ec 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,17 +599,25 @@ 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 < 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;
 }
@@ -617,6 +625,22 @@ static enum PixelFormat avcodec_find_best_pix_fmt1(int64_t 
pix_fmt_mask,
 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;
+
+    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;
     static const int loss_mask_order[] = {
@@ -633,7 +657,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;
-- 
1.7.8.6

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to