aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;