/* Checks whether the supplied caps contain VA surfaces */ gboolean gst_caps_has_vaapi_surface (GstCaps * caps) { g_return_val_if_fail (caps != NULL, FALSE); return _gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE); }
static gboolean srcpad_can_dmabuf (GstMsdkDec * thiz) { gboolean ret = FALSE; GstCaps *caps, *out_caps; GstPad *srcpad; srcpad = GST_VIDEO_DECODER_SRC_PAD (thiz); caps = gst_pad_get_pad_template_caps (srcpad); out_caps = gst_pad_peer_query_caps (srcpad, caps); if (!out_caps) goto done; if (gst_caps_is_any (out_caps) || gst_caps_is_empty (out_caps) || out_caps == caps) goto done; if (_gst_caps_has_feature (out_caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) ret = TRUE; done: if (caps) gst_caps_unref (caps); if (out_caps) gst_caps_unref (out_caps); return ret; }
gboolean gst_vaapi_caps_feature_contains (const GstCaps * caps, GstVaapiCapsFeature feature) { const gchar *feature_str; g_return_val_if_fail (caps != NULL, FALSE); feature_str = gst_vaapi_caps_feature_to_string (feature); if (!feature_str) return FALSE; return _gst_caps_has_feature (caps, feature_str); }
gboolean gst_caps_is_video_raw (GstCaps * caps) { GstStructure *structure; g_return_val_if_fail (caps != NULL, FALSE); if (!gst_caps_is_fixed (caps)) return FALSE; if (!_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY)) return FALSE; structure = gst_caps_get_structure (caps, 0); return gst_structure_has_name (structure, "video/x-raw"); }
static gboolean pad_can_dmabuf (GstMsdkVPP * thiz, GstPadDirection direction, GstCaps * filter) { gboolean ret = FALSE; GstCaps *caps, *out_caps; GstPad *pad; GstBaseTransform *trans = GST_BASE_TRANSFORM (thiz); if (direction == GST_PAD_SRC) pad = GST_BASE_TRANSFORM_SRC_PAD (trans); else pad = GST_BASE_TRANSFORM_SINK_PAD (trans); /* make a copy of filter caps since we need to alter the structure * by adding dmabuf-capsfeatures */ caps = gst_caps_copy (filter); gst_caps_set_features (caps, 0, gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_DMABUF)); out_caps = gst_pad_peer_query_caps (pad, caps); if (!out_caps) goto done; if (gst_caps_is_any (out_caps) || gst_caps_is_empty (out_caps) || out_caps == caps) goto done; if (_gst_caps_has_feature (out_caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) ret = TRUE; done: if (caps) gst_caps_unref (caps); if (out_caps) gst_caps_unref (out_caps); return ret; }
static gboolean gst_msdkvpp_propose_allocation (GstBaseTransform * trans, GstQuery * decide_query, GstQuery * query) { GstMsdkVPP *thiz = GST_MSDKVPP (trans); GstVideoInfo info; GstBufferPool *pool = NULL; GstAllocator *allocator = NULL; GstCaps *caps; GstStructure *config; gboolean need_pool; GstAllocationParams params; guint size; guint min_buffers = thiz->async_depth + 1; gst_query_parse_allocation (query, &caps, &need_pool); if (!caps) { GST_ERROR_OBJECT (thiz, "Failed to parse the allocation caps"); return FALSE; } if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (thiz, "Failed to get video info"); return FALSE; } /* if upstream allocation query supports dmabuf-capsfeatures, * we do allocate dmabuf backed memory */ if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) { GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory"); thiz->use_sinkpad_dmabuf = TRUE; } if (need_pool) { /* alwys provide a new pool for upstream to help re-negotiation * more info here: https://bugzilla.gnome.org/show_bug.cgi?id=748344 */ pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps, min_buffers); } /* Update the internal pool if any allocation attribute changed */ if (!gst_video_info_is_equal (&thiz->sinkpad_buffer_pool_info, &info)) { gst_object_unref (thiz->sinkpad_buffer_pool); thiz->sinkpad_buffer_pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SINK, caps, min_buffers); } /* get the size and allocator params from configured pool and set it in query */ if (!need_pool) pool = gst_object_ref (thiz->sinkpad_buffer_pool); config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); gst_buffer_pool_config_get_params (config, NULL, &size, NULL, NULL); if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) gst_query_add_allocation_param (query, allocator, ¶ms); gst_structure_free (config); /* if upstream does't have a pool requirement, set only * size, min_buffers and max_buffers in query */ gst_query_add_allocation_pool (query, need_pool ? pool : NULL, size, min_buffers, 0); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); gst_object_unref (pool); return GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (trans, decide_query, query); }
static gboolean gst_msdkvpp_decide_allocation (GstBaseTransform * trans, GstQuery * query) { GstMsdkVPP *thiz = GST_MSDKVPP (trans); GstVideoInfo info; GstBufferPool *pool = NULL; GstStructure *config = NULL; GstCaps *caps; guint size = 0, min_buffers = 0, max_buffers = 0; GstAllocator *allocator = NULL; GstAllocationParams params; gboolean update_pool = FALSE; gst_query_parse_allocation (query, &caps, NULL); if (!caps) { GST_ERROR_OBJECT (thiz, "Failed to parse the decide_allocation caps"); return FALSE; } if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR_OBJECT (thiz, "Failed to get video info"); return FALSE; } /* if downstream allocation query supports dmabuf-capsfeatures, * we do allocate dmabuf backed memory */ if (_gst_caps_has_feature (caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) { GST_INFO_OBJECT (thiz, "MSDK VPP srcpad uses DMABuf memory"); thiz->use_srcpad_dmabuf = TRUE; } if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) thiz->add_video_meta = TRUE; else thiz->add_video_meta = FALSE; /* Check whether the query has pool */ if (gst_query_get_n_allocation_pools (query) > 0) update_pool = TRUE; /* increase the min_buffers with number of concurrent vpp operations */ min_buffers += thiz->async_depth; /* invalidate the cached pool if there is an allocation_query */ if (thiz->srcpad_buffer_pool) gst_object_unref (thiz->srcpad_buffer_pool); /* Always create a pool for vpp out buffers. Each of the msdk element * has to create it's own mfxsurfacepool which is an msdk contraint. * For eg: Each Msdk component (vpp, dec and enc) will invoke the external * Frame allocator for video-memory usage.So sharing the pool between * gst-msdk elements might not be a good idea, rather each element * can check the buffer type (whether it is from msdk-buffer pool) * to make sure there is no copy. Since we share the context between * msdk elements, using buffers from one sdk's framealloator in another * sdk-components is perfectly fine */ pool = gst_msdkvpp_create_buffer_pool (thiz, GST_PAD_SRC, caps, min_buffers); thiz->srcpad_buffer_pool = pool; /* get the configured pool properties inorder to set in query */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers); if (gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms)) gst_query_add_allocation_param (query, allocator, ¶ms); gst_structure_free (config); if (update_pool) gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers, max_buffers); else gst_query_add_allocation_pool (query, pool, size, min_buffers, max_buffers); gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); /* Fixme if downstream doesn't have videometa support, msdkvpp should * copy the output buffers */ return TRUE; }
static gboolean gst_msdkdec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) { GstMsdkDec *thiz = GST_MSDKDEC (decoder); GstBufferPool *pool = NULL; GstStructure *pool_config = NULL; GstCaps *pool_caps /*, *negotiated_caps */ ; guint size, min_buffers, max_buffers; if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder, query)) return FALSE; /* Get the buffer pool config decided by the base class. The base class ensures that there will always be at least a 0th pool in the query. */ gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); pool_config = gst_buffer_pool_get_config (pool); /* Get the caps of pool and increase the min and max buffers by async_depth, * we will always have that number of decode operations in-flight */ gst_buffer_pool_config_get_params (pool_config, &pool_caps, &size, &min_buffers, &max_buffers); min_buffers += thiz->async_depth; if (max_buffers) max_buffers += thiz->async_depth; /* increase the min_buffers by 1 for smooth display in render pipeline */ min_buffers += 1; /* this will get updated with msdk requirement */ thiz->min_prealloc_buffers = min_buffers; if (_gst_caps_has_feature (pool_caps, GST_CAPS_FEATURE_MEMORY_DMABUF)) { GST_INFO_OBJECT (decoder, "This MSDK decoder uses DMABuf memory"); thiz->use_video_memory = thiz->use_dmabuf = TRUE; } /* Initialize MSDK decoder before new bufferpool tries to alloc each buffer, * which requires information of frame allocation. * No effect if already initialized. */ if (!gst_msdkdec_init_decoder (thiz)) return FALSE; /* get the updated min_buffers which account the msdk requirement too */ min_buffers = thiz->min_prealloc_buffers; /* Decoder always use its own pool. So we create a pool if msdk apis * previously requested for allocation (do_realloc = TRUE) */ if (thiz->do_realloc || !thiz->pool) { if (thiz->pool) gst_object_replace ((GstObject **) & thiz->pool, NULL); GST_INFO_OBJECT (decoder, "create new MSDK bufferpool"); thiz->pool = gst_msdkdec_create_buffer_pool (thiz, &thiz->output_info, min_buffers); if (!thiz->pool) goto failed_to_create_pool; } if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL) && gst_buffer_pool_has_option (pool, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)) { GstStructure *config; GstAllocator *allocator; /* If downstream supports video meta and video alignment, * we can replace our own msdk bufferpool and use it */ /* Remove downstream's pool */ gst_structure_free (pool_config); gst_object_unref (pool); pool = gst_object_ref (thiz->pool); /* Set the allocator of new msdk bufferpool */ config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool)); if (gst_buffer_pool_config_get_allocator (config, &allocator, NULL)) gst_query_set_nth_allocation_param (query, 0, allocator, NULL); gst_structure_free (config); } else { /* Unfortunately, dowstream doesn't have videometa or alignment support, * we keep msdk pool as a side-pool that will be decoded into and * then copied from. */ GST_INFO_OBJECT (decoder, "Keep MSDK bufferpool as a side-pool"); /* Update params to downstream's pool */ gst_buffer_pool_config_set_params (pool_config, pool_caps, size, min_buffers, max_buffers); if (!gst_buffer_pool_set_config (pool, pool_config)) goto error_set_config; gst_video_info_from_caps (&thiz->non_msdk_pool_info, pool_caps); /* update width and height with actual negotiated values */ GST_VIDEO_INFO_WIDTH (&thiz->non_msdk_pool_info) = GST_VIDEO_INFO_WIDTH (&thiz->output_info); GST_VIDEO_INFO_HEIGHT (&thiz->non_msdk_pool_info) = GST_VIDEO_INFO_HEIGHT (&thiz->output_info); } gst_query_set_nth_allocation_pool (query, 0, pool, size, min_buffers, max_buffers); if (pool) gst_object_unref (pool); return TRUE; failed_to_create_pool: GST_ERROR_OBJECT (decoder, "failed to set buffer pool config"); if (pool) gst_object_unref (pool); return FALSE; error_set_config: GST_ERROR_OBJECT (decoder, "failed to set buffer pool config"); if (pool) gst_object_unref (pool); return FALSE; }