This avoids a dependancy of libavfilter on libavcodec See Ticket 3592 Fixes Ticket2784 Signed-off-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.3
| @@ -4690,30 +4690,8 @@ void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int | |||
| */ | |||
| unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); | |||
| #define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ | |||
| #define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ | |||
| #define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ | |||
| #define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ | |||
| #define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ | |||
| #define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ | |||
| /** | |||
| * Compute what kind of losses will occur when converting from one specific | |||
| * pixel format to another. | |||
| * 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. These losses can involve loss of chroma, but also loss of | |||
| * resolution, loss of color depth, loss due to the color space conversion, loss | |||
| * of the alpha bits or loss due to color quantization. | |||
| * avcodec_get_fix_fmt_loss() informs you about the various types of losses | |||
| * which will occur when converting from one pixel format to another. | |||
| * | |||
| * @param[in] dst_pix_fmt destination pixel format | |||
| * @param[in] src_pix_fmt source pixel format | |||
| * @param[in] has_alpha Whether the source pixel format alpha channel is used. | |||
| * @return Combination of flags informing you what kind of losses will occur | |||
| * (maximum loss for an invalid dst_pix_fmt). | |||
| /** | |||
| * @deprecated see av_get_pix_fmt_loss() | |||
| */ | |||
| int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, | |||
| int has_alpha); | |||
| @@ -4740,34 +4718,7 @@ enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(const enum AVPixelFormat *p | |||
| int has_alpha, int *loss_ptr); | |||
| /** | |||
| * Find the best pixel format to convert to given a certain source pixel | |||
| * format and a selection of two destination pixel formats. 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_fmt_of_2() selects which of | |||
| * the given pixel formats should be used to suffer the least amount of loss. | |||
| * | |||
| * If one of the destination formats is AV_PIX_FMT_NONE the other pixel format (if valid) will be | |||
| * returned. | |||
| * | |||
| * @code | |||
| * src_pix_fmt = AV_PIX_FMT_YUV420P; | |||
| * dst_pix_fmt1= AV_PIX_FMT_RGB24; | |||
| * dst_pix_fmt2= AV_PIX_FMT_GRAY8; | |||
| * dst_pix_fmt3= AV_PIX_FMT_RGB8; | |||
| * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored. | |||
| * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss); | |||
| * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss); | |||
| * @endcode | |||
| * | |||
| * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from | |||
| * @param[in] dst_pix_fmt2 The other of the two destination 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[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e. | |||
| * NULL or value of zero means we care about all losses. Out: the loss | |||
| * that occurs when converting from src to selected dst pixel format. | |||
| * @return The best pixel format to convert to or -1 if none was found. | |||
| * @deprecated see av_find_best_pix_fmt_of_2() | |||
| */ | |||
| enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | |||
| enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); | |||
| @@ -40,12 +40,6 @@ | |||
| #include "libavutil/pixdesc.h" | |||
| #include "libavutil/imgutils.h" | |||
| #define FF_COLOR_NA -1 | |||
| #define FF_COLOR_RGB 0 /**< RGB color space */ | |||
| #define FF_COLOR_GRAY 1 /**< gray color space */ | |||
| #define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ | |||
| #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ | |||
| #if HAVE_MMX_EXTERNAL | |||
| #define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx | |||
| #define deinterlace_line ff_deinterlace_line_mmx | |||
| @@ -54,10 +48,6 @@ | |||
| #define deinterlace_line deinterlace_line_c | |||
| #endif | |||
| #define pixdesc_has_alpha(pixdesc) \ | |||
| ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL) | |||
| void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) | |||
| { | |||
| 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 | |||
| *v_shift = desc->log2_chroma_h; | |||
| } | |||
| static int get_color_type(const AVPixFmtDescriptor *desc) { | |||
| if (desc->flags & AV_PIX_FMT_FLAG_PAL) | |||
| return FF_COLOR_RGB; | |||
| if(desc->nb_components == 1 || desc->nb_components == 2) | |||
| return FF_COLOR_GRAY; | |||
| if(desc->name && !strncmp(desc->name, "yuvj", 4)) | |||
| return FF_COLOR_YUV_JPEG; | |||
| if(desc->flags & AV_PIX_FMT_FLAG_RGB) | |||
| return FF_COLOR_RGB; | |||
| if(desc->nb_components == 0) | |||
| return FF_COLOR_NA; | |||
| return FF_COLOR_YUV; | |||
| } | |||
| static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) | |||
| { | |||
| const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |||
| int i; | |||
| if (!desc || !desc->nb_components) { | |||
| *min = *max = 0; | |||
| return AVERROR(EINVAL); | |||
| } | |||
| *min = INT_MAX, *max = -INT_MAX; | |||
| for (i = 0; i < desc->nb_components; i++) { | |||
| *min = FFMIN(desc->comp[i].depth_minus1+1, *min); | |||
| *max = FFMAX(desc->comp[i].depth_minus1+1, *max); | |||
| } | |||
| return 0; | |||
| } | |||
| 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 - 1; | |||
| if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) | |||
| return ~0; | |||
| /* compute loss */ | |||
| *lossp = loss = 0; | |||
| if (dst_pix_fmt == src_pix_fmt) | |||
| return INT_MAX; | |||
| if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) | |||
| return ret; | |||
| if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) | |||
| return ret; | |||
| src_color = get_color_type(src_desc); | |||
| dst_color = get_color_type(dst_desc); | |||
| if (dst_pix_fmt == AV_PIX_FMT_PAL8) | |||
| nb_components = FFMIN(src_desc->nb_components, 4); | |||
| else | |||
| nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); | |||
| for (i = 0; i < nb_components; i++) { | |||
| int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1; | |||
| if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) { | |||
| loss |= FF_LOSS_DEPTH; | |||
| score -= 65536 >> depth_minus1; | |||
| } | |||
| } | |||
| 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; | |||
| } | |||
| // don't 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 && | |||
| src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_GRAY: | |||
| if (src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_YUV: | |||
| if (src_color != FF_COLOR_YUV) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_YUV_JPEG: | |||
| if (src_color != FF_COLOR_YUV_JPEG && | |||
| src_color != FF_COLOR_YUV && | |||
| src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| default: | |||
| /* fail safe test */ | |||
| if (src_color != dst_color) | |||
| 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 && (consider & FF_LOSS_CHROMA)) { | |||
| loss |= FF_LOSS_CHROMA; | |||
| score -= 2 * 65536; | |||
| } | |||
| if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { | |||
| loss |= FF_LOSS_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; | |||
| return av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); | |||
| } | |||
| enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | |||
| enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) | |||
| { | |||
| enum AVPixelFormat dst_pix_fmt; | |||
| int loss1, loss2, loss_mask; | |||
| const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); | |||
| const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); | |||
| int score1, score2; | |||
| loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ | |||
| if(!has_alpha) | |||
| loss_mask &= ~FF_LOSS_ALPHA; | |||
| dst_pix_fmt = AV_PIX_FMT_NONE; | |||
| score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); | |||
| score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); | |||
| if (score1 == score2) { | |||
| if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { | |||
| dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } else { | |||
| dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } | |||
| } else { | |||
| dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } | |||
| if (loss_ptr) | |||
| *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); | |||
| return dst_pix_fmt; | |||
| return av_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); | |||
| } | |||
| #if AV_HAVE_INCOMPATIBLE_LIBAV_ABI | |||
| @@ -657,7 +475,7 @@ int main(void){ | |||
| av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); | |||
| skip = 0; | |||
| } | |||
| 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)); | |||
| 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)); | |||
| if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { | |||
| av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); | |||
| err = 1; | |||
| @@ -31,7 +31,6 @@ | |||
| #include "libavutil/internal.h" | |||
| #include "libavutil/opt.h" | |||
| #include "libavutil/pixdesc.h" | |||
| #include "libavcodec/avcodec.h" // avcodec_find_best_pix_fmt_of_2() | |||
| #include "avfilter.h" | |||
| #include "formats.h" | |||
| @@ -628,7 +627,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) | |||
| int i; | |||
| for (i=0; i<link->in_formats->nb_formats; i++) { | |||
| enum AVPixelFormat p = link->in_formats->formats[i]; | |||
| best= avcodec_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); | |||
| best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); | |||
| } | |||
| av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n", | |||
| av_get_pix_fmt_name(best), link->in_formats->nb_formats, | |||
| @@ -164,6 +164,7 @@ TESTPROGS = adler32 \ | |||
| opt \ | |||
| pca \ | |||
| parseutils \ | |||
| pixdesc \ | |||
| random_seed \ | |||
| rational \ | |||
| ripemd \ | |||
| @@ -2082,3 +2082,226 @@ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) | |||
| return get_pix_fmt_internal(name); | |||
| } | |||
| #define FF_COLOR_NA -1 | |||
| #define FF_COLOR_RGB 0 /**< RGB color space */ | |||
| #define FF_COLOR_GRAY 1 /**< gray color space */ | |||
| #define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ | |||
| #define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ | |||
| #define pixdesc_has_alpha(pixdesc) \ | |||
| ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL) | |||
| static int get_color_type(const AVPixFmtDescriptor *desc) { | |||
| if (desc->flags & AV_PIX_FMT_FLAG_PAL) | |||
| return FF_COLOR_RGB; | |||
| if(desc->nb_components == 1 || desc->nb_components == 2) | |||
| return FF_COLOR_GRAY; | |||
| if(desc->name && !strncmp(desc->name, "yuvj", 4)) | |||
| return FF_COLOR_YUV_JPEG; | |||
| if(desc->flags & AV_PIX_FMT_FLAG_RGB) | |||
| return FF_COLOR_RGB; | |||
| if(desc->nb_components == 0) | |||
| return FF_COLOR_NA; | |||
| return FF_COLOR_YUV; | |||
| } | |||
| static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) | |||
| { | |||
| const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | |||
| int i; | |||
| if (!desc || !desc->nb_components) { | |||
| *min = *max = 0; | |||
| return AVERROR(EINVAL); | |||
| } | |||
| *min = INT_MAX, *max = -INT_MAX; | |||
| for (i = 0; i < desc->nb_components; i++) { | |||
| *min = FFMIN(desc->comp[i].depth_minus1+1, *min); | |||
| *max = FFMAX(desc->comp[i].depth_minus1+1, *max); | |||
| } | |||
| return 0; | |||
| } | |||
| 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 - 1; | |||
| if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) | |||
| return ~0; | |||
| /* compute loss */ | |||
| *lossp = loss = 0; | |||
| if (dst_pix_fmt == src_pix_fmt) | |||
| return INT_MAX; | |||
| if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) | |||
| return ret; | |||
| if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) | |||
| return ret; | |||
| src_color = get_color_type(src_desc); | |||
| dst_color = get_color_type(dst_desc); | |||
| if (dst_pix_fmt == AV_PIX_FMT_PAL8) | |||
| nb_components = FFMIN(src_desc->nb_components, 4); | |||
| else | |||
| nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); | |||
| for (i = 0; i < nb_components; i++) { | |||
| int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1; | |||
| if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) { | |||
| loss |= FF_LOSS_DEPTH; | |||
| score -= 65536 >> depth_minus1; | |||
| } | |||
| } | |||
| 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; | |||
| } | |||
| // don't 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 && | |||
| src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_GRAY: | |||
| if (src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_YUV: | |||
| if (src_color != FF_COLOR_YUV) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| case FF_COLOR_YUV_JPEG: | |||
| if (src_color != FF_COLOR_YUV_JPEG && | |||
| src_color != FF_COLOR_YUV && | |||
| src_color != FF_COLOR_GRAY) | |||
| loss |= FF_LOSS_COLORSPACE; | |||
| break; | |||
| default: | |||
| /* fail safe test */ | |||
| if (src_color != dst_color) | |||
| 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 && (consider & FF_LOSS_CHROMA)) { | |||
| loss |= FF_LOSS_CHROMA; | |||
| score -= 2 * 65536; | |||
| } | |||
| if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { | |||
| loss |= FF_LOSS_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 av_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; | |||
| } | |||
| enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | |||
| enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) | |||
| { | |||
| enum AVPixelFormat dst_pix_fmt; | |||
| int loss1, loss2, loss_mask; | |||
| const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); | |||
| const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); | |||
| int score1, score2; | |||
| loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ | |||
| if(!has_alpha) | |||
| loss_mask &= ~FF_LOSS_ALPHA; | |||
| dst_pix_fmt = AV_PIX_FMT_NONE; | |||
| score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); | |||
| score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); | |||
| if (score1 == score2) { | |||
| if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { | |||
| dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } else { | |||
| dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } | |||
| } else { | |||
| dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; | |||
| } | |||
| if (loss_ptr) | |||
| *loss_ptr = av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); | |||
| return dst_pix_fmt; | |||
| } | |||
| #ifdef TEST | |||
| int main(void){ | |||
| int i; | |||
| int err=0; | |||
| int skip = 0; | |||
| for (i=0; i<AV_PIX_FMT_NB*2; i++) { | |||
| const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); | |||
| if(!desc || !desc->name) { | |||
| skip ++; | |||
| continue; | |||
| } | |||
| if (skip) { | |||
| av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); | |||
| skip = 0; | |||
| } | |||
| 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)); | |||
| if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { | |||
| av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); | |||
| err = 1; | |||
| } | |||
| } | |||
| return err; | |||
| } | |||
| #endif | |||
| @@ -255,7 +255,7 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); | |||
| * Utility function to access log2_chroma_w log2_chroma_h from | |||
| * the pixel format AVPixFmtDescriptor. | |||
| * | |||
| * See avcodec_get_chroma_sub_sample() for a function that asserts a | |||
| * See av_get_chroma_sub_sample() for a function that asserts a | |||
| * valid pixel format instead of returning an error code. | |||
| * Its recommanded that you use avcodec_get_chroma_sub_sample unless | |||
| * you do check the return code! | |||
| @@ -287,5 +287,53 @@ void ff_check_pixfmt_descriptors(void); | |||
| */ | |||
| enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); | |||
| #define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ | |||
| #define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ | |||
| #define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ | |||
| #define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ | |||
| #define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ | |||
| #define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ | |||
| /** | |||
| * Compute what kind of losses will occur when converting from one specific | |||
| * pixel format to another. | |||
| * 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. These losses can involve loss of chroma, but also loss of | |||
| * resolution, loss of color depth, loss due to the color space conversion, loss | |||
| * of the alpha bits or loss due to color quantization. | |||
| * av_get_fix_fmt_loss() informs you about the various types of losses | |||
| * which will occur when converting from one pixel format to another. | |||
| * | |||
| * @param[in] dst_pix_fmt destination pixel format | |||
| * @param[in] src_pix_fmt source pixel format | |||
| * @param[in] has_alpha Whether the source pixel format alpha channel is used. | |||
| * @return Combination of flags informing you what kind of losses will occur | |||
| * (maximum loss for an invalid dst_pix_fmt). | |||
| */ | |||
| int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, | |||
| enum AVPixelFormat src_pix_fmt, | |||
| int has_alpha); | |||
| /** | |||
| * Compute what kind of losses will occur when converting from one specific | |||
| * pixel format to another. | |||
| * 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. These losses can involve loss of chroma, but also loss of | |||
| * resolution, loss of color depth, loss due to the color space conversion, loss | |||
| * of the alpha bits or loss due to color quantization. | |||
| * av_get_fix_fmt_loss() informs you about the various types of losses | |||
| * which will occur when converting from one pixel format to another. | |||
| * | |||
| * @param[in] dst_pix_fmt destination pixel format | |||
| * @param[in] src_pix_fmt source pixel format | |||
| * @param[in] has_alpha Whether the source pixel format alpha channel is used. | |||
| * @return Combination of flags informing you what kind of losses will occur | |||
| * (maximum loss for an invalid dst_pix_fmt). | |||
| */ | |||
| enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, | |||
| enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); | |||
| #endif /* AVUTIL_PIXDESC_H */ | |||