History

Move av_find_best_pix_fmt_of_2() from avcodec to avutil

This avoids a dependancy of libavfilter on libavcodec See Ticket 3592 Fixes Ticket2784

Michael Niedermayer committed 12 years ago

Commit 617e8661 parent 8ff72926 files · +280 −240Browse files

Unified · Split

6 files
  1. libavcodec/avcodec.h +3 −52
  2. libavcodec/imgconvert.c +3 −185
  3. libavfilter/avfiltergraph.c +1 −2
  4. libavutil/Makefile +1 −0
  5. libavutil/pixdesc.c +223 −0
  6. libavutil/pixdesc.h +49 −1
libavcodec/avcodec.h+3−52
@@ -4690,30 +4690,8 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int · 4689 unmodified lines
4690 */4690 */
4691unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt);4691unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt);
4692 4692
4693#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */4693/**
4694#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */4694 * @deprecated see av_get_pix_fmt_loss()
4695#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */
4696#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */
4697#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */
4698#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */
4699
4700/**
4701 * Compute what kind of losses will occur when converting from one specific
4702 * pixel format to another.
4703 * When converting from one pixel format to another, information loss may occur.
4704 * For example, when converting from RGB24 to GRAY, the color information will
4705 * be lost. Similarly, other losses occur when converting from some formats to
4706 * other formats. These losses can involve loss of chroma, but also loss of
4707 * resolution, loss of color depth, loss due to the color space conversion, loss
4708 * of the alpha bits or loss due to color quantization.
4709 * avcodec_get_fix_fmt_loss() informs you about the various types of losses
4710 * which will occur when converting from one pixel format to another.
4711 *
4712 * @param[in] dst_pix_fmt destination pixel format
4713 * @param[in] src_pix_fmt source pixel format
4714 * @param[in] has_alpha Whether the source pixel format alpha channel is used.
4715 * @return Combination of flags informing you what kind of losses will occur
4716 * (maximum loss for an invalid dst_pix_fmt).
4717 */4695 */
4718int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt,4696int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt,
4719 int has_alpha);4697 int has_alpha);
@@ -4740,34 +4718,7 @@ enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *p · 20 unmodified lines
4740 int has_alpha, int *loss_ptr);4718 int has_alpha, int *loss_ptr);
4741 4719
4742/**4720/**
4743 * Find the best pixel format to convert to given a certain source pixel4721 * @deprecated see av_find_best_pix_fmt_of_2()
4744 * format and a selection of two destination pixel formats. When converting from
4745 * one pixel format to another, information loss may occur. For example, when converting
4746 * from RGB24 to GRAY, the color information will be lost. Similarly, other losses occur when
4747 * converting from some formats to other formats. avcodec_find_best_pix_fmt_of_2() selects which of
4748 * the given pixel formats should be used to suffer the least amount of loss.
4749 *
4750 * If one of the destination formats is AV_PIX_FMT_NONE the other pixel format (if valid) will be
4751 * returned.
4752 *
4753 * @code
4754 * src_pix_fmt = AV_PIX_FMT_YUV420P;
4755 * dst_pix_fmt1= AV_PIX_FMT_RGB24;
4756 * dst_pix_fmt2= AV_PIX_FMT_GRAY8;
4757 * dst_pix_fmt3= AV_PIX_FMT_RGB8;
4758 * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored.
4759 * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss);
4760 * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss);
4761 * @endcode
4762 *
4763 * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from
4764 * @param[in] dst_pix_fmt2 The other of the two destination pixel formats to choose from
4765 * @param[in] src_pix_fmt Source pixel format
4766 * @param[in] has_alpha Whether the source pixel format alpha channel is used.
4767 * @param[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e.
4768 * NULL or value of zero means we care about all losses. Out: the loss
4769 * that occurs when converting from src to selected dst pixel format.
4770 * @return The best pixel format to convert to or -1 if none was found.
4771 */4722 */
4772enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,4723enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
4773 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);4724 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);
libavcodec/imgconvert.c+3−185
@@ -40,12 +40,6 @@ · 39 unmodified lines
40#include "libavutil/pixdesc.h"40#include "libavutil/pixdesc.h"
41#include "libavutil/imgutils.h"41#include "libavutil/imgutils.h"
42 42
43#define FF_COLOR_NA -1
44#define FF_COLOR_RGB 0 /**< RGB color space */
45#define FF_COLOR_GRAY 1 /**< gray color space */
46#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
47#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
48
49#if HAVE_MMX_EXTERNAL43#if HAVE_MMX_EXTERNAL
50#define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx44#define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx
51#define deinterlace_line ff_deinterlace_line_mmx45#define deinterlace_line ff_deinterlace_line_mmx
@@ -54,10 +48,6 @@ · 2 unmodified lines
54#define deinterlace_line deinterlace_line_c48#define deinterlace_line deinterlace_line_c
55#endif49#endif
56 50
57#define pixdesc_has_alpha(pixdesc) \
58 ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL)
59
60
61void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)51void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
62{52{
63 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);53 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
@@ -66,189 +56,17 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int · 2 unmodified lines
66 *v_shift = desc->log2_chroma_h;56 *v_shift = desc->log2_chroma_h;
67}57}
68 58
69static int get_color_type(const AVPixFmtDescriptor *desc) {
70 if (desc->flags & AV_PIX_FMT_FLAG_PAL)
71 return FF_COLOR_RGB;
72
73 if(desc->nb_components == 1 || desc->nb_components == 2)
74 return FF_COLOR_GRAY;
75
76 if(desc->name && !strncmp(desc->name, "yuvj", 4))
77 return FF_COLOR_YUV_JPEG;
78
79 if(desc->flags & AV_PIX_FMT_FLAG_RGB)
80 return FF_COLOR_RGB;
81
82 if(desc->nb_components == 0)
83 return FF_COLOR_NA;
84
85 return FF_COLOR_YUV;
86}
87
88static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
89{
90 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
91 int i;
92
93 if (!desc || !desc->nb_components) {
94 *min = *max = 0;
95 return AVERROR(EINVAL);
96 }
97
98 *min = INT_MAX, *max = -INT_MAX;
99 for (i = 0; i < desc->nb_components; i++) {
100 *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
101 *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
102 }
103 return 0;
104}
105
106static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
107 enum AVPixelFormat src_pix_fmt,
108 unsigned *lossp, unsigned consider)
109{
110 const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
111 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
112 int src_color, dst_color;
113 int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
114 int ret, loss, i, nb_components;
115 int score = INT_MAX - 1;
116
117 if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
118 return ~0;
119
120 /* compute loss */
121 *lossp = loss = 0;
122
123 if (dst_pix_fmt == src_pix_fmt)
124 return INT_MAX;
125
126 if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
127 return ret;
128 if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
129 return ret;
130
131 src_color = get_color_type(src_desc);
132 dst_color = get_color_type(dst_desc);
133 if (dst_pix_fmt == AV_PIX_FMT_PAL8)
134 nb_components = FFMIN(src_desc->nb_components, 4);
135 else
136 nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);
137
138 for (i = 0; i < nb_components; i++) {
139 int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1;
140 if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) {
141 loss |= FF_LOSS_DEPTH;
142 score -= 65536 >> depth_minus1;
143 }
144 }
145
146 if (consider & FF_LOSS_RESOLUTION) {
147 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
148 loss |= FF_LOSS_RESOLUTION;
149 score -= 256 << dst_desc->log2_chroma_w;
150 }
151 if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {
152 loss |= FF_LOSS_RESOLUTION;
153 score -= 256 << dst_desc->log2_chroma_h;
154 }
155 // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side
156 if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&
157 dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {
158 score += 512;
159 }
160 }
161
162 if(consider & FF_LOSS_COLORSPACE)
163 switch(dst_color) {
164 case FF_COLOR_RGB:
165 if (src_color != FF_COLOR_RGB &&
166 src_color != FF_COLOR_GRAY)
167 loss |= FF_LOSS_COLORSPACE;
168 break;
169 case FF_COLOR_GRAY:
170 if (src_color != FF_COLOR_GRAY)
171 loss |= FF_LOSS_COLORSPACE;
172 break;
173 case FF_COLOR_YUV:
174 if (src_color != FF_COLOR_YUV)
175 loss |= FF_LOSS_COLORSPACE;
176 break;
177 case FF_COLOR_YUV_JPEG:
178 if (src_color != FF_COLOR_YUV_JPEG &&
179 src_color != FF_COLOR_YUV &&
180 src_color != FF_COLOR_GRAY)
181 loss |= FF_LOSS_COLORSPACE;
182 break;
183 default:
184 /* fail safe test */
185 if (src_color != dst_color)
186 loss |= FF_LOSS_COLORSPACE;
187 break;
188 }
189 if(loss & FF_LOSS_COLORSPACE)
190 score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1);
191
192 if (dst_color == FF_COLOR_GRAY &&
193 src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {
194 loss |= FF_LOSS_CHROMA;
195 score -= 2 * 65536;
196 }
197 if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {
198 loss |= FF_LOSS_ALPHA;
199 score -= 65536;
200 }
201 if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&
202 (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {
203 loss |= FF_LOSS_COLORQUANT;
204 score -= 65536;
205 }
206
207 *lossp = loss;
208 return score;
209}
210
211int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,59int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
212 enum AVPixelFormat src_pix_fmt,60 enum AVPixelFormat src_pix_fmt,
213 int has_alpha)61 int has_alpha)
214{62{
215 int loss;63 return av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
216 int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA);
217 if (ret < 0)
218 return ret;
219 return loss;
220}64}
221 65
222enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,66enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
223 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)67 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
224{68{
225 enum AVPixelFormat dst_pix_fmt;69 return av_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr);
226 int loss1, loss2, loss_mask;
227 const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1);
228 const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2);
229 int score1, score2;
230
231 loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
232 if(!has_alpha)
233 loss_mask &= ~FF_LOSS_ALPHA;
234
235 dst_pix_fmt = AV_PIX_FMT_NONE;
236 score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
237 score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
238
239 if (score1 == score2) {
240 if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
241 dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
242 } else {
243 dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
244 }
245 } else {
246 dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
247 }
248
249 if (loss_ptr)
250 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
251 return dst_pix_fmt;
252}70}
253 71
254#if AV_HAVE_INCOMPATIBLE_LIBAV_ABI72#if AV_HAVE_INCOMPATIBLE_LIBAV_ABI
@@ -657,7 +475,7 @@ int main(void){ · 402 unmodified lines
657 av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);475 av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
658 skip = 0;476 skip = 0;
659 }477 }
660 av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d colortype:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc), get_color_type(desc));478 av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc));
661 if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {479 if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
662 av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");480 av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
663 err = 1;481 err = 1;
libavfilter/avfiltergraph.c+1−2
@@ -31,7 +31,6 @@ · 30 unmodified lines
31#include "libavutil/internal.h"31#include "libavutil/internal.h"
32#include "libavutil/opt.h"32#include "libavutil/opt.h"
33#include "libavutil/pixdesc.h"33#include "libavutil/pixdesc.h"
34#include "libavcodec/avcodec.h" // avcodec_find_best_pix_fmt_of_2()
35 34
36#include "avfilter.h"35#include "avfilter.h"
37#include "formats.h"36#include "formats.h"
@@ -628,7 +627,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) · 590 unmodified lines
628 int i;627 int i;
629 for (i=0; i<link->in_formats->nb_formats; i++) {628 for (i=0; i<link->in_formats->nb_formats; i++) {
630 enum AVPixelFormat p = link->in_formats->formats[i];629 enum AVPixelFormat p = link->in_formats->formats[i];
631 best= avcodec_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL);630 best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL);
632 }631 }
633 av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n",632 av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n",
634 av_get_pix_fmt_name(best), link->in_formats->nb_formats,633 av_get_pix_fmt_name(best), link->in_formats->nb_formats,
libavutil/Makefile+1−0
@@ -164,6 +164,7 @@ TESTPROGS = adler32 \ · 163 unmodified lines
164 opt \164 opt \
165 pca \165 pca \
166 parseutils \166 parseutils \
167 pixdesc \
167 random_seed \168 random_seed \
168 rational \169 rational \
169 ripemd \170 ripemd \
libavutil/pixdesc.c+223−0
@@ -2082,3 +2082,226 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) · 2081 unmodified lines
2082 2082
2083 return get_pix_fmt_internal(name);2083 return get_pix_fmt_internal(name);
2084}2084}
2085
2086#define FF_COLOR_NA -1
2087#define FF_COLOR_RGB 0 /**< RGB color space */
2088#define FF_COLOR_GRAY 1 /**< gray color space */
2089#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
2090#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
2091
2092#define pixdesc_has_alpha(pixdesc) \
2093 ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL)
2094
2095
2096static int get_color_type(const AVPixFmtDescriptor *desc) {
2097 if (desc->flags & AV_PIX_FMT_FLAG_PAL)
2098 return FF_COLOR_RGB;
2099
2100 if(desc->nb_components == 1 || desc->nb_components == 2)
2101 return FF_COLOR_GRAY;
2102
2103 if(desc->name && !strncmp(desc->name, "yuvj", 4))
2104 return FF_COLOR_YUV_JPEG;
2105
2106 if(desc->flags & AV_PIX_FMT_FLAG_RGB)
2107 return FF_COLOR_RGB;
2108
2109 if(desc->nb_components == 0)
2110 return FF_COLOR_NA;
2111
2112 return FF_COLOR_YUV;
2113}
2114
2115static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt)
2116{
2117 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
2118 int i;
2119
2120 if (!desc || !desc->nb_components) {
2121 *min = *max = 0;
2122 return AVERROR(EINVAL);
2123 }
2124
2125 *min = INT_MAX, *max = -INT_MAX;
2126 for (i = 0; i < desc->nb_components; i++) {
2127 *min = FFMIN(desc->comp[i].depth_minus1+1, *min);
2128 *max = FFMAX(desc->comp[i].depth_minus1+1, *max);
2129 }
2130 return 0;
2131}
2132
2133static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt,
2134 enum AVPixelFormat src_pix_fmt,
2135 unsigned *lossp, unsigned consider)
2136{
2137 const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
2138 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
2139 int src_color, dst_color;
2140 int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth;
2141 int ret, loss, i, nb_components;
2142 int score = INT_MAX - 1;
2143
2144 if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE)
2145 return ~0;
2146
2147 /* compute loss */
2148 *lossp = loss = 0;
2149
2150 if (dst_pix_fmt == src_pix_fmt)
2151 return INT_MAX;
2152
2153 if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0)
2154 return ret;
2155 if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0)
2156 return ret;
2157
2158 src_color = get_color_type(src_desc);
2159 dst_color = get_color_type(dst_desc);
2160 if (dst_pix_fmt == AV_PIX_FMT_PAL8)
2161 nb_components = FFMIN(src_desc->nb_components, 4);
2162 else
2163 nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components);
2164
2165 for (i = 0; i < nb_components; i++) {
2166 int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1;
2167 if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) {
2168 loss |= FF_LOSS_DEPTH;
2169 score -= 65536 >> depth_minus1;
2170 }
2171 }
2172
2173 if (consider & FF_LOSS_RESOLUTION) {
2174 if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) {
2175 loss |= FF_LOSS_RESOLUTION;
2176 score -= 256 << dst_desc->log2_chroma_w;
2177 }
2178 if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) {
2179 loss |= FF_LOSS_RESOLUTION;
2180 score -= 256 << dst_desc->log2_chroma_h;
2181 }
2182 // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side
2183 if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 &&
2184 dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) {
2185 score += 512;
2186 }
2187 }
2188
2189 if(consider & FF_LOSS_COLORSPACE)
2190 switch(dst_color) {
2191 case FF_COLOR_RGB:
2192 if (src_color != FF_COLOR_RGB &&
2193 src_color != FF_COLOR_GRAY)
2194 loss |= FF_LOSS_COLORSPACE;
2195 break;
2196 case FF_COLOR_GRAY:
2197 if (src_color != FF_COLOR_GRAY)
2198 loss |= FF_LOSS_COLORSPACE;
2199 break;
2200 case FF_COLOR_YUV:
2201 if (src_color != FF_COLOR_YUV)
2202 loss |= FF_LOSS_COLORSPACE;
2203 break;
2204 case FF_COLOR_YUV_JPEG:
2205 if (src_color != FF_COLOR_YUV_JPEG &&
2206 src_color != FF_COLOR_YUV &&
2207 src_color != FF_COLOR_GRAY)
2208 loss |= FF_LOSS_COLORSPACE;
2209 break;
2210 default:
2211 /* fail safe test */
2212 if (src_color != dst_color)
2213 loss |= FF_LOSS_COLORSPACE;
2214 break;
2215 }
2216 if(loss & FF_LOSS_COLORSPACE)
2217 score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1);
2218
2219 if (dst_color == FF_COLOR_GRAY &&
2220 src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) {
2221 loss |= FF_LOSS_CHROMA;
2222 score -= 2 * 65536;
2223 }
2224 if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) {
2225 loss |= FF_LOSS_ALPHA;
2226 score -= 65536;
2227 }
2228 if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) &&
2229 (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) {
2230 loss |= FF_LOSS_COLORQUANT;
2231 score -= 65536;
2232 }
2233
2234 *lossp = loss;
2235 return score;
2236}
2237
2238int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
2239 enum AVPixelFormat src_pix_fmt,
2240 int has_alpha)
2241{
2242 int loss;
2243 int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA);
2244 if (ret < 0)
2245 return ret;
2246 return loss;
2247}
2248
2249enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
2250 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
2251{
2252 enum AVPixelFormat dst_pix_fmt;
2253 int loss1, loss2, loss_mask;
2254 const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1);
2255 const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2);
2256 int score1, score2;
2257
2258 loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */
2259 if(!has_alpha)
2260 loss_mask &= ~FF_LOSS_ALPHA;
2261
2262 dst_pix_fmt = AV_PIX_FMT_NONE;
2263 score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask);
2264 score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask);
2265
2266 if (score1 == score2) {
2267 if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) {
2268 dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1;
2269 } else {
2270 dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1;
2271 }
2272 } else {
2273 dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1;
2274 }
2275
2276 if (loss_ptr)
2277 *loss_ptr = av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
2278 return dst_pix_fmt;
2279}
2280
2281#ifdef TEST
2282
2283int main(void){
2284 int i;
2285 int err=0;
2286 int skip = 0;
2287
2288 for (i=0; i<AV_PIX_FMT_NB*2; i++) {
2289 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
2290 if(!desc || !desc->name) {
2291 skip ++;
2292 continue;
2293 }
2294 if (skip) {
2295 av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
2296 skip = 0;
2297 }
2298 av_log(NULL, AV_LOG_INFO, "pix fmt %s avg_bpp:%d colortype:%d\n", desc->name, av_get_padded_bits_per_pixel(desc), get_color_type(desc));
2299 if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
2300 av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
2301 err = 1;
2302 }
2303 }
2304 return err;
2305}
2306
2307#endif
libavutil/pixdesc.h+49−1
@@ -255,7 +255,7 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); · 254 unmodified lines
255 * Utility function to access log2_chroma_w log2_chroma_h from255 * Utility function to access log2_chroma_w log2_chroma_h from
256 * the pixel format AVPixFmtDescriptor.256 * the pixel format AVPixFmtDescriptor.
257 *257 *
258 * See avcodec_get_chroma_sub_sample() for a function that asserts a258 * See av_get_chroma_sub_sample() for a function that asserts a
259 * valid pixel format instead of returning an error code.259 * valid pixel format instead of returning an error code.
260 * Its recommanded that you use avcodec_get_chroma_sub_sample unless260 * Its recommanded that you use avcodec_get_chroma_sub_sample unless
261 * you do check the return code!261 * you do check the return code!
@@ -287,5 +287,53 @@ void ff_check_pixfmt_descriptors(void); · 25 unmodified lines
287 */287 */
288enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt);288enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt);
289 289
290#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */
291#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */
292#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */
293#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */
294#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */
295#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */
290 296
297/**
298 * Compute what kind of losses will occur when converting from one specific
299 * pixel format to another.
300 * When converting from one pixel format to another, information loss may occur.
301 * For example, when converting from RGB24 to GRAY, the color information will
302 * be lost. Similarly, other losses occur when converting from some formats to
303 * other formats. These losses can involve loss of chroma, but also loss of
304 * resolution, loss of color depth, loss due to the color space conversion, loss
305 * of the alpha bits or loss due to color quantization.
306 * av_get_fix_fmt_loss() informs you about the various types of losses
307 * which will occur when converting from one pixel format to another.
308 *
309 * @param[in] dst_pix_fmt destination pixel format
310 * @param[in] src_pix_fmt source pixel format
311 * @param[in] has_alpha Whether the source pixel format alpha channel is used.
312 * @return Combination of flags informing you what kind of losses will occur
313 * (maximum loss for an invalid dst_pix_fmt).
314 */
315int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt,
316 enum AVPixelFormat src_pix_fmt,
317 int has_alpha);
318
319/**
320 * Compute what kind of losses will occur when converting from one specific
321 * pixel format to another.
322 * When converting from one pixel format to another, information loss may occur.
323 * For example, when converting from RGB24 to GRAY, the color information will
324 * be lost. Similarly, other losses occur when converting from some formats to
325 * other formats. These losses can involve loss of chroma, but also loss of
326 * resolution, loss of color depth, loss due to the color space conversion, loss
327 * of the alpha bits or loss due to color quantization.
328 * av_get_fix_fmt_loss() informs you about the various types of losses
329 * which will occur when converting from one pixel format to another.
330 *
331 * @param[in] dst_pix_fmt destination pixel format
332 * @param[in] src_pix_fmt source pixel format
333 * @param[in] has_alpha Whether the source pixel format alpha channel is used.
334 * @return Combination of flags informing you what kind of losses will occur
335 * (maximum loss for an invalid dst_pix_fmt).
336 */
337enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2,
338 enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr);
291#endif /* AVUTIL_PIXDESC_H */339#endif /* AVUTIL_PIXDESC_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t