This avoids a dependancy of libavfilter on libavcodec See Ticket 3592 Fixes Ticket2784
Unified · Split
| @@ -4690,30 +4690,8 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int · 4689 unmodified lines | |||
| 4690 | */ | 4690 | */ |
| 4691 | unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); | 4691 | unsigned 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 | */ |
| 4718 | int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, | 4696 | int 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 pixel | 4721 | * @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 | */ |
| 4772 | enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | 4723 | enum 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); |
| @@ -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_EXTERNAL | 43 | #if HAVE_MMX_EXTERNAL |
| 50 | #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx | 44 | #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx |
| 51 | #define deinterlace_line ff_deinterlace_line_mmx | 45 | #define deinterlace_line ff_deinterlace_line_mmx |
| @@ -54,10 +48,6 @@ · 2 unmodified lines | |||
| 54 | #define deinterlace_line deinterlace_line_c | 48 | #define deinterlace_line deinterlace_line_c |
| 55 | #endif | 49 | #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 | |||
| 61 | void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) | 51 | void 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 | ||
| 69 | static 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 | |||
| 88 | static 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 | |||
| 106 | static 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 | |||
| 211 | int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, | 59 | int 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 | ||
| 222 | enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | 66 | enum 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_ABI | 72 | #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; |
| @@ -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, |
| @@ -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 \ |
| @@ -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 | |||
| 2096 | static 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 | |||
| 2115 | static 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 | |||
| 2133 | static 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 | |||
| 2238 | int 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 | |||
| 2249 | enum 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 | |||
| 2283 | int 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 | ||
| @@ -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 from | 255 | * 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 a | 258 | * 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 unless | 260 | * 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 | */ |
| 288 | enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); | 288 | enum 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 | */ | ||
| 315 | int 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 | */ | ||
| 337 | enum 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 */ |