static gboolean gst_mfc_dec_negotiate (GstVideoDecoder * decoder) { GstMFCDec *self = GST_MFC_DEC (decoder); GstVideoCodecState *state; GstCaps *allowed_caps; GstVideoFormat format = GST_VIDEO_FORMAT_NV12; allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self)); allowed_caps = gst_caps_truncate (allowed_caps); allowed_caps = gst_caps_fixate (allowed_caps); if (!gst_caps_is_empty (allowed_caps)) { const gchar *format_str; GstStructure *s = gst_caps_get_structure (allowed_caps, 0); format_str = gst_structure_get_string (s, "format"); if (format_str) format = gst_video_format_from_string (format_str); } gst_caps_unref (allowed_caps); self->format = format; state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), self->format, self->crop_width, self->crop_height, self->input_state); gst_video_codec_state_unref (state); return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder); }
/* calculate how much loss a conversion would be */ static void score_value(GstBaseTransform * base, 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 = 1; 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_LOSS; if ((t_flags & COLOR_MASK) != (in_flags & COLOR_MASK)) loss += SCORE_COLOR_LOSS; if ((t_flags & ALPHA_MASK) != (in_flags & ALPHA_MASK)) loss += SCORE_ALPHA_LOSS; 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_LOSS; if ((in_info->bits) > (t_info->bits)) loss += SCORE_DEPTH_LOSS; GST_DEBUG_OBJECT(base, "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_OBJECT(base, "found new best %d", loss); *out_info = t_info; *min_loss = loss; } }
static void gst_video_convert_fixate_format (GstBaseTransform * base, GstCaps * caps, GstCaps * result) { GstStructure *ins, *outs; const gchar *in_format; const GstVideoFormatInfo *in_info, *out_info = NULL; gint min_loss = G_MAXINT; guint i, capslen; ins = gst_caps_get_structure (caps, 0); in_format = gst_structure_get_string (ins, "format"); if (!in_format) return; GST_DEBUG_OBJECT (base, "source format %s", in_format); in_info = gst_video_format_get_info (gst_video_format_from_string (in_format)); if (!in_info) return; outs = gst_caps_get_structure (result, 0); capslen = gst_caps_get_size (result); GST_DEBUG_OBJECT (base, "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_OBJECT (base, "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 (base, in_info, val, &min_loss, &out_info); if (min_loss == 0) break; } } } else if (G_VALUE_HOLDS_STRING (format)) { score_value (base, 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); }
static GstVideoFormat gst_vaapi_find_preferred_format (const GValue * format_list, GstVideoFormat native_format) { const GValue *frmt; GstVideoFormat out_format; guint i; /* if one format, that is the one */ if (G_VALUE_HOLDS_STRING (format_list)) return gst_video_format_from_string (g_value_get_string (format_list)); if (!GST_VALUE_HOLDS_LIST (format_list)) { GST_ERROR ("negotiated caps do not have a valid format"); return GST_VIDEO_FORMAT_UNKNOWN; } if (native_format == GST_VIDEO_FORMAT_UNKNOWN || native_format == GST_VIDEO_FORMAT_ENCODED) { native_format = GST_VIDEO_FORMAT_NV12; /* default VA format */ } /* search our native format in the list */ for (i = 0; i < gst_value_list_get_size (format_list); i++) { frmt = gst_value_list_get_value (format_list, i); out_format = gst_video_format_from_string (g_value_get_string (frmt)); /* GStreamer do not handle encoded formats nicely. Try the next * one. */ if (out_format == GST_VIDEO_FORMAT_ENCODED) continue; if (native_format == out_format) return out_format; } /* just pick the first valid format in the list */ i = 0; do { frmt = gst_value_list_get_value (format_list, i++); out_format = gst_video_format_from_string (g_value_get_string (frmt)); } while (out_format == GST_VIDEO_FORMAT_ENCODED); return out_format; }
static void check_pad_template (GstPadTemplate * tmpl) { const GValue *list_val, *fmt_val; GstStructure *s; gboolean *formats_supported; GstCaps *caps; guint i, num_formats; num_formats = get_num_formats (); formats_supported = g_new0 (gboolean, num_formats); caps = gst_pad_template_get_caps (tmpl); /* If this fails, we need to update this unit test */ fail_unless_equals_int (gst_caps_get_size (caps), 1); s = gst_caps_get_structure (caps, 0); fail_unless (gst_structure_has_name (s, "video/x-raw")); list_val = gst_structure_get_value (s, "format"); fail_unless (list_val != NULL); /* If this fails, we need to update this unit test */ fail_unless (GST_VALUE_HOLDS_LIST (list_val)); for (i = 0; i < gst_value_list_get_size (list_val); ++i) { GstVideoFormat fmt; const gchar *fmt_str; fmt_val = gst_value_list_get_value (list_val, i); fail_unless (G_VALUE_HOLDS_STRING (fmt_val)); fmt_str = g_value_get_string (fmt_val); GST_LOG ("format string: '%s'", fmt_str); fmt = gst_video_format_from_string (fmt_str); fail_unless (fmt != GST_VIDEO_FORMAT_UNKNOWN); formats_supported[(guint) fmt] = TRUE; } gst_caps_unref (caps); for (i = 2; i < num_formats; ++i) { if (!formats_supported[i]) { g_error ("videoconvert doesn't support format '%s'", gst_video_format_to_string ((GstVideoFormat) i)); } } g_free (formats_supported); }
static gboolean gst_opencv_get_ipl_depth_and_channels (GstStructure * structure, gint * ipldepth, gint * channels, GError ** err) { GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; const GstVideoFormatInfo *info; gint depth = 0, i; const gchar *s; if (gst_structure_has_name (structure, "video/x-raw")) { if (!(s = gst_structure_get_string (structure, "format"))) return FALSE; format = gst_video_format_from_string (s); if (format == GST_VIDEO_FORMAT_UNKNOWN) return FALSE; } info = gst_video_format_get_info (format); if (GST_VIDEO_FORMAT_INFO_IS_RGB (info)) *channels=3; else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (info)) *channels=1; else { g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, "Unsupported structure %s", gst_structure_get_name (structure)); return FALSE; } for (i = 0; i < GST_VIDEO_FORMAT_INFO_N_COMPONENTS (info); i++) depth += GST_VIDEO_FORMAT_INFO_DEPTH (info, i); if (depth / *channels == 8) { /* TODO signdness? */ *ipldepth = IPL_DEPTH_8U; } else if (depth / *channels == 16) { *ipldepth = IPL_DEPTH_16U; } else { g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, "Unsupported depth/channels %d/%d", depth, *channels); return FALSE; } return TRUE; }
static gboolean gst_vtdec_negotiate_output_format (GstVtdec * vtdec, GstVideoCodecState * input_state) { GstCaps *caps = NULL, *peercaps = NULL, *templcaps; GstVideoFormat output_format; GstVideoCodecState *output_state = NULL; GstCapsFeatures *features; GstStructure *structure; const gchar *s; peercaps = gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec), NULL); /* Check if output supports GL caps by preference */ templcaps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec)); caps = gst_caps_intersect_full (templcaps, peercaps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); gst_caps_unref (templcaps); caps = gst_caps_truncate (caps); structure = gst_caps_get_structure (caps, 0); s = gst_structure_get_string (structure, "format"); output_format = gst_video_format_from_string (s); features = gst_caps_features_copy (gst_caps_get_features (caps, 0)); gst_caps_unref (caps); if (!gst_vtdec_create_session (vtdec, output_format)) { gst_caps_features_free (features); return FALSE; } output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (vtdec), output_format, vtdec->video_info.width, vtdec->video_info.height, input_state); output_state->caps = gst_video_info_to_caps (&output_state->info); gst_caps_set_features (output_state->caps, 0, features); return TRUE; }
/** * gst_video_info_from_caps: * @info: a #GstVideoInfo * @caps: a #GstCaps * * Parse @caps and update @info. * * Returns: TRUE if @caps could be parsed */ gboolean gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps) { GstStructure *structure; const gchar *s; GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; gint width = 0, height = 0; gint fps_n, fps_d; gint par_n, par_d; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (caps != NULL, FALSE); g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps); structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw")) { if (!(s = gst_structure_get_string (structure, "format"))) goto no_format; format = gst_video_format_from_string (s); if (format == GST_VIDEO_FORMAT_UNKNOWN) goto unknown_format; } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") || g_str_has_prefix (gst_structure_get_name (structure), "image/")) { format = GST_VIDEO_FORMAT_ENCODED; } else { goto wrong_name; } /* width and height are mandatory, except for non-raw-formats */ if (!gst_structure_get_int (structure, "width", &width) && format != GST_VIDEO_FORMAT_ENCODED) goto no_width; if (!gst_structure_get_int (structure, "height", &height) && format != GST_VIDEO_FORMAT_ENCODED) goto no_height; gst_video_info_init (info); info->finfo = gst_video_format_get_info (format); info->width = width; info->height = height; if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) { if (fps_n == 0) { /* variable framerate */ info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS; /* see if we have a max-framerate */ gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d); } info->fps_n = fps_n; info->fps_d = fps_d; } else { /* unspecified is variable framerate */ info->fps_n = 0; info->fps_d = 1; } if (gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d)) { info->par_n = par_n; info->par_d = par_d; } else { info->par_n = 1; info->par_d = 1; } if ((s = gst_structure_get_string (structure, "interlace-mode"))) info->interlace_mode = gst_video_interlace_mode_from_string (s); else info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; { if ((s = gst_structure_get_string (structure, "multiview-mode"))) GST_VIDEO_INFO_MULTIVIEW_MODE (info) = gst_video_multiview_mode_from_caps_string (s); else GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE; gst_structure_get_flagset (structure, "multiview-flags", &GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), NULL); if (!gst_structure_get_int (structure, "views", &info->views)) info->views = 1; /* At one point, I tried normalising the half-aspect flag here, * but it behaves weird for GstVideoInfo operations other than * directly converting to/from caps - sometimes causing the * PAR to be doubled/halved too many times */ } if ((s = gst_structure_get_string (structure, "chroma-site"))) info->chroma_site = gst_video_chroma_from_string (s); else info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN; if ((s = gst_structure_get_string (structure, "colorimetry"))) { if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) { GST_WARNING ("unparsable colorimetry, using default"); set_default_colorimetry (info); } else if (!validate_colorimetry (info)) { GST_WARNING ("invalid colorimetry, using default"); set_default_colorimetry (info); } else { /* force RGB matrix for RGB formats */ if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) && info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) { GST_WARNING ("invalid matrix %d for RGB format, using RGB", info->colorimetry.matrix); info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB; } } } else { GST_DEBUG ("no colorimetry, using default"); set_default_colorimetry (info); } fill_planes (info); return TRUE; /* ERROR */ wrong_name: { GST_ERROR ("wrong name '%s', expected video/ or image/", gst_structure_get_name (structure)); return FALSE; } no_format: { GST_ERROR ("no format given"); return FALSE; } unknown_format: { GST_ERROR ("unknown format '%s' given", s); return FALSE; } no_width: { GST_ERROR ("no width property given"); return FALSE; } no_height: { GST_ERROR ("no height property given"); return FALSE; } }
static gboolean gst_vtdec_negotiate (GstVideoDecoder * decoder) { GstVideoCodecState *output_state = NULL; GstCaps *peercaps = NULL, *caps = NULL, *templcaps = NULL, *prevcaps = NULL; GstVideoFormat format; GstStructure *structure; const gchar *s; GstVtdec *vtdec; OSStatus err = noErr; GstCapsFeatures *features = NULL; gboolean output_textures; vtdec = GST_VTDEC (decoder); if (vtdec->session) gst_vtdec_push_frames_if_needed (vtdec, TRUE, FALSE); output_state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (vtdec)); if (output_state) { prevcaps = gst_caps_ref (output_state->caps); gst_video_codec_state_unref (output_state); } peercaps = gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (vtdec), NULL); if (prevcaps && gst_caps_can_intersect (prevcaps, peercaps)) { /* The hardware decoder can become (temporarily) unavailable across * VTDecompressionSessionCreate/Destroy calls. So if the currently configured * caps are still accepted by downstream we keep them so we don't have to * destroy and recreate the session. */ GST_INFO_OBJECT (vtdec, "current and peer caps are compatible, keeping current caps"); caps = gst_caps_ref (prevcaps); } else { templcaps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (decoder)); caps = gst_caps_intersect_full (peercaps, templcaps, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (templcaps); } gst_caps_unref (peercaps); caps = gst_caps_truncate (gst_caps_make_writable (caps)); structure = gst_caps_get_structure (caps, 0); s = gst_structure_get_string (structure, "format"); format = gst_video_format_from_string (s); features = gst_caps_get_features (caps, 0); if (features) features = gst_caps_features_copy (features); output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (vtdec), format, vtdec->video_info.width, vtdec->video_info.height, vtdec->input_state); output_state->caps = gst_video_info_to_caps (&output_state->info); if (features) { gst_caps_set_features (output_state->caps, 0, features); output_textures = gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY); if (output_textures) gst_caps_set_simple (output_state->caps, "texture-target", G_TYPE_STRING, #if !HAVE_IOS GST_GL_TEXTURE_TARGET_RECTANGLE_STR, #else GST_GL_TEXTURE_TARGET_2D_STR, #endif NULL); } gst_caps_unref (caps); if (!prevcaps || !gst_caps_is_equal (prevcaps, output_state->caps)) { gboolean renegotiating = vtdec->session != NULL; GST_INFO_OBJECT (vtdec, "negotiated output format %" GST_PTR_FORMAT " previous %" GST_PTR_FORMAT, output_state->caps, prevcaps); if (vtdec->session) gst_vtdec_invalidate_session (vtdec); err = gst_vtdec_create_session (vtdec, format, TRUE); if (err == noErr) { GST_INFO_OBJECT (vtdec, "using hardware decoder"); } else if (err == kVTVideoDecoderNotAvailableNowErr && renegotiating) { GST_WARNING_OBJECT (vtdec, "hw decoder not available anymore"); err = gst_vtdec_create_session (vtdec, format, FALSE); } if (err != noErr) { GST_ELEMENT_ERROR (vtdec, RESOURCE, FAILED, (NULL), ("VTDecompressionSessionCreate returned %d", (int) err)); } } if (vtdec->texture_cache != NULL && !output_textures) { gst_video_texture_cache_free (vtdec->texture_cache); vtdec->texture_cache = NULL; } if (err == noErr && output_textures) { /* call this regardless of whether caps have changed or not since a new * local context could have become available */ gst_gl_context_helper_ensure_context (vtdec->ctxh); GST_INFO_OBJECT (vtdec, "pushing textures, context %p old context %p", vtdec->ctxh->context, vtdec->texture_cache ? vtdec->texture_cache->ctx : NULL); if (vtdec->texture_cache && vtdec->texture_cache->ctx != vtdec->ctxh->context) { gst_video_texture_cache_free (vtdec->texture_cache); vtdec->texture_cache = NULL; } if (!vtdec->texture_cache) setup_texture_cache (vtdec, vtdec->ctxh->context); } if (prevcaps) gst_caps_unref (prevcaps); if (err != noErr) return FALSE; return GST_VIDEO_DECODER_CLASS (gst_vtdec_parent_class)->negotiate (decoder); }
static gboolean gst_validate_ssim_get_frame_from_file (GstValidateSsim * self, const char *file, GstVideoFrame * frame) { gchar *data; gsize length; GstBuffer *buf; GstVideoInfo info; GstVideoFormat format; gint strv_length, width, height; gboolean res = TRUE; gchar **splited_name = NULL, **splited_size = NULL, *strformat; GError *error = NULL; if (g_str_has_suffix (file, ".png")) { return gst_validate_ssim_get_frame_from_png (self, file, frame); } splited_name = g_strsplit (file, ".", -1); strv_length = g_strv_length (splited_name); strformat = splited_name[strv_length - 1]; format = gst_video_format_from_string (strformat); if (format == GST_VIDEO_FORMAT_UNKNOWN) { GST_VALIDATE_REPORT (self, WRONG_FORMAT, "Unknown format: %s", strformat); goto fail; } splited_size = g_strsplit (splited_name[strv_length - 2], "x", -1); if (g_strv_length (splited_size) != 2) { GST_VALIDATE_REPORT (self, WRONG_FORMAT, "Can not determine video size from filename: %s ", file); goto fail; } errno = 0; width = g_ascii_strtoull (splited_size[0], NULL, 10); if (errno) { GST_VALIDATE_REPORT (self, WRONG_FORMAT, "Can not determine video size from filename: %s ", file); goto fail; } errno = 0; height = g_ascii_strtoull (splited_size[1], NULL, 10); if (errno) { GST_VALIDATE_REPORT (self, WRONG_FORMAT, "Can not determine video size from filename: %s ", file); goto fail; } gst_video_info_init (&info); gst_video_info_set_format (&info, format, width, height); if (!g_file_get_contents (file, &data, &length, &error)) { GST_VALIDATE_REPORT (self, GENERAL_INPUT_ERROR, "Could not open %s: %s", file, error->message); g_error_free (error); goto fail; } buf = gst_buffer_new_wrapped (data, length); if (!gst_video_frame_map (frame, &info, buf, GST_MAP_READ)) { gst_buffer_unref (buf); GST_VALIDATE_REPORT (self, GENERAL_INPUT_ERROR, "Could not map input frame"); goto fail; } gst_buffer_unref (buf); done: g_strfreev (splited_name); g_strfreev (splited_size); return res; fail: res = FALSE; goto done; }
static void check_pad_template (GstPadTemplate * tmpl) { const GValue *list_val, *fmt_val; GstStructure *s; gboolean *formats_supported; GstCaps *caps; guint i, num_formats; num_formats = get_num_formats (); formats_supported = g_new0 (gboolean, num_formats); caps = gst_pad_template_get_caps (tmpl); /* If this fails, we need to update this unit test */ fail_unless_equals_int (gst_caps_get_size (caps), 2); /* Remove the ANY caps features structure */ caps = gst_caps_truncate (caps); s = gst_caps_get_structure (caps, 0); fail_unless (gst_structure_has_name (s, "video/x-raw")); list_val = gst_structure_get_value (s, "format"); fail_unless (list_val != NULL); /* If this fails, we need to update this unit test */ fail_unless (GST_VALUE_HOLDS_LIST (list_val)); for (i = 0; i < gst_value_list_get_size (list_val); ++i) { GstVideoFormat fmt; const gchar *fmt_str; fmt_val = gst_value_list_get_value (list_val, i); fail_unless (G_VALUE_HOLDS_STRING (fmt_val)); fmt_str = g_value_get_string (fmt_val); GST_LOG ("format string: '%s'", fmt_str); fmt = gst_video_format_from_string (fmt_str); if (fmt == GST_VIDEO_FORMAT_UNKNOWN) g_error ("Unknown raw format '%s' in pad template caps", fmt_str); formats_supported[(guint) fmt] = TRUE; } gst_caps_unref (caps); for (i = 2; i < num_formats; ++i) { if (!formats_supported[i]) { const gchar *fmt_str = gst_video_format_to_string ((GstVideoFormat) i); switch (i) { case GST_VIDEO_FORMAT_v210: case GST_VIDEO_FORMAT_v216: case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV16: case GST_VIDEO_FORMAT_NV21: case GST_VIDEO_FORMAT_NV24: case GST_VIDEO_FORMAT_UYVP: case GST_VIDEO_FORMAT_A420: case GST_VIDEO_FORMAT_YUV9: case GST_VIDEO_FORMAT_YVU9: case GST_VIDEO_FORMAT_IYU1: case GST_VIDEO_FORMAT_r210:{ static gboolean shown_fixme[100] = { FALSE, }; if (!shown_fixme[i]) { GST_FIXME ("FIXME: add %s support to videoscale", fmt_str); shown_fixme[i] = TRUE; } break; } case GST_VIDEO_FORMAT_BGR16: case GST_VIDEO_FORMAT_BGR15: case GST_VIDEO_FORMAT_RGB8P: case GST_VIDEO_FORMAT_I420_10BE: case GST_VIDEO_FORMAT_I420_10LE: case GST_VIDEO_FORMAT_I422_10BE: case GST_VIDEO_FORMAT_I422_10LE: case GST_VIDEO_FORMAT_Y444_10BE: case GST_VIDEO_FORMAT_Y444_10LE: case GST_VIDEO_FORMAT_GBR: case GST_VIDEO_FORMAT_GBR_10BE: case GST_VIDEO_FORMAT_GBR_10LE: GST_LOG ("Ignoring lack of support for format %s", fmt_str); break; default: g_error ("videoscale doesn't support format '%s'", fmt_str); break; } } } g_free (formats_supported); }
GstVaapiCapsFeature gst_vaapi_find_preferred_caps_feature (GstPad * pad, GstVideoFormat format, GstVideoFormat * out_format_ptr) { GstVaapiCapsFeature feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY; guint i, num_structures; GstCaps *caps = NULL; GstCaps *gl_texture_upload_caps = NULL; GstCaps *sysmem_caps = NULL; GstCaps *vaapi_caps = NULL; GstCaps *out_caps, *templ; GstVideoFormat out_format; templ = gst_pad_get_pad_template_caps (pad); out_caps = gst_pad_peer_query_caps (pad, templ); gst_caps_unref (templ); if (!out_caps) { feature = GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED; goto cleanup; } out_format = format == GST_VIDEO_FORMAT_ENCODED ? GST_VIDEO_FORMAT_I420 : format; gl_texture_upload_caps = new_gl_texture_upload_meta_caps (); if (!gl_texture_upload_caps) goto cleanup; vaapi_caps = gst_vaapi_video_format_new_template_caps_with_features (out_format, GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE); if (!vaapi_caps) goto cleanup; sysmem_caps = gst_vaapi_video_format_new_template_caps_with_features (out_format, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); if (!sysmem_caps) goto cleanup; num_structures = gst_caps_get_size (out_caps); for (i = 0; i < num_structures; i++) { GstCapsFeatures *const features = gst_caps_get_features (out_caps, i); GstStructure *const structure = gst_caps_get_structure (out_caps, i); #if GST_CHECK_VERSION(1,3,0) /* Skip ANY features, we need an exact match for correct evaluation */ if (gst_caps_features_is_any (features)) continue; #endif caps = gst_caps_new_full (gst_structure_copy (structure), NULL); if (!caps) continue; gst_caps_set_features (caps, 0, gst_caps_features_copy (features)); if (gst_caps_can_intersect (caps, vaapi_caps) && feature < GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE) feature = GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE; else if (gst_caps_can_intersect (caps, gl_texture_upload_caps) && feature < GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) feature = GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META; else if (gst_caps_can_intersect (caps, sysmem_caps) && feature < GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY) feature = GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY; gst_caps_replace (&caps, NULL); #if GST_CHECK_VERSION(1,3,0) /* Stop at the first match, the caps should already be sorted out by preference order from downstream elements */ if (feature != GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY) break; #endif } if (out_format_ptr) { if (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) { GstStructure *structure; gchar *format_str; out_format = GST_VIDEO_FORMAT_UNKNOWN; do { caps = gst_caps_intersect_full (out_caps, gl_texture_upload_caps, GST_CAPS_INTERSECT_FIRST); if (!caps) break; structure = gst_caps_get_structure (caps, 0); if (!structure) break; if (!gst_structure_get (structure, "format", G_TYPE_STRING, &format_str, NULL)) break; out_format = gst_video_format_from_string (format_str); g_free (format_str); } while (0); if (!out_format) goto cleanup; } *out_format_ptr = out_format; } cleanup: gst_caps_replace (&gl_texture_upload_caps, NULL); gst_caps_replace (&sysmem_caps, NULL); gst_caps_replace (&vaapi_caps, NULL); gst_caps_replace (&caps, NULL); gst_caps_replace (&out_caps, NULL); return feature; }
/* returns static descriptions and dynamic ones (such as video/x-raw), * or NULL if caps aren't known at all */ static gchar * format_info_get_desc (const FormatInfo * info, const GstCaps * caps) { const GstStructure *s; g_assert (info != NULL); if (info->desc != NULL) return g_strdup (_(info->desc)); s = gst_caps_get_structure (caps, 0); if (strcmp (info->type, "video/x-raw") == 0) { gchar *ret = NULL; const gchar *str = 0; GstVideoFormat format; const GstVideoFormatInfo *finfo; str = gst_structure_get_string (s, "format"); if (str == NULL) return g_strdup (_("Uncompressed video")); format = gst_video_format_from_string (str); if (format == GST_VIDEO_FORMAT_UNKNOWN) return g_strdup (_("Uncompressed video")); finfo = gst_video_format_get_info (format); if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) { ret = g_strdup (_("Uncompressed gray")); } else if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) { const gchar *subs; gint w_sub, h_sub, n_semi; w_sub = GST_VIDEO_FORMAT_INFO_W_SUB (finfo, 1); h_sub = GST_VIDEO_FORMAT_INFO_H_SUB (finfo, 1); if (w_sub == 1 && h_sub == 1) { subs = "4:4:4"; } else if (w_sub == 2 && h_sub == 1) { subs = "4:2:2"; } else if (w_sub == 2 && h_sub == 2) { subs = "4:2:0"; } else if (w_sub == 4 && h_sub == 1) { subs = "4:1:1"; } else { subs = ""; } n_semi = GST_VIDEO_FORMAT_INFO_HAS_ALPHA (finfo) ? 3 : 2; if (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) == 1) { ret = g_strdup_printf (_("Uncompressed packed YUV %s"), subs); } else if (GST_VIDEO_FORMAT_INFO_N_PLANES (finfo) == n_semi) { ret = g_strdup_printf (_("Uncompressed semi-planar YUV %s"), subs); } else { ret = g_strdup_printf (_("Uncompressed planar YUV %s"), subs); } } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) { gboolean alpha, palette; gint bits; alpha = GST_VIDEO_FORMAT_INFO_HAS_ALPHA (finfo); palette = GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo); bits = GST_VIDEO_FORMAT_INFO_BITS (finfo); if (palette) { ret = g_strdup_printf (_("Uncompressed palettized %d-bit %s"), bits, alpha ? "RGBA" : "RGB"); } else { ret = g_strdup_printf (_("Uncompressed %d-bit %s"), bits, alpha ? "RGBA" : "RGB"); } } else { ret = g_strdup (_("Uncompressed video")); } return ret; } else if (strcmp (info->type, "video/x-h263") == 0) { const gchar *variant, *ret; variant = gst_structure_get_string (s, "variant"); if (variant == NULL) ret = "H.263"; else if (strcmp (variant, "itu") == 0) ret = "ITU H.26n"; /* why not ITU H.263? (tpm) */ else if (strcmp (variant, "lead") == 0) ret = "Lead H.263"; else if (strcmp (variant, "microsoft") == 0) ret = "Microsoft H.263"; else if (strcmp (variant, "vdolive") == 0) ret = "VDOLive"; else if (strcmp (variant, "vivo") == 0) ret = "Vivo H.263"; else if (strcmp (variant, "xirlink") == 0) ret = "Xirlink H.263"; else { GST_WARNING ("Unknown H263 variant '%s'", variant); ret = "H.263"; } return g_strdup (ret); } else if (strcmp (info->type, "video/x-h264") == 0) { const gchar *variant, *ret; const gchar *profile; variant = gst_structure_get_string (s, "variant"); if (variant == NULL) ret = "H.264"; else if (strcmp (variant, "itu") == 0) ret = "ITU H.264"; else if (strcmp (variant, "videosoft") == 0) ret = "Videosoft H.264"; else if (strcmp (variant, "lead") == 0) ret = "Lead H.264"; else { GST_WARNING ("Unknown H264 variant '%s'", variant); ret = "H.264"; } /* profile */ profile = gst_structure_get_string (s, "profile"); if (profile != NULL) profile = pbutils_desc_get_h264_profile_name_from_nick (profile); if (profile == NULL) return g_strdup (ret); return g_strdup_printf ("%s (%s Profile)", ret, profile); } else if (strcmp (info->type, "video/x-h265") == 0) { const gchar *profile = gst_structure_get_string (s, "profile"); if (profile != NULL) profile = pbutils_desc_get_h265_profile_name_from_nick (profile); if (profile != NULL) return g_strdup_printf ("H.265 (%s Profile)", profile); return g_strdup ("H.265"); } else if (strcmp (info->type, "video/x-dirac") == 0) { const gchar *profile = gst_structure_get_string (s, "profile"); if (profile == NULL) return g_strdup ("Dirac"); if (strcmp (profile, "vc2-low-delay") == 0) return g_strdup_printf ("Dirac (%s)", "VC-2 Low Delay Profile"); else if (strcmp (profile, "vc2-simple") == 0) return g_strdup_printf ("Dirac (%s)", "VC-2 Simple Profile"); else if (strcmp (profile, "vc2-main") == 0) return g_strdup_printf ("Dirac (%s)", "VC-2 Main Profile"); else return g_strdup ("Dirac"); } else if (strcmp (info->type, "video/x-divx") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "divxversion", &ver) || ver <= 2) { GST_WARNING ("Unexpected DivX version in %" GST_PTR_FORMAT, caps); return g_strdup ("DivX MPEG-4"); } return g_strdup_printf (_("DivX MPEG-4 Version %d"), ver); } else if (strcmp (info->type, "video/x-msmpeg") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "msmpegversion", &ver) || ver < 40 || ver > 49) { GST_WARNING ("Unexpected msmpegversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Microsoft MPEG-4 4.x"); } return g_strdup_printf ("Microsoft MPEG-4 4.%d", ver % 10); } else if (strcmp (info->type, "video/x-truemotion") == 0) { gint ver = 0; gst_structure_get_int (s, "trueversion", &ver); switch (ver) { case 1: return g_strdup_printf ("Duck TrueMotion 1"); case 2: return g_strdup_printf ("TrueMotion 2.0"); default: GST_WARNING ("Unexpected trueversion in %" GST_PTR_FORMAT, caps); break; } return g_strdup_printf ("TrueMotion"); } else if (strcmp (info->type, "video/x-xan") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "wcversion", &ver) || ver < 1) { GST_WARNING ("Unexpected wcversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Xan Wing Commander"); } return g_strdup_printf ("Xan Wing Commander %u", ver); } else if (strcmp (info->type, "video/x-indeo") == 0) { gint ver = 0; if (!gst_structure_get_int (s, "indeoversion", &ver) || ver < 2) { GST_WARNING ("Unexpected indeoversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Intel Indeo"); } return g_strdup_printf ("Intel Indeo %u", ver); } else if (strcmp (info->type, "audio/x-wma") == 0) { gint ver = 0; gst_structure_get_int (s, "wmaversion", &ver); switch (ver) { case 1: case 2: case 3: return g_strdup_printf ("Windows Media Audio %d", ver + 6); default: break; } GST_WARNING ("Unexpected wmaversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Windows Media Audio"); } else if (strcmp (info->type, "video/x-wmv") == 0) { gint ver = 0; const gchar *str; gst_structure_get_int (s, "wmvversion", &ver); str = gst_structure_get_string (s, "format"); switch (ver) { case 1: case 2: case 3: if (str && strncmp (str, "MSS", 3)) { return g_strdup_printf ("Windows Media Video %d Screen", ver + 6); } else { return g_strdup_printf ("Windows Media Video %d", ver + 6); } default: break; } GST_WARNING ("Unexpected wmvversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Windows Media Video"); } else if (strcmp (info->type, "audio/x-mace") == 0) { gint ver = 0; gst_structure_get_int (s, "maceversion", &ver); if (ver == 3 || ver == 6) { return g_strdup_printf ("MACE-%d", ver); } else { GST_WARNING ("Unexpected maceversion in %" GST_PTR_FORMAT, caps); return g_strdup ("MACE"); } } else if (strcmp (info->type, "video/x-svq") == 0) { gint ver = 0; gst_structure_get_int (s, "svqversion", &ver); if (ver == 1 || ver == 3) { return g_strdup_printf ("Sorensen Video %d", ver); } else { GST_WARNING ("Unexpected svqversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Sorensen Video"); } } else if (strcmp (info->type, "video/x-asus") == 0) { gint ver = 0; gst_structure_get_int (s, "asusversion", &ver); if (ver == 1 || ver == 2) { return g_strdup_printf ("Asus Video %d", ver); } else { GST_WARNING ("Unexpected asusversion in %" GST_PTR_FORMAT, caps); return g_strdup ("Asus Video"); } } else if (strcmp (info->type, "video/x-ati-vcr") == 0) { gint ver = 0; gst_structure_get_int (s, "vcrversion", &ver); if (ver == 1 || ver == 2) { return g_strdup_printf ("ATI VCR %d", ver); } else { GST_WARNING ("Unexpected acrversion in %" GST_PTR_FORMAT, caps); return g_strdup ("ATI VCR"); } } else if (strcmp (info->type, "audio/x-adpcm") == 0) { const GValue *layout_val; layout_val = gst_structure_get_value (s, "layout"); if (layout_val != NULL && G_VALUE_HOLDS_STRING (layout_val)) { const gchar *layout; if ((layout = g_value_get_string (layout_val))) { gchar *layout_upper, *ret; if (strcmp (layout, "swf") == 0) return g_strdup ("Shockwave ADPCM"); if (strcmp (layout, "microsoft") == 0) return g_strdup ("Microsoft ADPCM"); if (strcmp (layout, "quicktime") == 0) return g_strdup ("Quicktime ADPCM"); if (strcmp (layout, "westwood") == 0) return g_strdup ("Westwood ADPCM"); if (strcmp (layout, "yamaha") == 0) return g_strdup ("Yamaha ADPCM"); /* FIXME: other layouts: sbpro2, sbpro3, sbpro4, ct, g726, ea, * adx, xa, 4xm, smjpeg, dk4, dk3, dvi */ layout_upper = g_ascii_strup (layout, -1); ret = g_strdup_printf ("%s ADPCM", layout_upper); g_free (layout_upper); return ret; } } return g_strdup ("ADPCM"); } else if (strcmp (info->type, "audio/mpeg") == 0) { gint ver = 0, layer = 0; gst_structure_get_int (s, "mpegversion", &ver); switch (ver) { case 1: gst_structure_get_int (s, "layer", &layer); switch (layer) { case 1: case 2: case 3: return g_strdup_printf ("MPEG-1 Layer %d (MP%d)", layer, layer); default: break; } GST_WARNING ("Unexpected MPEG-1 layer in %" GST_PTR_FORMAT, caps); return g_strdup ("MPEG-1 Audio"); case 2: return g_strdup ("MPEG-2 AAC"); case 4: return g_strdup ("MPEG-4 AAC"); default: break; } GST_WARNING ("Unexpected audio mpegversion in %" GST_PTR_FORMAT, caps); return g_strdup ("MPEG Audio"); } else if (strcmp (info->type, "audio/x-pn-realaudio") == 0) { gint ver = 0; gst_structure_get_int (s, "raversion", &ver); switch (ver) { case 1: return g_strdup ("RealAudio 14k4bps"); case 2: return g_strdup ("RealAudio 28k8bps"); case 8: return g_strdup ("RealAudio G2 (Cook)"); default: break; } GST_WARNING ("Unexpected raversion in %" GST_PTR_FORMAT, caps); return g_strdup ("RealAudio"); } else if (strcmp (info->type, "video/x-pn-realvideo") == 0) { gint ver = 0; gst_structure_get_int (s, "rmversion", &ver); switch (ver) { case 1: return g_strdup ("RealVideo 1.0"); case 2: return g_strdup ("RealVideo 2.0"); case 3: return g_strdup ("RealVideo 3.0"); case 4: return g_strdup ("RealVideo 4.0"); default: break; } GST_WARNING ("Unexpected rmversion in %" GST_PTR_FORMAT, caps); return g_strdup ("RealVideo"); } else if (strcmp (info->type, "video/mpeg") == 0) { gboolean sysstream; gint ver = 0; if (!gst_structure_get_boolean (s, "systemstream", &sysstream)) { GST_WARNING ("Missing systemstream field in mpeg video caps " "%" GST_PTR_FORMAT, caps); sysstream = FALSE; } if (gst_structure_get_int (s, "mpegversion", &ver) && ver > 0 && ver <= 4) { if (sysstream) { return g_strdup_printf ("MPEG-%d System Stream", ver); } else { const gchar *profile = gst_structure_get_string (s, "profile"); if (profile != NULL) { if (ver == 4) profile = pbutils_desc_get_mpeg4v_profile_name_from_nick (profile); else if (ver == 2) profile = pbutils_desc_get_mpeg2v_profile_name_from_nick (profile); else profile = NULL; } if (profile != NULL) return g_strdup_printf ("MPEG-%d Video (%s Profile)", ver, profile); else return g_strdup_printf ("MPEG-%d Video", ver); } } GST_WARNING ("Missing mpegversion field in mpeg video caps " "%" GST_PTR_FORMAT, caps); return g_strdup ("MPEG Video"); } else if (strcmp (info->type, "audio/x-raw") == 0) { gint depth = 0; gboolean is_float; const gchar *str; GstAudioFormat format; const GstAudioFormatInfo *finfo; str = gst_structure_get_string (s, "format"); format = gst_audio_format_from_string (str); if (format == GST_AUDIO_FORMAT_UNKNOWN) return g_strdup (_("Uncompressed audio")); finfo = gst_audio_format_get_info (format); depth = GST_AUDIO_FORMAT_INFO_DEPTH (finfo); is_float = GST_AUDIO_FORMAT_INFO_IS_FLOAT (finfo); return g_strdup_printf (_("Raw %d-bit %s audio"), depth, is_float ? "floating-point" : "PCM"); } else if (strcmp (info->type, "video/x-tscc") == 0) { gint version; gst_structure_get_int (s, "tsccversion", &version); switch (version) { case 1: return g_strdup ("TechSmith Screen Capture 1"); case 2: return g_strdup ("TechSmith Screen Capture 2"); default: break; } GST_WARNING ("Unexpected version in %" GST_PTR_FORMAT, caps); return g_strdup ("TechSmith Screen Capture"); } return NULL; }