• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
32 #include "gst_private.h"
33 
34 #include "gstsample.h"
35 
36 GST_DEBUG_CATEGORY_STATIC (gst_sample_debug);
37 #define GST_CAT_DEFAULT gst_sample_debug
38 
39 struct _GstSample
40 {
41   GstMiniObject mini_object;
42 
43   GstBuffer *buffer;
44   GstCaps *caps;
45   GstSegment segment;
46   GstStructure *info;
47   GstBufferList *buffer_list;
48 };
49 
50 GType _gst_sample_type = 0;
51 
52 GST_DEFINE_MINI_OBJECT_TYPE (GstSample, gst_sample);
53 
54 void
_priv_gst_sample_initialize(void)55 _priv_gst_sample_initialize (void)
56 {
57   _gst_sample_type = gst_sample_get_type ();
58 
59   GST_DEBUG_CATEGORY_INIT (gst_sample_debug, "sample", 0, "GstSample debug");
60 }
61 
62 static GstSample *
_gst_sample_copy(GstSample * sample)63 _gst_sample_copy (GstSample * sample)
64 {
65   GstSample *copy;
66 
67   copy = gst_sample_new (sample->buffer, sample->caps, &sample->segment,
68       (sample->info) ? gst_structure_copy (sample->info) : NULL);
69 
70   if (sample->buffer_list) {
71     copy->buffer_list = gst_buffer_list_ref (sample->buffer_list);
72     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (copy->buffer_list),
73         GST_MINI_OBJECT_CAST (copy));
74   }
75 
76   return copy;
77 }
78 
79 static void
_gst_sample_free(GstSample * sample)80 _gst_sample_free (GstSample * sample)
81 {
82   GST_LOG ("free %p", sample);
83 
84   if (sample->buffer) {
85     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->buffer),
86         GST_MINI_OBJECT_CAST (sample));
87     gst_buffer_unref (sample->buffer);
88   }
89 
90   if (sample->caps) {
91     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->caps),
92         GST_MINI_OBJECT_CAST (sample));
93     gst_caps_unref (sample->caps);
94   }
95 
96   if (sample->info) {
97     gst_structure_set_parent_refcount (sample->info, NULL);
98     gst_structure_free (sample->info);
99   }
100   if (sample->buffer_list) {
101     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (sample->buffer_list),
102         GST_MINI_OBJECT_CAST (sample));
103     gst_buffer_list_unref (sample->buffer_list);
104   }
105 #ifdef USE_POISONING
106   memset (sample, 0xff, sizeof (GstSample));
107 #endif
108 
109   g_slice_free1 (sizeof (GstSample), sample);
110 }
111 
112 /**
113  * gst_sample_new:
114  * @buffer: (transfer none) (allow-none): a #GstBuffer, or %NULL
115  * @caps: (transfer none) (allow-none): a #GstCaps, or %NULL
116  * @segment: (transfer none) (allow-none): a #GstSegment, or %NULL
117  * @info: (transfer full) (allow-none): a #GstStructure, or %NULL
118  *
119  * Create a new #GstSample with the provided details.
120  *
121  * Free-function: gst_sample_unref
122  *
123  * Returns: (transfer full): the new #GstSample. gst_sample_unref()
124  *     after usage.
125  */
126 GstSample *
gst_sample_new(GstBuffer * buffer,GstCaps * caps,const GstSegment * segment,GstStructure * info)127 gst_sample_new (GstBuffer * buffer, GstCaps * caps, const GstSegment * segment,
128     GstStructure * info)
129 {
130   GstSample *sample;
131 
132   sample = g_slice_new0 (GstSample);
133 
134   GST_LOG ("new %p", sample);
135 
136   gst_mini_object_init (GST_MINI_OBJECT_CAST (sample), 0, _gst_sample_type,
137       (GstMiniObjectCopyFunction) _gst_sample_copy, NULL,
138       (GstMiniObjectFreeFunction) _gst_sample_free);
139 
140   if (buffer) {
141     sample->buffer = gst_buffer_ref (buffer);
142     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer),
143         GST_MINI_OBJECT_CAST (sample));
144   }
145 
146   if (caps) {
147     sample->caps = gst_caps_ref (caps);
148     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->caps),
149         GST_MINI_OBJECT_CAST (sample));
150   }
151 
152   /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */
153   if (segment)
154     gst_segment_copy_into (segment, &sample->segment);
155   else
156     gst_segment_init (&sample->segment, GST_FORMAT_TIME);
157 
158   if (info) {
159     if (!gst_structure_set_parent_refcount (info,
160             &sample->mini_object.refcount))
161       goto had_parent;
162 
163     sample->info = info;
164   }
165   return sample;
166 
167   /* ERRORS */
168 had_parent:
169   {
170     gst_sample_unref (sample);
171     g_warning ("structure is already owned by another object");
172     return NULL;
173   }
174 }
175 
176 /**
177  * gst_sample_get_buffer:
178  * @sample: a #GstSample
179  *
180  * Get the buffer associated with @sample
181  *
182  * Returns: (transfer none) (nullable): the buffer of @sample or %NULL
183  *  when there is no buffer. The buffer remains valid as long as
184  *  @sample is valid.  If you need to hold on to it for longer than
185  *  that, take a ref to the buffer with gst_buffer_ref().
186  */
187 GstBuffer *
gst_sample_get_buffer(GstSample * sample)188 gst_sample_get_buffer (GstSample * sample)
189 {
190   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
191 
192   return sample->buffer;
193 }
194 
195 /**
196  * gst_sample_get_caps:
197  * @sample: a #GstSample
198  *
199  * Get the caps associated with @sample
200  *
201  * Returns: (transfer none) (nullable): the caps of @sample or %NULL
202  *  when there is no caps. The caps remain valid as long as @sample is
203  *  valid.  If you need to hold on to the caps for longer than that,
204  *  take a ref to the caps with gst_caps_ref().
205  */
206 GstCaps *
gst_sample_get_caps(GstSample * sample)207 gst_sample_get_caps (GstSample * sample)
208 {
209   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
210 
211   return sample->caps;
212 }
213 
214 /**
215  * gst_sample_get_segment:
216  * @sample: a #GstSample
217  *
218  * Get the segment associated with @sample
219  *
220  * Returns: (transfer none): the segment of @sample.
221  *  The segment remains valid as long as @sample is valid.
222  */
223 GstSegment *
gst_sample_get_segment(GstSample * sample)224 gst_sample_get_segment (GstSample * sample)
225 {
226   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
227 
228   return &sample->segment;
229 }
230 
231 /**
232  * gst_sample_get_info:
233  * @sample: a #GstSample
234  *
235  * Get extra information associated with @sample.
236  *
237  * Returns: (transfer none) (nullable): the extra info of @sample.
238  *  The info remains valid as long as @sample is valid.
239  */
240 const GstStructure *
gst_sample_get_info(GstSample * sample)241 gst_sample_get_info (GstSample * sample)
242 {
243   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
244 
245   return sample->info;
246 }
247 
248 /**
249  * gst_sample_get_buffer_list:
250  * @sample: a #GstSample
251  *
252  * Get the buffer list associated with @sample
253  *
254  * Returns: (transfer none) (nullable): the buffer list of @sample or %NULL
255  *  when there is no buffer list. The buffer list remains valid as long as
256  *  @sample is valid.  If you need to hold on to it for longer than
257  *  that, take a ref to the buffer list with gst_mini_object_ref ().
258  *
259  * Since: 1.6
260  */
261 GstBufferList *
gst_sample_get_buffer_list(GstSample * sample)262 gst_sample_get_buffer_list (GstSample * sample)
263 {
264   g_return_val_if_fail (GST_IS_SAMPLE (sample), NULL);
265 
266   return sample->buffer_list;
267 }
268 
269 /**
270  * gst_sample_set_buffer_list:
271  * @sample: a #GstSample
272  * @buffer_list: a #GstBufferList
273  *
274  * Set the buffer list associated with @sample. @sample must be writable.
275  *
276  * Since: 1.6
277  */
278 void
gst_sample_set_buffer_list(GstSample * sample,GstBufferList * buffer_list)279 gst_sample_set_buffer_list (GstSample * sample, GstBufferList * buffer_list)
280 {
281   GstBufferList *old = NULL;
282   g_return_if_fail (GST_IS_SAMPLE (sample));
283   g_return_if_fail (gst_sample_is_writable (sample));
284 
285   old = sample->buffer_list;
286 
287   if (old == buffer_list)
288     return;
289 
290   if (buffer_list) {
291     sample->buffer_list = gst_buffer_list_ref (buffer_list);
292     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer_list),
293         GST_MINI_OBJECT_CAST (sample));
294   } else {
295     sample->buffer_list = NULL;
296   }
297 
298   if (old) {
299     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
300         GST_MINI_OBJECT_CAST (sample));
301     gst_buffer_list_unref (old);
302   }
303 }
304 
305 /**
306  * gst_sample_set_buffer:
307  * @sample: A #GstSample
308  * @buffer: (transfer none): A #GstBuffer
309  *
310  * Set the buffer associated with @sample. @sample must be writable.
311  *
312  * Since: 1.16
313  */
314 void
gst_sample_set_buffer(GstSample * sample,GstBuffer * buffer)315 gst_sample_set_buffer (GstSample * sample, GstBuffer * buffer)
316 {
317   GstBuffer *old = NULL;
318 
319   g_return_if_fail (GST_IS_SAMPLE (sample));
320   g_return_if_fail (gst_sample_is_writable (sample));
321 
322   old = sample->buffer;
323 
324   if (old == buffer)
325     return;
326 
327   if (buffer) {
328     sample->buffer = gst_buffer_ref (buffer);
329     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->buffer),
330         GST_MINI_OBJECT_CAST (sample));
331   } else {
332     sample->buffer = NULL;
333   }
334 
335   if (old) {
336     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
337         GST_MINI_OBJECT_CAST (sample));
338     gst_buffer_unref (old);
339   }
340 }
341 
342 /**
343  * gst_sample_set_caps:
344  * @sample: A #GstSample
345  * @caps: (transfer none): A #GstCaps
346  *
347  * Set the caps associated with @sample. @sample must be writable.
348  *
349  * Since: 1.16
350  */
351 void
gst_sample_set_caps(GstSample * sample,GstCaps * caps)352 gst_sample_set_caps (GstSample * sample, GstCaps * caps)
353 {
354   GstCaps *old = NULL;
355 
356   g_return_if_fail (GST_IS_SAMPLE (sample));
357   g_return_if_fail (gst_sample_is_writable (sample));
358 
359   old = sample->caps;
360 
361   if (old == caps)
362     return;
363 
364   if (caps) {
365     sample->caps = gst_caps_ref (caps);
366     gst_mini_object_add_parent (GST_MINI_OBJECT_CAST (sample->caps),
367         GST_MINI_OBJECT_CAST (sample));
368   } else {
369     sample->caps = NULL;
370   }
371 
372   if (old) {
373     gst_mini_object_remove_parent (GST_MINI_OBJECT_CAST (old),
374         GST_MINI_OBJECT_CAST (sample));
375     gst_caps_unref (old);
376   }
377 }
378 
379 /**
380  * gst_sample_set_segment:
381  * @sample: A #GstSample
382  * @segment: (transfer none): A #GstSegment
383  *
384  * Set the segment associated with @sample. @sample must be writable.
385  *
386  * Since: 1.16
387  */
388 void
gst_sample_set_segment(GstSample * sample,const GstSegment * segment)389 gst_sample_set_segment (GstSample * sample, const GstSegment * segment)
390 {
391   g_return_if_fail (GST_IS_SAMPLE (sample));
392   g_return_if_fail (gst_sample_is_writable (sample));
393 
394   /* FIXME 2.0: initialize with GST_FORMAT_UNDEFINED by default */
395   if (segment)
396     gst_segment_copy_into (segment, &sample->segment);
397   else
398     gst_segment_init (&sample->segment, GST_FORMAT_TIME);
399 }
400 
401 /**
402  * gst_sample_set_info:
403  * @sample: A #GstSample
404  * @info: (transfer full): A #GstStructure
405  *
406  * Set the info structure associated with @sample. @sample must be writable,
407  * and @info must not have a parent set already.
408  *
409  * Since: 1.16
410  */
411 gboolean
gst_sample_set_info(GstSample * sample,GstStructure * info)412 gst_sample_set_info (GstSample * sample, GstStructure * info)
413 {
414   g_return_val_if_fail (GST_IS_SAMPLE (sample), FALSE);
415   g_return_val_if_fail (gst_sample_is_writable (sample), FALSE);
416 
417   if (info) {
418     if (!gst_structure_set_parent_refcount (info,
419             &sample->mini_object.refcount))
420       goto had_parent;
421   }
422 
423   if (sample->info) {
424     gst_structure_set_parent_refcount (sample->info, NULL);
425     gst_structure_free (sample->info);
426   }
427 
428   sample->info = info;
429 
430   return TRUE;
431 
432 had_parent:
433   g_warning ("structure is already owned by another object");
434   return FALSE;
435 }
436 
437 /**
438  * gst_sample_ref: (skip)
439  * @sample: a #GstSample
440  *
441  * Increases the refcount of the given sample by one.
442  *
443  * Returns: (transfer full): @sample
444  */
445 GstSample *
gst_sample_ref(GstSample * sample)446 gst_sample_ref (GstSample * sample)
447 {
448   return GST_SAMPLE_CAST (gst_mini_object_ref (GST_MINI_OBJECT_CAST (sample)));
449 }
450 
451 /**
452  * gst_sample_unref: (skip)
453  * @sample: (transfer full): a #GstSample
454  *
455  * Decreases the refcount of the sample. If the refcount reaches 0, the
456  * sample will be freed.
457  */
458 void
gst_sample_unref(GstSample * sample)459 gst_sample_unref (GstSample * sample)
460 {
461   gst_mini_object_unref (GST_MINI_OBJECT_CAST (sample));
462 }
463 
464 /**
465  * gst_sample_copy: (skip)
466  * @buf: a #GstSample.
467  *
468  * Create a copy of the given sample. This will also make a newly allocated
469  * copy of the data the source sample contains.
470  *
471  * Returns: (transfer full): a new copy of @buf.
472  *
473  * Since: 1.2
474  */
475 GstSample *
gst_sample_copy(const GstSample * buf)476 gst_sample_copy (const GstSample * buf)
477 {
478   return
479       GST_SAMPLE_CAST (gst_mini_object_copy (GST_MINI_OBJECT_CONST_CAST (buf)));
480 }
481