Taking photos in burst mode

Using the Camera C API, you can take photos in burst mode, that is, taking photos in rapid succession. The Camera service supports two types of burst capture:

  • Fixed burst: Takes a fixed number of photos as defined by the app
  • Continuous burst: Continues to take burst capture until stopped by the user

Fixed burst and continuous burst require different viewfinder modes, as shown in the following table:

Type of burst capture API function Required viewfinder mode
Fixed burst camera_take_burst() CAMERA_VFMODE_FIXED_BURST or CAMERA_VFMODE_EV_BRACKETING
Continuous burst camera_start_burst(), camera_stop_burst() CAMERA_VFMODE_CONTINUOUS_BURST

Set up the camera for burst mode

To set up the camera for burst mode, you need to:

  1. Find available cameras.
  2. Open a camera.
  3. Set the required viewfinder mode.
  4. Set viewfinder properties.
  5. Start the viewfinder.

Not applicable

Not applicable

The following code samples demonstrate how to take photos in fixed burst mode. First, your app needs to find the cameras that support the burst feature.

camera_error_t  err;
bool found = 0;

/* Find out if any camera supports both
   PHOTO and BURST features
 */
camera_feature_t features[] = { CAMERA_FEATURE_PHOTO, CAMERA_FEATURE_BURST };
camera_unit_t next = CAMERA_UNIT_NONE;
num = 0;
/* Loop through all cameras; take the first one
   that supports the required features
 */
while (camera_find_capable(features,
						   sizeof(features)/sizeof(*features),
						   next,
						   &next) == CAMERA_EOK) {
	err = camera_open(next,
                      CAMERA_MODE_RW | CAMERA_MODE_ROLL,
                      &handle);
    if (err == CAMERA_EOK) {
        fprintf(stderr, "camera unit %d supports the required features\n", next);
		found = true;
		break;
    }
}
if (!found) {
    /* Handle error */
}

Before starting the viewfinder, you need to find out if the camera supports the required viewfinder mode.

/* Find out if viewfinder burst mode is supported */
bool is_burst_supported() {
    uint32_t supported;  /* The number of supported viewfinder modes */
    camera_error_t  err;

	/* Find the number of supported viewfinder modes */
    err = camera_get_supported_vf_modes(handle, 0, &supported, NULL);
    if (err == CAMERA_EOK) {
        camera_vf_mode_t modes[supported];
		/* Get all supported viewfinder modes in the modes array */
        err = camera_get_supported_vf_modes(handle, supported, &supported, modes);
	    if (err == CAMERA_EOK) {
	        for (int i = 0; i < supported; i++) {
		        if ((modes[i] == CAMERA_VFMODE_FIXED_BURST)) {
			        return true;
			}
			return false;
		}
	}
	return false;
}

To use burst mode, you also need to configure the frame rate at which you want the camera to take photos. You set the frame rate before starting the viewfinder.

The following code sample queries the camera's supported frame rates. If a frame rate of 5 is supported, it sets the frame rate to 5; otherwise, it uses the first frame rate in the returned array.

/* Find the supported frame rates
   Set frame rate and other viewfinder properties
 */
int set_viewfinder_properties() {
    /* First, get supported frame rates */
	uint32_t supported = 0; /* number of supported frame rates */
	bool maxmin; found = false;
	double framerate = 5.0;   /* intended frame rate */
	
	/* Invoke API in presizing mode to get the 
       number of supported frame rates
     */
	err = camera_get_supported_vf_framerates(handle,
                                  CAMERA_FRAMETYPE_UNSPECIFIED,
	                              0, &supported,
                                  NULL, &maxmin);
									   
	/* Invoke again to get the array of supported frame rates */
    if (err == CAMERA_EOK) {
        double rates[supported];
        err = camera_get_supported_vf_framerates(handle,
		                              CAMERA_FRAMETYPE_UNSPECIFIED,
                                      supported, &supported,
                                      rates, &maxmin);
        if (err == CAMERA_EOK) {
            /* If the returned maxmin is true, it indicates that
               the array contains the max and min values of the
               supported frame rates, where rates[0] is the max.
			   If max >= 5, take 5; otherwise, take the max
             */
			if (maxmin) {
			    if (rates[0] < framerate) {
				    framerate = rates[0];
				}
			} else {
                /* The returned array contains actual supported
			       rates. Search for 5; if not found, take the
                   first one
                 */
			    for (int i = 0; i < supported; i++) {
				    if (rates[i] == framerate) {
					    found = true;
					    break;
					}
				}
				if (!found) {
				    framerate = rates[0];
				}
			}
			fprintf(stderr, "frame rate = %d\n", framerate);
			
		    /* Set the framerate and other viewfinder properties */
	        err = camera_set_vf_property(handle,
                            CAMERA_IMGPROP_WIN_GROUPID, vf_group,
			                CAMERA_IMGPROP_WIN_ID, "my_viewfinder",
                            CAMERA_IMGPROP_FRAMERATE, framerate);
            if (err == CAMERA_EOK) {
                return 0;
            }
        }
    }
    /* Failed to set viewfinder property */
    return -1;
}

Now you can set the viewfinder mode and frame rate, and then start the viewfinder. For an example of the status_callback function, see Setting up a camera.

/* If this camera supports taking photo in burst mode,
   set the frame rate and start the viewfinder
 */
int start_viewfinder() {
    if (is_burst_supported()) {
        /* Set viewfinder mode to "fixed burst" */
        if (camera_set_vf_mode(handle, CAMERA_VFMODE_FIXED_BURST) == CAMERA_EOK) {
	        if (set_viewfinder_properties() == 0) {
	            err = camera_start_viewfinder(handle,
	                                   NULL,
						           	&status_callback,
							           (void*)123);
	            if (err == CAMERA_EOK) {
	                 /* Camera is ready for use */
					 return 0;
			    }
	        }
	    }
	}
	/* Failed to start the viewfinder */
	return -1;
}

Take photos in fixed burst mode

When the user touches the screen, a screen event, SCREEN_EVENT_MTOUCH_TOUCH, is sent. You can trigger fixed burst capture when receiving this event. Handle screen events demonstrate how to receive and handle a screen event.

The following code sample shows you how to start fixed burst capture when a screen touch event is received.

Not applicable

Not applicable

if (touch) {
    touch = false;

    /* Attempt to take 5 photos in one burst */
    err = camera_take_burst(handle,
                            5,
                            &shutter_callback,
                            NULL,
                            NULL,
                            &image_callback,
                            NULL,
                            false);  /* nonblocking call */
    if (err != CAMERA_EOK) {
        fprintf(stderr, "camera_take_burst() error %d\n", err);
    }
}                
            

Two callback pointers are passed in. You can define the shutter_callback to play a shutter sound. See Play a shutter sound for an example of shutter_callback. The following code sample defines the image_callback function to save the buffered frames to memory. When taking an individual photo, you can use image_callback to save the photo to a file. In burst mode, however, because multiple frames are generated quickly, you might not be able to write to disk fast enough to keep up with the incoming frames. You should buffer the images in memory while taking the burst capture, and save the images later when the burst capture is complete.

static int burst_frame_count = 0;
static uint8_t* burst_bufs[10] = { 0 };
static uint64_t burst_sizes[10] = { 0 };

/* ... */

static void
image_callback(camera_handle_t handle,
               camera_buffer_t* buf,
               void* arg)
{
    if (buf->frametype == CAMERA_FRAMETYPE_JPEG) {
        fprintf(stderr, "still image size: %lld\n", buf->framedesc.jpeg.bufsize);

        /* If there is enough room left in the burst buffer list... */
        if (burst_frame_count+1 < sizeof(burst_bufs) / sizeof(*burst_bufs)) {
            /* Make a copy of the jpeg buffer in memory */
            burst_sizes[burst_frame_count] = buf->framedesc.jpeg.bufsize;
            burst_bufs[burst_frame_count] = malloc(burst_sizes[burst_frame_count]);
            if (!burst_bufs[burst_frame_count]) {
                fprintf(stderr, "could not malloc a buffer to cache frame %d\n", burst_frame_count+1);
            } else {
                memcpy(burst_bufs[burst_frame_count], buf->framebuf, burst_sizes[burst_frame_count]);
                burst_frame_count++;
                fprintf(stderr, "cached burst frame %d\n", burst_frame_count);
            }
        }
    }
}

/* Save to file when all images are done */
/* ... */

Last modified: 2015-05-07



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus