예제 #1
0
void test_value_collection()
{
  GstBuffer *buf = NULL;
  MyFoo *foo;
  
  xmlfile = "gstminiobject_test_value_collection";
  std_log(LOG_FILENAME_LINE, "Test Started test_value_collection");

  foo = (MyFoo *) g_object_new (my_foo_get_type (), NULL);

  /* test g_object_get() refcounting */
  g_object_get (foo, "buffer", &buf, NULL);
  g_assert (GST_IS_BUFFER (buf));
  g_assert (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1);
  gst_buffer_unref (buf);

  /* test g_object_set() refcounting */
  buf = gst_buffer_new_and_alloc (1024);
  g_object_set (foo, "buffer", buf, NULL);
  g_assert (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1);
  gst_buffer_unref (buf);

  g_object_unref (foo);
  
  std_log(LOG_FILENAME_LINE, "Test Successful");
  create_xml(0);
}
예제 #2
0
void test_make_writable()
{
  GstBuffer *buffer;
  GstMiniObject *mobj, *mobj2, *mobj3;
  
  xmlfile = "gstminiobject_test_make_writable";
      std_log(LOG_FILENAME_LINE, "Test Started test_make_writable");

  buffer = gst_buffer_new_and_alloc (4);
  mobj = GST_MINI_OBJECT (buffer);

  mobj2 = gst_mini_object_make_writable (mobj);
  fail_unless (GST_IS_BUFFER (mobj2), "make_writable did not return a buffer");
  fail_unless (mobj == mobj2,
      "make_writable returned a copy for a buffer with refcount 1");

  mobj2 = gst_mini_object_ref (mobj);
  mobj3 = gst_mini_object_make_writable (mobj);
  fail_unless (GST_IS_BUFFER (mobj3), "make_writable did not return a buffer");
  fail_if (mobj == mobj3,
      "make_writable returned same object for a buffer with refcount > 1");

  fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (mobj) == 1,
      "refcount of original mobj object should be back to 1");

  mobj2 = gst_mini_object_make_writable (mobj);
  fail_unless (GST_IS_BUFFER (mobj2), "make_writable did not return a buffer");
  fail_unless (mobj == mobj2,
      "make_writable returned a copy for a buffer with refcount 1");
  
  std_log(LOG_FILENAME_LINE, "Test Successful");
    create_xml(0);
}
예제 #3
0
GstImxVpuFramebufferArray * gst_imx_vpu_framebuffer_array_new(ImxVpuColorFormat color_format, unsigned int frame_width, unsigned int frame_height, unsigned int framebuffer_alignment, gboolean uses_interlacing, gboolean chroma_interleave, unsigned int num_framebuffers, GstImxPhysMemAllocator *phys_mem_allocator)
{
	guint i;
	GstImxVpuFramebufferArray *framebuffer_array = g_object_new(gst_imx_vpu_framebuffer_array_get_type(), NULL);

	framebuffer_array->original_frame_width = frame_width;
	framebuffer_array->original_frame_height = frame_height;

	imx_vpu_calc_framebuffer_sizes(
		color_format,
		frame_width, frame_height,
		framebuffer_alignment,
		uses_interlacing,
		chroma_interleave,
		&(framebuffer_array->framebuffer_sizes)
	);

	framebuffer_array->framebuffers = (ImxVpuFramebuffer *)g_slice_alloc(sizeof(ImxVpuFramebuffer) * num_framebuffers);
	framebuffer_array->num_framebuffers = num_framebuffers;

	framebuffer_array->allocator = (GstAllocator *)gst_object_ref(GST_OBJECT(phys_mem_allocator));

	GST_DEBUG_OBJECT(framebuffer_array, "allocating and registering %u framebuffers", num_framebuffers);

	for (i = 0; i < num_framebuffers; ++i)
	{
		GstImxPhysMemory *memory;
		ImxVpuFramebuffer *framebuffer = &(framebuffer_array->framebuffers[i]);

		// TODO: pass on framebuffer_alignment to the internal allocator somehow
		memory = (GstImxPhysMemory *)gst_allocator_alloc(
			framebuffer_array->allocator,
			framebuffer_array->framebuffer_sizes.total_size,
			NULL
		);

		if (memory == NULL)
			return FALSE;

		/* When filling in the params, use "memory" as the user-defined context parameter
		 * This is useful to be able to later determine which memory block this framebuffer
		 * is associated with. See gst_imx_vpu_framebuffer_array_get_gst_phys_memory(). */
		imx_vpu_fill_framebuffer_params(
			framebuffer,
			&(framebuffer_array->framebuffer_sizes),
			GST_IMX_VPU_MEM_IMXVPUAPI_DMA_BUFFER(memory),
			memory
		);

		GST_DEBUG_OBJECT(
			framebuffer_array,
			"memory block %p   physical address %" GST_IMX_PHYS_ADDR_FORMAT "  ref count %d",
			(gpointer)memory,
			memory->phys_addr,
			GST_MINI_OBJECT_REFCOUNT_VALUE(memory)
		);
	}

	return framebuffer_array;
}
예제 #4
0
/**
 * gst_mini_object_is_writable:
 * @mini_object: the mini-object to check
 *
 * Checks if a mini-object is writable.  A mini-object is writable
 * if the reference count is one and the #GST_MINI_OBJECT_FLAG_READONLY
 * flag is not set.  Modification of a mini-object should only be
 * done after verifying that it is writable.
 *
 * MT safe
 *
 * Returns: TRUE if the object is writable.
 */
gboolean
gst_mini_object_is_writable (const GstMiniObject * mini_object)
{
  g_return_val_if_fail (mini_object != NULL, FALSE);

  return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1) &&
      ((mini_object->flags & GST_MINI_OBJECT_FLAG_READONLY) == 0);
}
예제 #5
0
/**
 * gst_mini_object_ref:
 * @mini_object: the mini-object
 *
 * Increase the reference count of the mini-object.
 *
 * Note that the refcount affects the writability
 * of @mini-object, see gst_mini_object_is_writable(). It is
 * important to note that keeping additional references to
 * GstMiniObject instances can potentially increase the number
 * of memcpy operations in a pipeline, especially if the miniobject
 * is a #GstBuffer.
 *
 * Returns: (transfer full): the mini-object.
 */
GstMiniObject *
gst_mini_object_ref (GstMiniObject * mini_object)
{
  g_return_val_if_fail (mini_object != NULL, NULL);
  /* we can't assert that the refcount > 0 since the _free functions
   * increments the refcount from 0 to 1 again to allow resurecting
   * the object
   g_return_val_if_fail (mini_object->refcount > 0, NULL);
   */

  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object,
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) + 1);

  g_atomic_int_inc (&mini_object->refcount);

  return mini_object;
}
예제 #6
0
/**
 * gst_mini_object_unref:
 * @mini_object: the mini-object
 *
 * Decreases the reference count of the mini-object, possibly freeing
 * the mini-object.
 */
void
gst_mini_object_unref (GstMiniObject * mini_object)
{
  g_return_if_fail (mini_object != NULL);
  g_return_if_fail (mini_object->refcount > 0);

#ifdef DEBUG_REFCOUNT
  g_return_if_fail (GST_IS_MINI_OBJECT (mini_object));

  GST_CAT_LOG (GST_CAT_REFCOUNTING, "%p unref %d->%d",
      mini_object,
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);
#endif

  if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
    gst_mini_object_free (mini_object);
  }
}
예제 #7
0
/**
 * gst_mini_object_weak_ref: (skip)
 * @object: #GstMiniObject to reference weakly
 * @notify: callback to invoke before the mini object is freed
 * @data: extra data to pass to notify
 *
 * Adds a weak reference callback to a mini object. Weak references are
 * used for notification when a mini object is finalized. They are called
 * "weak references" because they allow you to safely hold a pointer
 * to the mini object without calling gst_mini_object_ref()
 * (gst_mini_object_ref() adds a strong reference, that is, forces the object
 * to stay alive).
 */
void
gst_mini_object_weak_ref (GstMiniObject * object,
    GstMiniObjectNotify notify, gpointer data)
{
  g_return_if_fail (object != NULL);
  g_return_if_fail (notify != NULL);
  g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);

  G_LOCK (qdata_mutex);
  set_notify (object, -1, weak_ref_quark, notify, data, NULL);
  G_UNLOCK (qdata_mutex);
}
예제 #8
0
static void
gst_alloc_trace_print (const GstAllocTrace * trace)
{
  GSList *mem_live;

  g_return_if_fail (trace != NULL);

  if (trace->flags & GST_ALLOC_TRACE_LIVE) {
    g_print ("%-22.22s : %d\n", trace->name, trace->live);
  } else {
    g_print ("%-22.22s : (no live count)\n", trace->name);
  }

  if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
    mem_live = trace->mem_live;

    while (mem_live) {
      gpointer data = mem_live->data;
      const gchar *type_name;
      gchar *extra = NULL;
      gint refcount = -1;

      if (trace->offset == -2) {
        if (G_IS_OBJECT (data)) {
          type_name = G_OBJECT_TYPE_NAME (data);
          refcount = G_OBJECT (data)->ref_count;
        } else
          type_name = "<invalid>";
      } else if (trace->offset == -1) {
        type_name = "<unknown>";
      } else {
        GType type;

        type = G_STRUCT_MEMBER (GType, data, trace->offset);
        type_name = g_type_name (type);

        if (type == GST_TYPE_CAPS) {
          extra = gst_caps_to_string (data);
        }
        refcount = GST_MINI_OBJECT_REFCOUNT_VALUE (data);
      }

      if (extra) {
        g_print ("  %-20.20s : (%d) %p (\"%s\")\n", type_name, refcount, data,
            extra);
        g_free (extra);
      } else
        g_print ("  %-20.20s : (%d) %p\n", type_name, refcount, data);

      mem_live = mem_live->next;
    }
  }
}
예제 #9
0
/**
 * gst_mini_object_unref:
 * @mini_object: the mini-object
 *
 * Decreases the reference count of the mini-object, possibly freeing
 * the mini-object.
 */
void
gst_mini_object_unref (GstMiniObject * mini_object)
{
  g_return_if_fail (mini_object != NULL);

  GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p unref %d->%d",
      mini_object,
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
      GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);

  g_return_if_fail (mini_object->refcount > 0);

  if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
    gboolean do_free;

    if (mini_object->dispose)
      do_free = mini_object->dispose (mini_object);
    else
      do_free = TRUE;

    /* if the subclass recycled the object (and returned FALSE) we don't
     * want to free the instance anymore */
    if (G_LIKELY (do_free)) {
      /* there should be no outstanding locks */
      g_return_if_fail ((g_atomic_int_get (&mini_object->lockstate) & LOCK_MASK)
          < 4);

      if (mini_object->n_qdata) {
        call_finalize_notify (mini_object);
        g_free (mini_object->qdata);
      }
#ifndef GST_DISABLE_TRACE
      _gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
#endif
      if (mini_object->free)
        mini_object->free (mini_object);
    }
  }
}
/**
 * gst_video_overlay_composition_add_rectangle:
 * @comp: a #GstVideoOverlayComposition
 * @rectangle: (transfer none): a #GstVideoOverlayRectangle to add to the
 *     composition
 *
 * Adds an overlay rectangle to an existing overlay composition object. This
 * must be done right after creating the overlay composition.
 *
 * Since: 0.10.36
 */
void
gst_video_overlay_composition_add_rectangle (GstVideoOverlayComposition * comp,
        GstVideoOverlayRectangle * rectangle)
{
    g_return_if_fail (GST_IS_VIDEO_OVERLAY_COMPOSITION (comp));
    g_return_if_fail (GST_IS_VIDEO_OVERLAY_RECTANGLE (rectangle));
    g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (comp) == 1);

    if (comp->num_rectangles % RECTANGLE_ARRAY_STEP == 0) {
        comp->rectangles =
            g_renew (GstVideoOverlayRectangle *, comp->rectangles,
                     comp->num_rectangles + RECTANGLE_ARRAY_STEP);
    }
예제 #11
0
/**
 * gst_mini_object_is_writable:
 * @mini_object: the mini-object to check
 *
 * If @mini_object has the LOCKABLE flag set, check if the current EXCLUSIVE
 * lock on @object is the only one, this means that changes to the object will
 * not be visible to any other object.
 *
 * If the LOCKABLE flag is not set, check if the refcount of @mini_object is
 * exactly 1, meaning that no other reference exists to the object and that the
 * object is therefore writable.
 *
 * Modification of a mini-object should only be done after verifying that it
 * is writable.
 *
 * Returns: TRUE if the object is writable.
 */
gboolean
gst_mini_object_is_writable (const GstMiniObject * mini_object)
{
  gboolean result;

  g_return_val_if_fail (mini_object != NULL, FALSE);

  if (GST_MINI_OBJECT_IS_LOCKABLE (mini_object)) {
    result = !IS_SHARED (g_atomic_int_get (&mini_object->lockstate));
  } else {
    result = (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
  }
  return result;
}
예제 #12
0
/**
 * gst_buffer_is_metadata_writable:
 * @buf: a #GstBuffer
 *
 * Similar to gst_buffer_is_writable, but this only ensures that the
 * refcount of the buffer is 1, indicating that the caller is the sole
 * owner and can change the buffer metadata, such as caps and timestamps.
 *
 * Returns: TRUE if the metadata is writable.
 */
gboolean
gst_buffer_is_metadata_writable (GstBuffer * buf)
{
  return (GST_MINI_OBJECT_REFCOUNT_VALUE (GST_MINI_OBJECT_CAST (buf)) == 1);
}
static void
gst_alloc_trace_print (const GstAllocTrace * trace)
{
  GSList *mem_live;

  g_return_if_fail (trace != NULL);

  if (trace->flags & GST_ALLOC_TRACE_LIVE) {
    g_print ("%-22.22s : %d\n", trace->name, trace->live);
  } else {
    g_print ("%-22.22s : (no live count)\n", trace->name);
  }

  if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
    mem_live = trace->mem_live;

    while (mem_live) {
      gpointer data = mem_live->data;
      const gchar *type_name;
      gchar *extra = NULL;
      gint refcount = -1;

      if (trace->offset == -2) {
        if (G_IS_OBJECT (data)) {
          type_name = G_OBJECT_TYPE_NAME (data);
          refcount = G_OBJECT (data)->ref_count;
        } else
          type_name = "<invalid>";
      } else if (trace->offset == -1) {
        type_name = "<unknown>";
      } else {
        GType type;

        type = G_STRUCT_MEMBER (GType, data, trace->offset);
        type_name = g_type_name (type);

        if (type == GST_TYPE_CAPS) {
          extra = gst_caps_to_string (data);
        } else if (type == GST_TYPE_EVENT) {
          const GstStructure *s = gst_event_get_structure (data);

          if (s == NULL)
            extra = g_strdup_printf ("%s", GST_EVENT_TYPE_NAME (data));
          else
            extra = gst_structure_to_string (s);
        } else if (type == GST_TYPE_MESSAGE) {
          const GstStructure *s = gst_message_get_structure (data);

          if (s == NULL)
            extra = g_strdup_printf ("%s", GST_MESSAGE_TYPE_NAME (data));
          else
            extra = gst_structure_to_string (s);
        } else if (type == GST_TYPE_BUFFER) {
          guint size = gst_buffer_get_size (data);

          extra = g_strdup_printf ("%u bytes", size);
        } else if (type == GST_TYPE_MEMORY) {
          GstMemory *mem = (GstMemory *) data;

          extra = g_strdup_printf ("%u bytes, %s allocator", (guint) mem->size,
              mem->allocator ? mem->allocator->mem_type : "unknown");
        }
        refcount = GST_MINI_OBJECT_REFCOUNT_VALUE (data);
      }

      if (extra) {
        g_print ("  %-20.20s : (%d) %p (\"%s\")\n", type_name, refcount, data,
            extra);
        g_free (extra);
      } else
        g_print ("  %-20.20s : (%d) %p\n", type_name, refcount, data);

      mem_live = mem_live->next;
    }
  }
}
예제 #14
0
static void gst_imx_vpu_framebuffer_array_finalize(GObject *object)
{
	guint i;
	GstImxVpuFramebufferArray *framebuffer_array = GST_IMX_VPU_FRAMEBUFFER_ARRAY(object);

	GST_DEBUG_OBJECT(object, "shutting down framebuffer array %p", (gpointer)object);

	if (framebuffer_array->framebuffers != NULL)
	{
		for (i = 0; i < framebuffer_array->num_framebuffers; ++i)
		{
			ImxVpuFramebuffer *framebuffer = &(framebuffer_array->framebuffers[i]);
			GstImxPhysMemory *memory = gst_imx_vpu_framebuffer_array_get_gst_phys_memory(framebuffer);

			GST_DEBUG_OBJECT(object, "freeing gstmemory block %p with physical address %" GST_IMX_PHYS_ADDR_FORMAT " and ref count %d", (gpointer)memory, memory->phys_addr, GST_MINI_OBJECT_REFCOUNT_VALUE(memory));

			/* at this point, the memory's refcount is 1, so unref'ing will deallocate it */
			gst_memory_unref((GstMemory *)memory);
		}

		g_slice_free1(sizeof(ImxVpuFramebuffer) * framebuffer_array->num_framebuffers, framebuffer_array->framebuffers);
	}

	if (framebuffer_array->allocator != NULL)
		gst_object_unref(GST_OBJECT(framebuffer_array->allocator));

	G_OBJECT_CLASS(gst_imx_vpu_framebuffer_array_parent_class)->finalize(object);
}