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); }
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); }
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; }
/** * 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); }
/** * 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; }
/** * 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); } }
/** * 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); }
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; } } }
/** * 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); }
/** * 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; }
/** * 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; } } }
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); }