mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
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:
parent
9337a293e1
commit
dd36e4cd0e
1 changed files with 54 additions and 4 deletions
|
@ -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). */
|
||||||
|
|
Loading…
Reference in a new issue