aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2010-08-06 22:18:01 +0200
committerMax Kellermann <max@duempel.org>2010-08-31 06:49:06 +0200
commita77506ae215df09ed02c30f39a3be663a3180d5b (patch)
tree3e3bc932f7d78721285a51b7c260576eb323ef91
parented5d297301ad07e1c8f59b25184b4148046c1ebe (diff)
downloadmpd-a77506ae215df09ed02c30f39a3be663a3180d5b.tar.gz
mpd-a77506ae215df09ed02c30f39a3be663a3180d5b.tar.xz
mpd-a77506ae215df09ed02c30f39a3be663a3180d5b.zip
output/httpd: forced flush after 32 kB of input data
Avoid buffer underruns on the streaming client, if the encoder is "too efficient" (e.g. when encoding silence while paused).
Diffstat (limited to '')
-rw-r--r--src/output/httpd_internal.h8
-rw-r--r--src/output/httpd_output_plugin.c15
2 files changed, 23 insertions, 0 deletions
diff --git a/src/output/httpd_internal.h b/src/output/httpd_internal.h
index 55843e73f..14a5cf350 100644
--- a/src/output/httpd_internal.h
+++ b/src/output/httpd_internal.h
@@ -52,6 +52,14 @@ struct httpd_output {
struct encoder *encoder;
/**
+ * Number of bytes which were fed into the encoder, without
+ * ever receiving new output. This is used to estimate
+ * whether MPD should manually flush the encoder, to avoid
+ * buffer underruns in the client.
+ */
+ size_t unflushed_input;
+
+ /**
* The MIME type produced by the #encoder.
*/
const char *content_type;
diff --git a/src/output/httpd_output_plugin.c b/src/output/httpd_output_plugin.c
index 140ea7d82..a71e21604 100644
--- a/src/output/httpd_output_plugin.c
+++ b/src/output/httpd_output_plugin.c
@@ -262,12 +262,22 @@ httpd_output_read_page(struct httpd_output *httpd)
{
size_t size = 0, nbytes;
+ if (httpd->unflushed_input >= 65536) {
+ /* we have fed a lot of input into the encoder, but it
+ didn't give anything back yet - flush now to avoid
+ buffer underruns */
+ encoder_flush(httpd->encoder, NULL);
+ httpd->unflushed_input = 0;
+ }
+
do {
nbytes = encoder_read(httpd->encoder, httpd->buffer + size,
sizeof(httpd->buffer) - size);
if (nbytes == 0)
break;
+ httpd->unflushed_input = 0;
+
size += nbytes;
} while (size < sizeof(httpd->buffer));
@@ -292,6 +302,9 @@ httpd_output_encoder_open(struct httpd_output *httpd,
bytes of encoder output after opening it, because it has to
be sent to every new client */
httpd->header = httpd_output_read_page(httpd);
+
+ httpd->unflushed_input = 0;
+
return true;
}
@@ -451,6 +464,8 @@ httpd_output_encode_and_play(struct httpd_output *httpd,
if (!success)
return false;
+ httpd->unflushed_input += size;
+
httpd_output_encoder_to_clients(httpd);
return true;