GstRTSPMessage * request, GstRTSPMessage * response, GstRTSPSrc * src);
static gboolean gst_rtspsrc_open (GstRTSPSrc * src);
-static gboolean gst_rtspsrc_play (GstRTSPSrc * src);
+static gboolean gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment);
static gboolean gst_rtspsrc_pause (GstRTSPSrc * src);
static gboolean gst_rtspsrc_close (GstRTSPSrc * src);
gint cmd, i;
GstState state;
GList *walk;
+ GstClock *clock;
+ GstClockTime base_time = -1;
if (flush) {
event = gst_event_new_flush_start ();
GST_DEBUG_OBJECT (src, "stop flush");
cmd = CMD_WAIT;
state = GST_STATE_PLAYING;
+ clock = gst_element_get_clock (GST_ELEMENT_CAST (src));
+ if (clock) {
+ base_time = gst_clock_get_time (clock);
+ gst_object_unref (clock);
+ }
}
gst_rtspsrc_push_event (src, event);
gst_rtspsrc_loop_send_cmd (src, cmd, flush);
for (i = 0; i < 2; i++) {
if (stream->udpsrc[i]) {
+ if (base_time != -1)
+ gst_element_set_base_time (stream->udpsrc[i], base_time);
gst_element_set_state (stream->udpsrc[i], state);
}
}
{
gboolean res;
- /* PLAY will add the range header now. */
src->state = GST_RTSP_STATE_SEEKING;
+ /* PLAY will add the range header now. */
src->need_range = TRUE;
- res = gst_rtspsrc_play (src);
+ res = gst_rtspsrc_play (src, segment);
return res;
}
gboolean flush;
gboolean update;
GstSegment seeksegment = { 0, };
- gint64 last_stop;
if (event) {
GST_DEBUG_OBJECT (src, "doing seek with event");
/* stop flushing state */
gst_rtspsrc_loop_send_cmd (src, CMD_WAIT, FALSE);
- /* save current position */
- last_stop = src->segment.last_stop;
-
- GST_DEBUG_OBJECT (src, "stopped streaming at %" G_GINT64_FORMAT, last_stop);
+ GST_DEBUG_OBJECT (src, "stopped streaming");
/* copy segment, we need this because we still need the old
* segment when we close the current segment. */
src->segment.format, src->segment.last_stop, stop,
src->segment.last_stop);
- /* mark discont if we are going to stream from another position. */
- if (last_stop != src->segment.last_stop) {
- GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
- //src->discont = TRUE;
- }
+ /* mark discont */
+ GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
+
GST_RTSP_STREAM_UNLOCK (src);
return TRUE;
}
static void
-gst_rtspsrc_configure_caps (GstRTSPSrc * src)
+gst_rtspsrc_configure_caps (GstRTSPSrc * src, GstSegment * segment)
{
GList *walk;
guint64 start, stop;
GST_DEBUG_OBJECT (src, "configuring stream caps");
- start = src->segment.last_stop;
- stop = src->segment.duration;
- play_speed = src->segment.rate;
- play_scale = src->segment.applied_rate;
+ start = segment->last_stop;
+ stop = segment->duration;
+ play_speed = segment->rate;
+ play_scale = segment->applied_rate;
for (walk = src->streams; walk; walk = g_list_next (walk)) {
GstRTSPStream *stream = (GstRTSPStream *) walk->data;
stream->caps = caps;
}
}
+ GST_DEBUG_OBJECT (src, "stream %p, caps %" GST_PTR_FORMAT, stream, caps);
}
- if (src->session)
+ if (src->session) {
+ GST_DEBUG_OBJECT (src, "clear session");
g_signal_emit_by_name (src->session, "clear-pt-map", NULL);
+ }
}
static GstFlowReturn
goto open_failed;
/* start playback */
- if (!gst_rtspsrc_play (src))
+ if (!gst_rtspsrc_play (src, &src->segment))
goto play_failed;
done:
}
static void
-gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range)
+gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range,
+ GstSegment * segment)
{
GstRTSPTimeRange *therange;
GST_DEBUG_OBJECT (src, "range: min %" GST_TIME_FORMAT,
GST_TIME_ARGS (seconds));
- gst_segment_set_last_stop (&src->segment, GST_FORMAT_TIME, seconds);
+ gst_segment_set_last_stop (segment, GST_FORMAT_TIME, seconds);
if (therange->max.type == GST_RTSP_TIME_NOW)
seconds = -1;
/* don't change duration with unknown value, we might have a valid value
* there that we want to keep. */
if (seconds != -1)
- gst_segment_set_duration (&src->segment, GST_FORMAT_TIME, seconds);
+ gst_segment_set_duration (segment, GST_FORMAT_TIME, seconds);
} else {
GST_WARNING_OBJECT (src, "could not parse range: '%s'", range);
}
range = gst_sdp_message_get_attribute_val (&sdp, "range");
if (range)
- gst_rtspsrc_parse_range (src, range);
+ gst_rtspsrc_parse_range (src, range, &src->segment);
}
/* create streams */
}
static gboolean
-gst_rtspsrc_play (GstRTSPSrc * src)
+gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment)
{
GstRTSPMessage request = { 0 };
GstRTSPMessage response = { 0 };
goto create_request_failed;
if (src->need_range) {
- if (src->segment.last_stop == 0)
+ if (segment->last_stop == 0)
hval = g_strdup_printf ("npt=0-");
else
hval =
gst_rtspsrc_dup_printf ("npt=%f-",
- ((gdouble) src->segment.last_stop) / GST_SECOND);
+ ((gdouble) segment->last_stop) / GST_SECOND);
gst_rtsp_message_add_header (&request, GST_RTSP_HDR_RANGE, hval);
g_free (hval);
src->need_range = FALSE;
}
- if (src->segment.rate != 1.0) {
- hval = gst_rtspsrc_dup_printf ("%f", src->segment.rate);
+ if (segment->rate != 1.0) {
+ hval = gst_rtspsrc_dup_printf ("%f", segment->rate);
gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SPEED, hval);
g_free (hval);
}
- if (src->segment.applied_rate != 1.0) {
- hval = gst_rtspsrc_dup_printf ("%f", src->segment.applied_rate);
+ if (segment->applied_rate != 1.0) {
+ hval = gst_rtspsrc_dup_printf ("%f", segment->applied_rate);
gst_rtsp_message_add_header (&request, GST_RTSP_HDR_SCALE, hval);
g_free (hval);
}
* Play Time) and should be put in the NEWSEGMENT position field. */
if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_RANGE, &hval,
0) == GST_RTSP_OK)
- gst_rtspsrc_parse_range (src, hval);
+ gst_rtspsrc_parse_range (src, hval, segment);
/* parse Speed header. This is the intended playback rate of the stream
* and should be put in the NEWSEGMENT rate field. */
gfloat fval;
if (gst_rtspsrc_get_float (hval, &fval) > 0)
- src->segment.rate = fval;
+ segment->rate = fval;
} else {
- src->segment.rate = 1.0;
+ segment->rate = 1.0;
}
/* parse Scale header. This is the playback rate as sent by the server
gfloat fval;
if (gst_rtspsrc_get_float (hval, &fval) > 0)
- src->segment.applied_rate = fval;
+ segment->applied_rate = fval;
} else {
- src->segment.applied_rate = 1.0;
+ segment->applied_rate = 1.0;
}
/* parse the RTP-Info header field (if ANY) to get the base seqnum and timestamp
gst_rtsp_message_unset (&response);
/* configure the caps of the streams after we parsed all headers. */
- gst_rtspsrc_configure_caps (src);
+ gst_rtspsrc_configure_caps (src, segment);
/* for interleaved transport, we receive the data on the RTSP connection
* instead of UDP. We start a task to select and read from that connection.
gst_rtsp_connection_flush (rtspsrc->connection, FALSE);
/* FIXME, the server might send UDP packets before we activate the UDP
* ports */
- gst_rtspsrc_play (rtspsrc);
+ gst_rtspsrc_play (rtspsrc, &rtspsrc->segment);
break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
case GST_STATE_CHANGE_PAUSED_TO_READY: