diff --git a/sys/d3d11/gstd3d11colorconvert.c b/sys/d3d11/gstd3d11colorconvert.c index 344079d82a..3b43caea16 100644 --- a/sys/d3d11/gstd3d11colorconvert.c +++ b/sys/d3d11/gstd3d11colorconvert.c @@ -252,6 +252,207 @@ gst_d3d11_color_convert_transform_caps (GstBaseTransform * return result; } +/* + * This is an incomplete matrix of in formats and a score for the prefered output + * format. + * + * out: RGB24 RGB16 ARGB AYUV YUV444 YUV422 YUV420 YUV411 YUV410 PAL GRAY + * in + * RGB24 0 2 1 2 2 3 4 5 6 7 8 + * RGB16 1 0 1 2 2 3 4 5 6 7 8 + * ARGB 2 3 0 1 4 5 6 7 8 9 10 + * AYUV 3 4 1 0 2 5 6 7 8 9 10 + * YUV444 2 4 3 1 0 5 6 7 8 9 10 + * YUV422 3 5 4 2 1 0 6 7 8 9 10 + * YUV420 4 6 5 3 2 1 0 7 8 9 10 + * YUV411 4 6 5 3 2 1 7 0 8 9 10 + * YUV410 6 8 7 5 4 3 2 1 0 9 10 + * PAL 1 3 2 6 4 6 7 8 9 0 10 + * GRAY 1 4 3 2 1 5 6 7 8 9 0 + * + * PAL or GRAY are never prefered, if we can we would convert to PAL instead + * of GRAY, though + * less subsampling is prefered and if any, preferably horizontal + * We would like to keep the alpha, even if we would need to to colorspace conversion + * or lose depth. + */ +#define SCORE_FORMAT_CHANGE 1 +#define SCORE_DEPTH_CHANGE 1 +#define SCORE_ALPHA_CHANGE 1 +#define SCORE_CHROMA_W_CHANGE 1 +#define SCORE_CHROMA_H_CHANGE 1 +#define SCORE_PALETTE_CHANGE 1 + +#define SCORE_COLORSPACE_LOSS 2 /* RGB <-> YUV */ +#define SCORE_DEPTH_LOSS 4 /* change bit depth */ +#define SCORE_ALPHA_LOSS 8 /* lose the alpha channel */ +#define SCORE_CHROMA_W_LOSS 16 /* vertical subsample */ +#define SCORE_CHROMA_H_LOSS 32 /* horizontal subsample */ +#define SCORE_PALETTE_LOSS 64 /* convert to palette format */ +#define SCORE_COLOR_LOSS 128 /* convert to GRAY */ + +#define COLORSPACE_MASK (GST_VIDEO_FORMAT_FLAG_YUV | \ + GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_GRAY) +#define ALPHA_MASK (GST_VIDEO_FORMAT_FLAG_ALPHA) +#define PALETTE_MASK (GST_VIDEO_FORMAT_FLAG_PALETTE) + +/* calculate how much loss a conversion would be */ +static void +score_value (const GstVideoFormatInfo * in_info, + const GValue * val, gint * min_loss, const GstVideoFormatInfo ** out_info) +{ + const gchar *fname; + const GstVideoFormatInfo *t_info; + GstVideoFormatFlags in_flags, t_flags; + gint loss; + + fname = g_value_get_string (val); + t_info = gst_video_format_get_info (gst_video_format_from_string (fname)); + if (!t_info) + return; + + /* accept input format immediately without loss */ + if (in_info == t_info) { + *min_loss = 0; + *out_info = t_info; + return; + } + + loss = SCORE_FORMAT_CHANGE; + + in_flags = GST_VIDEO_FORMAT_INFO_FLAGS (in_info); + in_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; + in_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; + in_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; + + t_flags = GST_VIDEO_FORMAT_INFO_FLAGS (t_info); + t_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; + t_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; + t_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; + + if ((t_flags & PALETTE_MASK) != (in_flags & PALETTE_MASK)) { + loss += SCORE_PALETTE_CHANGE; + if (t_flags & PALETTE_MASK) + loss += SCORE_PALETTE_LOSS; + } + + if ((t_flags & COLORSPACE_MASK) != (in_flags & COLORSPACE_MASK)) { + loss += SCORE_COLORSPACE_LOSS; + if (t_flags & GST_VIDEO_FORMAT_FLAG_GRAY) + loss += SCORE_COLOR_LOSS; + } + + if ((t_flags & ALPHA_MASK) != (in_flags & ALPHA_MASK)) { + loss += SCORE_ALPHA_CHANGE; + if (in_flags & ALPHA_MASK) + loss += SCORE_ALPHA_LOSS; + } + + if ((in_info->h_sub[1]) != (t_info->h_sub[1])) { + loss += SCORE_CHROMA_H_CHANGE; + if ((in_info->h_sub[1]) < (t_info->h_sub[1])) + loss += SCORE_CHROMA_H_LOSS; + } + if ((in_info->w_sub[1]) != (t_info->w_sub[1])) { + loss += SCORE_CHROMA_W_CHANGE; + if ((in_info->w_sub[1]) < (t_info->w_sub[1])) + loss += SCORE_CHROMA_W_LOSS; + } + + if ((in_info->bits) != (t_info->bits)) { + loss += SCORE_DEPTH_CHANGE; + if ((in_info->bits) > (t_info->bits)) + loss += SCORE_DEPTH_LOSS + (in_info->bits - t_info->bits); + } + + GST_DEBUG ("score %s -> %s = %d", + GST_VIDEO_FORMAT_INFO_NAME (in_info), + GST_VIDEO_FORMAT_INFO_NAME (t_info), loss); + + if (loss < *min_loss) { + GST_DEBUG ("found new best %d", loss); + *out_info = t_info; + *min_loss = loss; + } +} + +static GstCaps * +gst_d3d11_color_convert_fixate_format (GstBaseTransform * trans, + GstCaps * caps, GstCaps * othercaps) +{ + GstStructure *ins, *outs; + const gchar *in_format; + const GstVideoFormatInfo *in_info, *out_info = NULL; + gint min_loss = G_MAXINT; + guint i, capslen; + GstCaps *result; + + result = gst_caps_intersect (othercaps, caps); + if (gst_caps_is_empty (result)) { + gst_caps_unref (result); + result = othercaps; + } else { + gst_caps_unref (othercaps); + } + + result = gst_caps_make_writable (result); + + ins = gst_caps_get_structure (caps, 0); + in_format = gst_structure_get_string (ins, "format"); + if (!in_format) { + gst_caps_unref (result); + return NULL; + } + + GST_DEBUG ("source format %s", in_format); + + in_info = + gst_video_format_get_info (gst_video_format_from_string (in_format)); + if (!in_info) { + gst_caps_unref (result); + return NULL; + } + + outs = gst_caps_get_structure (result, 0); + + capslen = gst_caps_get_size (result); + GST_DEBUG ("iterate %d structures", capslen); + for (i = 0; i < capslen; i++) { + GstStructure *tests; + const GValue *format; + + tests = gst_caps_get_structure (result, i); + format = gst_structure_get_value (tests, "format"); + /* should not happen */ + if (format == NULL) + continue; + + if (GST_VALUE_HOLDS_LIST (format)) { + gint j, len; + + len = gst_value_list_get_size (format); + GST_DEBUG ("have %d formats", len); + for (j = 0; j < len; j++) { + const GValue *val; + + val = gst_value_list_get_value (format, j); + if (G_VALUE_HOLDS_STRING (val)) { + score_value (in_info, val, &min_loss, &out_info); + if (min_loss == 0) + break; + } + } + } else if (G_VALUE_HOLDS_STRING (format)) { + score_value (in_info, format, &min_loss, &out_info); + } + } + if (out_info) + gst_structure_set (outs, "format", G_TYPE_STRING, + GST_VIDEO_FORMAT_INFO_NAME (out_info), NULL); + + return result; +} + static GstCaps * gst_d3d11_color_convert_fixate_caps (GstBaseTransform * trans, GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) @@ -261,7 +462,9 @@ gst_d3d11_color_convert_fixate_caps (GstBaseTransform * trans, GST_DEBUG_OBJECT (trans, "trying to fixate othercaps %" GST_PTR_FORMAT " based on caps %" GST_PTR_FORMAT, othercaps, caps); - result = gst_d3d11_caps_fixate_format (caps, gst_caps_ref (othercaps)); + result = + gst_d3d11_color_convert_fixate_format (trans, + caps, gst_caps_ref (othercaps)); if (!result) result = othercaps; diff --git a/sys/d3d11/gstd3d11utils.c b/sys/d3d11/gstd3d11utils.c index 404dbdef2c..32a7018289 100644 --- a/sys/d3d11/gstd3d11utils.c +++ b/sys/d3d11/gstd3d11utils.c @@ -342,206 +342,6 @@ gst_d3d11_is_windows_8_or_greater (void) return ret; } -/* - * This is an incomplete matrix of in formats and a score for the prefered output - * format. - * - * out: RGB24 RGB16 ARGB AYUV YUV444 YUV422 YUV420 YUV411 YUV410 PAL GRAY - * in - * RGB24 0 2 1 2 2 3 4 5 6 7 8 - * RGB16 1 0 1 2 2 3 4 5 6 7 8 - * ARGB 2 3 0 1 4 5 6 7 8 9 10 - * AYUV 3 4 1 0 2 5 6 7 8 9 10 - * YUV444 2 4 3 1 0 5 6 7 8 9 10 - * YUV422 3 5 4 2 1 0 6 7 8 9 10 - * YUV420 4 6 5 3 2 1 0 7 8 9 10 - * YUV411 4 6 5 3 2 1 7 0 8 9 10 - * YUV410 6 8 7 5 4 3 2 1 0 9 10 - * PAL 1 3 2 6 4 6 7 8 9 0 10 - * GRAY 1 4 3 2 1 5 6 7 8 9 0 - * - * PAL or GRAY are never prefered, if we can we would convert to PAL instead - * of GRAY, though - * less subsampling is prefered and if any, preferably horizontal - * We would like to keep the alpha, even if we would need to to colorspace conversion - * or lose depth. - */ -#define SCORE_FORMAT_CHANGE 1 -#define SCORE_DEPTH_CHANGE 1 -#define SCORE_ALPHA_CHANGE 1 -#define SCORE_CHROMA_W_CHANGE 1 -#define SCORE_CHROMA_H_CHANGE 1 -#define SCORE_PALETTE_CHANGE 1 - -#define SCORE_COLORSPACE_LOSS 2 /* RGB <-> YUV */ -#define SCORE_DEPTH_LOSS 4 /* change bit depth */ -#define SCORE_ALPHA_LOSS 8 /* lose the alpha channel */ -#define SCORE_CHROMA_W_LOSS 16 /* vertical subsample */ -#define SCORE_CHROMA_H_LOSS 32 /* horizontal subsample */ -#define SCORE_PALETTE_LOSS 64 /* convert to palette format */ -#define SCORE_COLOR_LOSS 128 /* convert to GRAY */ - -#define COLORSPACE_MASK (GST_VIDEO_FORMAT_FLAG_YUV | \ - GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_GRAY) -#define ALPHA_MASK (GST_VIDEO_FORMAT_FLAG_ALPHA) -#define PALETTE_MASK (GST_VIDEO_FORMAT_FLAG_PALETTE) - -/* calculate how much loss a conversion would be */ -static void -score_value (const GstVideoFormatInfo * in_info, - const GValue * val, gint * min_loss, const GstVideoFormatInfo ** out_info) -{ - const gchar *fname; - const GstVideoFormatInfo *t_info; - GstVideoFormatFlags in_flags, t_flags; - gint loss; - - fname = g_value_get_string (val); - t_info = gst_video_format_get_info (gst_video_format_from_string (fname)); - if (!t_info) - return; - - /* accept input format immediately without loss */ - if (in_info == t_info) { - *min_loss = 0; - *out_info = t_info; - return; - } - - loss = SCORE_FORMAT_CHANGE; - - in_flags = GST_VIDEO_FORMAT_INFO_FLAGS (in_info); - in_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; - in_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; - in_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; - - t_flags = GST_VIDEO_FORMAT_INFO_FLAGS (t_info); - t_flags &= ~GST_VIDEO_FORMAT_FLAG_LE; - t_flags &= ~GST_VIDEO_FORMAT_FLAG_COMPLEX; - t_flags &= ~GST_VIDEO_FORMAT_FLAG_UNPACK; - - if ((t_flags & PALETTE_MASK) != (in_flags & PALETTE_MASK)) { - loss += SCORE_PALETTE_CHANGE; - if (t_flags & PALETTE_MASK) - loss += SCORE_PALETTE_LOSS; - } - - if ((t_flags & COLORSPACE_MASK) != (in_flags & COLORSPACE_MASK)) { - loss += SCORE_COLORSPACE_LOSS; - if (t_flags & GST_VIDEO_FORMAT_FLAG_GRAY) - loss += SCORE_COLOR_LOSS; - } - - if ((t_flags & ALPHA_MASK) != (in_flags & ALPHA_MASK)) { - loss += SCORE_ALPHA_CHANGE; - if (in_flags & ALPHA_MASK) - loss += SCORE_ALPHA_LOSS; - } - - if ((in_info->h_sub[1]) != (t_info->h_sub[1])) { - loss += SCORE_CHROMA_H_CHANGE; - if ((in_info->h_sub[1]) < (t_info->h_sub[1])) - loss += SCORE_CHROMA_H_LOSS; - } - if ((in_info->w_sub[1]) != (t_info->w_sub[1])) { - loss += SCORE_CHROMA_W_CHANGE; - if ((in_info->w_sub[1]) < (t_info->w_sub[1])) - loss += SCORE_CHROMA_W_LOSS; - } - - if ((in_info->bits) != (t_info->bits)) { - loss += SCORE_DEPTH_CHANGE; - if ((in_info->bits) > (t_info->bits)) - loss += SCORE_DEPTH_LOSS + (in_info->bits - t_info->bits); - } - - GST_DEBUG ("score %s -> %s = %d", - GST_VIDEO_FORMAT_INFO_NAME (in_info), - GST_VIDEO_FORMAT_INFO_NAME (t_info), loss); - - if (loss < *min_loss) { - GST_DEBUG ("found new best %d", loss); - *out_info = t_info; - *min_loss = loss; - } -} - -GstCaps * -gst_d3d11_caps_fixate_format (GstCaps * caps, GstCaps * othercaps) -{ - GstStructure *ins, *outs; - const gchar *in_format; - const GstVideoFormatInfo *in_info, *out_info = NULL; - gint min_loss = G_MAXINT; - guint i, capslen; - GstCaps *result; - - result = gst_caps_intersect (othercaps, caps); - if (gst_caps_is_empty (result)) { - gst_caps_unref (result); - result = othercaps; - } else { - gst_caps_unref (othercaps); - } - - result = gst_caps_make_writable (result); - - ins = gst_caps_get_structure (caps, 0); - in_format = gst_structure_get_string (ins, "format"); - if (!in_format) { - gst_caps_unref (result); - return NULL; - } - - GST_DEBUG ("source format %s", in_format); - - in_info = - gst_video_format_get_info (gst_video_format_from_string (in_format)); - if (!in_info) { - gst_caps_unref (result); - return NULL; - } - - outs = gst_caps_get_structure (result, 0); - - capslen = gst_caps_get_size (result); - GST_DEBUG ("iterate %d structures", capslen); - for (i = 0; i < capslen; i++) { - GstStructure *tests; - const GValue *format; - - tests = gst_caps_get_structure (result, i); - format = gst_structure_get_value (tests, "format"); - /* should not happen */ - if (format == NULL) - continue; - - if (GST_VALUE_HOLDS_LIST (format)) { - gint j, len; - - len = gst_value_list_get_size (format); - GST_DEBUG ("have %d formats", len); - for (j = 0; j < len; j++) { - const GValue *val; - - val = gst_value_list_get_value (format, j); - if (G_VALUE_HOLDS_STRING (val)) { - score_value (in_info, val, &min_loss, &out_info); - if (min_loss == 0) - break; - } - } - } else if (G_VALUE_HOLDS_STRING (format)) { - score_value (in_info, format, &min_loss, &out_info); - } - } - if (out_info) - gst_structure_set (outs, "format", G_TYPE_STRING, - GST_VIDEO_FORMAT_INFO_NAME (out_info), NULL); - - return result; -} - static gchar * gst_d3d11_hres_to_string (HRESULT hr) { diff --git a/sys/d3d11/gstd3d11utils.h b/sys/d3d11/gstd3d11utils.h index 7616285bcf..eb02945a89 100644 --- a/sys/d3d11/gstd3d11utils.h +++ b/sys/d3d11/gstd3d11utils.h @@ -42,9 +42,6 @@ gboolean gst_d3d11_ensure_element_data (GstElement * element, gboolean gst_d3d11_is_windows_8_or_greater (void); -GstCaps * gst_d3d11_caps_fixate_format (GstCaps * caps, - GstCaps * othercaps); - gboolean _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,