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 #ifdef GSTREAMER_LITE 527 if (datetime == NULL) { 528 return NULL; 529 } 530 #endif // GSTREAMER_LITE 531 datetime->usec += tv.tv_usec; 532 gst_date_time_set_local_timezone (datetime); 533 return datetime; 534 } 535 536 static GstDateTime * 537 gst_date_time_copy (const GstDateTime * dt) 538 { 539 GstDateTime *copy = gst_date_time_alloc (); 540 541 memcpy (copy, dt, sizeof (GstDateTime)); 542 copy->ref_count = 1; 543 544 return copy; 545 } 546 547 static GstDateTime * 548 gst_date_time_to_utc (const GstDateTime * dt) 549 { 550 GstDateTime *utc; 551 gint64 usec; 552 gint days; 553 gint leap; 554 555 g_return_val_if_fail (dt != NULL, NULL); 556 557 utc = gst_date_time_copy (dt); 558 559 usec = dt->usec - dt->tzoffset * GST_DATE_TIME_USEC_PER_MINUTE; 560 days = usec / GST_DATE_TIME_USEC_PER_DAY; 561 if (usec < 0) 562 days--; 563 utc->day += days; 564 565 leap = GREGORIAN_LEAP (utc->year) ? 1 : 0; 566 567 /* check if we should update month/year */ 568 if (utc->day < 1) { 569 if (utc->month == 1) { 570 utc->year--; 571 utc->month = 12; 572 } else { 573 utc->month--; 574 } 575 if (GREGORIAN_LEAP (utc->year)) 576 utc->day = days_in_months[1][utc->month]; 577 else 578 utc->day = days_in_months[0][utc->month]; 579 } else if (utc->day > days_in_months[leap][utc->month]) { 580 if (utc->month == 12) { 581 utc->year++; 582 utc->month = 1; 583 } else { 584 utc->month++; 585 } 586 utc->day = 1; 587 } 588 589 if (usec < 0) 590 utc->usec = 591 GST_DATE_TIME_USEC_PER_DAY + (usec % GST_DATE_TIME_USEC_PER_DAY); 592 else 593 utc->usec = usec % GST_DATE_TIME_USEC_PER_DAY; 594 595 return utc; 596 } 597 598 GstDateTime * 599 gst_date_time_new_now_utc (void) 600 { 601 GstDateTime *now, *utc; 602 603 now = gst_date_time_new_now_local_time (); 604 utc = gst_date_time_to_utc (now); 605 gst_date_time_unref (now); 606 return utc; 607 } 608 609 gint 610 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2) 611 { 612 GstDateTime *a, *b; 613 gint res = 0; 614 615 a = gst_date_time_to_utc (dt1); 616 b = gst_date_time_to_utc (dt2); 617 618 #define GST_DATE_TIME_COMPARE_VALUE(a,b,v) \ 619 if ((a)->v > (b)->v) { \ 620 res = 1; \ 621 goto done; \ 622 } else if ((a)->v < (b)->v) { \ 623 res = -1; \ 624 goto done; \ 625 } 626 627 GST_DATE_TIME_COMPARE_VALUE (a, b, year); 628 GST_DATE_TIME_COMPARE_VALUE (a, b, month); 629 GST_DATE_TIME_COMPARE_VALUE (a, b, day); 630 GST_DATE_TIME_COMPARE_VALUE (a, b, usec); 631 632 #undef GST_DATE_TIME_COMPARE_VALUE 633 634 done: 635 gst_date_time_unref (a); 636 gst_date_time_unref (b); 637 return res; 638 } 639 640 #else 641 642 struct _GstDateTime 643 { 644 GDateTime *datetime; 645 646 volatile gint ref_count; 647 }; 648 649 static GstDateTime * 650 gst_date_time_new_from_gdatetime (GDateTime * dt) 651 { 652 GstDateTime *gst_dt; 653 654 if (!dt) 655 return NULL; 656 657 gst_dt = g_slice_new (GstDateTime); 658 gst_dt->datetime = dt; 659 gst_dt->ref_count = 1; 660 return gst_dt; 661 } 662 663 gint 664 gst_date_time_get_year (const GstDateTime * datetime) 665 { 666 return g_date_time_get_year (datetime->datetime); 667 } 668 669 gint 670 gst_date_time_get_month (const GstDateTime * datetime) 671 { 672 return g_date_time_get_month (datetime->datetime); 673 } 674 675 gint 676 gst_date_time_get_day (const GstDateTime * datetime) 677 { 678 return g_date_time_get_day_of_month (datetime->datetime); 679 } 680 681 gint 682 gst_date_time_get_hour (const GstDateTime * datetime) 683 { 684 return g_date_time_get_hour (datetime->datetime); 685 } 686 687 gint 688 gst_date_time_get_minute (const GstDateTime * datetime) 689 { 690 return g_date_time_get_minute (datetime->datetime); 691 } 692 693 gint 694 gst_date_time_get_second (const GstDateTime * datetime) 695 { 696 return g_date_time_get_second (datetime->datetime); 697 } 698 699 gint 700 gst_date_time_get_microsecond (const GstDateTime * datetime) 701 { 702 return g_date_time_get_microsecond (datetime->datetime); 703 } 704 705 gfloat 706 gst_date_time_get_time_zone_offset (const GstDateTime * datetime) 707 { 708 return (g_date_time_get_utc_offset (datetime->datetime) / 709 G_USEC_PER_SEC) / 3600.0; 710 } 711 712 GstDateTime * 713 gst_date_time_new_from_unix_epoch_local_time (gint64 secs) 714 { 715 return 716 gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_local (secs)); 717 } 718 719 GstDateTime * 720 gst_date_time_new_from_unix_epoch_utc (gint64 secs) 721 { 722 return 723 gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_utc (secs)); 724 } 725 726 GstDateTime * 727 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour, 728 gint minute, gdouble seconds) 729 { 730 return gst_date_time_new_from_gdatetime (g_date_time_new_local (year, month, 731 day, hour, minute, seconds)); 732 } 733 734 GstDateTime * 735 gst_date_time_new_now_local_time (void) 736 { 737 return gst_date_time_new_from_gdatetime (g_date_time_new_now_local ()); 738 } 739 740 GstDateTime * 741 gst_date_time_new_now_utc (void) 742 { 743 return gst_date_time_new_from_gdatetime (g_date_time_new_now_utc ()); 744 } 745 746 gint 747 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2) 748 { 749 const GstDateTime *datetime1 = dt1; 750 const GstDateTime *datetime2 = dt2; 751 return g_date_time_compare (datetime1->datetime, datetime2->datetime); 752 } 753 754 GstDateTime * 755 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour, 756 gint minute, gdouble seconds) 757 { 758 gchar buf[6]; 759 GTimeZone *tz; 760 GDateTime *dt; 761 gint tzhour, tzminute; 762 763 tzhour = (gint) ABS (tzoffset); 764 tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60); 765 766 g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour, 767 tzminute); 768 769 tz = g_time_zone_new (buf); 770 771 dt = g_date_time_new (tz, year, month, day, hour, minute, seconds); 772 g_time_zone_unref (tz); 773 return gst_date_time_new_from_gdatetime (dt); 774 } 775 776 static void 777 gst_date_time_free (GstDateTime * datetime) 778 { 779 g_date_time_unref (datetime->datetime); 780 g_slice_free (GstDateTime, datetime); 781 } 782 783 #endif 784 785 /** 786 * gst_date_time_ref: 787 * @datetime: a #GstDateTime 788 * 789 * Atomically increments the reference count of @datetime by one. 790 * 791 * Return value: (transfer full): the reference @datetime 792 * 793 * Since: 0.10.31 794 */ 795 GstDateTime * 796 gst_date_time_ref (GstDateTime * datetime) 797 { 798 g_return_val_if_fail (datetime != NULL, NULL); 799 g_return_val_if_fail (datetime->ref_count > 0, NULL); 800 g_atomic_int_inc (&datetime->ref_count); 801 return datetime; 802 } 803 804 /** 805 * gst_date_time_unref: 806 * @datetime: (transfer full): a #GstDateTime 807 * 808 * Atomically decrements the reference count of @datetime by one. When the 809 * reference count reaches zero, the structure is freed. 810 * 811 * Since: 0.10.31 812 */ 813 void 814 gst_date_time_unref (GstDateTime * datetime) 815 { 816 g_return_if_fail (datetime != NULL); 817 g_return_if_fail (datetime->ref_count > 0); 818 819 if (g_atomic_int_dec_and_test (&datetime->ref_count)) 820 gst_date_time_free (datetime); 821 }