Merge branch '0.10'
[platform/upstream/gstreamer.git] / gst / gstdatetime.c
1 /* GStreamer
2  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "glib-compat-private.h"
25 #include "gst_private.h"
26 #include "gstdatetime.h"
27 #include <glib.h>
28 #include <math.h>
29
30 /**
31  * SECTION:gstdatetime
32  * @title: GstDateTime
33  * @short_description: A date, time and timezone structure
34  *
35  * Struct to store date, time and timezone information altogether.
36  * #GstDateTime is refcounted and immutable.
37  *
38  * Date information is handled using the proleptic Gregorian calendar.
39  *
40  * Provides basic creation functions and accessor functions to its fields.
41  *
42  * Since: 0.10.31
43  */
44
45 /**
46  * gst_date_time_get_year:
47  * @datetime: a #GstDateTime
48  *
49  * Returns the year of this #GstDateTime
50  *
51  * Return value: The year of this #GstDateTime
52  * Since: 0.10.31
53  */
54
55 /**
56  * gst_date_time_get_month:
57  * @datetime: a #GstDateTime
58  *
59  * Returns the month of this #GstDateTime. January is 1, February is 2, etc..
60  *
61  * Return value: The month of this #GstDateTime
62  * Since: 0.10.31
63  */
64
65 /**
66  * gst_date_time_get_day:
67  * @datetime: a #GstDateTime
68  *
69  * Returns the day of this #GstDateTime.
70  *
71  * Return value: The day of this #GstDateTime
72  * Since: 0.10.31
73  */
74
75 /**
76  * gst_date_time_get_hour:
77  * @datetime: a #GstDateTime
78  *
79  * Retrieves the hour of the day represented by @datetime in the gregorian
80  * calendar. The return is in the range of 0 to 23.
81  *
82  * Return value: the hour of the day
83  *
84  * Since: 0.10.31
85  */
86
87 /**
88  * gst_date_time_get_microsecond:
89  * @datetime: a #GstDateTime
90  *
91  * Retrieves the fractional part of the seconds in microseconds represented by
92  * @datetime in the gregorian calendar.
93  *
94  * Return value: the microsecond of the second
95  *
96  * Since: 0.10.31
97  */
98
99 /**
100  * gst_date_time_get_minute:
101  * @datetime: a #GstDateTime
102  *
103  * Retrieves the minute of the hour represented by @datetime in the gregorian
104  * calendar.
105  *
106  * Return value: the minute of the hour
107  *
108  * Since: 0.10.31
109  */
110
111 /**
112  * gst_date_time_get_second:
113  * @datetime: a #GstDateTime
114  *
115  * Retrieves the second of the minute represented by @datetime in the gregorian
116  * calendar.
117  *
118  * Return value: the second represented by @datetime
119  *
120  * Since: 0.10.31
121  */
122
123 /**
124  * gst_date_time_get_second:
125  * @datetime: a #GstDateTime
126  *
127  * Retrieves the second of the minute represented by @datetime in the gregorian
128  * calendar.
129  *
130  * Return value: the second represented by @datetime
131  *
132  * Since: 0.10.31
133  */
134
135 /**
136  * gst_date_time_get_time_zone_offset:
137  * @datetime: a #GstDateTime
138  *
139  * Retrieves the offset from UTC in hours that the timezone specified
140  * by @datetime represents. Timezones ahead (to the east) of UTC have positive
141  * values, timezones before (to the west) of UTC have negative values.
142  * If @datetime represents UTC time, then the offset is zero.
143  *
144  * Return value: the offset from UTC in hours
145  * Since: 0.10.31
146  */
147
148 /**
149  * gst_date_time_new_from_unix_epoch_local_time:
150  * @secs: seconds from the Unix epoch
151  *
152  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
153  * @secs. The #GstDateTime is in the local timezone.
154  *
155  * Free-function: gst_date_time_unref
156  *
157  * Return value: (transfer full): the newly created #GstDateTime
158  *
159  * Since: 0.10.31
160  */
161
162 /**
163  * gst_date_time_new_from_unix_epoch_utc:
164  * @secs: seconds from the Unix epoch
165  *
166  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
167  * @secs. The #GstDateTime is in the UTC timezone.
168  *
169  * Free-function: gst_date_time_unref
170  *
171  * Return value: (transfer full): the newly created #GstDateTime
172  *
173  * Since: 0.10.31
174  */
175
176 /**
177  * gst_date_time_new_local_time:
178  * @year: the gregorian year
179  * @month: the gregorian month
180  * @day: the day of the gregorian month
181  * @hour: the hour of the day
182  * @minute: the minute of the hour
183  * @seconds: the second of the minute
184  *
185  * Creates a new #GstDateTime using the date and times in the gregorian calendar
186  * in the local timezone.
187  *
188  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
189  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
190  *
191  * Free-function: gst_date_time_unref
192  *
193  * Return value: (transfer full): the newly created #GstDateTime
194  *
195  * Since: 0.10.31
196  */
197
198 /**
199  * gst_date_time_new:
200  * @tzoffset: Offset from UTC in hours.
201  * @year: the gregorian year
202  * @month: the gregorian month
203  * @day: the day of the gregorian month
204  * @hour: the hour of the day
205  * @minute: the minute of the hour
206  * @seconds: the second of the minute
207  *
208  * Creates a new #GstDateTime using the date and times in the gregorian calendar
209  * in the supplied timezone.
210  *
211  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
212  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
213  *
214  * Note that @tzoffset is a float and was chosen so for being able to handle
215  * some fractional timezones, while it still keeps the readability of
216  * represeting it in hours for most timezones.
217  *
218  * Free-function: gst_date_time_unref
219  *
220  * Return value: (transfer full): the newly created #GstDateTime
221  *
222  * Since: 0.10.31
223  */
224
225 /**
226  * gst_date_time_new_now_local_time:
227  *
228  * Creates a new #GstDateTime representing the current date and time.
229  *
230  * Free-function: gst_date_time_unref
231  *
232  * Return value: (transfer full): the newly created #GstDateTime which should
233  *     be freed with gst_date_time_unref().
234  *
235  * Since: 0.10.31
236  */
237
238 /**
239  * gst_date_time_new_now_utc:
240  *
241  * Creates a new #GstDateTime that represents the current instant at Universal
242  * coordinated time.
243  *
244  * Free-function: gst_date_time_unref
245  *
246  * Return value: (transfer full): the newly created #GstDateTime which should
247  *   be freed with gst_date_time_unref().
248  *
249  * Since: 0.10.31
250  */
251
252
253 #define GST_DATE_TIME_SEC_PER_DAY          (G_GINT64_CONSTANT (86400))
254 #define GST_DATE_TIME_USEC_PER_DAY         (G_GINT64_CONSTANT (86400000000))
255 #define GST_DATE_TIME_USEC_PER_HOUR        (G_GINT64_CONSTANT (3600000000))
256 #define GST_DATE_TIME_USEC_PER_MINUTE      (G_GINT64_CONSTANT (60000000))
257 #define GST_DATE_TIME_USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
258 #define GST_DATE_TIME_USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
259
260 /* FIXME: this bug was resolved NOTGNOME */
261 /* Jan 5th 2011 (Edward) : GLib's GDateTime is broken in regards to gmt offset
262  * on macosx. Re-enable it once the following bug is fixed:
263  * https://bugzilla.gnome.org/show_bug.cgi?id=638666 */
264 #ifdef HAVE_OSX
265 #undef GLIB_HAS_GDATETIME
266 #else
267 #define GLIB_HAS_GDATETIME
268 #endif
269
270
271 #ifndef GLIB_HAS_GDATETIME
272
273 #define MAX_SUPPORTED_YEAR 9999
274 #define GREGORIAN_LEAP(y)  (((y%4)==0)&&(!(((y%100)==0)&&((y%400)!=0))))
275
276 static const guint16 days_in_months[2][13] = {
277   {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
278   {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
279 };
280
281 struct _GstDateTime
282 {
283   /*
284    * As we don't have a datetime math API, we can have fields split here.
285    * (There is still some math done internally, but nothing really relevant).
286    *
287    * If we ever add one, we should go for a days since some epoch counter.
288    * (Proleptic Gregorian with 0001-01-01 as day 1)
289    */
290   gint16 year;
291   gint8 month;
292   gint8 day;
293   guint64 usec;                 /* Microsecond timekeeping within Day */
294
295   gint tzoffset;
296
297   volatile gint ref_count;
298 };
299
300 /*
301  * Returns the utc offset in seconds for this time structure
302  */
303 static gint
304 gmt_offset (struct tm *tm, time_t t)
305 {
306 #if defined (HAVE_TM_GMTOFF)
307   return tm->tm_gmtoff;
308 #else
309   struct tm g;
310   time_t t2;
311 #ifdef HAVE_GMTIME_R
312   gmtime_r (&t, &g);
313 #else
314   g = *gmtime (&t);
315 #endif
316   t2 = mktime (&g);
317   return (int) difftime (t, t2);
318 #endif
319 }
320
321 static void
322 gst_date_time_set_local_timezone (GstDateTime * dt)
323 {
324   struct tm tt;
325   time_t t;
326
327   g_return_if_fail (dt != NULL);
328
329   memset (&tt, 0, sizeof (tt));
330
331   tt.tm_mday = gst_date_time_get_day (dt);
332   tt.tm_mon = gst_date_time_get_month (dt) - 1;
333   tt.tm_year = gst_date_time_get_year (dt) - 1900;
334   tt.tm_hour = gst_date_time_get_hour (dt);
335   tt.tm_min = gst_date_time_get_minute (dt);
336   tt.tm_sec = gst_date_time_get_second (dt);
337
338   t = mktime (&tt);
339
340   dt->tzoffset = gmt_offset (&tt, t) / 60;
341 }
342
343 static GstDateTime *
344 gst_date_time_alloc (void)
345 {
346   GstDateTime *datetime;
347
348   datetime = g_slice_new0 (GstDateTime);
349   datetime->ref_count = 1;
350
351   return datetime;
352 }
353
354 static void
355 gst_date_time_free (GstDateTime * datetime)
356 {
357   g_slice_free (GstDateTime, datetime);
358 }
359
360 static GstDateTime *
361 gst_date_time_new_from_date (gint year, gint month, gint day)
362 {
363   GstDateTime *dt;
364
365   g_return_val_if_fail (year > 0 && year <= 9999, NULL);
366   g_return_val_if_fail ((month > 0 && month <= 12), NULL);
367   g_return_val_if_fail ((day > 0 && day <= 31), NULL);
368
369   dt = gst_date_time_alloc ();
370
371   dt->year = year;
372   dt->month = month;
373   dt->day = day;
374   gst_date_time_set_local_timezone (dt);
375
376   return dt;
377 }
378
379 gint
380 gst_date_time_get_year (const GstDateTime * datetime)
381 {
382   g_return_val_if_fail (datetime != NULL, 0);
383
384   return datetime->year;
385 }
386
387 gint
388 gst_date_time_get_month (const GstDateTime * datetime)
389 {
390   g_return_val_if_fail (datetime != NULL, 0);
391
392   return datetime->month;
393 }
394
395 gint
396 gst_date_time_get_day (const GstDateTime * datetime)
397 {
398   g_return_val_if_fail (datetime != NULL, 0);
399
400   return datetime->day;
401 }
402
403 gint
404 gst_date_time_get_hour (const GstDateTime * datetime)
405 {
406   g_return_val_if_fail (datetime != NULL, 0);
407   return (datetime->usec / GST_DATE_TIME_USEC_PER_HOUR);
408 }
409
410 gint
411 gst_date_time_get_microsecond (const GstDateTime * datetime)
412 {
413   g_return_val_if_fail (datetime != NULL, 0);
414   return (datetime->usec % GST_DATE_TIME_USEC_PER_SECOND);
415 }
416
417 gint
418 gst_date_time_get_minute (const GstDateTime * datetime)
419 {
420   g_return_val_if_fail (datetime != NULL, 0);
421   return (datetime->usec % GST_DATE_TIME_USEC_PER_HOUR) /
422       GST_DATE_TIME_USEC_PER_MINUTE;
423 }
424
425 gint
426 gst_date_time_get_second (const GstDateTime * datetime)
427 {
428   g_return_val_if_fail (datetime != NULL, 0);
429   return (datetime->usec % GST_DATE_TIME_USEC_PER_MINUTE) /
430       GST_DATE_TIME_USEC_PER_SECOND;
431 }
432
433 gfloat
434 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
435 {
436   g_return_val_if_fail (datetime != NULL, 0);
437
438   return datetime->tzoffset / 60.0f;
439 }
440
441 GstDateTime *
442 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
443 {
444   GstDateTime *dt;
445   struct tm tm;
446   time_t tt;
447
448   memset (&tm, 0, sizeof (tm));
449   tt = (time_t) secs;
450
451 #ifdef HAVE_LOCALTIME_R
452   localtime_r (&tt, &tm);
453 #else
454   memcpy (&tm, localtime (&tt), sizeof (struct tm));
455 #endif
456
457   dt = gst_date_time_new (0, tm.tm_year + 1900,
458       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
459   gst_date_time_set_local_timezone (dt);
460   return dt;
461 }
462
463 GstDateTime *
464 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
465 {
466   GstDateTime *dt;
467   struct tm tm;
468   time_t tt;
469
470   memset (&tm, 0, sizeof (tm));
471   tt = (time_t) secs;
472
473 #ifdef HAVE_GMTIME_R
474   gmtime_r (&tt, &tm);
475 #else
476   memcpy (&tm, gmtime (&tt), sizeof (struct tm));
477 #endif
478
479   dt = gst_date_time_new (0, tm.tm_year + 1900,
480       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
481   return dt;
482 }
483
484 GstDateTime *
485 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
486     gint minute, gdouble seconds)
487 {
488   GstDateTime *dt;
489
490   dt = gst_date_time_new (0, year, month, day, hour, minute, seconds);
491
492   gst_date_time_set_local_timezone (dt);
493
494   return dt;
495 }
496
497 GstDateTime *
498 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
499     gint minute, gdouble seconds)
500 {
501   GstDateTime *dt;
502
503   g_return_val_if_fail (hour >= 0 && hour < 24, NULL);
504   g_return_val_if_fail (minute >= 0 && minute < 60, NULL);
505   g_return_val_if_fail (seconds >= 0 && seconds < 60, NULL);
506   g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL);
507
508   if (!(dt = gst_date_time_new_from_date (year, month, day)))
509     return NULL;
510
511   dt->usec = (hour * GST_DATE_TIME_USEC_PER_HOUR)
512       + (minute * GST_DATE_TIME_USEC_PER_MINUTE)
513       + (guint64) (floor (seconds * GST_DATE_TIME_USEC_PER_SECOND + 0.5));
514
515   /* we store in minutes */
516   dt->tzoffset = (gint) (tzoffset * 60.0);
517
518   return dt;
519 }
520
521 GstDateTime *
522 gst_date_time_new_now_local_time (void)
523 {
524   GstDateTime *datetime;
525   GTimeVal tv;
526   g_get_current_time (&tv);
527
528   datetime = gst_date_time_new_from_unix_epoch_local_time (tv.tv_sec);
529   datetime->usec += tv.tv_usec;
530   gst_date_time_set_local_timezone (datetime);
531   return datetime;
532 }
533
534 static GstDateTime *
535 gst_date_time_copy (const GstDateTime * dt)
536 {
537   GstDateTime *copy = gst_date_time_alloc ();
538
539   memcpy (copy, dt, sizeof (GstDateTime));
540   copy->ref_count = 1;
541
542   return copy;
543 }
544
545 static GstDateTime *
546 gst_date_time_to_utc (const GstDateTime * dt)
547 {
548   GstDateTime *utc;
549   gint64 usec;
550   gint days;
551   gint leap;
552
553   g_return_val_if_fail (dt != NULL, NULL);
554
555   utc = gst_date_time_copy (dt);
556
557   usec = dt->usec - dt->tzoffset * GST_DATE_TIME_USEC_PER_MINUTE;
558   days = usec / GST_DATE_TIME_USEC_PER_DAY;
559   if (usec < 0)
560     days--;
561   utc->day += days;
562
563   leap = GREGORIAN_LEAP (utc->year) ? 1 : 0;
564
565   /* check if we should update month/year */
566   if (utc->day < 1) {
567     if (utc->month == 1) {
568       utc->year--;
569       utc->month = 12;
570     } else {
571       utc->month--;
572     }
573     if (GREGORIAN_LEAP (utc->year))
574       utc->day = days_in_months[1][utc->month];
575     else
576       utc->day = days_in_months[0][utc->month];
577   } else if (utc->day > days_in_months[leap][utc->month]) {
578     if (utc->month == 12) {
579       utc->year++;
580       utc->month = 1;
581     } else {
582       utc->month++;
583     }
584     utc->day = 1;
585   }
586
587   if (usec < 0)
588     utc->usec =
589         GST_DATE_TIME_USEC_PER_DAY + (usec % GST_DATE_TIME_USEC_PER_DAY);
590   else
591     utc->usec = usec % GST_DATE_TIME_USEC_PER_DAY;
592
593   return utc;
594 }
595
596 GstDateTime *
597 gst_date_time_new_now_utc (void)
598 {
599   GstDateTime *now, *utc;
600
601   now = gst_date_time_new_now_local_time ();
602   utc = gst_date_time_to_utc (now);
603   gst_date_time_unref (now);
604   return utc;
605 }
606
607 gint
608 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
609 {
610   GstDateTime *a, *b;
611   gint res = 0;
612
613   a = gst_date_time_to_utc (dt1);
614   b = gst_date_time_to_utc (dt2);
615
616 #define GST_DATE_TIME_COMPARE_VALUE(a,b,v)   \
617   if ((a)->v > (b)->v) {                     \
618     res = 1;                                 \
619     goto done;                               \
620   } else if ((a)->v < (b)->v) {              \
621     res = -1;                                \
622     goto done;                               \
623   }
624
625   GST_DATE_TIME_COMPARE_VALUE (a, b, year);
626   GST_DATE_TIME_COMPARE_VALUE (a, b, month);
627   GST_DATE_TIME_COMPARE_VALUE (a, b, day);
628   GST_DATE_TIME_COMPARE_VALUE (a, b, usec);
629
630 #undef GST_DATE_TIME_COMPARE_VALUE
631
632 done:
633   gst_date_time_unref (a);
634   gst_date_time_unref (b);
635   return res;
636 }
637
638 #else
639
640 struct _GstDateTime
641 {
642   GDateTime *datetime;
643
644   volatile gint ref_count;
645 };
646
647 static GstDateTime *
648 gst_date_time_new_from_gdatetime (GDateTime * dt)
649 {
650   GstDateTime *gst_dt;
651
652   if (!dt)
653     return NULL;
654
655   gst_dt = g_slice_new (GstDateTime);
656   gst_dt->datetime = dt;
657   gst_dt->ref_count = 1;
658   return gst_dt;
659 }
660
661 gint
662 gst_date_time_get_year (const GstDateTime * datetime)
663 {
664   return g_date_time_get_year (datetime->datetime);
665 }
666
667 gint
668 gst_date_time_get_month (const GstDateTime * datetime)
669 {
670   return g_date_time_get_month (datetime->datetime);
671 }
672
673 gint
674 gst_date_time_get_day (const GstDateTime * datetime)
675 {
676   return g_date_time_get_day_of_month (datetime->datetime);
677 }
678
679 gint
680 gst_date_time_get_hour (const GstDateTime * datetime)
681 {
682   return g_date_time_get_hour (datetime->datetime);
683 }
684
685 gint
686 gst_date_time_get_minute (const GstDateTime * datetime)
687 {
688   return g_date_time_get_minute (datetime->datetime);
689 }
690
691 gint
692 gst_date_time_get_second (const GstDateTime * datetime)
693 {
694   return g_date_time_get_second (datetime->datetime);
695 }
696
697 gint
698 gst_date_time_get_microsecond (const GstDateTime * datetime)
699 {
700   return g_date_time_get_microsecond (datetime->datetime);
701 }
702
703 gfloat
704 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
705 {
706   return (g_date_time_get_utc_offset (datetime->datetime) /
707       G_USEC_PER_SEC) / 3600.0;
708 }
709
710 GstDateTime *
711 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
712 {
713   return
714       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_local (secs));
715 }
716
717 GstDateTime *
718 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
719 {
720   return
721       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_utc (secs));
722 }
723
724 GstDateTime *
725 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
726     gint minute, gdouble seconds)
727 {
728   return gst_date_time_new_from_gdatetime (g_date_time_new_local (year, month,
729           day, hour, minute, seconds));
730 }
731
732 GstDateTime *
733 gst_date_time_new_now_local_time (void)
734 {
735   return gst_date_time_new_from_gdatetime (g_date_time_new_now_local ());
736 }
737
738 GstDateTime *
739 gst_date_time_new_now_utc (void)
740 {
741   return gst_date_time_new_from_gdatetime (g_date_time_new_now_utc ());
742 }
743
744 gint
745 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
746 {
747   const GstDateTime *datetime1 = dt1;
748   const GstDateTime *datetime2 = dt2;
749   return g_date_time_compare (datetime1->datetime, datetime2->datetime);
750 }
751
752 GstDateTime *
753 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
754     gint minute, gdouble seconds)
755 {
756   gchar buf[6];
757   GTimeZone *tz;
758   GDateTime *dt;
759   gint tzhour, tzminute;
760
761   tzhour = (gint) ABS (tzoffset);
762   tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);
763
764   g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
765       tzminute);
766
767   tz = g_time_zone_new (buf);
768
769   dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
770   g_time_zone_unref (tz);
771   return gst_date_time_new_from_gdatetime (dt);
772 }
773
774 static void
775 gst_date_time_free (GstDateTime * datetime)
776 {
777   g_date_time_unref (datetime->datetime);
778   g_slice_free (GstDateTime, datetime);
779 }
780
781 #endif
782
783 /**
784  * gst_date_time_ref:
785  * @datetime: a #GstDateTime
786  *
787  * Atomically increments the reference count of @datetime by one.
788  *
789  * Return value: (transfer full): the reference @datetime
790  *
791  * Since: 0.10.31
792  */
793 GstDateTime *
794 gst_date_time_ref (GstDateTime * datetime)
795 {
796   g_return_val_if_fail (datetime != NULL, NULL);
797   g_return_val_if_fail (datetime->ref_count > 0, NULL);
798   g_atomic_int_inc (&datetime->ref_count);
799   return datetime;
800 }
801
802 /**
803  * gst_date_time_unref:
804  * @datetime: (transfer full): a #GstDateTime
805  *
806  * Atomically decrements the reference count of @datetime by one.  When the
807  * reference count reaches zero, the structure is freed.
808  *
809  * Since: 0.10.31
810  */
811 void
812 gst_date_time_unref (GstDateTime * datetime)
813 {
814   g_return_if_fail (datetime != NULL);
815   g_return_if_fail (datetime->ref_count > 0);
816
817   if (g_atomic_int_dec_and_test (&datetime->ref_count))
818     gst_date_time_free (datetime);
819 }