If you’ve read my big post on the Zoneminder configuration I have at home, you’ll notice that I favored capture of JPEG stills over using MJPEG during initial configuration.

At the time, the reason was simple; I couldn’t make MJPEG work. I’ve now succeed in doing so, and understand why it didn’t work the first time.

Memory Settings

I remembered reading something in the Zoneminder documentation about a shared memory setting resulting in capture at higher resolutions failing. Originally, when I first encountered the problem I decided that it was simply me getting something wrong with the path to the .mjpeg streams on the cameras, since I was more familiar with capture of jpeg stills from prior scripting.

However, I stumbled across some documentation here from another tinkerer, which also pointed to the memory sharing issue.

The problem is that the buffer of frames (usually between 50 and 100 for the camera) must be contained in memory for processing. If the size of the image:

buffer\, size\times image\, width\times image\, height\times3_{for\,24\, bits}+overhead

Exceeds this shared memory maximum, you’ll run into errors or see the camera status go to yellow/orange instead of green. (It can get pretty confusing trying to troubleshoot based on those status colors unless you’re checking the logs… /doh)

In fact, the problem I was seeing was likely directly as a result of the large capture image size of my Axis 207mW, as they cite it directly:

Note that with Megapixel cameras like the Axis 207mw becoming cheaper and more attractive, the above memory settings are not adequate. To get Zoneminder working with a full 1280×1024 resolution camera in full colour, increase 134217728 to, for example, 268424446

/facepalm. I really wish I had come across this the first time around. Either way, you’re going to ultimately run into this problem with either higher framerate connections, color, or higher resolutions.

I followed the tips, here, but doubled them since the machine I’m running ZM has a pretty good chunk of memory available.

The process is simple. You’re going to have to edit /etc/sysctl.conf to include the following somewhere:

# Memory modifications for ZoneMinder (kernel.shmall = 32 MB, kernel.shmmax = 512 MB)
kernel.shmall = 33554432
kernel.shmmax = 536870912

Now, apply the settings with

sysctl -p

Which forces a reload of that file. Next, you can check that the memory parameters have been changed:

brian@brian-desktop:~$ cat /proc/sys/kernel/shmall
brian@brian-desktop:~$ cat /proc/sys/kernel/shmmax

Which is successful. You can also check it with ipcs -l. Now, reboot ZoneMinder and you shouldn’t have any problems.

Motion JPEG Time!

Having made these changes, I was ready to finally explore whether MJPEG works! I went ahead and decided to use the MJPEG streams from my two respective types of cameras in place of the static video links. These are:

Linksys WVC54GCA: http://YOURIPADDY/img/video.mjpeg

Axis 207mW: http://YOURIPADDY/axis-cgi/mjpg/video.cgi?resolution=640×480&clock=0&date=0&text=0

I also discovered (by reading the manual) that there’s a handy utility on the Axis config page (under Live Video Config -> HTML Examples -> Motion JPEG) which generates the proper URL based on a handy configuration tool where you can select size, compression, and other options:

Handy config page

The idle load on the system has increased, as expected, but that’s partly from me raising the FPS limit to 10 which seems reasonable, and enabling continual recording with motion detection (mocord).

Nice, 10 FPS! (still a gaping hole though...)

I’m making a lot of tweaks as I get ready to transition everything onto a VM on a faster computer with much more disk space (on the order of 8 TB). If you’re interested in reading more about the Linux kernel shared memory settings, I found some good documentation:

  • IBM/RedHat settings: here
  • Configuring shared memory: here