Here's the basic run-down of difficulties:
- PHP buffers output to the client and this keeps you from doing continuous streams of data easily
- PHP doesn't allow you to send headers after it thinks the headers have already been sent
- Apache has some other handlers that also cause buffering
- Apache does some client negotiation that conflicts with MJPEG (mod_gzip)
Searching the Eentarnets did not produce good results on how to handle this. At least, not in a single place and easily findable. So here's my solution for others to use:
<?
# Used to separate multipart
$boundary = "my_mjpeg";
# We start with the standard headers. PHP allows us this much
header("Cache-Control: no-cache");
header("Cache-Control: private");
header("Pragma: no-cache");
header("Content-type: multipart/x-mixed-replace; boundary=$boundary");
# From here out, we no longer expect to be able to use the header() function
print "--$boundary\n";
# Set this so PHP doesn't timeout during a long stream
set_time_limit(0);
# Disable Apache and PHP's compression of output to the client
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
# Set implicit flush, and flush all current buffers
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++)
ob_end_flush();
ob_implicit_flush(1);
# The loop, producing one jpeg frame per iteration
while (true) {
# Per-image header, note the two new-lines
print "Content-type: image/jpeg\n\n";
# Your function to get one jpeg image
print get_one_jpeg();
# The separator
print "--$boundary\n";
}
?>
That's it in a nutshell. Make sure that your PHP script does not contain any newlines or data before or after the PHP enclosures (<? ... ?>).