コード例 #1
0
static gboolean
gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps)
{
  GstInputSelector *sel;
  gboolean res;

  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));

  GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer");
  res = gst_pad_peer_accept_caps (sel->srcpad, caps);
  gst_object_unref (sel);

  return res;
}
コード例 #2
0
static gboolean
gst_caps_debug_acceptcaps (GstPad * pad, GstCaps * caps)
{
  GstCapsDebug *capsdebug;
  gchar *s;
  gboolean ret;
  GstPad *otherpad;

  capsdebug = GST_CAPS_DEBUG (gst_pad_get_parent (pad));
  otherpad =
      (pad == capsdebug->srcpad) ? capsdebug->sinkpad : capsdebug->srcpad;

  s = gst_caps_to_string (caps);
  GST_INFO ("%s called acceptcaps with %s", THISPAD, s);
  g_free (s);

  ret = gst_pad_peer_accept_caps (otherpad, caps);

  GST_INFO ("%s returned %s", OTHERPAD, ret ? "TRUE" : "FALSE");

  gst_object_unref (capsdebug);

  return ret;
}
コード例 #3
0
ファイル: gstvdpsink.c プロジェクト: spunktsch/svtplayer
/* Buffer management
 *
 * The buffer_alloc function must either return a buffer with given size and
 * caps or create a buffer with different caps attached to the buffer. This
 * last option is called reverse negotiation, ie, where the sink suggests a
 * different format from the upstream peer. 
 *
 * We try to do reverse negotiation when our geometry changes and we like a
 * resized buffer.
 */
static GstFlowReturn
gst_vdp_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
    GstCaps * caps, GstBuffer ** buf)
{
  VdpSink *vdp_sink;
  GstStructure *structure = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  gint width, height;
  GstCaps *alloc_caps;
  gint w_width, w_height;
  GError *err;

  vdp_sink = GST_VDP_SINK (bsink);

  GST_LOG_OBJECT (vdp_sink,
      "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
      " and offset %" G_GUINT64_FORMAT, size, caps, offset);

  /* get struct to see what is requested */
  structure = gst_caps_get_structure (caps, 0);
  if (!gst_structure_get_int (structure, "width", &width) ||
      !gst_structure_get_int (structure, "height", &height)) {
    GST_WARNING_OBJECT (vdp_sink, "invalid caps for buffer allocation %"
        GST_PTR_FORMAT, caps);
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto beach;
  }

  alloc_caps = gst_caps_ref (caps);

  /* We take the flow_lock because the window might go away */
  g_mutex_lock (vdp_sink->flow_lock);
  if (!vdp_sink->window) {
    g_mutex_unlock (vdp_sink->flow_lock);
    goto alloc;
  }

  /* What is our geometry */
  gst_vdp_sink_window_update_geometry (vdp_sink, vdp_sink->window);
  w_width = vdp_sink->window->width;
  w_height = vdp_sink->window->height;

  g_mutex_unlock (vdp_sink->flow_lock);

  /* We would like another geometry */
  if (width != w_width || height != w_height) {
    GstCaps *new_caps, *allowed_caps, *desired_caps;
    GstStructure *desired_struct;

    /* make a copy of the incomming caps to create the new
     * suggestion. We can't use make_writable because we might
     * then destroy the original caps which we still need when the
     * peer does not accept the suggestion. */
    new_caps = gst_caps_copy (caps);
    desired_struct = gst_caps_get_structure (new_caps, 0);

    GST_DEBUG ("we would love to receive a %dx%d video", w_width, w_height);
    gst_structure_set (desired_struct, "width", G_TYPE_INT, w_width, NULL);
    gst_structure_set (desired_struct, "height", G_TYPE_INT, w_height, NULL);

    allowed_caps = gst_pad_get_caps (GST_BASE_SINK_PAD (vdp_sink));
    desired_caps = gst_caps_intersect (new_caps, allowed_caps);

    gst_caps_unref (new_caps);
    gst_caps_unref (allowed_caps);

    /* see if peer accepts our new suggestion, if there is no peer, this 
     * function returns true. */
    if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (vdp_sink), desired_caps)) {
      /* we will not alloc a buffer of the new suggested caps. Make sure
       * we also unref this new caps after we set it on the buffer. */
      GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT,
          desired_caps);
      gst_caps_unref (alloc_caps);
      alloc_caps = desired_caps;
    } else {
      GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT,
          desired_caps);
      /* we alloc a buffer with the original incomming caps already in the
       * width and height variables */
      gst_caps_unref (desired_caps);
    }
  }

alloc:
  gst_vdp_buffer_pool_set_caps (vdp_sink->bpool, alloc_caps);
  gst_caps_unref (alloc_caps);

  err = NULL;
  *buf =
      GST_BUFFER_CAST (gst_vdp_buffer_pool_get_buffer (vdp_sink->bpool, &err));
  if (!*buf) {
    gst_vdp_sink_post_error (vdp_sink, err);
    return GST_FLOW_ERROR;
  }

beach:
  return ret;
}
コード例 #4
0
static GstFlowReturn
gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
			  GstCaps * caps, GstBuffer ** buf)
{
	gint width, height;
	GstStructure *structure = NULL;
	GstSLVideo *slvideo;
	slvideo = GST_SLVIDEO(bsink);

	// caps == requested caps
	// we can ignore these and reverse-negotiate our preferred dimensions with
	// the peer if we like - we need to do this to obey dynamic resize requests
	// flowing in from the app.
	structure = gst_caps_get_structure (caps, 0);
	if (!gst_structure_get_int(structure, "width", &width) ||
	    !gst_structure_get_int(structure, "height", &height))
	{
		GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
		return GST_FLOW_NOT_NEGOTIATED;
	}

	GstBuffer *newbuf = gst_buffer_new();
	bool made_bufferdata_ptr = false;
#define MAXDEPTHHACK 4
	
	GST_OBJECT_LOCK(slvideo);
	if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
	{
		gint slwantwidth, slwantheight;
		slwantwidth = slvideo->resize_try_width;
		slwantheight = slvideo->resize_try_height;
	
		if (slwantwidth != width ||
		    slwantheight != height)
		{
			// don't like requested caps, we will issue our own suggestion - copy
			// the requested caps but substitute our own width and height and see
			// if our peer is happy with that.
		
			GstCaps *desired_caps;
			GstStructure *desired_struct;
			desired_caps = gst_caps_copy (caps);
			desired_struct = gst_caps_get_structure (desired_caps, 0);
			
			GValue value = {0};
			g_value_init(&value, G_TYPE_INT);
			g_value_set_int(&value, slwantwidth);
			gst_structure_set_value (desired_struct, "width", &value);
			g_value_unset(&value);
			g_value_init(&value, G_TYPE_INT);
			g_value_set_int(&value, slwantheight);
			gst_structure_set_value (desired_struct, "height", &value);
			
			if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
							desired_caps))
			{
				// todo: re-use buffers from a pool?
				// todo: set MALLOCDATA to null, set DATA to point straight to shm?
				
				// peer likes our cap suggestion
				DEBUGMSG("peer loves us :)");
				GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
				GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
				GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
				gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);

				made_bufferdata_ptr = true;
			} else {
				// peer hates our cap suggestion
				INFOMSG("peer hates us :(");
				gst_caps_unref(desired_caps);
			}
		}
	}

	GST_OBJECT_UNLOCK(slvideo);

	if (!made_bufferdata_ptr) // need to fallback to malloc at original size
	{
		GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
		GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
		GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
		gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
	}

	*buf = GST_BUFFER_CAST(newbuf);

	return GST_FLOW_OK;
}