rtsp: parse UTC ranges
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 19 Nov 2012 15:59:48 +0000 (16:59 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 19 Nov 2012 15:59:48 +0000 (16:59 +0100)
gst-libs/gst/rtsp/gstrtsprange.c
gst-libs/gst/rtsp/gstrtsprange.h
tests/check/libs/rtsp.c

index 3c914c9..4487729 100644 (file)
@@ -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);
index 9d86686..a1429b0 100644 (file)
@@ -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;
 };
 
 /**
index f9d422e..62b989a 100644 (file)
@@ -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;
 }