From ed5d888ba5ffcaa9561e60c6b237bcf4a9ca3853 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Wed, 11 Apr 2018 00:49:02 +0200 Subject: [PATCH] gstsample: new API gst_sample_set_buffer gst_sample_set_caps gst_sample_set_segment gst_sample_set_info gst_sample_is_writable gst_sample_make_writable This commit makes it possible to reuse a sample object and avoid unnecessary memory allocations, for example in appsink. In addition, writability is now required to set the buffer list. https://bugzilla.gnome.org/show_bug.cgi?id=795144 --- docs/gst/gstreamer-sections.txt | 6 +++ gst/gstsample.c | 95 +++++++++++++++++++++++++++++++-- gst/gstsample.h | 50 +++++++++++++++++ win32/common/libgstreamer.def | 4 ++ 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index e0b993ff00..2da2fc6e3b 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -560,11 +560,17 @@ gst_sample_get_buffer_list gst_sample_get_caps gst_sample_get_info gst_sample_get_segment +gst_sample_set_buffer gst_sample_set_buffer_list +gst_sample_set_caps +gst_sample_set_segment +gst_sample_set_info gst_sample_new gst_sample_ref gst_sample_unref gst_sample_copy +gst_buffer_is_writable +gst_buffer_make_writable GST_IS_SAMPLE GST_SAMPLE diff --git a/gst/gstsample.c b/gst/gstsample.c index 6479048807..143215f591 100644 --- a/gst/gstsample.c +++ b/gst/gstsample.c @@ -123,6 +123,7 @@ gst_sample_new (GstBuffer * buffer, GstCaps * caps, const GstSegment * segment, sample->buffer = buffer ? gst_buffer_ref (buffer) : NULL; sample->caps = caps ? gst_caps_ref (caps) : NULL; + /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */ if (segment) gst_segment_copy_into (segment, &sample->segment); else @@ -244,7 +245,7 @@ gst_sample_get_buffer_list (GstSample * sample) * @sample: a #GstSample * @buffer_list: a #GstBufferList * - * Set the buffer list associated with @sample + * Set the buffer list associated with @sample. @sample must be writable. * * Since: 1.6 */ @@ -253,10 +254,98 @@ gst_sample_set_buffer_list (GstSample * sample, GstBufferList * buffer_list) { GstBufferList *old = NULL; g_return_if_fail (GST_IS_SAMPLE (sample)); + g_return_if_fail (gst_sample_is_writable (sample)); + old = sample->buffer_list; - sample->buffer_list = (GstBufferList *) - gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer_list)); + sample->buffer_list = buffer_list ? (GstBufferList *) + gst_mini_object_ref (GST_MINI_OBJECT_CAST (buffer_list)) : NULL; if (old) gst_mini_object_unref (GST_MINI_OBJECT_CAST (old)); } + +/** + * gst_sample_set_buffer: + * + * Set the buffer associated with @sample. @sample must be writable. + * + * Since: 1.16 + */ +void +gst_sample_set_buffer (GstSample * sample, GstBuffer * buffer) +{ + g_return_if_fail (GST_IS_SAMPLE (sample)); + g_return_if_fail (gst_sample_is_writable (sample)); + + gst_buffer_replace (&sample->buffer, buffer); +} + +/** + * gst_sample_set_caps: + * + * Set the caps associated with @sample. @sample must be writable. + * + * Since: 1.16 + */ +void +gst_sample_set_caps (GstSample * sample, GstCaps * caps) +{ + g_return_if_fail (GST_IS_SAMPLE (sample)); + g_return_if_fail (gst_sample_is_writable (sample)); + + gst_caps_replace (&sample->caps, caps); +} + +/** + * gst_sample_set_segment: + * + * Set the segment associated with @sample. @sample must be writable. + * + * Since: 1.16 + */ +void +gst_sample_set_segment (GstSample * sample, const GstSegment * segment) +{ + g_return_if_fail (GST_IS_SAMPLE (sample)); + g_return_if_fail (gst_sample_is_writable (sample)); + + /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */ + if (segment) + gst_segment_copy_into (segment, &sample->segment); + else + gst_segment_init (&sample->segment, GST_FORMAT_TIME); +} + +/** + * gst_sample_set_info: + * + * Set the info structure associated with @sample. @sample must be writable, + * and @info must not have a parent set already. + * + * Since: 1.16 + */ +gboolean +gst_sample_set_info (GstSample * sample, GstStructure * info) +{ + g_return_val_if_fail (GST_IS_SAMPLE (sample), FALSE); + g_return_val_if_fail (gst_sample_is_writable (sample), FALSE); + + if (info) { + if (!gst_structure_set_parent_refcount (info, + &sample->mini_object.refcount)) + goto had_parent; + } + + if (sample->info) { + gst_structure_set_parent_refcount (sample->info, NULL); + gst_structure_free (sample->info); + } + + sample->info = info; + + return TRUE; + +had_parent: + g_warning ("structure is already owned by another object"); + return FALSE; +} diff --git a/gst/gstsample.h b/gst/gstsample.h index 84c6ef1ec7..7cbf07249f 100644 --- a/gst/gstsample.h +++ b/gst/gstsample.h @@ -75,6 +75,18 @@ GstBufferList * gst_sample_get_buffer_list (GstSample *sample); GST_API void gst_sample_set_buffer_list (GstSample *sample, GstBufferList *buffer_list); +GST_API +void gst_sample_set_buffer (GstSample *sample, GstBuffer *buffer); + +GST_API +void gst_sample_set_caps (GstSample *sample, GstCaps *caps); + +GST_API +void gst_sample_set_segment (GstSample * sample, const GstSegment *segment); + +GST_API +gboolean gst_sample_set_info (GstSample *sample, GstStructure *info); + /* refcounting */ /** * gst_sample_ref: @@ -104,6 +116,44 @@ gst_sample_unref (GstSample * sample) gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample)); } +/** + * gst_sample_is_writable: + * + * Tests if you can safely set the buffer and / or buffer list of @sample. + * + * Since: 1.16 + */ +#define gst_sample_is_writable(sample) gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (sample)) + +/** + * gst_sample_make_writable: + * @sample: (transfer full): + * + * Returns a writable copy of @sample. If the source sample is + * already writable, this will simply return the same sample. + * + * Use this function to ensure that a sample can be safely modified before + * making changes to it, for example before calling gst_sample_set_buffer() + * + * If the reference count of the source sample @sample is exactly one, the caller + * is the sole owner and this function will return the sample object unchanged. + * + * If there is more than one reference on the object, a copy will be made using + * gst_sample_copy(). The passed-in @sample will be unreffed in that case, and the + * caller will now own a reference to the new returned sample object. + * + * In short, this function unrefs the sample in the argument and refs the sample + * that it returns. Don't access the argument after calling this function unless + * you have an additional reference to it. + * + * Returns: (transfer full): a writable sample which may or may not be the + * same as @sample + * + * Since: 1.16 + */ +#define gst_sample_make_writable(sample) GST_SAMPLE_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (sample))) + + /* copy sample */ /** * gst_sample_copy: diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 4abfeec55f..2eadc29c18 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -1235,7 +1235,11 @@ EXPORTS gst_sample_get_segment gst_sample_get_type gst_sample_new + gst_sample_set_buffer gst_sample_set_buffer_list + gst_sample_set_caps + gst_sample_set_info + gst_sample_set_segment gst_scheduling_flags_get_type gst_search_mode_get_type gst_seek_flags_get_type