Swap_File
Posts: 24
Joined: Sun Apr 06, 2014 5:31 pm

Signals for raspivid Control

Mon Apr 07, 2014 1:05 am

By default, SIGUSR1 just toggles pause and capture in raspivid. While toggling is useful for human input, it isn't very useful to me when scripting.

I wanted Raspivid to start and stop on signals similar to gst-launch does, meaning...
Pipeline Control

A pipeline can be controlled by signals. SIGUSR2 will stop the pipeline (GST_STATE_NULL); SIGUSR1 will put it back to play (GST_STATE_PLAYING). By default, the pipeline will start in the playing state.
To make raspivid to act like gst-launch, I made the following changes in raspivid.c:

Old:

Code: Select all

      case CommandSignal:
         state->waitMethod = WAIT_METHOD_SIGNAL;
         // Reenable the signal
         signal(SIGUSR1, signal_handler);
         break;
New:

Code: Select all

      case CommandSignal:
         state->waitMethod = WAIT_METHOD_SIGNAL;
         // Reenable the signal
         signal(SIGUSR1, signal_handler);
         signal(SIGUSR2, signal_handler);
         break;
Old:

Code: Select all

static void signal_handler(int signal_number)
{
   if (signal_number == SIGUSR1)
   {
New:

Code: Select all

static void signal_handler(int signal_number)
{
   if (signal_number == SIGUSR1 || signal_number == SIGUSR2)
   {
Old:

Code: Select all

      sigemptyset( &waitset );
      sigaddset( &waitset, SIGUSR1 );

      // We are multi threaded because we use mmal, so need to use the pthread
      // variant of procmask to block SIGUSR1 so we can wait on it.
      pthread_sigmask( SIG_BLOCK, &waitset, NULL );

      if (state->verbose)
      {
         fprintf(stderr, "Waiting for SIGUSR1 to %s\n", state->bCapturing ? "pause" : "capture");
      }

      result = sigwait( &waitset, &sig );
New:

Code: Select all

      sigemptyset( &waitset );

      if (state->bCapturing)
      	sigaddset( &waitset, SIGUSR2 );
      else
        sigaddset( &waitset, SIGUSR1 );	


      // We are multi threaded because we use mmal, so need to use the pthread
      // variant of procmask to block SIGUSR1 so we can wait on it.
      pthread_sigmask( SIG_BLOCK, &waitset, NULL );

      if (state->verbose)
      {
         fprintf(stderr, "Waiting for %s to %s\n", state->bCapturing ? "SIGUSR2" : "SIGUSR1" , state->bCapturing ? "pause" : "capture");
      }

      result = sigwait( &waitset, &sig );
Once compiled, this version of raspivid used in conjunction with gst-launch-0.10 (or gst-launch-1.0) will allow you to pause and restart the entire pipeline by simply sending signals to raspivid.

Ideally, you would be able to use the signal control built into gst-launch, but for that to work it appears to require use of the V4L2 driver, which currently does not work with gstreamer due to how gstreamer probes the V4L2 driver for supported resolutions and modes.

This is my gst-launch-0.10 pipeline:

Code: Select all

raspivid -w 800 -h 480 -s -fps 20 -n -pf baseline -ex auto -o - -t 0 | \
gst-launch-1.0 -v fdsrc !  h264parse ! rtph264pay config-interval=10 pt=96 ! udpsink host=192.168.1.255 port=9000 
To test functionally, I used:

Code: Select all

kill -s SIGUSR2 PIDHERE
kill -s SIGUSR1 PIDHERE
This will quickly start and stop the entire pipeline without closing or restarting any programs, which is perfect for maximizing available CPU during half-duplex video and audio streaming.

Return to “Camera board”