Controlling the Raspberry Pi camera from C

I wanted to be able to stop and start the camera driven by events instead of just calling raspivid to record for a preset time.

My code is really just a simple wrapper around raspivid using the SIGUSR1 option to stop the video under program control rather than after a preset time.

The example main() function starts the video, sleeps for five seconds and then stops it.  For demo purposes I included the options for black and white inverted video.  To record with the normal raspivid defaults you just call startVideo with an empty options string:

startVideo(“filename.h264”, “”);

Obviously you can put any of the normal raspivid options in the string – but you should avoid -t, -n, -o, and -s as the code fills those in for you.  If you want to enable preview/monitoring then make the obvious change to remove the -n (no preview) option.

Save code as, say, video.c and compile with gcc -o video video.c

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static pid_t pid = 0;

void startVideo(char *filename, char *options) {
    if ((pid = fork()) == 0) {
        char **cmd;

        // count tokens in options string
        int count = 0;
        char *copy;
        copy = strdup(options);
        if (strtok(copy, " \t") != NULL) {
            count = 1;
            while (strtok(NULL, " \t") != NULL)
                count++;
        }

        cmd = malloc((count + 8) * sizeof(char **));
        free(copy);

        // if any tokens in options, 
        // copy them to cmd starting at positon[1]
        if (count) {
            int i;
            copy = strdup(options);
            cmd[1] = strtok(copy, " \t");
            for (i = 2; i <= count; i++)
                cmd[i] = strtok(NULL, " \t");
        }

        // add default options
        cmd[0] = "raspivid"; // executable name
        cmd[count + 1] = "-n"; // no preview
        cmd[count + 2] = "-t"; // default time (overridden by -s)
                               // but needed for clean exit
        cmd[count + 3] = "10"; // 10 millisecond (minimum) time for -t
        cmd[count + 4] = "-s"; // enable USR1 signal to stop recording
        cmd[count + 5] = "-o"; // output file specifer
        cmd[count + 6] = filename;
        cmd[count + 7] = (char *)0; // terminator
        execv("/usr/bin/raspivid", cmd);
    }
}

void stopVideo(void) {
    if (pid) {
        kill(pid, 10); // seems to stop with two signals separated
                       // by 1 second if started with -t 10 parameter
        sleep(1);
        kill(pid, 10);
    }
}

int main(int argc, char **argv) {
    printf("Recording video for 5 secs...");
    // example options give an upside-down black and white video
    startVideo("temp.h264", "-cfx 128:128 -rot 180"); 
    fflush(stdout);
    sleep(5);
    stopVideo();
    printf("\nVideo stopped - exiting in 2 secs.\n");
    sleep(2);
    return 0;
}