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).
This commit is contained in:
Max Kellermann 2010-08-06 22:18:01 +02:00
parent ed5d297301
commit a77506ae21
2 changed files with 23 additions and 0 deletions

View File

@ -51,6 +51,14 @@ struct httpd_output {
*/ */
struct encoder *encoder; 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. * The MIME type produced by the #encoder.
*/ */

View File

@ -262,12 +262,22 @@ httpd_output_read_page(struct httpd_output *httpd)
{ {
size_t size = 0, nbytes; 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 { do {
nbytes = encoder_read(httpd->encoder, httpd->buffer + size, nbytes = encoder_read(httpd->encoder, httpd->buffer + size,
sizeof(httpd->buffer) - size); sizeof(httpd->buffer) - size);
if (nbytes == 0) if (nbytes == 0)
break; break;
httpd->unflushed_input = 0;
size += nbytes; size += nbytes;
} while (size < sizeof(httpd->buffer)); } 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 bytes of encoder output after opening it, because it has to
be sent to every new client */ be sent to every new client */
httpd->header = httpd_output_read_page(httpd); httpd->header = httpd_output_read_page(httpd);
httpd->unflushed_input = 0;
return true; return true;
} }
@ -451,6 +464,8 @@ httpd_output_encode_and_play(struct httpd_output *httpd,
if (!success) if (!success)
return false; return false;
httpd->unflushed_input += size;
httpd_output_encoder_to_clients(httpd); httpd_output_encoder_to_clients(httpd);
return true; return true;