mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 03:29:50 +00:00
rtsp-client: allow sub classes to adjust the seek
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
This commit is contained in:
parent
421ac85150
commit
65d9aa327c
2 changed files with 91 additions and 38 deletions
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue