decodebin2: fix preroll for streams at low bitrates

For streams at low bitrates we need to set a limit in time because the limit
in bytes might not reached too late, sometimes more than 30 seconds.
This limit can only be set if upstream is seekable (see #584104)
Closes #647769
This commit is contained in:
Andoni Morales Alastruey 2011-05-09 22:20:23 +02:00 committed by Sebastian Dröge
parent 9337a293e1
commit dd36e4cd0e

View file

@ -170,6 +170,8 @@ struct _GstDecodeBin
GList *blocked_pads; /* pads that have set to block */ GList *blocked_pads; /* pads that have set to block */
gboolean expose_allstreams; /* Whether to expose unknow type streams or not */ gboolean expose_allstreams; /* Whether to expose unknow type streams or not */
gboolean upstream_seekable; /* if upstream is seekable */
}; };
struct _GstDecodeBinClass struct _GstDecodeBinClass
@ -216,9 +218,10 @@ enum
/* automatic sizes, while prerolling we buffer up to 2MB, we ignore time /* automatic sizes, while prerolling we buffer up to 2MB, we ignore time
* and buffers in this case. */ * and buffers in this case. */
#define AUTO_PREROLL_SIZE_BYTES 2 * 1024 * 1024 #define AUTO_PREROLL_SIZE_BYTES 2 * 1024 * 1024
#define AUTO_PREROLL_SIZE_BUFFERS 0 #define AUTO_PREROLL_SIZE_BUFFERS 0
#define AUTO_PREROLL_SIZE_TIME 0 #define AUTO_PREROLL_NOT_SEEKABLE_SIZE_TIME 0
#define AUTO_PREROLL_SEEKABLE_SIZE_TIME 10 * GST_SECOND
/* whan playing, keep a max of 2MB of data but try to keep the number of buffers /* whan playing, keep a max of 2MB of data but try to keep the number of buffers
* as low as possible (try to aim for 5 buffers) */ * as low as possible (try to aim for 5 buffers) */
@ -2045,6 +2048,48 @@ beach:
return; return;
} }
/* check_upstream_seekable:
*
* Check if upstream is seekable.
*/
static void
check_upstream_seekable (GstDecodeBin * dbin, GstPad * pad)
{
GstQuery *query;
gint64 start = -1, stop = -1;
dbin->upstream_seekable = FALSE;
query = gst_query_new_seeking (GST_FORMAT_BYTES);
if (!gst_pad_peer_query (pad, query)) {
GST_DEBUG_OBJECT (dbin, "seeking query failed");
gst_query_unref (query);
return;
}
gst_query_parse_seeking (query, NULL, &dbin->upstream_seekable,
&start, &stop);
gst_query_unref (query);
/* try harder to query upstream size if we didn't get it the first time */
if (dbin->upstream_seekable && stop == -1) {
GstFormat fmt = GST_FORMAT_BYTES;
GST_DEBUG_OBJECT (dbin, "doing duration query to fix up unset stop");
gst_pad_query_peer_duration (pad, &fmt, &stop);
}
/* if upstream doesn't know the size, it's likely that it's not seekable in
* practice even if it technically may be seekable */
if (dbin->upstream_seekable && (start != 0 || stop <= start)) {
GST_DEBUG_OBJECT (dbin, "seekable but unknown start/stop -> disable");
dbin->upstream_seekable = FALSE;
}
GST_DEBUG_OBJECT (dbin, "upstream seekable: %d", dbin->upstream_seekable);
}
static void static void
type_found (GstElement * typefind, guint probability, type_found (GstElement * typefind, guint probability,
GstCaps * caps, GstDecodeBin * decode_bin) GstCaps * caps, GstDecodeBin * decode_bin)
@ -2073,6 +2118,10 @@ type_found (GstElement * typefind, guint probability,
pad = gst_element_get_static_pad (typefind, "src"); pad = gst_element_get_static_pad (typefind, "src");
sink_pad = gst_element_get_static_pad (typefind, "sink"); sink_pad = gst_element_get_static_pad (typefind, "sink");
/* if upstream is seekable we can safely set a limit in time to the queues so
* that streams at low bitrates can preroll */
check_upstream_seekable (decode_bin, sink_pad);
/* need some lock here to prevent race with shutdown state change /* need some lock here to prevent race with shutdown state change
* which might yank away e.g. decode_chain while building stuff here. * which might yank away e.g. decode_chain while building stuff here.
* In typical cases, STREAM_LOCK is held and handles that, it need not * In typical cases, STREAM_LOCK is held and handles that, it need not
@ -2656,7 +2705,8 @@ decodebin_set_queue_size (GstDecodeBin * dbin, GstElement * multiqueue,
if ((max_buffers = dbin->max_size_buffers) == 0) if ((max_buffers = dbin->max_size_buffers) == 0)
max_buffers = AUTO_PREROLL_SIZE_BUFFERS; max_buffers = AUTO_PREROLL_SIZE_BUFFERS;
if ((max_time = dbin->max_size_time) == 0) if ((max_time = dbin->max_size_time) == 0)
max_time = AUTO_PREROLL_SIZE_TIME; max_time = dbin->upstream_seekable ? AUTO_PREROLL_SEEKABLE_SIZE_TIME :
AUTO_PREROLL_NOT_SEEKABLE_SIZE_TIME;
} else { } else {
/* update runtime limits. At runtime, we try to keep the amount of buffers /* update runtime limits. At runtime, we try to keep the amount of buffers
* in the queues as low as possible (but at least 5 buffers). */ * in the queues as low as possible (but at least 5 buffers). */