/* 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;
}
示例#3
0
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;

}
示例#4
0
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;
  }
}