FreeBSD CCTV Setup

A friend of mine recently bought a CCTV card and some cameras after having a serious break in. I decided to have a play with getting his setup to work on FreeBSD, rather than using the crappy Linux live-CD he had been using. Our goal was to record a bunch of cameras to disk, and to share the recording over the network using samba, such that anyone on the network can review the CCTV footage at any time.

The capture card is a massive 32-bit PCI card with 8 BT878 chips (supported by the FreeBSD bktr driver) connected via a pci-pci bridge. I imagine most of the generic cards you can find on eBay have very similar specs, as practically all analog TV tuners use this chipset or a compatible variant.

Kernel configuration

This is exactly the same as setting up an analog TV tuner card. Just add bktr_load="yes" to /boot/loader.conf and reboot. Just loading the module at runtime with kldload doesn't work, because for some reason the bktr driver needs to grab memory early in the boot process.

You should now be able to see bktr[0-n] in /dev. The card I'm using doesn't have any tuners, just a bunch of composite inputs. Don't panic about error messages related to this in dmesg, since it will still work for composite input.

Testing with xawtv

At this point you should install xawtv from ports. Xawtv is a basic application for viewing the output of a TV tuner card. To test bktr 0, you would run xawtv -c /dev/bktr0. After that just click through the welcome screen, right click on the image (or more likely, lack of image), to play with the settings.

The only settings that really matter are the "TV norm", "Video Source" and "Capture" settings. For debugging I would recommend changing capture from overlay to grabdisplay. This prevent xawtv trying to set up direct DMA from the capture card to the video card, which in my experience doesn't work very well at all when you have multiple bktr-s present. After that it is a matter of selecting the "Video source" and "TV norm" to suit your camera and capture card. Ignore the names of the video sources, they are meaningless because you're using a capture card instead of a TV tuner card, so just try a few and see what works. If you get a screen that isn't blue, you've got the right input and just need to adjust the "TV norm" setting to match your camera's output.

At this point you should be able to see the input from your camera. Repeat this process for the other bktr devices if you want to verify all your cameras are working, otherwise skip on to the next section at your own risk.

Mencoder configuration

First of all, you need to work-around a bug in mplayer and mencoder where the bsdbt848 tv input driver has a hard-coded device name... even though the man page indicates that you can specify the bktr device, even if you do this it will always open /dev/bktr0. Sorry I don't have a patch handy, but basically my solution was to hack the mplayer source to use the command-line parameter, though it was an ugly and temporary solution because I couldn't be bothered reading a lot of mplayer source. Hopefully this will be fixed eventually.

The other thing I did was use this CCTV timestamp patch which uses the subtitling mechanisms in mplayer to insert a timestamp into the recording.

First I set up mencoder.conf with some generic options that are used by each camera:

[camera]
profile-desc="Camera shared settings"
tv=driver=bsdbt848:input=1:norm=PAL:fps=12.5
nosound=yes
ovc=xvid=yes
xvidencopts=fixed_quant=2
vf=pp=l5/al/tn,crop=640:480,denoise3d
osd-timestamp-alignment=1
subfont-text-scale=2
subfont-outline=3

Roughly explained:

1. Use the bsdbt848 driver, input number 1, PAL video format, record at 12.5 frames per second (25 is default for PAL, but we use 12.5 because we want to keep file-sizes down. This still gives reasonable video quality.)

2. Don't record any sound (our capture card has audio, but we don't use it)

3. Use "xvid" as the output video codec (works in windows)

4. Use a fixed quantizer of 2 (fairly high quality)

5. video filtering options:

6. put the timestamp overlay in the top left corner

7. make the timestamp font size smaller

8. put a larger black outline around the timestamp

Then I added a separate profile for each individual camera.

[camera0]
profile-desc="Input from bktr0"
profile=camera
tv=device=/dev/bktr0
#osd-timestamp-format="Camera 0 - %Y-%m-%d %H:%M:%S"
osd-timestamp-format="Camera 0 - %Y-%m-%d %H:%M"

This profile is duplicated and modified for each individual camera.

Regarding the timestamps, you can get slightly smaller file-sizes by not overlaying seconds into the recording.

Once mencoder.conf is ready, recording is simply a matter of using: mencoder -profile camera0 -o output.avi tv://

Magic shell-script

Next I wrote a little shell-script to record continuously. It has several aims:

* record to a new file at regular intervals * use appropriate time-stamped filenames * delete video recordings once disk space exceeds a defined threshold

#!/usr/local/bin/bash

# location of mencoder
MENCODER="/path/to/mencoder"

# location of mencoder configuration file
MCONFIG="/path/to/mencoder.conf"

# location of font file
FONT="/path/to/font.ttf"

# which bktr devices to record from
CAMERAS="0 1 2"

# directory to output to (must exist)
OUTPUT="/path/to/video"

# length of each recording (hh:mm:ss)
RECLEN="00:30:00"

# maximum capacity of the drive containing $OUTPUT (in %)
# (oldest file is deleted when this value is exceeded)
MAX_CAPACITY=80

# name of log file
#LOGFILE="/var/log/camera.log"
LOGFILE="/dev/null"

while [ true ];
do
  DATE=`date +%y-%m-%d-%H:%M:%S`
  for CAM in $CAMERAS
  do
    FILE="${OUTPUT}/${DATE}-cam${CAM}.avi"
    $MENCODER -quiet -include $MCONFIG -profile camera$CAM -o $FILE -font $FONT -endpos $RECLEN tv:// 1>/dev/null 2>/dev/null &
    echo Recording $FILE >> $LOGFILE
  done

  wait

  for FILE in `ls ${OUTPUT}/*.avi`
  do
    CAPACITY=`df $OUTPUT | grep -o "[[:digit:]]\{1,3\}%" | grep -o "[[:digit:]]\{1,3\}"`
    if [ $CAPACITY -gt $MAX_CAPACITY ]
    then
      rm -f $FILE
      echo Deleted $FILE >> $LOGFILE
    else
      break
    fi
  done
done

I don't claim to be any expert at shell scripting, so there are probably bugs, so use and modify at your own risk.

This script can be started from /etc/rc.local or from rc.d or from crontab at boot time.

FreeBsdCctv (last edited 2007-04-01 04:38:21 by LukeMacpherson)