BTTV mmap problems (still)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



I am still having problems with getting mmap to work in a system with a
BT848 card.

The current system works fine on my development system with a USB Webcam
that only supports read(), but on my test system with a BT848 Capture card
that only supports mmap, I'm having problems.

My main problem is that the mmap doesn't seem to be working, it prints out
the output line, but the screen remains black no matter what combination of
resolutions and video sources I use.  I've used XawTV to get an image from
the camera, so I know it works so I assume that the problem is in my code
somehwere, possibly with using the wrong buffers.

I hope someone can help me, thanks in advance

Incidently, it's a Redhat 7.2 running kernel 2.4.7-10, which has the default
kernel version of v4l on it (not v4l2).  I'm loath to modify the kernel as
it might cause problems with a lot of the other custom hardware that is in
this machine, but am willing to give it a try if necessary.

Thanks in Advance.
Michael Spall


My relevant code is as follows (it's c++, so have shown the two methods of
my objects that are important, needless to say I do some checks to make sure
that the VIDEO_CAPS shows that we support mmap).

Before this we have setup SIZE, PAL, MAXY and MAXX, MAXX and MAXY are user
configurable, PAL is the pallette type, currently VIDEO_PALETTE_RGB565.
SIZE = MAXY * MAXX * BYTES, where BYTES is BPP / 8, and BPP is set of this
pallete to 16.
dispaly is a SDL Surface, it's arranged to match the video palette as
closely as possibly, RGB565 for this mode, haven't started on matching other
formats :(


main 
-->
				if (bttv)
				{
					cout << "BTTV cards need mmap, so
try that" << endl;
					// BTTV cards don't handle read()
functions so we mmap
					v.SetMmap(SIZE, PAL, MAXY, MAXX);
				}
	
				// this is our processing loop, hope it
works!
				while (running)
				{
					if (SDL_PollEvent(&event))
					{
						if (event.type==SDL_KEYDOWN)
							running = false;
					};
					// This should now have a buffer
from my webcam, scary huh?  
					// I need to dispaly this somehow, I
hate this stuff
					// guess it's off ot SDL for a quick
and dirty window 
					// to blit onto.
					SDL_LockSurface(display);
					v.GetImage(display->pixels, SIZE);
					SDL_UnlockSurface(display);
					SDL_Flip(display);
				// End of processing Loop
				}
<--
Set Mmap is supposed to deal with initialising the mmap structures, and so
on, This was based on the code that Gontran Fournier very kindly sent me
-->
       struct video_mbuff  memBuffer
       ioctl( fd, VIDIOCGMBUF, memBuffer )

       char *memAdrs
       memAdrs = (char*)mmap( 0, memBuffer.size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0 ); 

   // Update the video_mmap structure array for each frame and start the
capture
   //======================================================================

      struct video_mmap  mappedFrames[memBuffer.frames]
      int i;
      for( i = 0; i < memBuffer.frames; i++ )
      {
         mappedFrames[i].frame  = i;
         mappedFrames[i].width  = width;
         mappedFrames[i].height = height;
         mappedFrames[i].format = palette;
      }

   // Set first frame to be grabbed  (keep a variable containing the next
frame to be grabbed)
   //================================================================

      frameNo = 0;   // This is the frame you will SYNC on

      if( ioctl( fd, VIDIOCMCAPTURE, &(mappedFrames[frameNo]) ) == -1 )
      {
         perror( "ioctl( VIDIOCMCAPTURE )" );
         return -1;
      }
<--          
and here is my take on it.
-->
	void Video::SetMmap(size_t buffer_size, unsigned int format, int h,
int w)
	{
		if (m_valid)
		{
			if (GetCaps()->Supports(VID_TYPE_CAPTURE))
			{
				if
(ioctl(mp_device->Descriptor(),VIDIOCGMBUF, mp_vmb) == 0)
				{
					mp_buffer = mmap(0, mp_vmb->size,
PROT_READ | PROT_WRITE, MAP_SHARED, mp_device->Descriptor(), 0);
					if (mp_buffer != MAP_FAILED)
					{
						for (int i = 0; i <
mp_vmb->frames; i++)
						{
							m_vmm[i].frame = i;
							m_vmm[i].height = h;
							m_vmm[i].width = w;
							m_vmm[i].format =
format;
						}
						if
(ioctl(mp_device->Descriptor(),VIDIOCMCAPTURE, &(m_vmm[0])) == 0)
						{
							m_mmap = true;
							cout << "Setup mmap
OK" << endl;
						} else {
							cout << "could not
start capture with mmap" << endl;
						}
					} else {
						cout << "mmap returned
invalid memory location" << endl;
					}
				} else {
					cout << "Could not get mbuf
structure filled" << endl;
				}
			} else {
				cout << "Device does not support mmap
capture" << endl;
			}
		}
			
	}
<--

Finally my read function, this is supposed ot be a dual usable function, if
the member m_mmap is false then we just do read(), if it is set then we do
mmap to transfer the data.
Currently I am only interested in getting some frame data, I don't want to
buffer multiple frames or anything, os we only ever request frame 0.
There is currenlty an output statement in the read function, that is there
for debugging, it showed me that the read() was blocking but would never
complete on a bttv system.
-->
	void Video::GetImage(void * buffer, size_t buffer_size)
	{
		if (m_valid)
		{
			if (m_mmap)
			{
				// Use mmap to get screen
				cout << "Using mmap Read" << endl;
				// Tell MMAP to sync the device and get a
full frame into mp_buffer
				ioctl(mp_device->Descriptor(),VIDIOCSYNC,0);
				// Copy from buffer to external buffer
				memcpy(mp_buffer,buffer,buffer_size);
				// Now tell it to start getting the next
frame, cos we have got the full frame
	
ioctl(mp_device->Descriptor(),VIDIOCMCAPTURE,&(m_vmm[0]));
			} else {			
				// Standard Read
				cout << "Using Standard Read" << endl;
				read(mp_device->Descriptor(),buffer,
buffer_size);
			}
		}
	}
<--

---
Mib 





[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux