sample: Set buffer/caps/buffer-lists to NULL correctly when replacing them with NULL
[platform/upstream/gstreamer.git] / gst / gstsample.c
1 /* GStreamer
2  * Copyright (C) 2011 Wim Taymans <wim.taymans@gmail.com>
3  *
4  * gstsample.c: media sample
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:gstsample
24  * @title: GstSample
25  * @short_description: A media sample
26  * @see_also: #GstBuffer, #GstCaps, #GstSegment
27  *
28  * A #GstSample is a small object containing data, a type, timing and
29  * extra arbitrary information.
30  */
31 #include "gst_private.h"
32
33 #include "gstsample.h"
34
35 GST_DEBUG_CATEGORY_STATIC (gst_sample_debug);
36 #define GST_CAT_DEFAULT gst_sample_debug
37
38 struct _GstSample
39 {
40   GstMiniObject mini_object;
41
42   GstBuffer *buffer;
43   GstCaps *caps;
44   GstSegment segment;
45   GstStructure *info;
46   GstBufferList *buffer_list;
47 };
48
49 GType _gst_sample_type = 0;
50
51 GST_DEFINE_MINI_OBJECT_TYPE (GstSample, gst_sample);
52
53 void
54 _priv_gst_sample_initialize (void)
55 {
56   _gst_sample_type = gst_sample_get_type ();
57
58   GST_DEBUG_CATEGORY_INIT (gst_sample_debug, "sample", 0, "GstSample debug");
59 }
60
61 static GstSample *
62 _gst_sample_copy (GstSample * sample)
63 {
64   GstSample *copy;
65
66   copy = gst_sample_new (sample->buffer, sample->caps, &sample->segment,
67       (sample->info) ? gst_structure_copy (sample->info) : NULL);
68
69   if (sample->buffer_list) {
70     copy->buffer_list = gst_buffer_list_ref (sample->buffer_list);
71     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (copy->buffer_list),
72         GST_MINI_OBJECT_CAST (copy));
73   }
74
75   return copy;
76 }
77
78 static void
79 _gst_sample_free (GstSample * sample)
80 {
81   GST_LOG ("free %p", sample);
82
83   if (sample->buffer) {
84     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->buffer),
85         GST_MINI_OBJECT_CAST (sample));
86     gst_buffer_unref (sample->buffer);
87   }
88
89   if (sample->caps) {
90     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->caps),
91         GST_MINI_OBJECT_CAST (sample));
92     gst_caps_unref (sample->caps);
93   }
94
95   if (sample->info) {
96     gst_structure_set_parent_refcount (sample->info, NULL);
97     gst_structure_free (sample->info);
98   }
99   if (sample->buffer_list) {
100     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->buffer_list),
101         GST_MINI_OBJECT_CAST (sample));
102     gst_buffer_list_unref (sample->buffer_list);
103   }
104
105   g_slice_free1 (sizeof (GstSample), sample);
106 }
107
108 /**
109  * gst_sample_new:
110  * @buffer: (transfer none) (allow-none): a #GstBuffer, or %NULL
111  * @caps: (transfer none) (allow-none): a #GstCaps, or %NULL
112  * @segment: (transfer none) (allow-none): a #GstSegment, or %NULL
113  * @info: (transfer full) (allow-none): a #GstStructure, or %NULL
114  *
115  * Create a new #GstSample with the provided details.
116  *
117  * Free-function: gst_sample_unref
118  *
119  * Returns: (transfer full): the new #GstSample. gst_sample_unref()
120  *     after usage.
121  */
122 GstSample *
123 gst_sample_new (GstBuffer * buffer, GstCaps * caps, const GstSegment * segment,
124     GstStructure * info)
125 {
126   GstSample *sample;
127
128   sample = g_slice_new0 (GstSample);
129
130   GST_LOG ("new %p", sample);
131
132   gst_mini_object_init (GST_MINI_OBJECT_CAST (sample), 0, _gst_sample_type,
133       (GstMiniObjectCopyFunction) _gst_sample_copy, NULL,
134       (GstMiniObjectFreeFunction) _gst_sample_free);
135
136   if (buffer) {
137     sample->buffer = gst_buffer_ref (buffer);
138     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer),
139         GST_MINI_OBJECT_CAST (sample));
140   }
141
142   if (caps) {
143     sample->caps = gst_caps_ref (caps);
144     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->caps),
145         GST_MINI_OBJECT_CAST (sample));
146   }
147
148   /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */
149   if (segment)
150     gst_segment_copy_into (segment, &sample->segment);
151   else
152     gst_segment_init (&sample->segment, GST_FORMAT_TIME);
153
154   if (info) {
155     if (!gst_structure_set_parent_refcount (info,
156             &sample->mini_object.refcount))
157       goto had_parent;
158
159     sample->info = info;
160   }
161   return sample;
162
163   /* ERRORS */
164 had_parent:
165   {
166     gst_sample_unref (sample);
167     g_warning ("structure is already owned by another object");
168     return NULL;
169   }
170 }
171
172 /**
173  * gst_sample_get_buffer:
174  * @sample: a #GstSample
175  *
176  * Get the buffer associated with @sample
177  *
178  * Returns: (transfer none) (nullable): the buffer of @sample or %NULL
179  *  when there is no buffer. The buffer remains valid as long as
180  *  @sample is valid.  If you need to hold on to it for longer than
181  *  that, take a ref to the buffer with gst_buffer_ref().
182  */
183 GstBuffer *
184 gst_sample_get_buffer (GstSample * sample)
185 {
186   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
187
188   return sample->buffer;
189 }
190
191 /**
192  * gst_sample_get_caps:
193  * @sample: a #GstSample
194  *
195  * Get the caps associated with @sample
196  *
197  * Returns: (transfer none) (nullable): the caps of @sample or %NULL
198  *  when there is no caps. The caps remain valid as long as @sample is
199  *  valid.  If you need to hold on to the caps for longer than that,
200  *  take a ref to the caps with gst_caps_ref().
201  */
202 GstCaps *
203 gst_sample_get_caps (GstSample * sample)
204 {
205   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
206
207   return sample->caps;
208 }
209
210 /**
211  * gst_sample_get_segment:
212  * @sample: a #GstSample
213  *
214  * Get the segment associated with @sample
215  *
216  * Returns: (transfer none): the segment of @sample.
217  *  The segment remains valid as long as @sample is valid.
218  */
219 GstSegment *
220 gst_sample_get_segment (GstSample * sample)
221 {
222   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
223
224   return &sample->segment;
225 }
226
227 /**
228  * gst_sample_get_info:
229  * @sample: a #GstSample
230  *
231  * Get extra information associated with @sample.
232  *
233  * Returns: (transfer none) (nullable): the extra info of @sample.
234  *  The info remains valid as long as @sample is valid.
235  */
236 const GstStructure *
237 gst_sample_get_info (GstSample * sample)
238 {
239   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
240
241   return sample->info;
242 }
243
244 /**
245  * gst_sample_get_buffer_list:
246  * @sample: a #GstSample
247  *
248  * Get the buffer list associated with @sample
249  *
250  * Returns: (transfer none) (nullable): the buffer list of @sample or %NULL
251  *  when there is no buffer list. The buffer list remains valid as long as
252  *  @sample is valid.  If you need to hold on to it for longer than
253  *  that, take a ref to the buffer list with gst_mini_object_ref ().
254  *
255  * Since: 1.6
256  */
257 GstBufferList *
258 gst_sample_get_buffer_list (GstSample * sample)
259 {
260   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
261
262   return sample->buffer_list;
263 }
264
265 /**
266  * gst_sample_set_buffer_list:
267  * @sample: a #GstSample
268  * @buffer_list: a #GstBufferList
269  *
270  * Set the buffer list associated with @sample. @sample must be writable.
271  *
272  * Since: 1.6
273  */
274 void
275 gst_sample_set_buffer_list (GstSample * sample, GstBufferList * buffer_list)
276 {
277   GstBufferList *old = NULL;
278   g_return_if_fail (GST_IS_SAMPLE (sample));
279   g_return_if_fail (gst_sample_is_writable (sample));
280
281   old = sample->buffer_list;
282
283   if (old == buffer_list)
284     return;
285
286   if (buffer_list) {
287     sample->buffer_list = gst_buffer_list_ref (buffer_list);
288     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer_list),
289         GST_MINI_OBJECT_CAST (sample));
290   } else {
291     sample->buffer_list = NULL;
292   }
293
294   if (old) {
295     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
296         GST_MINI_OBJECT_CAST (sample));
297     gst_buffer_list_unref (old);
298   }
299 }
300
301 /**
302  * gst_sample_set_buffer:
303  * @sample: A #GstSample
304  * @buffer: (transfer none): A #GstBuffer
305  *
306  * Set the buffer associated with @sample. @sample must be writable.
307  *
308  * Since: 1.16
309  */
310 void
311 gst_sample_set_buffer (GstSample * sample, GstBuffer * buffer)
312 {
313   GstBuffer *old = NULL;
314
315   g_return_if_fail (GST_IS_SAMPLE (sample));
316   g_return_if_fail (gst_sample_is_writable (sample));
317
318   old = sample->buffer;
319
320   if (old == buffer)
321     return;
322
323   if (buffer) {
324     sample->buffer = gst_buffer_ref (buffer);
325     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer),
326         GST_MINI_OBJECT_CAST (sample));
327   } else {
328     sample->buffer = NULL;
329   }
330
331   if (old) {
332     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
333         GST_MINI_OBJECT_CAST (sample));
334     gst_buffer_unref (old);
335   }
336 }
337
338 /**
339  * gst_sample_set_caps:
340  * @sample: A #GstSample
341  * @caps: (transfer none): A #GstCaps
342  *
343  * Set the caps associated with @sample. @sample must be writable.
344  *
345  * Since: 1.16
346  */
347 void
348 gst_sample_set_caps (GstSample * sample, GstCaps * caps)
349 {
350   GstCaps *old = NULL;
351
352   g_return_if_fail (GST_IS_SAMPLE (sample));
353   g_return_if_fail (gst_sample_is_writable (sample));
354
355   old = sample->caps;
356
357   if (old == caps)
358     return;
359
360   if (caps) {
361     sample->caps = gst_caps_ref (caps);
362     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->caps),
363         GST_MINI_OBJECT_CAST (sample));
364   } else {
365     sample->caps = NULL;
366   }
367
368   if (old) {
369     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
370         GST_MINI_OBJECT_CAST (sample));
371     gst_caps_unref (old);
372   }
373 }
374
375 /**
376  * gst_sample_set_segment:
377  * @sample: A #GstSample
378  * @segment: (transfer none): A #GstSegment
379  *
380  * Set the segment associated with @sample. @sample must be writable.
381  *
382  * Since: 1.16
383  */
384 void
385 gst_sample_set_segment (GstSample * sample, const GstSegment * segment)
386 {
387   g_return_if_fail (GST_IS_SAMPLE (sample));
388   g_return_if_fail (gst_sample_is_writable (sample));
389
390   /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */
391   if (segment)
392     gst_segment_copy_into (segment, &sample->segment);
393   else
394     gst_segment_init (&sample->segment, GST_FORMAT_TIME);
395 }
396
397 /**
398  * gst_sample_set_info:
399  * @sample: A #GstSample
400  * @info: (transfer full): A #GstStructure
401  *
402  * Set the info structure associated with @sample. @sample must be writable,
403  * and @info must not have a parent set already.
404  *
405  * Since: 1.16
406  */
407 gboolean
408 gst_sample_set_info (GstSample * sample, GstStructure * info)
409 {
410   g_return_val_if_fail (GST_IS_SAMPLE (sample), FALSE);
411   g_return_val_if_fail (gst_sample_is_writable (sample), FALSE);
412
413   if (info) {
414     if (!gst_structure_set_parent_refcount (info,
415             &sample->mini_object.refcount))
416       goto had_parent;
417   }
418
419   if (sample->info) {
420     gst_structure_set_parent_refcount (sample->info, NULL);
421     gst_structure_free (sample->info);
422   }
423
424   sample->info = info;
425
426   return TRUE;
427
428 had_parent:
429   g_warning ("structure is already owned by another object");
430   return FALSE;
431 }