This is the hack I made to discard a couple of frames after a camera switch when one BT8x8 chip is being used for multiple cameras at a resolution that means the images are interlaced. I noticed, when using a large image (768x576 PAL) that sometimes the image appeared to have the odd and even half-frames swapped as seen in the first small snippet rather than in the correct order as seen in the second. It seemed to be a side-effect of the switching, so I used this patch to discard a couple of frames after a switch. The end result is that I now always (seem to) be getting good images, though the maximum possible frame rate is reduced significantly (to about 3fps for two cameras on one chip). For me, with clarity and resolution being more important than frame-rate (for now) it's an acceptable compromise, but it wouldn't do for everybody.
Code: Select all
--- zm_local_camera.cpp.orig Wed Mar 17 10:26:17 2004
+++ zm_local_camera.cpp Fri Apr 16 12:57:46 2004
@@ -29,6 +29,7 @@
int LocalCamera::camera_count = 0;
int LocalCamera::m_cap_frame = 0;
+int LocalCamera::m_cap_frame_active = 0;
int LocalCamera::m_sync_frame = 0;
video_mbuf LocalCamera::m_vmb;
video_mmap *LocalCamera::m_vmm;
@@ -80,11 +81,13 @@
Debug( 1, ( "Old Y:%d", vid_win.y ));
Debug( 1, ( "Old W:%d", vid_win.width ));
Debug( 1, ( "Old H:%d", vid_win.height ));
+ Debug(1, ( "Old Fl:%x", vid_win.flags ));
vid_win.x = 0;
vid_win.y = 0;
vid_win.width = width;
vid_win.height = height;
+ vid_win.flags = 0;
if ( ioctl( m_videohandle, VIDIOCSWIN, &vid_win ) < 0 )
{
@@ -187,6 +190,7 @@
Debug( 1, ( "New Y:%d", vid_win.y ));
Debug( 1, ( "New W:%d", vid_win.width ));
Debug( 1, ( "New H:%d", vid_win.height ));
+ Debug(1, ( "New Fl:%x", vid_win.flags ));
if ( ioctl( m_videohandle, VIDIOCGPICT, &vid_pic) < 0 )
{
@@ -530,6 +534,13 @@
{
//Info(( "Switching" ));
struct video_channel vid_src;
+ memset( &vid_src, 0, sizeof(vid_src) );
+ vid_src.channel = channel;
+ if ( ioctl( m_videohandle, VIDIOCGCHAN, &vid_src) < 0 )
+ {
+ Error(( "Failed to get camera source %d: %s", channel, strerror(errno) ));
+ return(-1);
+ }
vid_src.channel = channel;
vid_src.norm = format;
@@ -541,9 +552,10 @@
return( -1 );
}
}
- if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame] ) < 0 )
+ m_cap_frame_active = m_cap_frame;
+ if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
{
- Error(( "Capture failure for frame %d: %s", m_cap_frame, strerror(errno)));
+ Error(( "Capture failure for frame %d: %s", m_cap_frame_active, strerror(errno)));
return( -1 );
}
m_cap_frame = (m_cap_frame+1)%m_vmb.frames;
@@ -553,12 +565,26 @@
int LocalCamera::PostCapture( Image &image )
{
//Info(( "%s: Capturing image", id ));
-
- if ( ioctl( m_videohandle, VIDIOCSYNC, &m_sync_frame ) )
+ int lag_reduce = 1;
+ if ( camera_count > 1 ) lag_reduce = 3;
+ while (lag_reduce)
{
- Error(( "Sync failure for frame %d: %s", m_sync_frame, strerror(errno)));
+ if ( ioctl( m_videohandle, VIDIOCSYNC, &m_sync_frame ) < 0 )
+ {
+ Error(( "Sync failure for frame %d buffer %d(%d): %s", m_sync_frame, m_cap_frame_active, lag_reduce, strerror(errno)));
return( -1 );
}
+ lag_reduce--;
+ if (lag_reduce)
+ {
+ if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
+ {
+ Error(( "Capture failure for buffer %d(%d): %s", m_cap_frame_active, lag_reduce, strerror(errno)));
+ return( -1 );
+ }
+ }
+ }
+ //Info(( "Captured %d for %d into %d", m_sync_frame, channel, m_cap_frame_active));
unsigned char *buffer = m_buffer+(m_sync_frame*m_vmb.size/m_vmb.frames);
m_sync_frame = (m_sync_frame+1)%m_vmb.frames;
--- zm_local_camera.h.orig Sun Feb 15 19:53:10 2004
+++ zm_local_camera.h Wed Apr 7 13:33:56 2004
@@ -39,6 +39,7 @@
protected:
static int m_cap_frame;
+ static int m_cap_frame_active;
static int m_sync_frame;
static video_mbuf m_vmb;
static video_mmap *m_vmm;