Monday, February 17, 2014

Getting Raw image in ARGB format from Camera using BB10 Native API

Recently I was trying to get Raw image from Camera in BB10, I wanted to display image in Unity3D game and process it. I created a Native Plugin to pass image data from native API to Unity3D script.

I will post more about Native plugin creation process in separate post, in this post I will describe process to get camera frame in ARGB format.

Before we begin, we need to request access to Camera by using following statement in bar_descriptor.xml and we also need to link our source to camapi library in Pro file.
<permission>use_camera</permission>
Following code is for initializing the camera, it opens camera, set proper resolution required by application, then set format and lastly starts the view finder with callback function which will be called once we camera frame is ready.

One thing to notice is, We are setting image format to CAMERA_FRAMETYPE_RGB8888 by using camera_set_videovf_property function, so we will receive image data in ARGB format and we will not need to do any conversion from native format to ARGB our self.

#define DELTA(x,y) ((x>y)?(x-y):(y-x))

int initCamera()
{
    //Open camera
    if (camera_open(CAMERA_UNIT_REAR, CAMERA_MODE_RW, &handle)){
        //camera_open fails...
        return -1;
    }

    //Camera_open success...
    unsigned int orientation = 0;
    camera_get_native_orientation(handle, &orientation);

    // going to run a query here to find a 480P 16:9 resolution
    unsigned int num;
    camera_get_video_vf_resolutions(handle, 0, &num, NULL);
    camera_res_t res[num];
    camera_get_video_vf_resolutions(handle, num, &num, res);
    unsigned int best = 0;
    unsigned int i;
    for (i=0; i < num; i++) {
        fprintf(stderr, "Supported resolution: %d x %d\n", res[i].width, res[i].height);
        if ((orientation % 180) == 0) {
            if ((DELTA(res[i].height, 480) <= DELTA(res[best].height, 480)) &&
            (DELTA(res[i].width, 480*16/9) <= DELTA(res[best].width, 480*16/9))) 
            {
                best = i;
            }
        } else {
            if ((DELTA(res[i].width, 480) <= DELTA(res[best].width, 480)) &&
           (DELTA(res[i].height, 480*16/9) <= DELTA(res[best].height, 480*16/9))) 
            {
                best = i;
            }
        }
    }
    fprintf(stderr, "Selecting resolution %d x %d\n", 
            res[best].width, res[best].height);

    // get camera running
    if (camera_set_videovf_property(handle,
            CAMERA_IMGPROP_CREATEWINDOW, 0,
            CAMERA_IMGPROP_FORMAT, CAMERA_FRAMETYPE_RGB8888,
            CAMERA_IMGPROP_FRAMERATE, 30.0,
            // note: using the rotation value corresponding to the native orientation
            // gives the best performance since the output from the sensor will not be
            // passed through a rotation stage on devices that require such a step.
            CAMERA_IMGPROP_ROTATION, (360-orientation) % 360,
            CAMERA_IMGPROP_WIDTH, res[best].width,
            CAMERA_IMGPROP_HEIGHT, res[best].height)) {
        return -1;
    }
    //camera_set_videovf_property done...

    if (camera_start_video_viewfinder(handle, 
        &viewfinder_callback, 
        &status_callback, NULL)) {
        return -1;
    }

    //camera_start_video_viewfinder started...
    return 0;
}
Following function is called by viewfinder once frame is ready. Once you receive callback from viewfinder with image data, you can either show it or process further it by applying some filter and do something with it.
static void viewfinder_callback(camera_handle_t handle,camera_buffer_t* buf,void* arg)
{
    if (buf->frametype != CAMERA_FRAMETYPE_RGB8888) {
        //viewfinder_callback, format not CAMERA_FRAMETYPE_RGB8888");
        return;
    }

    fprintf(stderr,"frame %d(%d) x %d\n",
            buf->framedesc.rgb8888.width,
            buf->framedesc.rgb8888.stride,
            buf->framedesc.rgb8888.height);

    cameraBuffer = buf;
}
Following function is called when viewfinder wanted to deliver error message.
static void status_callback(camera_handle_t handle,
                camera_devstatus_t status,
                uint16_t extra,
                void* arg)
{
    fprintf(stderr, "status notification: %d, %d\n", status, extra);
}
While working on this code, I referred this link, please check out that link as well. Hope this post will be helpful.

No comments:

Post a Comment