/* XXX: this is a workaround to the absence of any proposer way to specify DMABUF memory capsfeatures or bufferpool option to downstream */ static gboolean has_dmabuf_capable_peer (GstVaapiPluginBase * plugin, GstPad * pad) { GstPad *other_pad = NULL; GstElement *element = NULL; gchar *element_name = NULL; gboolean is_dmabuf_capable = FALSE; gint v; gst_object_ref (pad); for (;;) { other_pad = gst_pad_get_peer (pad); gst_object_unref (pad); if (!other_pad) break; element = gst_pad_get_parent_element (other_pad); gst_object_unref (other_pad); if (!element) break; if (GST_IS_PUSH_SRC (element)) { element_name = gst_element_get_name (element); if (!element_name) break; if ((sscanf (element_name, "v4l2src%d", &v) != 1) && (sscanf (element_name, "camerasrc%d", &v) != 1)) break; v = 0; g_object_get (element, "io-mode", &v, NULL); if (strncmp (element_name, "camerasrc", 9) == 0) is_dmabuf_capable = v == 3; else is_dmabuf_capable = v == 5; /* "dmabuf-import" enum value */ break; } else if (GST_IS_BASE_TRANSFORM (element)) { element_name = gst_element_get_name (element); if (!element_name || sscanf (element_name, "capsfilter%d", &v) != 1) break; pad = gst_element_get_static_pad (element, "sink"); if (!pad) break; } else break; g_free (element_name); element_name = NULL; g_clear_object (&element); } g_free (element_name); g_clear_object (&element); return is_dmabuf_capable; }
static inline GstAllocator * create_dmabuf_srcpad_allocator (GstVaapiPluginBase * plugin, GstVideoInfo * vinfo, gboolean check_for_map) { GstAllocator *allocator; if (!GST_IS_VIDEO_DECODER (plugin) && !GST_IS_BASE_TRANSFORM (plugin)) return NULL; allocator = gst_vaapi_dmabuf_allocator_new (plugin->display, vinfo, get_dmabuf_surface_allocation_flags (), GST_PAD_SRC); if (!allocator || !check_for_map) return allocator; /* the dmabuf allocator *must* be capable to map a buffer with raw * caps and the there's no evidence of downstream dmabuf * importation */ if (!gst_vaapi_dmabuf_can_map (plugin->display, allocator)) { GST_INFO_OBJECT (plugin, "dmabuf allocator generates unmappable buffers"); gst_object_replace ((GstObject **) & allocator, NULL); } return allocator; }
static void gst_dasf_change_peer_omx_state (GstDasfSrc* self) { GST_INFO (""); GstPad *peer; GstElement *next_element; GooComponent *component; GstBaseSrc *base_src; peer = gst_pad_get_peer (GST_BASE_SRC_PAD (self)); if (G_UNLIKELY (peer == NULL)) { GST_INFO ("No next pad"); return; } next_element = GST_ELEMENT (gst_pad_get_parent (peer)); if (G_UNLIKELY (next_element == NULL)) { GST_INFO ("Cannot find a next element"); gst_object_unref (next_element); return; } /** expecting a capsfilter between dasfsrc and goo audio component **/ while (GST_IS_BASE_TRANSFORM (next_element)) { GST_DEBUG_OBJECT(self, "next element name: %s", gst_element_get_name (next_element)); gst_object_unref (peer); peer = gst_pad_get_peer (GST_BASE_TRANSFORM_SRC_PAD (next_element)); gst_object_unref (next_element); next_element = GST_ELEMENT(gst_pad_get_parent (peer)) ; GST_DEBUG_OBJECT (self, "one after element name: %s", gst_element_get_name(next_element)); } /** capsfilter might be found * element next to the caps filter should be goo **/ component = GOO_COMPONENT (g_object_get_data (G_OBJECT (next_element), "goo")); if (G_UNLIKELY (component == NULL)) { GST_INFO ("Previous element does not have a Goo component"); gst_object_unref (peer); gst_object_unref (next_element); return; } if (!GOO_IS_TI_AUDIO_COMPONENT (component)) { GST_WARNING ("The component in previous element is not TI Audio"); gst_object_unref (peer); gst_object_unref (next_element); return; } self->peer_element = g_object_ref (GST_GOO_AUDIO_FILTER (next_element)); /* Work with a queue on the output buffers */ g_object_set (GST_GOO_AUDIO_FILTER (next_element)->component, "outport-queue", TRUE, NULL); /** This fixates the caps on the next goo element to configure the output omx port **/ gst_goo_audio_filter_check_fixed_src_caps (GST_GOO_AUDIO_FILTER (next_element)); g_object_set (GST_GOO_AUDIO_FILTER (next_element)->inport, "buffercount", 1, NULL); g_object_set (GST_GOO_AUDIO_FILTER (next_element)->outport, "buffercount", 1, NULL); GST_INFO ("Setting peer omx component to idle"); goo_component_set_state_idle (GST_GOO_AUDIO_FILTER (next_element)->component); GST_INFO ("Setting peer omx component to executing"); goo_component_set_state_executing (GST_GOO_AUDIO_FILTER (next_element)->component); gst_object_unref (peer); gst_object_unref (next_element); GST_DEBUG_OBJECT (self, "peer refcount = %d", G_OBJECT (peer)->ref_count); GST_DEBUG_OBJECT (self, "next element refcount = %d", G_OBJECT (next_element)->ref_count); return; }
static void gst_dasf_enable (GstDasfSrc* self) { GST_INFO (""); GstPad *peer; GstElement *next_element; GooComponent *component; GstBaseSrc *base_src; if (self->component != NULL) { return; } peer = gst_pad_get_peer (GST_BASE_SRC_PAD (self)); if (G_UNLIKELY (peer == NULL)) { GST_INFO ("No next pad"); return; } next_element = GST_ELEMENT (gst_pad_get_parent (peer)); if (G_UNLIKELY (next_element == NULL)) { GST_INFO ("Cannot find a next element"); goto done; } /** expecting a capsfilter between dasfsrc and goo audio component **/ while (GST_IS_BASE_TRANSFORM (next_element)) { GST_DEBUG_OBJECT(self, "next element name: %s", gst_element_get_name (next_element)); gst_object_unref (peer); peer = gst_pad_get_peer (GST_BASE_TRANSFORM_SRC_PAD (next_element)); gst_object_unref (next_element); next_element = GST_ELEMENT(gst_pad_get_parent (peer)) ; GST_DEBUG_OBJECT (self, "one after element name: %s", gst_element_get_name(next_element)); } /** capsfilter might be found * element next to the caps filter should be goo **/ component = GOO_COMPONENT (g_object_get_data (G_OBJECT (next_element), "goo")); if (G_UNLIKELY (component == NULL)) { GST_INFO ("Previous element does not have a Goo component"); goto done; } if (!GOO_IS_TI_AUDIO_COMPONENT (component)) { GST_WARNING ("The component in previous element is not TI Audio"); goto done; } self->component = GOO_TI_AUDIO_COMPONENT (component); goo_ti_audio_component_set_dasf_mode (self->component, TRUE); GST_DEBUG_OBJECT (self, "set data path"); goo_ti_audio_component_set_data_path (self->component, 0); /** getting num-buffers from base src **/ base_src = GST_BASE_SRC (self); goo_ti_audio_encoder_set_number_buffers (GOO_TI_AUDIO_ENCODER (component), base_src->num_buffers); done: gst_object_unref (peer); gst_object_unref (next_element); GST_DEBUG_OBJECT (self, "peer refcount = %d", G_OBJECT (peer)->ref_count); GST_DEBUG_OBJECT (self, "next element refcount = %d", G_OBJECT (next_element)->ref_count); return; }
static gboolean ensure_srcpad_allocator (GstVaapiPluginBase * plugin, GstVideoInfo * vinfo, GstCaps * caps) { gboolean different_caps; GstVideoInfo vi; GstVaapiImageUsageFlags usage_flag = GST_VAAPI_IMAGE_USAGE_FLAG_NATIVE_FORMATS; /* the received caps are the "allocation caps" which may be * different from the "negotiation caps". In this case, we should * indicate the allocator to store the negotiation caps since they * are the one should be used for frame mapping with GstVideoMeta */ different_caps = GST_IS_VIDEO_DECODER (plugin) && plugin->srcpad_caps && !gst_caps_is_strictly_equal (plugin->srcpad_caps, caps); if (different_caps) { vi = plugin->srcpad_info; } else { vi = *vinfo; } if (!reset_allocator (plugin->srcpad_allocator, &vi)) return TRUE; plugin->srcpad_allocator = NULL; if (caps && gst_caps_is_video_raw (caps)) { if (plugin->srcpad_can_dmabuf) { if (GST_IS_VIDEO_DECODER (plugin) || GST_IS_BASE_TRANSFORM (plugin)) { plugin->srcpad_allocator = gst_vaapi_dmabuf_allocator_new (plugin->display, vinfo, get_dmabuf_surface_allocation_flags (), GST_PAD_SRC); } } else if (plugin->enable_direct_rendering) { usage_flag = GST_VAAPI_IMAGE_USAGE_FLAG_DIRECT_RENDER; GST_INFO_OBJECT (plugin, "enabling direct rendering in source allocator"); } } if (!plugin->srcpad_allocator) { plugin->srcpad_allocator = gst_vaapi_video_allocator_new (plugin->display, vinfo, 0, usage_flag); } if (!plugin->srcpad_allocator) goto error_create_allocator; if (different_caps) { guint i, flags = 0; const GstVideoInfo *alloc_vi = gst_allocator_get_vaapi_video_info (plugin->srcpad_allocator, &flags); /* update the planes and the size with the allocator image info, * but not the resolution */ if (alloc_vi) { for (i = 0; i < GST_VIDEO_INFO_N_PLANES (alloc_vi); i++) { GST_VIDEO_INFO_PLANE_OFFSET (&vi, i) = GST_VIDEO_INFO_PLANE_OFFSET (alloc_vi, i); GST_VIDEO_INFO_PLANE_STRIDE (&vi, i) = GST_VIDEO_INFO_PLANE_STRIDE (alloc_vi, i); } GST_VIDEO_INFO_SIZE (&vi) = GST_VIDEO_INFO_SIZE (alloc_vi); gst_allocator_set_vaapi_video_info (plugin->srcpad_allocator, &vi, flags); } } return TRUE; /* ERRORS */ error_create_allocator: { GST_ERROR_OBJECT (plugin, "failed to create src pad's allocator"); return FALSE; } }