CptSkripto has asked for the wisdom of the Perl Monks concerning the following question:

Dear PerlMonks, I am in need of capturing/grabbing frames via the aforementioned module. Unfortunately by running the following code:
#!/usr/bin/perl use strict; use Video::Capture::V4l; my $grab = new Video::Capture::V4l("/dev/video0") or die "Unable to op +en Video device: $!"; print "silent error:$!\n"; $grab->sync(0) or die "unable to sync: $!\n"; #
I obtain:
silent error: Illegal seek unable to sync: Invalid argument
That suggests v4l cannot lock and sync the frame 0. I have tested, successfully, my video input via mplayer through the following command:
mplayer -tv device=/dev/video0:input=2:driver=v4l2:width=320:height=24 +0:norm=ntsc:adevice=/dev/dsp tv://1 -zoom -aspect 4:3
This suggests I have to find a way to pass the -tv and the tv://1 options through Video::Capture::V4l. Do you happen to know how to do this? Thank you again in advance, CptSkripto

Replies are listed 'Best First'.
Re: Video::Capture::V4l tv parameters.
by zentara (Cardinal) on Sep 04, 2008 at 18:34 UTC
    You need to initialize the camera, and for some reason (possibly interlacing) you need to grab 2. This is a Tk gui to take a picture, notice you must initialize properly, and it's complicated by the use of the term "Channel", it's not what you think. See the grab script mentioned above for grabinfo for your setup.
    #!/usr/bin/perl use warnings; use strict; use Video::Capture::V4l; use Imager; use Tk; use Tk::JPEG; use MIME::Base64; my $timestamp; my $temp = ''; sub grab_one { $temp = ''; $timestamp = scalar(localtime); $timestamp =~ tr/ /_/; $| = 1; my $grab = new Video::Capture::V4l or die "Unable to open Videodevice: $!"; # the following initializes the camera for NTSC my $channel = $grab->channel(1); #1 is composite 0 is for tuner my $tuner = $grab->tuner(0); $tuner->mode(1); $channel->norm(1); $tuner->set; $channel->set; my $frame = 0; my $fr = $grab->capture( $frame, 320, 240 ); my $count = 0; for ( 0 .. 1 ) { my $nfr = $grab->capture( 1 - $frame, 320, 240 ); $grab->sync($frame) or die "unable to sync"; unless ( $count == 0 ) { # save $fr now, as it contains the raw BGR data $temp = ''; open( JP, '>', \$temp ) or die $!; print JP "P6\n320 240\n255\n"; #header $nfr = reverse $nfr; print JP $nfr; close JP; my $img = Imager->new(); $img->read( data => $temp, type => 'pnm' ) or warn $img->errstr(); $img->flip( dir => "hv" ); $img->write( data => \$temp, type => 'jpeg' ) or warn $img->errstr; } $count++; $frame = 1 - $frame; $fr = $nfr; } } grab_one(); my $mw = MainWindow->new(); my $image = $mw->Photo( -data => encode_base64($temp) ); $mw->Label( -image => $image )->pack( -expand => 1, -fill => 'both' ); my $label = $mw->Label( -text => $timestamp )->pack( -side => 'top', -padx => 3 +); my $center = $mw->Frame->pack( -anchor => 'center' ); $center->Button( -text => 'Quit', -command => [ destroy => $mw ] ) ->pack( -side => 'left', -padx => 3 ); $center->Button( -text => 'Update', -command => \&update ) ->pack( -side => 'left', -padx => 3 ); $center->Button( -text => 'Save', -command => \&save_it ) ->pack( -side => 'left', -padx => 3 ); MainLoop; sub save_it { open( JP, "> $timestamp.jpg" ) or die $!; print JP $temp; close JP; $label->configure( -text => "$timestamp.jpg SAVED" ); $label->update; } sub update { grab_one(); $label->configure( -text => "$timestamp" ); $label->update; $image->configure( -data => encode_base64($temp) ); $image->update; $mw->update; }

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      Zentara, I apologize for my thickness, could you please elaborate on the "...and for some reason (possibly interlacing) you need to grab 2..."? Does it mean I have to save two frames at a time? TIA CptSkripto
        Look at the grab_one sub, and the for(0..1){...}

        To be honest, I don't fully understand why, but without that, the picture won't sync. I translated the code from a V4l2 code I saw, I think it was in c IIRC. The other thing you will notice, is that the picture comes out BGR, instead of RGB, and it is flipped vertically. Luckily, you can just reverse the data, and it comes out OK, then use Imager to flip it upright.

        The reason why I suspect it needs 2 (and why I guess it's due to interlacing) is the way NTSC video works. It is sent as 2 frames(called odd and even). This was originally done to reduce flicker, as it essentially doubles the refresh rate.

        <guess_hat_on>

        So think what happens when you try to grab a picture. You may be intercepting the video stream at any point in a frame, so you need to latch on to it first, and wait for the sync signal, which resets to the upper left corner, then start the grab on the next frame.

        I'm guessing this won't be a problem with pure digital cameras, but NTSC cameras need it. I see from your grabinfo, that your camera supports pal, ntsc and secam.....those are the basic old analog video formats used in Europe, the US, and S. America.


        I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Video::Capture::V4l tv parameters.
by shmem (Chancellor) on Sep 04, 2008 at 17:24 UTC

    There's a grab script in the module's example directory. Tried that?

      Indeed I have attempted to use the grab and unfortunately it shows the same problem in syncing.
      [root@localhost examples]# ./grab Device: name Unknown EM2800 video grabber, type capture tuner, channel +s 2, audios 0, sizes 48x32-360x576 Channel 0: name Composite1, tuners 0, flags, type camera, norm 0 Channel 0: name Composite1, tuners 0, flags, type camera, norm 0 Tuner 0: name Tuner, range 0-0, flags pal ntsc secam, mode 0, signal 0 Picture Settings: brightness 0, hue 0, colour 0, contrast 0, whiteness + 0, depth 16, palette 8 196250 .unable to sync at ./grab line 121. [root@localhost examples]#
      CptSkripto