MeeGo 1.2 Harmattan Developer Documentation Develop for the Nokia N9



Minimal Example FCam Programs

These examples demonstrate basic API usage. To build them, see the examples subdirectory in the FCam source package.

Note that this page contains only the source code of the examples. To be able to run an FCam application on Nokia N9, a syspart.conf file must always be installed onto the device with the application executable. See the instructions on main page.


Example 1

  • Capture and save a single photograph. Demonstrates Shot, Sensor, and Frame.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

// Select the platform
#include <FCam/N9.h>
namespace Plat = FCam::N9;

/***********************************************************/
/* A program that takes a single shot                      */
/*                                                         */
/* This example is a simple demonstration of the usage of  */
/* the FCam API.                                           */
/***********************************************************/

void errorCheck();

int main(int argc, char **argv) {
    char path[256];
    // Make the image sensor
    Plat::Sensor sensor;
    
    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // Make a new shot
    FCam::Shot shot1;
    shot1.exposure = 66000; // 66 ms exposure
    shot1.gain = 1.0f;      // minimum ISO

    // Specify the output resolution and format, and allocate storage for the resulting image
    shot1.image = FCam::Image(2592, 1968, FCam::UYVY);

    // Order the sensor to capture a shot
    sensor.capture(shot1);

    // Check for errors
    errorCheck();

    assert(sensor.shotsPending() == 1); // There should be exactly one shot

    // Retrieve the frame from the sensor
    FCam::Frame frame = sensor.getFrame();

    // This frame should be the result of the shot we made
    assert(frame.shot().id == shot1.id);

    // This frame should be valid too
    assert(frame.valid());
    assert(frame.image().valid());

    // Save the frame
    snprintf(path, 256, "%s/example1.jpg", getenv("HOME"));
    FCam::saveJPEG(frame, path);

    // Check that the pipeline is empty
    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);

    return 0;
}




void errorCheck() {
    // Make sure FCam is running properly by looking for DriverError
    FCam::Event e;
    while (FCam::getNextEvent(&e, FCam::Event::Error)) {
        printf("Error: %s\n", e.description.c_str());
        if (e.data == FCam::Event::DriverMissingError) {
            printf("example1: FCam can't find its driver. Did you install "
                   "fcam-drivers on your platform, and reboot the device "
                   "after installation?\n");
            exit(1);
        }
        if (e.data == FCam::Event::DriverLockedError) {
            printf("example1: Another FCam program appears to be running "
                   "already. Only one can run at a time.\n");
            exit(1);
        }
    }
}

Example 2

  • Capture and save a flash/no-flash pair. Demonstrates use of a Device, and a Flash Action.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <FCam/N9.h>

#include <linux/videodev2.h>
#include <fcntl.h>
#include <sys/ioctl.h>

// Select the platform
namespace Plat = FCam::N9;

/***********************************************************/
/* Flash / No-flash                                        */
/*                                                         */
/* This example demonstrates capturing multiple shots with */
/* possibly different settings.                            */
/***********************************************************/

int main(int argc, char **argv) {
    // Devices
    Plat::Sensor sensor;
    Plat::Flash flash;
    sensor.attach(&flash); // Attach the flash to the sensor

    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // Make two shots
    std::vector<FCam::Shot> shot(2);

    // Set the first shot parameters (to be done with flash)
    shot[0].exposure = 80000;
    shot[0].gain = 1.0f;
    shot[0].whiteBalance = 3500;
    shot[0].image = FCam::Image(2592, 1968, FCam::UYVY);

    // Set the second shot parameters (to be done without flash)
    shot[1].exposure = 80000;
    shot[1].gain = 1.0f;
    shot[1].whiteBalance = 3500;
    shot[1].image = FCam::Image(2592, 1968, FCam::UYVY);

    // Make an action to fire the flash
    Plat::Flash::FireAction fire(&flash);
    fire.duration = flash.minDuration();          // flash briefly
    fire.time = shot[0].exposure - fire.duration; // at the end of the exposure
    fire.brightness = flash.maxBrightness();      // at full power

    // Attach the action to the first shot
    shot[0].addAction(fire);

    // Order the sensor to capture the two shots
    sensor.capture(shot);
    assert(sensor.shotsPending() == 2);    // There should be exactly two shots

    // Retrieve the first frame
    FCam::Frame frame = sensor.getFrame();
    assert(sensor.shotsPending() == 1);    // There should be one shot pending
    assert(frame.shot().id == shot[0].id); // Check the source of the request

    // Write out file if needed
    if (argc > 1) { FCam::saveJPEG(frame, argv[1]); }

    // Retrieve the second frame
    frame = sensor.getFrame();
    assert(frame.shot().id == shot[1].id); // Check the source of the request

    // Write out file
    FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example2.jpg");

    // Check the pipeline is empty
    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);
}

Example 3

  • Capture a photograph during which the focus ramps from near to far. Demonstrates use of a Device, a Lens Action, and a Tag.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <FCam/N9.h>

// Select the platform
namespace Plat = FCam::N9;

/***********************************************************/
/* Focus sweep                                             */
/*                                                         */
/* This example demonstrates moving the lens during an     */
/* exposure via the use of Lens::FocusAction. It also      */
/* shows how to use the metadata tagged by the devices.    */
/* Because the lens on the N900 zooms slightly when it     */
/* focuses, you'll also get a zoom-blur effect.            */
/***********************************************************/
int main(int argc, char **argv) {

    // Devices
    Plat::Sensor sensor;
    Plat::Lens lens;

    // Attach the lens to the sensor
    sensor.attach(&lens);

    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // First focus near with maximal speed
    lens.setFocus(lens.nearFocus(), lens.maxFocusSpeed());
    while (lens.focusChanging()) { ; } // Wait to be done


    // Now make a shot that will sweep the lens
    FCam::Shot shot1;

    FCam::Lens::FocusAction sweep(&lens);
    // Set the parameters of this action
    sweep.focus = lens.farFocus();
    sweep.speed = lens.maxFocusSpeed();
    // Calculate how long it takes to move the lens to the desired
    // location in microseconds
    float duration = 1000000.0f *
                     (lens.nearFocus() - lens.farFocus()) / sweep.speed;

    printf("The lens will sweep from near to far in %f milliseconds\n",
           duration / 1000.0);

    // 30 ms exposure time
    shot1.exposure = 30000;
    shot1.gain = 1.0f;

    // Perform the sweep at half way through exposure
    sweep.time = (shot1.exposure-duration)/2;

    shot1.image = FCam::Image(2592, 1968, FCam::UYVY);

    // Attach the action to the shot
    shot1.addAction(sweep);

    // Order the sensor to capture the shot
    sensor.capture(shot1);
    assert(sensor.shotsPending() == 1); // There should be exactly one shot

    // Retrieve the frame
    FCam::Frame frame = sensor.getFrame();
    assert(frame.shot().id == shot1.id); // Check the source of the request

    // Print out some metadata
    const FCam::Lens::Tags lensTags(frame);
    printf("Aperture        : %.4f\n", lensTags.aperture);
    printf("Initial focus   : %.4f\n", lensTags.initialFocus);
    printf("Final focus     : %.4f\n", lensTags.finalFocus);

    // Save the resulting file
    FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example3.jpg");

    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);
}

Example 4

  • Stream frames and auto-expose.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <FCam/N9.h>
#include <FCam/AutoExposure.h>
#include <FCam/AutoWhiteBalance.h>

// Select the platform
namespace Plat = FCam::N9;

/***********************************************************/
/* Autoexposure                                            */
/*                                                         */
/* This example shows how to request streams and deal with */
/* the incoming frames, and also uses the provided         */
/* auto-exposure and auto-white-balance routines.          */
/***********************************************************/
int main(int argc, char **argv) {

    // Make a sensor
    Plat::Sensor sensor;

    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // Shot
    FCam::Shot stream1;
    // Set the shot parameters
    stream1.exposure = 33333;
    stream1.gain = 1.0f;

    // We don't bother to set frameTime in this example. It defaults
    // to zero, which the implementation will clamp to the minimum
    // possible value given the exposure time.

    // Request an image size and allocate storage
    stream1.image = FCam::Image(2592, 1968, FCam::UYVY);

    // Enable the histogram unit
    stream1.histogram.enabled = true;
    stream1.histogram.region = FCam::Rect(0, 0, 2592, 1968);

    // We will stream until the exposure stabilizes
    int count = 0;          // # of frames streamed
    int stableCount = 0;    // # of consecutive frames with stable exposure
    float exposure;         // total exposure for the current frame (exposure time * gain)
    float lastExposure = 0; // total exposure for the previous frame

    FCam::Frame frame;

    do {
        // Ask the sensor to stream with the given parameters
        sensor.stream(stream1);

        // Retrieve a frame
        frame = sensor.getFrame();
        assert(frame.shot().id == stream1.id); // Check the source of the request

        printf("Exposure time: %d, gain: %f\n", frame.exposure(), frame.gain());

        // Calculate the total exposure used (including gain)
        exposure = frame.exposure() * frame.gain();

        // Call the autoexposure algorithm. It will update stream1
        // using this frame's histogram.
        autoExpose(&stream1, frame);

        // Call the auto white-balance algorithm. It will similarly
        // update the white balance using the histogram.
        autoWhiteBalance(&stream1, frame);

        // Increment stableCount if the exposure is within 5% of the
        // previous one
        if (fabs(exposure - lastExposure) < 0.05f * lastExposure) {
            stableCount++;
        } else {
            stableCount = 0;
        }

        // Update lastExposure
        lastExposure = exposure;

    } while (stableCount < 5); // Terminate when stable for 5 frames

    // Write out the well-exposed frame
    FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example4.jpg");

    // Order the sensor to stop streaming
    sensor.stopStreaming();
    printf("Processed %d frames until stable for 5 frames!\n", count);

    // There may still be shots in the pipeline. Consume them.
    while (sensor.shotsPending() > 0) { frame = sensor.getFrame(); }

    // Check that the pipeline is empty
    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);
}

Example 5

  • Stream frames, auto-focus, and auto-white-balance.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <FCam/N9.h>
#include <FCam/AutoFocus.h>

// Select the platform
namespace Plat = FCam::N9;

/***********************************************************/
/* Autofocus                                               */
/*                                                         */
/* This example shows how to request streams and deal with */
/* the incoming frames, and also uses the provided         */
/* autofocus routine.                                      */
/***********************************************************/
int main(int argc, char **argv) {

    // Devices
    Plat::Sensor sensor;
    Plat::Lens lens;
    sensor.attach(&lens); // Attach the lens to the sensor

    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // Autofocus supplied by FCam API
    FCam::AutoFocus autoFocus(&lens);

    // Shot
    FCam::Shot stream1;
    // Set the shot parameters
    stream1.exposure = 50000;
    stream1.gain = 1.0f;

    // Request a resolution, and allocate storage
    stream1.image = FCam::Image(2592, 1968, FCam::UYVY);

    // Enable the sharpness unit
    stream1.sharpness.enabled = true;

    // We will stream until the focus stabilizes
    int count = 0;        // # of frames streamed

    // Order the sensor to stream
    sensor.stream(stream1);

    // Ask the autofocus algorithm to start sweeping the lens
    autoFocus.startSweep();

    // Stream until autofocus algorithm completes
    FCam::Frame frame;

    do {
        // Retrieve a frame
        frame = sensor.getFrame();
        assert(frame.shot().id == stream1.id); // Check the source of the request

        // The lens has tagged each frame with where it was focused
        // during that frame. Let's retrieve it so we can print it out.
        float diopters = frame["lens.focus"];
        printf("Lens focused at %2.0f cm\n", 100/diopters);

        // The sensor has attached a sharpness map to each frame.
        // Let's sum up all the values in it so we can print out
        // the total sharpness of this frame.
        int totalSharpness = 0;
        for (int y = 0; y < frame.sharpness().height(); y++) {
            for (int x = 0; x < frame.sharpness().width(); x++) {
                totalSharpness += frame.sharpness()(x, y);
            }
        }
        printf("Total sharpness is %d\n\n", totalSharpness);

        // Call the autofocus algorithm
        autoFocus.update(frame);

        // Increment frame counter
        count++;
    } while (!autoFocus.idle());

    printf("Autofocus chose to focus at %2.0f cm\n\n", 100/lens.getFocus());

    // Write out the focused frame
    FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example5.jpg");

    // Order the sensor to stop streaming
    sensor.stopStreaming();
    printf("Processed %d frames until autofocus completed!\n", count);

    // There may still be shots in the pipeline. Consume them.
    while (sensor.shotsPending() > 0) { frame = sensor.getFrame(); }

    // Check that the pipeline is empty
    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);
}

Example 6

  • Make a noise synchronized to the start of the exposure. Demonstrates making a custom Device, and synchronizing that device's Action with exposure.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <FCam/N9.h>

#include "SoundPlayer.h"
#include <linux/videodev2.h>
#include <fcntl.h>
#include <sys/ioctl.h>

//SDK doesn't have these defines
#ifndef V4L2_CID_FLASH_LED_MODE
#define V4L2_CID_FLASH_LED_MODE 10225921
#endif

#ifndef V4L2_FLASH_LED_MODE_FLASH
#define V4L2_FLASH_LED_MODE_FLASH 1
#endif


// Select the platform
namespace Plat = FCam::N9;

/***********************************************************/
/* Shutter sound                                           */
/*                                                         */
/* This example shows how to declare and attach a device,  */
/* and write the appropriate actions. In this example, the */
/* camera will trigger two actions at the beginning of the */
/* exposure: a flash, and a shutter sound.                 */
/* See SoundPlayer class for more information.             */
/***********************************************************/
int main(int argc, char **argv) {

    // Devices
    Plat::Sensor sensor;
    Plat::Flash flash;

    // We defined a custom device to play a sound during the
    // exposure. See SoundPlayer.h/cpp for details.
    SoundPlayer audio;

    sensor.attach(&flash); // Attach the flash to the sensor
    sensor.attach(&audio); // Attach the sound player to the sensor

    // Explicitly power up the sensor
    if (sensor.initialize(0) == -1){
        printf("Error powering up the sensor.\n");
        return 1;
    }

    // Tell flash to use LED Flash
    int fd = open("/dev/v4l-subdev10", O_RDWR);
    struct v4l2_control ctrl;
    ctrl.id = V4L2_CID_FLASH_LED_MODE;
    ctrl.value = V4L2_FLASH_LED_MODE_FLASH;
    ioctl(fd, VIDIOC_S_CTRL, &ctrl);

    // Set the shot parameters
    FCam::Shot shot1;
    shot1.exposure = 800000;
    shot1.gain = 1.0f;
    shot1.whiteBalance = 3500;
    shot1.image = FCam::Image(2592, 1968, FCam::UYVY);

    // Action (Flash)
    FCam::Flash::FireAction fire(&flash);
    fire.duration = flash.minDuration();
    fire.time = 0;//shot1.exposure - fire.duration;
    fire.brightness = flash.maxBrightness();

    // Action (Sound)
    SoundPlayer::SoundAction click(&audio);
    click.time = 0; // Start at the beginning of the exposure
    click.setWavFile("/usr/share/sounds/ui-tones/snd_camera_shutter.wav");

    // Attach actions
    shot1.addAction(fire);
    shot1.addAction(click);

    // Order the sensor to capture a shot.
    // The flash and the shutter sound should happen simultaneously.
    sensor.capture(shot1);
    assert(sensor.shotsPending() == 1); // There should be exactly one shot
    // Retrieve the frame from the sensor
    FCam::Frame frame = sensor.getFrame();
    assert(frame.shot().id == shot1.id); // Check the source of the request

    // Write out the file
    FCam::saveJPEG(frame, "/home/user/MyDocs/DCIM/example6.jpg");

    // Check that the pipeline is empty
    assert(sensor.framesPending() == 0);
    assert(sensor.shotsPending() == 0);
}

Copyright (c) 2012, Nokia Corporation and/or its subsidiary(-ies). All rights reserved. See Copyright.
MeeGo 1.2 Harmattan API