rtspsrc: Use the synced buffer mode in auto mode if a clock provider is in the SDP

This commit is contained in:
Sebastian Dröge 2013-11-13 10:23:19 +01:00
parent bc87f39a90
commit 9ae6981578
2 changed files with 74 additions and 32 deletions

View file

@ -2654,6 +2654,55 @@ on_ssrc_active (GObject * session, GObject * source, GstRTSPStream * stream)
stream->id); stream->id);
} }
static void
set_manager_buffer_mode (GstRTSPSrc * src)
{
GObjectClass *klass;
g_return_if_fail (G_IS_OBJECT (src->manager));
klass = G_OBJECT_GET_CLASS (G_OBJECT (src->manager));
if (!g_object_class_find_property (klass, "buffer-mode"))
return;
if (src->buffer_mode != BUFFER_MODE_AUTO) {
g_object_set (src->manager, "buffer-mode", src->buffer_mode, NULL);
return;
}
GST_DEBUG_OBJECT (src,
"auto buffering mode, have clock %" GST_PTR_FORMAT, src->provided_clock);
if (src->provided_clock) {
GstClock *clock = gst_element_get_clock (GST_ELEMENT_CAST (src));
if (clock == src->provided_clock) {
GST_DEBUG_OBJECT (src, "selected synced");
g_object_set (src->manager, "buffer-mode", BUFFER_MODE_SYNCED, NULL);
if (clock)
gst_object_unref (clock);
return;
}
/* Otherwise fall-through and use another buffer mode */
if (clock)
gst_object_unref (clock);
}
GST_DEBUG_OBJECT (src, "auto buffering mode");
if (src->use_buffering) {
GST_DEBUG_OBJECT (src, "selected buffer");
g_object_set (src->manager, "buffer-mode", BUFFER_MODE_BUFFER, NULL);
} else {
GST_DEBUG_OBJECT (src, "selected slave");
g_object_set (src->manager, "buffer-mode", BUFFER_MODE_SLAVE, NULL);
}
}
/* try to get and configure a manager */ /* try to get and configure a manager */
static gboolean static gboolean
gst_rtspsrc_stream_configure_manager (GstRTSPSrc * src, GstRTSPStream * stream, gst_rtspsrc_stream_configure_manager (GstRTSPSrc * src, GstRTSPStream * stream,
@ -2673,6 +2722,9 @@ gst_rtspsrc_stream_configure_manager (GstRTSPSrc * src, GstRTSPStream * stream,
/* configure the manager */ /* configure the manager */
if (src->manager == NULL) { if (src->manager == NULL) {
GObjectClass *klass; GObjectClass *klass;
GstStructure *s;
const gchar *encoding;
gboolean need_slave;
if (!(src->manager = gst_element_factory_make (manager, "manager"))) { if (!(src->manager = gst_element_factory_make (manager, "manager"))) {
/* fallback */ /* fallback */
@ -2716,40 +2768,27 @@ gst_rtspsrc_stream_configure_manager (GstRTSPSrc * src, GstRTSPStream * stream,
NULL); NULL);
} }
if (g_object_class_find_property (klass, "buffer-mode")) { /* buffer mode pauses are handled by adding offsets to buffer times,
if (src->buffer_mode != BUFFER_MODE_AUTO) { * but some depayloaders may have a hard time syncing output times
g_object_set (src->manager, "buffer-mode", src->buffer_mode, NULL); * with such input times, e.g. container ones, most notably ASF */
} else { /* TODO alternatives are having an event that indicates these shifts,
gboolean need_slave; * or having rtsp extensions provide suggestion on buffer mode */
GstStructure *s; need_slave = stream->container;
const gchar *encoding; if (stream->caps && (s = gst_caps_get_structure (stream->caps, 0)) &&
(encoding = gst_structure_get_string (s, "encoding-name")))
/* buffer mode pauses are handled by adding offsets to buffer times, need_slave = need_slave || (strcmp (encoding, "X-ASF-PF") == 0);
* but some depayloaders may have a hard time syncing output times /* valid duration implies not likely live pipeline,
* with such input times, e.g. container ones, most notably ASF */ * so slaving in jitterbuffer does not make much sense
/* TODO alternatives are having an event that indicates these shifts, * (and might mess things up due to bursts) */
* or having rtsp extensions provide suggestion on buffer mode */ if (GST_CLOCK_TIME_IS_VALID (src->segment.duration) &&
need_slave = stream->container; src->segment.duration && !need_slave) {
if (stream->caps && (s = gst_caps_get_structure (stream->caps, 0)) && src->use_buffering = TRUE;
(encoding = gst_structure_get_string (s, "encoding-name"))) } else {
need_slave = need_slave || (strcmp (encoding, "X-ASF-PF") == 0); src->use_buffering = FALSE;
GST_DEBUG_OBJECT (src, "auto buffering mode, need_slave %d",
need_slave);
/* valid duration implies not likely live pipeline,
* so slaving in jitterbuffer does not make much sense
* (and might mess things up due to bursts) */
if (GST_CLOCK_TIME_IS_VALID (src->segment.duration) &&
src->segment.duration && !need_slave) {
GST_DEBUG_OBJECT (src, "selected buffer");
g_object_set (src->manager, "buffer-mode", BUFFER_MODE_BUFFER,
NULL);
} else {
GST_DEBUG_OBJECT (src, "selected slave");
g_object_set (src->manager, "buffer-mode", BUFFER_MODE_SLAVE, NULL);
}
}
} }
set_manager_buffer_mode (src);
/* connect to signals if we did not already do so */ /* connect to signals if we did not already do so */
GST_DEBUG_OBJECT (src, "connect to signals on session manager, stream %p", GST_DEBUG_OBJECT (src, "connect to signals on session manager, stream %p",
stream); stream);
@ -7135,6 +7174,8 @@ gst_rtspsrc_change_state (GstElement * element, GstStateChange transition)
gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_OPEN, 0); gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_OPEN, 0);
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
set_manager_buffer_mode (rtspsrc);
/* fall-through */
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
/* unblock the tcp tasks and make the loop waiting */ /* unblock the tcp tasks and make the loop waiting */
if (gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_WAIT, CMD_LOOP)) { if (gst_rtspsrc_loop_send_cmd (rtspsrc, CMD_WAIT, CMD_LOOP)) {

View file

@ -251,6 +251,7 @@ struct _GstRTSPSrc {
GstElement *manager; GstElement *manager;
gulong manager_sig_id; gulong manager_sig_id;
gulong manager_ptmap_id; gulong manager_ptmap_id;
gboolean use_buffering;
GstRTSPConnInfo conninfo; GstRTSPConnInfo conninfo;