From fe4b415f98597e1ab3e3a442e117f9d8b580a88f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 19 Nov 2012 16:59:48 +0100 Subject: [PATCH] rtsp: parse UTC ranges --- gst-libs/gst/rtsp/gstrtsprange.c | 67 ++++++++++++++++++++++++++++++++++++++-- gst-libs/gst/rtsp/gstrtsprange.h | 13 ++++++-- tests/check/libs/rtsp.c | 43 +++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/rtsp/gstrtsprange.c b/gst-libs/gst/rtsp/gstrtsprange.c index 3c914c9..4487729 100644 --- a/gst-libs/gst/rtsp/gstrtsprange.c +++ b/gst-libs/gst/rtsp/gstrtsprange.c @@ -132,11 +132,72 @@ done: return res; } +/* utc-time = utc-date "T" utc-time "Z" + * utc-date = 8DIGIT ; < YYYYMMDD > + * utc-time = 6DIGIT [ "." fraction ] ; < HHMMSS.fraction > + * + * Example for November 8, 1996 at 14h37 and 20 and a quarter seconds + * UTC: + * + * 19961108T143720.25Z + */ +static GstRTSPResult +parse_utc_time (const gchar * str, GstRTSPTime * time, const gchar * limit) +{ + + if (str[0] == '\0') { + time->type = GST_RTSP_TIME_END; + return GST_RTSP_OK; + } else { + gint year, month, day; + gint hours, mins; + gdouble secs; + gchar *T, *Z; + + T = strchr (str, 'T'); + if (T == NULL || T != str + 8) + return GST_RTSP_EINVAL; + + Z = strchr (T + 1, 'Z'); + if (Z == NULL) + return GST_RTSP_EINVAL; + + time->type = GST_RTSP_TIME_UTC; + + if (sscanf (str, "%4d%2d%2dT%2d%2d%lfZ", &year, &month, &day, &hours, + &mins, &secs) != 6) + return GST_RTSP_EINVAL; + + time->year = year; + time->month = month; + time->day = day; + time->seconds = ((hours * 60) + mins) * 60 + secs; + } + return GST_RTSP_OK; +} +/* utc-range = "clock" "=" utc-time "-" [ utc-time ] + */ static GstRTSPResult -parse_clock_range (const gchar * str, GstRTSPTimeRange * range) +parse_utc_range (const gchar * str, GstRTSPTimeRange * range) { - return GST_RTSP_ENOTIMPL; + GstRTSPResult res; + gchar *p; + + range->unit = GST_RTSP_RANGE_CLOCK; + + /* find '-' separator, can't have a single - */ + p = strstr (str, "-"); + if (p == NULL || p == str) + return GST_RTSP_EINVAL; + + if ((res = parse_utc_time (str, &range->min, p)) != GST_RTSP_OK) + goto done; + + res = parse_utc_time (p + 1, &range->max, NULL); + +done: + return res; } /* smpte-time = 1*2DIGIT ":" 1*2DIGIT ":" 1*2DIGIT [ ":" 1*2DIGIT ] @@ -216,7 +277,7 @@ gst_rtsp_range_parse (const gchar * rangestr, GstRTSPTimeRange ** range) if (g_str_has_prefix (p, "npt=")) { ret = parse_npt_range (p + 4, res); } else if (g_str_has_prefix (p, "clock=")) { - ret = parse_clock_range (p + 6, res); + ret = parse_utc_range (p + 6, res); } else if (g_str_has_prefix (p, "smpte=")) { res->unit = GST_RTSP_RANGE_SMPTE; ret = parse_smpte_range (p + 6, res); diff --git a/gst-libs/gst/rtsp/gstrtsprange.h b/gst-libs/gst/rtsp/gstrtsprange.h index 9d86686..a1429b0 100644 --- a/gst-libs/gst/rtsp/gstrtsprange.h +++ b/gst-libs/gst/rtsp/gstrtsprange.h @@ -84,15 +84,19 @@ typedef enum { GST_RTSP_TIME_SECONDS, GST_RTSP_TIME_NOW, GST_RTSP_TIME_END, - GST_RTSP_TIME_FRAMES + GST_RTSP_TIME_FRAMES, + GST_RTSP_TIME_UTC } GstRTSPTimeType; /** * GstRTSPTime: * @type: the time of the time - * @seconds: seconds when @type is GST_RTSP_TIME_SECONDS and - * GST_RTSP_TIME_FRAMES + * @seconds: seconds when @type is GST_RTSP_TIME_SECONDS, + * GST_RTSP_TIME_UTC and GST_RTSP_TIME_FRAMES * @frames: frames and subframes when @type is GST_RTSP_TIME_FRAMES + * @year: year when @type is GST_RTSP_TIME_UTC + * @month: month when @type is GST_RTSP_TIME_UTC + * @day: day when @type is GST_RTSP_TIME_UTC * * A time indication. */ @@ -100,6 +104,9 @@ struct _GstRTSPTime { GstRTSPTimeType type; gdouble seconds; gdouble frames; + guint year; + guint month; + guint day; }; /** diff --git a/tests/check/libs/rtsp.c b/tests/check/libs/rtsp.c index f9d422e..62b989a 100644 --- a/tests/check/libs/rtsp.c +++ b/tests/check/libs/rtsp.c @@ -223,7 +223,8 @@ GST_START_TEST (test_rtsp_range_smpte) GstRTSPTimeRange *range; fail_unless (gst_rtsp_range_parse ("smpte=", &range) == GST_RTSP_EINVAL); - fail_unless (gst_rtsp_range_parse ("smpte=0", &range) == GST_RTSP_EINVAL); + fail_unless (gst_rtsp_range_parse ("smpte=10:34:23", + &range) == GST_RTSP_EINVAL); fail_unless (gst_rtsp_range_parse ("smpte=-", &range) == GST_RTSP_EINVAL); fail_unless (gst_rtsp_range_parse ("smpte=-12:09:34", &range) == GST_RTSP_EINVAL); @@ -252,6 +253,45 @@ GST_START_TEST (test_rtsp_range_smpte) GST_END_TEST; +GST_START_TEST (test_rtsp_range_clock) +{ + GstRTSPTimeRange *range; + + fail_unless (gst_rtsp_range_parse ("clock=", &range) == GST_RTSP_EINVAL); + fail_unless (gst_rtsp_range_parse ("clock=20001010T120023Z", + &range) == GST_RTSP_EINVAL); + fail_unless (gst_rtsp_range_parse ("clock=-", &range) == GST_RTSP_EINVAL); + fail_unless (gst_rtsp_range_parse ("clock=-20001010T120934Z", + &range) == GST_RTSP_EINVAL); + + fail_unless (gst_rtsp_range_parse ("clock=20001010T122345Z-", + &range) == GST_RTSP_OK); + fail_unless (range->unit == GST_RTSP_RANGE_CLOCK); + fail_unless (range->min.type == GST_RTSP_TIME_UTC); + fail_unless (range->min.year == 2000); + fail_unless (range->min.month == 10); + fail_unless (range->min.day == 10); + fail_unless (range->min.seconds == 44625.0); + fail_unless (range->max.type == GST_RTSP_TIME_END); + gst_rtsp_range_free (range); + + fail_unless (gst_rtsp_range_parse + ("clock=19700101T103423Z-30001230T201209.89Z", &range) == GST_RTSP_OK); + fail_unless (range->unit == GST_RTSP_RANGE_CLOCK); + fail_unless (range->min.type == GST_RTSP_TIME_UTC); + fail_unless (range->min.year == 1970); + fail_unless (range->min.month == 1); + fail_unless (range->min.day == 1); + fail_unless (range->min.seconds == 38063.0); + fail_unless (range->max.type == GST_RTSP_TIME_UTC); + fail_unless (range->max.year == 3000); + fail_unless (range->max.month == 12); + fail_unless (range->max.day == 30); + fail_unless (range->max.seconds == 72729.89); + gst_rtsp_range_free (range); +} + +GST_END_TEST; static Suite * rtsp_suite (void) @@ -266,6 +306,7 @@ rtsp_suite (void) tcase_add_test (tc_chain, test_rtsp_url_components_3); tcase_add_test (tc_chain, test_rtsp_range_npt); tcase_add_test (tc_chain, test_rtsp_range_smpte); + tcase_add_test (tc_chain, test_rtsp_range_clock); return s; } -- 2.7.4