コード例 #1
0
ファイル: RaspiStillYUV.c プロジェクト: WilsonTW/userland
/**
 * Function to wait in various ways (depending on settings) for the next frame
 *
 * @param state Pointer to the state data
 * @param [in][out] frame The last frame number, adjusted to next frame number on output
 * @return !0 if to continue, 0 if reached end of run
 */
static int wait_for_next_frame(RASPISTILLYUV_STATE *state, int *frame)
{
   static int64_t complete_time = -1;
   int keep_running = 1;

   int64_t current_time =  vcos_getmicrosecs64()/1000;

   if (complete_time == -1)
      complete_time =  current_time + state->timeout;

   // if we have run out of time, flag we need to exit
   // If timeout = 0 then always continue
   if (current_time >= complete_time && state->timeout != 0)
      keep_running = 0;

   switch (state->frameNextMethod)
   {
   case FRAME_NEXT_SINGLE :
      // simple timeout for a single capture
      vcos_sleep(state->timeout);
      return 0;

   case FRAME_NEXT_FOREVER :
   {
      *frame+=1;

      // Have a sleep so we don't hog the CPU.
      vcos_sleep(10000);

      // Run forever so never indicate end of loop
      return 1;
   }

   case FRAME_NEXT_TIMELAPSE :
   {
      static int64_t next_frame_ms = -1;

      // Always need to increment by at least one, may add a skip later
      *frame += 1;

      if (next_frame_ms == -1)
      {
         vcos_sleep(state->timelapse);

         // Update our current time after the sleep
         current_time =  vcos_getmicrosecs64()/1000;

         // Set our initial 'next frame time'
         next_frame_ms = current_time + state->timelapse;
      }
      else
      {
         int64_t this_delay_ms = next_frame_ms - current_time;

         if (this_delay_ms < 0)
         {
            // We are already past the next exposure time
            if (-this_delay_ms < -state->timelapse/2)
            {
               // Less than a half frame late, take a frame and hope to catch up next time
               next_frame_ms += state->timelapse;
               vcos_log_error("Frame %d is %d ms late", *frame, (int)(-this_delay_ms));
            }
            else
            {
               int nskip = 1 + (-this_delay_ms)/state->timelapse;
               vcos_log_error("Skipping frame %d to restart at frame %d", *frame, *frame+nskip);
               *frame += nskip;
               this_delay_ms += nskip * state->timelapse;
               vcos_sleep(this_delay_ms);
               next_frame_ms += (nskip + 1) * state->timelapse;
            }
         }
         else
         {
            vcos_sleep(this_delay_ms);
            next_frame_ms += state->timelapse;
         }
      }

      return keep_running;
   }

   case FRAME_NEXT_KEYPRESS :
   {
    	int ch;

    	if (state->verbose)
         fprintf(stderr, "Press Enter to capture, X then ENTER to exit\n");

    	ch = getchar();
    	*frame+=1;
    	if (ch == 'x' || ch == 'X')
    	   return 0;
    	else
    	{
 	      return keep_running;
    	}
   }

   case FRAME_NEXT_IMMEDIATELY :
   {
      // Not waiting, just go to next frame.
      // Actually, we do need a slight delay here otherwise exposure goes
      // badly wrong since we never allow it frames to work it out
      // This could probably be tuned down.
      // First frame has a much longer delay to ensure we get exposure to a steady state
      if (*frame == 0)
         vcos_sleep(1000);
      else
         vcos_sleep(30);

      *frame+=1;

      return keep_running;
   }

   case FRAME_NEXT_GPIO :
   {
       // Intended for GPIO firing of a capture
      return 0;
   }

   case FRAME_NEXT_SIGNAL :
   {
      // Need to wait for a SIGUSR1 signal
      sigset_t waitset;
      int sig;
      int result = 0;

      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 initiate capture\n");
      }

      result = sigwait( &waitset, &sig );

      if (state->verbose)
      {
         if( result == 0)
         {
            fprintf(stderr, "Received SIGUSR1\n");
         }
         else
         {
            fprintf(stderr, "Bad signal received - error %d\n", errno);
         }
      }

      *frame+=1;

      return keep_running;
   }
   } // end of switch

   // Should have returned by now, but default to timeout
   return keep_running;
}
コード例 #2
0
ファイル: RaspiCamCV.c プロジェクト: nettercm/raspicam-opencv
/**
*  buffer header callback function for encoder
*
*  Callback will dump buffer data to the specific file
*
* @param port Pointer to port from which callback originated
* @param buffer mmal buffer header pointer
*/
static void encoder_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
	MMAL_BUFFER_HEADER_T *new_buffer;
	static int64_t base_time =  -1;

	//fprintf(stderr,"*");fflush(stderr);

	// All our segment times based on the receipt of the first encoder callback
	if (base_time == -1)
		base_time = vcos_getmicrosecs64()/1000;

	// We pass our file handle and other stuff in via the userdata field.

	PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata;

	if (pData)
	{
		int bytes_written = buffer->length;
		int64_t current_time = vcos_getmicrosecs64()/1000;

		vcos_assert(pData->file_handle);
		if(pData->pstate->inlineMotionVectors) vcos_assert(pData->imv_file_handle);

		//else 
		//{
		// For segmented record mode, we need to see if we have exceeded our time/size,
		// but also since we have inline headers turned on we need to break when we get one to
		// ensure that the new stream has the header in it. If we break on an I-frame, the
		// SPS/PPS header is actually in the previous chunk.
		/*if ((buffer->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG) &&
		((pData->pstate->segmentSize && current_time > base_time + pData->pstate->segmentSize) ||
		(pData->pstate->splitWait && pData->pstate->splitNow)))
		{
		FILE *new_handle;

		base_time = current_time;

		pData->pstate->splitNow = 0;
		pData->pstate->segmentNumber++;

		// Only wrap if we have a wrap point set
		if (pData->pstate->segmentWrap && pData->pstate->segmentNumber > pData->pstate->segmentWrap)
		pData->pstate->segmentNumber = 1;

		new_handle = open_filename(pData->pstate);

		if (new_handle)
		{
		fclose(pData->file_handle);
		pData->file_handle = new_handle;
		}

		new_handle = open_imv_filename(pData->pstate);

		if (new_handle)
		{
		fclose(pData->imv_file_handle);
		pData->imv_file_handle = new_handle;
		}
		}*/
		if (buffer->length)
		{
			//printf("writing...");
			mmal_buffer_header_mem_lock(buffer);
			if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO)
			{
				if(pData->pstate->inlineMotionVectors)
				{
					bytes_written = fwrite(buffer->data, 1, buffer->length, pData->imv_file_handle);
				}
				else
				{
					//We do not want to save inlineMotionVectors...
					bytes_written = buffer->length;
				}
			}
			else
			{
				bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);				
			}

			mmal_buffer_header_mem_unlock(buffer);

			if (bytes_written != buffer->length)
			{
				vcos_log_error("Failed to write buffer data (%d from %d)- aborting", bytes_written, buffer->length);
				pData->abort = 1;
			}
		}
		//}
	}
	else
	{
		vcos_log_error("Received a encoder buffer callback with no state");
	}

	// release buffer back to the pool
	mmal_buffer_header_release(buffer);

	// and send one back to the port (if still open)
	if (port->is_enabled)
	{
		MMAL_STATUS_T status;

		new_buffer = mmal_queue_get(pData->pstate->encoder_pool->queue);

		if (new_buffer)
			status = mmal_port_send_buffer(port, new_buffer);

		if (!new_buffer || status != MMAL_SUCCESS)
			vcos_log_error("Unable to return a buffer to the encoder port");
	}
	//printf("done.\n");
}