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 [L1 ] that makes it simple to capture data from a digital video camera. A program called xine [L2 ] 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 ]