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

index 76701fa..3c914c9 100644 (file)
@@ -132,16 +132,62 @@ done:
   return res;
 }
 
+
 static GstRTSPResult
 parse_clock_range (const gchar * str, GstRTSPTimeRange * range)
 {
   return GST_RTSP_ENOTIMPL;
 }
 
+/* smpte-time   =   1*2DIGIT ":" 1*2DIGIT ":" 1*2DIGIT [ ":" 1*2DIGIT ]
+ *                     [ "." 1*2DIGIT ]
+ *  hours:minutes:seconds:frames.subframes
+*/
+static GstRTSPResult
+parse_smpte_time (const gchar * str, GstRTSPTime * time, const gchar * limit)
+{
+  gint hours, mins, secs;
+
+  if (str[0] == '\0') {
+    time->type = GST_RTSP_TIME_END;
+    return GST_RTSP_OK;
+  } else {
+    if (sscanf (str, "%02d:%2d:%02d", &hours, &mins, &secs) != 3)
+      return GST_RTSP_EINVAL;
+
+    time->type = GST_RTSP_TIME_FRAMES;
+    time->seconds = ((hours * 60) + mins) * 60 + secs;
+    str = strchr (str, ':');
+    str = strchr (str + 1, ':');
+    str = strchr (str + 1, ':');
+    if (str && (limit == NULL || str < limit))
+      time->frames = gst_strtod (str + 1);
+  }
+  return GST_RTSP_OK;
+}
+
+/* smpte-range  =   smpte-type "=" smpte-time "-" [ smpte-time ]
+ */
 static GstRTSPResult
 parse_smpte_range (const gchar * str, GstRTSPTimeRange * range)
 {
-  return GST_RTSP_ENOTIMPL;
+  GstRTSPResult res;
+  gchar *p;
+
+  range->unit = GST_RTSP_RANGE_SMPTE;
+
+  /* find '-' separator, can't have a single - */
+  p = strstr (str, "-");
+  if (p == NULL || p == str)
+    return GST_RTSP_EINVAL;
+
+  if ((res = parse_smpte_time (str, &range->min, p)) != GST_RTSP_OK)
+    goto done;
+
+  res = parse_smpte_time (p + 1, &range->max, NULL);
+
+done:
+  return res;
 }
 
 /**
index 5e6034c..9d86686 100644 (file)
@@ -76,25 +76,30 @@ typedef struct _GstRTSPTime GstRTSPTime;
  * @GST_RTSP_TIME_SECONDS: seconds
  * @GST_RTSP_TIME_NOW: now
  * @GST_RTSP_TIME_END: end
+ * @GST_RTSP_TIME_FRAMES: frames and subframes
  *
  * Possible time types.
  */
 typedef enum {
   GST_RTSP_TIME_SECONDS,
   GST_RTSP_TIME_NOW,
-  GST_RTSP_TIME_END
+  GST_RTSP_TIME_END,
+  GST_RTSP_TIME_FRAMES
 } GstRTSPTimeType;
 
 /**
  * GstRTSPTime:
  * @type: the time of the time
- * @seconds: seconds when @type is GST_RTSP_TIME_SECONDS
+ * @seconds: seconds when @type is GST_RTSP_TIME_SECONDS and
+ *           GST_RTSP_TIME_FRAMES
+ * @frames: frames and subframes when @type is GST_RTSP_TIME_FRAMES
  *
  * A time indication.
  */
 struct _GstRTSPTime {
   GstRTSPTimeType type;
   gdouble         seconds;
+  gdouble         frames;
 };
 
 /**
index faed017..f9d422e 100644 (file)
@@ -199,10 +199,60 @@ GST_START_TEST (test_rtsp_range_npt)
   fail_unless (range->max.type == GST_RTSP_TIME_SECONDS);
   fail_unless (range->max.seconds == 15.001);
   gst_rtsp_range_free (range);
+
+  fail_unless (gst_rtsp_range_parse ("npt=20:34.23-",
+          &range) == GST_RTSP_EINVAL);
+  fail_unless (gst_rtsp_range_parse ("npt=10:20;34.23-",
+          &range) == GST_RTSP_EINVAL);
+  fail_unless (gst_rtsp_range_parse ("npt=0:4.23-", &range) == GST_RTSP_EINVAL);
+
+  fail_unless (gst_rtsp_range_parse ("npt=20:12:34.23-21:45:00.01",
+          &range) == GST_RTSP_OK);
+  fail_unless (range->unit == GST_RTSP_RANGE_NPT);
+  fail_unless (range->min.type == GST_RTSP_TIME_SECONDS);
+  fail_unless (range->min.seconds == 72754.23);
+  fail_unless (range->max.type == GST_RTSP_TIME_SECONDS);
+  fail_unless (range->max.seconds == 78300.01);
+  gst_rtsp_range_free (range);
 }
 
 GST_END_TEST;
 
+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=-", &range) == GST_RTSP_EINVAL);
+  fail_unless (gst_rtsp_range_parse ("smpte=-12:09:34",
+          &range) == GST_RTSP_EINVAL);
+  fail_unless (gst_rtsp_range_parse ("smpte=12:09:34",
+          &range) == GST_RTSP_EINVAL);
+
+  fail_unless (gst_rtsp_range_parse ("smpte=00:00:00-", &range) == GST_RTSP_OK);
+  fail_unless (range->unit == GST_RTSP_RANGE_SMPTE);
+  fail_unless (range->min.type == GST_RTSP_TIME_FRAMES);
+  fail_unless (range->min.seconds == 0.0);
+  fail_unless (range->min.frames == 0.0);
+  fail_unless (range->max.type == GST_RTSP_TIME_END);
+  gst_rtsp_range_free (range);
+
+  fail_unless (gst_rtsp_range_parse ("smpte=10:34:23-20:12:09:20.89",
+          &range) == GST_RTSP_OK);
+  fail_unless (range->unit == GST_RTSP_RANGE_SMPTE);
+  fail_unless (range->min.type == GST_RTSP_TIME_FRAMES);
+  fail_unless (range->min.seconds == 38063.0);
+  fail_unless (range->min.frames == 0.0);
+  fail_unless (range->max.type == GST_RTSP_TIME_FRAMES);
+  fail_unless (range->max.seconds == 72729.0);
+  fail_unless (range->max.frames == 20.89);
+  gst_rtsp_range_free (range);
+}
+
+GST_END_TEST;
+
+
 static Suite *
 rtsp_suite (void)
 {
@@ -215,6 +265,7 @@ rtsp_suite (void)
   tcase_add_test (tc_chain, test_rtsp_url_components_2);
   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);
 
   return s;
 }