2.0 beta init
[framework/multimedia/gstreamer0.10.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 /* Jan 5th 2011 (Edward) : GLib's GDateTime is broken in regards to gmt offset
261  * on macosx. Re-enable it once the following bug is fixed:
262  * https://bugzilla.gnome.org/show_bug.cgi?id=638666 */
263 #ifdef HAVE_OSX
264 #undef GLIB_HAS_GDATETIME
265 #endif
266
267
268 #ifndef GLIB_HAS_GDATETIME
269
270 #define MAX_SUPPORTED_YEAR 9999
271 #define GREGORIAN_LEAP(y)  (((y%4)==0)&&(!(((y%100)==0)&&((y%400)!=0))))
272
273 static const guint16 days_in_months[2][13] = {
274   {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
275   {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
276 };
277
278 struct _GstDateTime
279 {
280   /*
281    * As we don't have a datetime math API, we can have fields split here.
282    * (There is still some math done internally, but nothing really relevant).
283    *
284    * If we ever add one, we should go for a days since some epoch counter.
285    * (Proleptic Gregorian with 0001-01-01 as day 1)
286    */
287   gint16 year;
288   gint8 month;
289   gint8 day;
290   guint64 usec;                 /* Microsecond timekeeping within Day */
291
292   gint tzoffset;
293
294   volatile gint ref_count;
295 };
296
297 /*
298  * Returns the utc offset in seconds for this time structure
299  */
300 static gint
301 gmt_offset (struct tm *tm, time_t t)
302 {
303 #if defined (HAVE_TM_GMTOFF)
304   return tm->tm_gmtoff;
305 #else
306   struct tm g;
307   time_t t2;
308 #ifdef HAVE_GMTIME_R
309   gmtime_r (&t, &g);
310 #else
311   g = *gmtime (&t);
312 #endif
313   t2 = mktime (&g);
314   return (int) difftime (t, t2);
315 #endif
316 }
317
318 static void
319 gst_date_time_set_local_timezone (GstDateTime * dt)
320 {
321   struct tm tt;
322   time_t t;
323
324   g_return_if_fail (dt != NULL);
325
326   memset (&tt, 0, sizeof (tt));
327
328   tt.tm_mday = gst_date_time_get_day (dt);
329   tt.tm_mon = gst_date_time_get_month (dt) - 1;
330   tt.tm_year = gst_date_time_get_year (dt) - 1900;
331   tt.tm_hour = gst_date_time_get_hour (dt);
332   tt.tm_min = gst_date_time_get_minute (dt);
333   tt.tm_sec = gst_date_time_get_second (dt);
334
335   t = mktime (&tt);
336
337   dt->tzoffset = gmt_offset (&tt, t) / 60;
338 }
339
340 static GstDateTime *
341 gst_date_time_alloc (void)
342 {
343   GstDateTime *datetime;
344
345   datetime = g_slice_new0 (GstDateTime);
346   datetime->ref_count = 1;
347
348   return datetime;
349 }
350
351 static void
352 gst_date_time_free (GstDateTime * datetime)
353 {
354   g_slice_free (GstDateTime, datetime);
355 }
356
357 static GstDateTime *
358 gst_date_time_new_from_date (gint year, gint month, gint day)
359 {
360   GstDateTime *dt;
361
362   g_return_val_if_fail (year > 0 && year <= 9999, NULL);
363   g_return_val_if_fail ((month > 0 && month <= 12), NULL);
364   g_return_val_if_fail ((day > 0 && day <= 31), NULL);
365
366   dt = gst_date_time_alloc ();
367
368   dt->year = year;
369   dt->month = month;
370   dt->day = day;
371   gst_date_time_set_local_timezone (dt);
372
373   return dt;
374 }
375
376 gint
377 gst_date_time_get_year (const GstDateTime * datetime)
378 {
379   g_return_val_if_fail (datetime != NULL, 0);
380
381   return datetime->year;
382 }
383
384 gint
385 gst_date_time_get_month (const GstDateTime * datetime)
386 {
387   g_return_val_if_fail (datetime != NULL, 0);
388
389   return datetime->month;
390 }
391
392 gint
393 gst_date_time_get_day (const GstDateTime * datetime)
394 {
395   g_return_val_if_fail (datetime != NULL, 0);
396
397   return datetime->day;
398 }
399
400 gint
401 gst_date_time_get_hour (const GstDateTime * datetime)
402 {
403   g_return_val_if_fail (datetime != NULL, 0);
404   return (datetime->usec / GST_DATE_TIME_USEC_PER_HOUR);
405 }
406
407 gint
408 gst_date_time_get_microsecond (const GstDateTime * datetime)
409 {
410   g_return_val_if_fail (datetime != NULL, 0);
411   return (datetime->usec % GST_DATE_TIME_USEC_PER_SECOND);
412 }
413
414 gint
415 gst_date_time_get_minute (const GstDateTime * datetime)
416 {
417   g_return_val_if_fail (datetime != NULL, 0);
418   return (datetime->usec % GST_DATE_TIME_USEC_PER_HOUR) /
419       GST_DATE_TIME_USEC_PER_MINUTE;
420 }
421
422 gint
423 gst_date_time_get_second (const GstDateTime * datetime)
424 {
425   g_return_val_if_fail (datetime != NULL, 0);
426   return (datetime->usec % GST_DATE_TIME_USEC_PER_MINUTE) /
427       GST_DATE_TIME_USEC_PER_SECOND;
428 }
429
430 gfloat
431 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
432 {
433   g_return_val_if_fail (datetime != NULL, 0);
434
435   return datetime->tzoffset / 60.0f;
436 }
437
438 GstDateTime *
439 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
440 {
441   GstDateTime *dt;
442   struct tm tm;
443   time_t tt;
444
445   memset (&tm, 0, sizeof (tm));
446   tt = (time_t) secs;
447
448 #ifdef HAVE_LOCALTIME_R
449   localtime_r (&tt, &tm);
450 #else
451   memcpy (&tm, localtime (&tt), sizeof (struct tm));
452 #endif
453
454   dt = gst_date_time_new (0, tm.tm_year + 1900,
455       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
456   gst_date_time_set_local_timezone (dt);
457   return dt;
458 }
459
460 GstDateTime *
461 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
462 {
463   GstDateTime *dt;
464   struct tm tm;
465   time_t tt;
466
467   memset (&tm, 0, sizeof (tm));
468   tt = (time_t) secs;
469
470 #ifdef HAVE_GMTIME_R
471   gmtime_r (&tt, &tm);
472 #else
473   memcpy (&tm, gmtime (&tt), sizeof (struct tm));
474 #endif
475
476   dt = gst_date_time_new (0, tm.tm_year + 1900,
477       tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
478   return dt;
479 }
480
481 GstDateTime *
482 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
483     gint minute, gdouble seconds)
484 {
485   GstDateTime *dt;
486
487   dt = gst_date_time_new (0, year, month, day, hour, minute, seconds);
488
489   gst_date_time_set_local_timezone (dt);
490
491   return dt;
492 }
493
494 GstDateTime *
495 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
496     gint minute, gdouble seconds)
497 {
498   GstDateTime *dt;
499
500   g_return_val_if_fail (hour >= 0 && hour < 24, NULL);
501   g_return_val_if_fail (minute >= 0 && minute < 60, NULL);
502   g_return_val_if_fail (seconds >= 0 && seconds < 60, NULL);
503   g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL);
504
505   if (!(dt = gst_date_time_new_from_date (year, month, day)))
506     return NULL;
507
508   dt->usec = (hour * GST_DATE_TIME_USEC_PER_HOUR)
509       + (minute * GST_DATE_TIME_USEC_PER_MINUTE)
510       + (guint64) (floor (seconds * GST_DATE_TIME_USEC_PER_SECOND + 0.5));
511
512   /* we store in minutes */
513   dt->tzoffset = (gint) (tzoffset * 60.0);
514
515   return dt;
516 }
517
518 GstDateTime *
519 gst_date_time_new_now_local_time (void)
520 {
521   GstDateTime *datetime;
522   GTimeVal tv;
523   g_get_current_time (&tv);
524
525   datetime = gst_date_time_new_from_unix_epoch_local_time (tv.tv_sec);
526   datetime->usec += tv.tv_usec;
527   gst_date_time_set_local_timezone (datetime);
528   return datetime;
529 }
530
531 static GstDateTime *
532 gst_date_time_copy (const GstDateTime * dt)
533 {
534   GstDateTime *copy = gst_date_time_alloc ();
535
536   memcpy (copy, dt, sizeof (GstDateTime));
537   copy->ref_count = 1;
538
539   return copy;
540 }
541
542 static GstDateTime *
543 gst_date_time_to_utc (const GstDateTime * dt)
544 {
545   GstDateTime *utc;
546   gint64 usec;
547   gint days;
548   gint leap;
549
550   g_return_val_if_fail (dt != NULL, NULL);
551
552   utc = gst_date_time_copy (dt);
553
554   usec = dt->usec - dt->tzoffset * GST_DATE_TIME_USEC_PER_MINUTE;
555   days = usec / GST_DATE_TIME_USEC_PER_DAY;
556   if (usec < 0)
557     days--;
558   utc->day += days;
559
560   leap = GREGORIAN_LEAP (utc->year) ? 1 : 0;
561
562   /* check if we should update month/year */
563   if (utc->day < 1) {
564     if (utc->month == 1) {
565       utc->year--;
566       utc->month = 12;
567     } else {
568       utc->month--;
569     }
570     if (GREGORIAN_LEAP (utc->year))
571       utc->day = days_in_months[1][utc->month];
572     else
573       utc->day = days_in_months[0][utc->month];
574   } else if (utc->day > days_in_months[leap][utc->month]) {
575     if (utc->month == 12) {
576       utc->year++;
577       utc->month = 1;
578     } else {
579       utc->month++;
580     }
581     utc->day = 1;
582   }
583
584   if (usec < 0)
585     utc->usec =
586         GST_DATE_TIME_USEC_PER_DAY + (usec % GST_DATE_TIME_USEC_PER_DAY);
587   else
588     utc->usec = usec % GST_DATE_TIME_USEC_PER_DAY;
589
590   return utc;
591 }
592
593 GstDateTime *
594 gst_date_time_new_now_utc (void)
595 {
596   GstDateTime *now, *utc;
597
598   now = gst_date_time_new_now_local_time ();
599   utc = gst_date_time_to_utc (now);
600   gst_date_time_unref (now);
601   return utc;
602 }
603
604 gint
605 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
606 {
607   GstDateTime *a, *b;
608   gint res = 0;
609
610   a = gst_date_time_to_utc (dt1);
611   b = gst_date_time_to_utc (dt2);
612
613 #define GST_DATE_TIME_COMPARE_VALUE(a,b,v)   \
614   if ((a)->v > (b)->v) {                     \
615     res = 1;                                 \
616     goto done;                               \
617   } else if ((a)->v < (b)->v) {              \
618     res = -1;                                \
619     goto done;                               \
620   }
621
622   GST_DATE_TIME_COMPARE_VALUE (a, b, year);
623   GST_DATE_TIME_COMPARE_VALUE (a, b, month);
624   GST_DATE_TIME_COMPARE_VALUE (a, b, day);
625   GST_DATE_TIME_COMPARE_VALUE (a, b, usec);
626
627 #undef GST_DATE_TIME_COMPARE_VALUE
628
629 done:
630   gst_date_time_unref (a);
631   gst_date_time_unref (b);
632   return res;
633 }
634
635 #else
636
637 struct _GstDateTime
638 {
639   GDateTime *datetime;
640
641   volatile gint ref_count;
642 };
643
644 static GstDateTime *
645 gst_date_time_new_from_gdatetime (GDateTime * dt)
646 {
647   GstDateTime *gst_dt;
648
649   if (!dt)
650     return NULL;
651
652   gst_dt = g_slice_new (GstDateTime);
653   gst_dt->datetime = dt;
654   gst_dt->ref_count = 1;
655   return gst_dt;
656 }
657
658 gint
659 gst_date_time_get_year (const GstDateTime * datetime)
660 {
661   return g_date_time_get_year (datetime->datetime);
662 }
663
664 gint
665 gst_date_time_get_month (const GstDateTime * datetime)
666 {
667   return g_date_time_get_month (datetime->datetime);
668 }
669
670 gint
671 gst_date_time_get_day (const GstDateTime * datetime)
672 {
673   return g_date_time_get_day_of_month (datetime->datetime);
674 }
675
676 gint
677 gst_date_time_get_hour (const GstDateTime * datetime)
678 {
679   return g_date_time_get_hour (datetime->datetime);
680 }
681
682 gint
683 gst_date_time_get_minute (const GstDateTime * datetime)
684 {
685   return g_date_time_get_minute (datetime->datetime);
686 }
687
688 gint
689 gst_date_time_get_second (const GstDateTime * datetime)
690 {
691   return g_date_time_get_second (datetime->datetime);
692 }
693
694 gint
695 gst_date_time_get_microsecond (const GstDateTime * datetime)
696 {
697   return g_date_time_get_microsecond (datetime->datetime);
698 }
699
700 gfloat
701 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
702 {
703   return (g_date_time_get_utc_offset (datetime->datetime) /
704       G_USEC_PER_SEC) / 3600.0;
705 }
706
707 GstDateTime *
708 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
709 {
710   return
711       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_local (secs));
712 }
713
714 GstDateTime *
715 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
716 {
717   return
718       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_utc (secs));
719 }
720
721 GstDateTime *
722 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
723     gint minute, gdouble seconds)
724 {
725   return gst_date_time_new_from_gdatetime (g_date_time_new_local (year, month,
726           day, hour, minute, seconds));
727 }
728
729 GstDateTime *
730 gst_date_time_new_now_local_time (void)
731 {
732   return gst_date_time_new_from_gdatetime (g_date_time_new_now_local ());
733 }
734
735 GstDateTime *
736 gst_date_time_new_now_utc (void)
737 {
738   return gst_date_time_new_from_gdatetime (g_date_time_new_now_utc ());
739 }
740
741 gint
742 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
743 {
744   const GstDateTime *datetime1 = dt1;
745   const GstDateTime *datetime2 = dt2;
746   return g_date_time_compare (datetime1->datetime, datetime2->datetime);
747 }
748
749 GstDateTime *
750 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
751     gint minute, gdouble seconds)
752 {
753   gchar buf[6];
754   GTimeZone *tz;
755   GDateTime *dt;
756   gint tzhour, tzminute;
757
758   tzhour = (gint) ABS (tzoffset);
759   tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);
760
761   g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
762       tzminute);
763
764   tz = g_time_zone_new (buf);
765
766   dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
767   g_time_zone_unref (tz);
768   return gst_date_time_new_from_gdatetime (dt);
769 }
770
771 static void
772 gst_date_time_free (GstDateTime * datetime)
773 {
774   g_date_time_unref (datetime->datetime);
775   g_slice_free (GstDateTime, datetime);
776 }
777
778 #endif
779
780 /**
781  * gst_date_time_ref:
782  * @datetime: a #GstDateTime
783  *
784  * Atomically increments the reference count of @datetime by one.
785  *
786  * Return value: (transfer full): the reference @datetime
787  *
788  * Since: 0.10.31
789  */
790 GstDateTime *
791 gst_date_time_ref (GstDateTime * datetime)
792 {
793   g_return_val_if_fail (datetime != NULL, NULL);
794   g_return_val_if_fail (datetime->ref_count > 0, NULL);
795   g_atomic_int_inc (&datetime->ref_count);
796   return datetime;
797 }
798
799 /**
800  * gst_date_time_unref:
801  * @datetime: (transfer full): a #GstDateTime
802  *
803  * Atomically decrements the reference count of @datetime by one.  When the
804  * reference count reaches zero, the structure is freed.
805  *
806  * Since: 0.10.31
807  */
808 void
809 gst_date_time_unref (GstDateTime * datetime)
810 {
811   g_return_if_fail (datetime != NULL);
812   g_return_if_fail (datetime->ref_count > 0);
813
814   if (g_atomic_int_dec_and_test (&datetime->ref_count))
815     gst_date_time_free (datetime);
816 }