Using the camera via video for linux ("/dev/video0") via "linux/videodev.h" ?

2,230 views
Skip to first unread message

Mustapha

unread,
Apr 16, 2010, 9:52:09 AM4/16/10
to android-ndk
Hi,

Does someone know how I can use the camera via V4L (video for linux)
via the android ndk? I would like to read the camera's framebuffer
without using Java API (because the camera API is very bugged on my
Motorola Droid). Do you think that is possible?

Thanks in advance,
Mustapha

This my code :

#define TAG "LowLevelActivity"

// Those lines of code work
int fdv;
fdv = open ("/dev/video0", O_RDWR);
if (fdv <= 0)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "open video error");
}
else
{
struct video_capability vcap;
struct video_channel vc;

__android_log_print(ANDROID_LOG_VERBOSE, TAG, "open video success");
if (ioctl (fdv, VIDIOCGCAP, &vcap) < 0)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "Video Capture Device
Error");
}
else
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG "Video Capture Device
Name : %s %ix%i %ix%i", vcap.name, vcap.minwidth,vcap.minwidth,
vcap.maxwidth,vcap.maxheight);
for (i = 0 ; i < vcap.channels ; i++)
{
vc.channel = i;
if(ioctl (fdv, VIDIOCGCHAN, &vc) < 0)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGCHAN Error");
break;
}
else
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "Video Source (%d)
Name : %s\n", i, vc.name);
}
}
}

// Here, I have an "mmap error" message (camerafb = -1)
{
unsigned char * camerafb;
int width = 320;
int height = 240;

camerafb = (unsigned char*)mmap(0, (width * height * 3)/2, PROT_READ,
MAP_SHARED, fdv, 0);
if ((unsigned char *)-1 == (unsigned char *)camerafb)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "mmap error");
}
}

// we check all format (RGB, YUV, ...) => but it doesn't work
{
for (mm.format = 0; mm.format <= 20; mm.format ++)
{
int error = 0;
mm.frame = 0;
mm.height = height; // vcap.minheight
mm.width = width;
//mm.format = VIDEO_PALETTE_YUV420P;

/* Get frame */
if (ioctl(fdv, VIDIOCMCAPTURE, &mm) < 0)
{
error |= 1;
}

/* Wait frame to be completed */
if (ioctl(fdv, VIDIOCSYNC, &mm.frame) < 0)
{
error |= 2;
}

if (!error)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "format OK = %ix%i
%i", mm.width, mm.height, mm.format);
}
}
}

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.

Hans-Werner Hilse

unread,
Apr 16, 2010, 10:04:45 AM4/16/10
to andro...@googlegroups.com
Hi Mustapha,

I didn't do a lot of checking, but just a short hint: There's not
necessarily mmap access for V4L(2) devices. You might need to fallback
to basic "read" access.

Besides that, did you try to set up the video device? I.e. VIDIOCSCHAN,
VIDIOCSPICT, VIDIOCSWIN?

-hwh

On 04/16/2010 03:52 PM, Mustapha wrote:
> Hi,
>
> Does someone know how I can use the camera via V4L (video for linux)
> via the android ndk? I would like to read the camera's framebuffer
> without using Java API (because the camera API is very bugged on my
> Motorola Droid). Do you think that is possible?
>
> Thanks in advance,
> Mustapha
>
> This my code :
>
> #define TAG "LowLevelActivity"
>
> // Those lines of code work
> int fdv;
> fdv = open ("/dev/video0", O_RDWR);
> if (fdv<= 0)
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "open video error");
> }
> else
> {
> struct video_capability vcap;
> struct video_channel vc;
>
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "open video success");
> if (ioctl (fdv, VIDIOCGCAP,&vcap)< 0)
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Video Capture Device
> Error");
> }
> else
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG "Video Capture Device
> Name : %s %ix%i %ix%i", vcap.name, vcap.minwidth,vcap.minwidth,
> vcap.maxwidth,vcap.maxheight);
> for (i = 0 ; i< vcap.channels ; i++)
> {
> vc.channel = i;
> if(ioctl (fdv, VIDIOCGCHAN,&vc)< 0)
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGCHAN Error");
> break;
> }
> else
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "Video Source (%d)
> Name : %s\n", i, vc.name);
> }
> }
> }
>
> // Here, I have an "mmap error" message (camerafb = -1)
> {
> unsigned char * camerafb;
> int width = 320;
> int height = 240;
>
> camerafb = (unsigned char*)mmap(0, (width * height * 3)/2, PROT_READ,
> MAP_SHARED, fdv, 0);
> if ((unsigned char *)-1 == (unsigned char *)camerafb)
> {
> __android_log_print(ANDROID_LOG_VERBOSE, TAG, "mmap error");
> }
> }
>
> // we check all format (RGB, YUV, ...) => but it doesn't work
> {
> for (mm.format = 0; mm.format<= 20; mm.format ++)
> {
> int error = 0;
> mm.frame = 0;
> mm.height = height; // vcap.minheight
> mm.width = width;
> //mm.format = VIDEO_PALETTE_YUV420P;
>
> /* Get frame */
> if (ioctl(fdv, VIDIOCMCAPTURE,&mm)< 0)
> {
> error |= 1;
> }
>
> /* Wait frame to be completed */
> if (ioctl(fdv, VIDIOCSYNC,&mm.frame)< 0)

Mustapha Tachouct

unread,
Apr 16, 2010, 11:08:34 AM4/16/10
to andro...@googlegroups.com
Besides that, did you try to set up the video device? I.e. VIDIOCSCHAN, VIDIOCSPICT, VIDIOCSWIN?
VIDIOCSCHAN, VIDIOCSPICT, VIDIOCSWIN work fine but VIDIOCGFBUF doesn't work.Do you know how VIDIOCGFBUF works?


This is my code :

                    void InitCamera(void)
                    {
                        struct video_picture pict;
                       struct video_channel vc;
                       struct video_window vw;
                       struct video_buffer vb;

                        if (ioctl(fdv, VIDIOCGPICT, &pict) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGPICT error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGPICT %i", pict.palette);
                        }


                        pict.palette = VIDEO_PALETTE_YUV420P;

                        if (ioctl(fdv, VIDIOCSPICT, &pict) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCSPICT error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCSPICT %i", pict.palette);
                        }

                       
                        vc.channel = 0;

                        if (ioctl(fdv, VIDIOCGCHAN, &vc) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGCHAN error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGCHAN ok (is camera = %i)", (vc.type & VIDEO_TYPE_CAMERA) != 0);
                        }

                        if (ioctl(fdv, VIDIOCGWIN, &vw) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGWIN error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGWIN x=%i y=%i w=%i h=%i", vw.x, vw.y, vw.width, vw.height);
                        }                   


                        if (ioctl(fdv, VIDIOCSWIN, &vw) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCSWIN error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCSWIN x=%i y=%i w=%i h=%i", vw.x, vw.y, vw.width, vw.height);
                        }


                       

                        //vb.base = malloc(vw.width * vw.height * 2);

                        memset(&vb,0,sizeof(vb));
                        vb.width = vw.width;
                        vb.height = vw.height;
                        vb.base = malloc (vb.width * vb.height * 4);
                        vb.bytesperline = vb.width;

                        if (ioctl(fdv, VIDIOCGFBUF, &vb) < 0)
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGFBUF error");
                        }
                        else
                        {
                            __android_log_print(ANDROID_LOG_VERBOSE, TAG, "VIDIOCGFBUF ptr=%x bytesperline=%i size=%ix%i", vb.base, vb.bytesperline, vb.width, vb.height);
                        }


                    }

This is the output :

V/LowLevelActivity(11367): VIDIOCGPICT 8
V/LowLevelActivity(11367): VIDIOCSPICT 15
V/LowLevelActivity(11367): VIDIOCGCHAN ok (is camera = 1)
V/LowLevelActivity(11367): VIDIOCGWIN x=0 y=0 w=320 h=240
V/LowLevelActivity(11367): VIDIOCSWIN x=0 y=0 w=320 h=240
V/LowLevelActivity(11367): VIDIOCGFBUF error

Mustapha Tachouct

unread,
Apr 16, 2010, 12:11:13 PM4/16/10
to andro...@googlegroups.com
Hi,

I'm trying to read the camera buffer directy but I have an error. "read" function always returns -1.

Thanks in advance,
Mustapha

This is my code :
int ReadCameraBuffer(int fdv, int unsigned char * camerafb, int w, int h, int bpp)
{
   int n;

   n = read(fdv, camerafb, (w * h * bpp) / 8);
   __android_log_print(ANDROID_LOG_VERBOSE,  TAG , "read %i", n);
  return n;
}

This is the output :
read -1


$ ls -l /dev/video0
crwxrwx---  media             camera           81,       0  2010-04-15 15:24 video0

Hans-Werner Hilse

unread,
Apr 16, 2010, 2:28:14 PM4/16/10
to andro...@googlegroups.com
Hi,

before I continue, in the light of a different thread:

CAVEAT: This is probably highly unsupported terrain, too. AFAICS, the
exakt implementation of video image aquiring is device-specific. So if
you found this thread and are just thinking "hey, I can get the video
this way?" you're probably wrong or on the way to build an app that will
not run on some, maybe many, some time in the future all devices.

-----------------

But I think Mustapha, you know what you're doing.

For a start, read() should set errno if it's failing. So you might want
to check its value when read() fails.

As to why it's failing, that's hard to tell. And here we are leaving
POSIX, which is probably all you can really rely on with Android. After
all, the driver might just not be strictly v4l-conformant, I think
there's nothing that would guarantee that.

I'm not too sure if your bitrate calculations are right, but read()
should at least give some bytes.

In fact my knowlegde of v4l is quite limited, I've never done an
implementation of software using it. So I suggest to look at other
example code, e.g. the mplayer implementation for v4l input (though
mplayer code tends to be quite hackish).

Did you think of reverse engineering -- e.g. using something like
"strace" on the camera process? Might be a faster approach than
try&error.... But it's a sensitive area in terms of law, depending on
legislation.

The VIDIOCGFBUF is supposed to fail if there is no camera framebuffer,
which might well be the case. But then it is mentioned in the v4l specs
that this is a "privileged" ioctl, so you might have to be root, I dunno.

Doug Schaefer

unread,
Apr 16, 2010, 3:28:47 PM4/16/10
to andro...@googlegroups.com
Supported or not, it really is off-topic for this group. I'm wasting a lot of time going through all these messages that aren't related to the NDK and real issues I may run into as a legit NDK user.
Reply all
Reply to author
Forward
0 new messages