Updated 2005-10-05 19:03:50 by btheado

Brian Theado - 01Jan04 - After writing the babbleback machine program, my daughter begged me daily for more than a month to play. Her interest is finally starting to wane. She still enjoys playing with it if I turn it on. Along the way, I got the idea of making a video camera version of the same program. I have a digital camera with Firewire (aka iLink, aka IEEE1394) connectivity. I searched to no avail for a program or set of programs that would make doing this easy on Microsoft Windows.

I turned my search to Linux and hit the jackpot. Linux has a command-line program called dvgrab [1] that makes it simple to capture data from a digital video camera. A program called xine [2] will playback video files. Tcl is a great language to glue the two applications together.

Update 05Oct05

I just discovered that dvgrab allows the number of buffered frames to be specified. This option obsoletes all of the code below. Now having continuous "instant" replay with your firewire video camera is a one-liner:
 dvgrab --format raw --buffers 400 - | xine --fullscreen --hide-gui stdin://#demux:rawdv

Increase or decrease the buffers parameter to have longer or shorter delays.

Update 16Sep04

My now three-year-old daughter still loves playing with this game. She asks for it on a weekly basis.

My first version of this (see bottom of the page) stored the video in avi files. Every period, a new avi file was created and the old one was sent to xine for playback. At the moment of swapping files, there was a slight jump in the playback.

Newer versions of dvgrab and xine support streaming raw dv formatted data via stdout and stdin and I rewrote the code to take advantage of these features. With no file switching to deal with, the playback discontinuity has disappeared. In order to insert a delay in data stream, I make use of fifo channels from the memchan package.

One disadvantage of the new version over the old version is that is uses RAM to buffer the memory instead of files on disk. For me, since I run this in Knoppix which uses a ramdisk for the home directory, it is no change.

One advantage of the new version is that only one line of code is specific to using dvgrab/firewire and xine. Change that line of code and the same continuous-playback-with-delay can work for other media streams such as USB webcams.

I'd love to see this program work using a cheap webcam or on a Windows platform. If anyone knows how to do this, then please let me know.

I'm using dvgrab 1.5 and libxine-1-rc5-1/xine-ui-0.99.1-1 from Knoppix 3.6-2004-08-16 to run this script.

Version 2 - stream based
 # fcopy completion callback
 proc copyComplete {fd1 fd2 args} {
    puts "Copy complete: $fd1 $fd2 $args"
    close $fd2
    set ::copyComplete$fd2 1
 }

 # Read data from file1 and buffer it for delay milliseconds and then start copying
 # to file2
 proc bufferingFifoWithDelay {file1 file2 delay} {
    package require Memchan

    # Open the in memory fifo channels and the input file
    set fifos [fifo2]
    set input [open $file1]
    foreach f [concat $fifos $input] {fconfigure $f -translation binary}

    # Initiate asynchronous copying of data from input into one side of the fifo
    fcopy $input [lindex $fifos 0] -command [list copyComplete $input [lindex $fifos 0]]

    # Open the output file and after a delay start copying from the other end of
    # the fifo into the output file
    set output [open $file2 w]
    fconfigure $output -translation binary
    after $delay "fcopy [lindex $fifos 1] $output -command [list [list copyComplete [lindex $fifos 1] $output]]"
    return [concat $input $fifos $output]
 }

 # Default delay is 5000 ms and can be overridden on the command-line
 if {[llength $argv] == 0} {
    set delay 5000
 } else {
    set delay [lindex $argv 0]
 }

 # The "-" causes dvgrab to not save to an avi file and it automatically
 # spews rawdv to stdout if someone is reading stdout
 set fds [bufferingFifoWithDelay "|sudo dvgrab -" "|xine --fullscreen --hide-gui stdin://#demux:rawdv" $delay]

 # Enter the event loop
 vwait copyComplete[lindex $fds end]

Version 1 - file swapping based

Note: this code only workds with versions of dvgrab older than 1.3 as the newer versions of dvgrab have a differnt stdout messages format.

Here's the sourcecode for the script
 #!/usr/bin/tclsh
 proc queueFile dv {
    # Read the line of output from dvgrab and extract the filename
    set line [gets $dv]
    puts $line
    regexp {(.+):} $line -> file

    # Queue the file for playback using the existing xine session
    exec xine -S mrl=$file

    # Delete the file when it is done playing (hopefully it will be done)
    variable delay
    after [expr ($delay * 1000) + 100] [list file delete $file]
 }
 # Launch xine
    set xinePid [exec xine --hide-gui &]
 # Launch dvgrab.  Configure it to split off a new file every $delay seconds
    set delay 2
    set framesPerSecond 30 ;# NTSC format
    set framesToGrab [expr $delay *  $framesPerSecond]
    set dv [open "|dvgrab --frames $framesToGrab --format dv2  --autosplit cinemaback"]

 # dvgrab outputs a line with the file name each time it splits off a new file
    fileevent $dv readable [list queueFile $dv]
    vwait forever

If you don't have Linux installed and you want to try this script out, then check out Knoppix (http://www.knoppix.org). It is a live CD distribution of Linux that will run directly from a CD with no installation necessary. Just download the iso image and burn it to a CD. It comes with firewire drivers, dvgrab, and xine all pre-installed.

Knoppix 3.2 from June 2003 comes with a compatible version of dvgrab.

To activate the firewire drivers, just execute:
 sudo insmod ieee1394
 sudo insmod ohci1394
 sudo insmod raw1394

Camera idiosyncrasies: My camera is a Panasonic PV-DV202 and I found that if it has a tape in it and it isn't recording, then it shuts off after a few minutes. It doesn't seem to recognize that data is being sent across the firewire cable. I work around this by removing the tape.

[ Category Graphics | Category Image Processing | Category Multimedia ]