rtsp-client: allow sub classes to adjust the seek
authorBranko Subasic <branko@subasic.net>
Mon, 1 Oct 2018 16:51:49 +0000 (18:51 +0200)
committerMathieu Duponchelle <mathieu@centricular.com>
Tue, 4 Jun 2019 12:32:51 +0000 (14:32 +0200)
Adds a new virtual function, adjust_play_mode(), that allows
sub classes to adjust the seek done on the media. The sub class can
modify the values of the the seek flags and the rate.

https://bugzilla.gnome.org/show_bug.cgi?id=754575

gst/rtsp-server/rtsp-client.c
gst/rtsp-server/rtsp-client.h

index 3820189..6f58b37 100644 (file)
@@ -1730,6 +1730,83 @@ make_base_url (GstRTSPClient * client, GstRTSPUrl * url, const gchar * path)
   return result;
 }
 
+static GstRTSPStatusCode
+setup_play_mode (GstRTSPClient * client, GstRTSPContext * ctx,
+    GstRTSPRangeUnit * unit)
+{
+  gchar *str;
+  GstRTSPResult res;
+  GstRTSPTimeRange *range = NULL;
+  gdouble rate = 1.0;
+  GstSeekFlags flags = GST_SEEK_FLAG_NONE;
+  GstRTSPClientClass *klass = GST_RTSP_CLIENT_GET_CLASS (client);
+  GstRTSPStatusCode status;
+
+  /* parse the range header if we have one */
+  res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_RANGE, &str, 0);
+  if (res == GST_RTSP_OK) {
+    gchar *seek_style = NULL;
+
+    res = gst_rtsp_range_parse (str, &range);
+    if (res != GST_RTSP_OK)
+      goto parse_range_failed;
+
+    *unit = range->unit;
+
+    /* parse seek style header, if present */
+    res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_SEEK_STYLE,
+        &seek_style, 0);
+
+    if (res == GST_RTSP_OK) {
+      if (g_strcmp0 (seek_style, "RAP") == 0)
+        flags = GST_SEEK_FLAG_ACCURATE;
+      else if (g_strcmp0 (seek_style, "CoRAP") == 0)
+        flags = GST_SEEK_FLAG_KEY_UNIT;
+      else if (g_strcmp0 (seek_style, "First-Prior") == 0)
+        flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_BEFORE;
+      else if (g_strcmp0 (seek_style, "Next") == 0)
+        flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_AFTER;
+      else
+        GST_FIXME_OBJECT (client, "Add support for seek style %s", seek_style);
+    }
+  }
+
+  /* give the application a chance to tweak range, flags, or rate */
+  if (klass->adjust_play_mode != NULL) {
+    status = klass->adjust_play_mode (client, ctx, &range, &flags, &rate);
+    if (status != GST_RTSP_STS_OK)
+      goto adjust_play_mode_failed;
+  }
+
+  /* now do the seek with the seek options */
+  (void) gst_rtsp_media_seek_full_with_rate (ctx->media, range, flags, rate);
+  if (range != NULL)
+    gst_rtsp_range_free (range);
+
+  if (gst_rtsp_media_get_status (ctx->media) == GST_RTSP_MEDIA_STATUS_ERROR)
+    goto seek_failed;
+
+  return GST_RTSP_STS_OK;
+
+parse_range_failed:
+  {
+    GST_ERROR ("client %p: failed parsing range header", client);
+    return GST_RTSP_STS_BAD_REQUEST;
+  }
+adjust_play_mode_failed:
+  {
+    GST_ERROR ("client %p: sub class returned bad code (%d)", client, status);
+    if (range != NULL)
+      gst_rtsp_range_free (range);
+    return status;
+  }
+seek_failed:
+  {
+    GST_ERROR ("client %p: seek failed", client);
+    return GST_RTSP_STS_SERVICE_UNAVAILABLE;
+  }
+}
+
 static gboolean
 handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
 {
@@ -1740,8 +1817,6 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
   GstRTSPStatusCode code;
   GstRTSPUrl *uri;
   gchar *str;
-  GstRTSPTimeRange *range;
-  GstRTSPResult res;
   GstRTSPState rtspstate;
   GstRTSPRangeUnit unit = GST_RTSP_RANGE_NPT;
   gchar *path, *rtpinfo;
@@ -1799,38 +1874,9 @@ handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
   if (!gst_rtsp_media_unsuspend (media))
     goto unsuspend_failed;
 
-  /* parse the range header if we have one */
-  res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_RANGE, &str, 0);
-  if (res == GST_RTSP_OK) {
-    if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
-      GstRTSPMediaStatus media_status;
-      GstSeekFlags flags = 0;
-
-      if (gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_SEEK_STYLE,
-              &seek_style, 0)) {
-        if (g_strcmp0 (seek_style, "RAP") == 0)
-          flags = GST_SEEK_FLAG_ACCURATE;
-        else if (g_strcmp0 (seek_style, "CoRAP") == 0)
-          flags = GST_SEEK_FLAG_KEY_UNIT;
-        else if (g_strcmp0 (seek_style, "First-Prior") == 0)
-          flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_BEFORE;
-        else if (g_strcmp0 (seek_style, "Next") == 0)
-          flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_AFTER;
-        else
-          GST_FIXME_OBJECT (client, "Add support for seek style %s",
-              seek_style);
-      }
-
-      /* we have a range, seek to the position */
-      unit = range->unit;
-      gst_rtsp_media_seek_full (media, range, flags);
-      gst_rtsp_range_free (range);
-
-      media_status = gst_rtsp_media_get_status (media);
-      if (media_status == GST_RTSP_MEDIA_STATUS_ERROR)
-        goto seek_failed;
-    }
-  }
+  code = setup_play_mode (client, ctx, &unit);
+  if (code != GST_RTSP_STS_OK)
+    goto invalid_mode;
 
   /* grab RTPInfo from the media now */
   rtpinfo = gst_rtsp_session_media_get_rtpinfo (sessmedia);
@@ -1918,10 +1964,10 @@ unsuspend_failed:
     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
     return FALSE;
   }
-seek_failed:
+invalid_mode:
   {
     GST_ERROR ("client %p: seek failed", client);
-    send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
+    send_generic_response (client, code, ctx);
     return FALSE;
   }
 unsupported_mode:
index 8dbc3dd..2e47203 100644 (file)
@@ -107,6 +107,9 @@ struct _GstRTSPClient {
  *    RTSP response(ctx->response) via a call to gst_rtsp_message_init_response()
  * @params_get: get parameters. This function should also initialize the
  *    RTSP response(ctx->response) via a call to gst_rtsp_message_init_response()
+ * @make_path_from_uri: called to create path from uri.
+ * @adjust_play_mode: called to give the application the possibility to adjust
+ *    the range, seek flags, and/or rate. Since 1.18
  * @tunnel_http_response: called when a response to the GET request is about to
  *   be sent for a tunneled connection. The response can be modified. Since: 1.4
  *
@@ -125,7 +128,11 @@ struct _GstRTSPClientClass {
   GstRTSPResult   (*params_set) (GstRTSPClient *client, GstRTSPContext *ctx);
   GstRTSPResult   (*params_get) (GstRTSPClient *client, GstRTSPContext *ctx);
   gchar *         (*make_path_from_uri) (GstRTSPClient *client, const GstRTSPUrl *uri);
-
+  GstRTSPStatusCode (*adjust_play_mode) (GstRTSPClient * client,
+                                         GstRTSPContext * context,
+                                         GstRTSPTimeRange ** range,
+                                         GstSeekFlags * flags,
+                                         gdouble * rate);
   /* signals */
   void     (*closed)                  (GstRTSPClient *client);
   void     (*new_session)             (GstRTSPClient *client, GstRTSPSession *session);
@@ -162,7 +169,7 @@ struct _GstRTSPClientClass {
   GstRTSPStatusCode (*pre_record_request)        (GstRTSPClient *client, GstRTSPContext *ctx);
 
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING_LARGE-16];
+  gpointer _gst_reserved[GST_PADDING_LARGE-17];
 };
 
 GST_RTSP_SERVER_API