souphttpsrc: dynamically adjust blocksize

Update the blocksize depending on how much is obtained from a read
of the input stream. This avoids doing too many reads in small chunks
when larger amounts of data are available and also prevents using
a very large memory area to read a small chunk of data.

https://bugzilla.gnome.org/show_bug.cgi?id=767833
This commit is contained in:
Thiago Santos 2016-06-19 02:08:25 -03:00
parent 75963b47f4
commit 11c61f14bf
2 changed files with 57 additions and 0 deletions

View file

@ -134,6 +134,13 @@ enum
#define DEFAULT_RETRIES 3
#define DEFAULT_SOUP_METHOD NULL
#define GROW_BLOCKSIZE_LIMIT 1
#define GROW_BLOCKSIZE_COUNT 1
#define GROW_BLOCKSIZE_FACTOR 2
#define REDUCE_BLOCKSIZE_LIMIT 0.20
#define REDUCE_BLOCKSIZE_COUNT 2
#define REDUCE_BLOCKSIZE_FACTOR 0.5
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static void gst_soup_http_src_finalize (GObject * gobject);
@ -439,6 +446,9 @@ gst_soup_http_src_reset (GstSoupHTTPSrc * src)
src->content_size = 0;
src->have_body = FALSE;
src->reduce_blocksize_count = 0;
src->increase_blocksize_count = 0;
src->ret = GST_FLOW_OK;
g_cancellable_reset (src->cancellable);
gst_soup_http_src_destroy_input_stream (src);
@ -481,6 +491,7 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src)
src->tls_interaction = DEFAULT_TLS_INTERACTION;
src->max_retries = DEFAULT_RETRIES;
src->method = DEFAULT_SOUP_METHOD;
src->minimum_blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
proxy = g_getenv ("http_proxy");
if (!gst_soup_http_src_set_proxy (src, proxy)) {
GST_WARNING_OBJECT (src,
@ -1457,6 +1468,46 @@ done:
return src->ret;
}
/*
* Check if the bytes_read is above a certain threshold of the blocksize, if
* that happens a few times in a row, increase the blocksize; Do the same in
* the opposite direction to reduce the blocksize.
*/
static void
gst_soup_http_src_check_update_blocksize (GstSoupHTTPSrc * src,
gint64 bytes_read)
{
guint blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
GST_LOG_OBJECT (src, "Checking to update blocksize. Read:%" G_GINT64_FORMAT
" blocksize:%u", bytes_read, blocksize);
if (bytes_read >= blocksize * GROW_BLOCKSIZE_LIMIT) {
src->reduce_blocksize_count = 0;
src->increase_blocksize_count++;
if (src->increase_blocksize_count >= GROW_BLOCKSIZE_COUNT) {
blocksize *= GROW_BLOCKSIZE_FACTOR;
GST_DEBUG_OBJECT (src, "Increased blocksize to %u", blocksize);
gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src), blocksize);
src->increase_blocksize_count = 0;
}
} else if (bytes_read < blocksize * REDUCE_BLOCKSIZE_LIMIT) {
src->reduce_blocksize_count++;
src->increase_blocksize_count = 0;
if (src->reduce_blocksize_count >= REDUCE_BLOCKSIZE_COUNT) {
blocksize *= REDUCE_BLOCKSIZE_FACTOR;
blocksize = MAX (blocksize, src->minimum_blocksize);
GST_DEBUG_OBJECT (src, "Decreased blocksize to %u", blocksize);
gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src), blocksize);
src->reduce_blocksize_count = 0;
}
} else {
src->reduce_blocksize_count = src->increase_blocksize_count = 0;
}
}
static void
gst_soup_http_src_update_position (GstSoupHTTPSrc * src, gint64 bytes_read)
{
@ -1586,6 +1637,8 @@ gst_soup_http_src_read_buffer (GstSoupHTTPSrc * src, GstBuffer ** outbuf)
/* Got some data, reset retry counter */
src->retry_count = 0;
gst_soup_http_src_check_update_blocksize (src, read_bytes);
} else {
gst_buffer_unref (*outbuf);
if (read_bytes < 0) {

View file

@ -94,6 +94,10 @@ struct _GstSoupHTTPSrc {
GMainContext *poll_context;
GSource *poll_source;
gint reduce_blocksize_count;
gint increase_blocksize_count;
guint minimum_blocksize;
/* Shoutcast/icecast metadata extraction handling. */
gboolean iradio_mode;
GstCaps *src_caps;