예제 #1
0
bool CCameraOutput::BeginReadFrame(const void* &out_buffer, int& out_buffer_size)
{
	//printf("Attempting to read camera output\n");

	//try and get buffer
	if(MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(OutputQueue))
	{
		//printf("Reading buffer of %d bytes from output\n",buffer->length);

		//lock it
		mmal_buffer_header_mem_lock(buffer);

		//store it
		LockedBuffer = buffer;

		//fill out the output variables and return success
		out_buffer = buffer->data;
		out_buffer_size = buffer->length;
		return true;
	}
	//no buffer - return false
	return false;
}
예제 #2
0
/** Send a buffer header to a port */
static MMAL_STATUS_T splitter_send_output(MMAL_BUFFER_HEADER_T *buffer, MMAL_PORT_T *out_port)
{
   MMAL_BUFFER_HEADER_T *out;
   MMAL_STATUS_T status;

   /* Get a buffer header from output port */
   out = mmal_queue_get(out_port->priv->module->queue);
   if (!out)
      return MMAL_EAGAIN;

   /* Copy our input buffer header */
   status = mmal_buffer_header_replicate(out, buffer);
   if (status != MMAL_SUCCESS)
      goto error;

   /* Send buffer back */
   mmal_port_buffer_header_callback(out_port, out);
   return MMAL_SUCCESS;

 error:
   mmal_queue_put_back(out_port->priv->module->queue, out);
   return status;
}
예제 #3
0
파일: RaspiMJPEG.c 프로젝트: jrv/userland
static void jpegencoder2_buffer_callback (MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {

  int bytes_written = buffer->length;

  if(buffer->length) {
    mmal_buffer_header_mem_lock(buffer);
    bytes_written = fwrite(buffer->data, 1, buffer->length, jpegoutput2_file);
    mmal_buffer_header_mem_unlock(buffer);
  }
  if(bytes_written != buffer->length) error("Could not write all bytes");
  
  if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) {
    fclose(jpegoutput2_file);
    if(status_filename != 0) {
      if(!timelapse) {
        status_file = fopen(status_filename, "w");
        fprintf(status_file, "ready");
        fclose(status_file);
      }
    }
    image2_cnt++;
    capturing = 0;
  }

  mmal_buffer_header_release(buffer);

  if (port->is_enabled) {
    MMAL_STATUS_T status = MMAL_SUCCESS;
    MMAL_BUFFER_HEADER_T *new_buffer;

    new_buffer = mmal_queue_get(pool_jpegencoder2->queue);

    if (new_buffer) status = mmal_port_send_buffer(port, new_buffer);
    if (!new_buffer || status != MMAL_SUCCESS) error("Could not send buffers to port");
  }

}
예제 #4
0
파일: RaspiMJPEG.c 프로젝트: jrv/userland
static void h264encoder_buffer_callback (MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)  {

  int bytes_written = buffer->length;

  if(buffer->length) {
    mmal_buffer_header_mem_lock(buffer);
    bytes_written = fwrite(buffer->data, 1, buffer->length, h264output_file);
    mmal_buffer_header_mem_unlock(buffer);
    if(bytes_written != buffer->length) error("Could not write all bytes");
  }

  mmal_buffer_header_release(buffer);

  if (port->is_enabled) {
    MMAL_STATUS_T status = MMAL_SUCCESS;
    MMAL_BUFFER_HEADER_T *new_buffer;

    new_buffer = mmal_queue_get(pool_h264encoder->queue);

    if (new_buffer) status = mmal_port_send_buffer(port, new_buffer);
    if (!new_buffer || status != MMAL_SUCCESS) error("Could not send buffers to port");
  }

}
예제 #5
0
파일: deinterlace.c 프로젝트: tguillem/vlc
static void Close(filter_t *filter)
{
    filter_sys_t *sys = filter->p_sys;
    MMAL_BUFFER_HEADER_T *buffer;

    if (!sys)
        return;

    if (sys->component && sys->component->control->is_enabled)
        mmal_port_disable(sys->component->control);

    if (sys->input && sys->input->is_enabled)
        mmal_port_disable(sys->input);

    if (sys->output && sys->output->is_enabled)
        mmal_port_disable(sys->output);

    if (sys->component && sys->component->is_enabled)
        mmal_component_disable(sys->component);

    while ((buffer = mmal_queue_get(sys->filtered_pictures))) {
        picture_t *pic = (picture_t *)buffer->user_data;
        picture_Release(pic);
    }

    if (sys->filtered_pictures)
        mmal_queue_destroy(sys->filtered_pictures);

    if (sys->component)
        mmal_component_release(sys->component);

    vlc_sem_destroy(&sys->sem);
    free(sys);

    bcm_host_deinit();
}
예제 #6
0
/**
 *  buffer header callback function for camera output port
 *
 *  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 camera_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
   int complete = 0;
   // 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;

      if (buffer->length && pData->file_handle)
      {
         mmal_buffer_header_mem_lock(buffer);

         bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);

         mmal_buffer_header_mem_unlock(buffer);
      }

      // We need to check we wrote what we wanted - it's possible we have run out of storage.
      if (bytes_written != buffer->length)
      {
         vcos_log_error("Unable to write buffer to file - aborting");
         complete = 1;
      }

      // Check end of frame or error
      if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED))
         complete = 1;
   }
   else
   {
      vcos_log_error("Received a camera still 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;
      MMAL_BUFFER_HEADER_T *new_buffer = mmal_queue_get(pData->pstate->camera_pool->queue);

      // and back to the port from there.
      if (new_buffer)
      {
         status = mmal_port_send_buffer(port, new_buffer);
      }

      if (!new_buffer || status != MMAL_SUCCESS)
         vcos_log_error("Unable to return the buffer to the camera still port");
   }

   if (complete)
   {
      vcos_semaphore_post(&(pData->complete_semaphore));
   }
}
예제 #7
0
static void EncoderBufferCallback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
   //std::cout << "EncoderBufferCallback: " << pthread_self() << std::endl;

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

   bool mappedBuffer = false;

   if (pData)
   {
	   if (buffer->length)
	   {
         // Copy the image data
         pData->cs.enter("EncoderBufferCallback");
         try
         {
			 if (pData->acquire)
			 {
				 MmalImageStoreItem * item = pData->imageStore.reserve(buffer);
				 if (item == NULL)
				 {
					 throw Exception("No images available in the MmalImageStore");
				 }

				 pData->image = &item->image;

				 pData->acquire = false;
				 mappedBuffer = true;
			 }
         }
         catch (Exception& e)
         {
        	 std::cerr << "!! Exception thrown in EncoderBufferCallback: " << e << std::endl;
         }
         catch (...)
         {
        	 std::cerr << "!! Exception thrown in EncoderBufferCallback" << std::endl;
         }
         pData->cs.leave();
	   }
   }
   else
   {
	   std::cerr << "!! Received a encoder buffer callback with no state" << std::endl;
   }

   // release buffer back to the pool
   if (mappedBuffer)
   {
	   vcos_semaphore_post(&(pData->complete_semaphore));
   }
   else
   {
	   mmal_buffer_header_release(buffer);
   }

   // and send one back to the port (if still open)
   if (port->is_enabled)
   {
      MMAL_BUFFER_HEADER_T *new_buffer = mmal_queue_get(pData->pool->queue);

      if (new_buffer)
      {
          mmal_port_send_buffer(port, new_buffer);
      }
   }
}
RaspiCamCvCapture * raspiCamCvCreateCameraCapture(int index)
{
	RaspiCamCvCapture * capture = (RaspiCamCvCapture*)malloc(sizeof(RaspiCamCvCapture));
	// Our main data storage vessel..
	RASPIVID_STATE * state = (RASPIVID_STATE*)malloc(sizeof(RASPIVID_STATE));
	capture->pState = state;
	
	MMAL_STATUS_T status = -1;
	MMAL_PORT_T *camera_video_port = NULL;
	MMAL_PORT_T *camera_still_port = NULL;

	bcm_host_init();

	// read default status
	default_status(state);

	int w = state->width;
	int h = state->height;
	state->py = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);		// Y component of YUV I420 frame
	if (state->graymode==0) {
		state->pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// U component of YUV I420 frame
		state->pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// V component of YUV I420 frame
	}
	vcos_semaphore_create(&state->capture_sem, "Capture-Sem", 0);
	vcos_semaphore_create(&state->capture_done_sem, "Capture-Done-Sem", 0);

	if (state->graymode==0) {
		state->pu_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
		state->pv_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
		state->yuvImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);
		state->dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); // final picture to display
	}

	// create camera
	if (!create_camera_component(state))
	{
	   vcos_log_error("%s: Failed to create camera component", __func__);
	   raspiCamCvReleaseCapture(&capture);
	   return NULL;
	}

	camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT];
	camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT];

	// assign data to use for callback
	camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)state;

	// start capture
	if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
	{
	   vcos_log_error("%s: Failed to start capture", __func__);
	   raspiCamCvReleaseCapture(&capture);
	   return NULL;
	}

	// Send all the buffers to the video port
		
	int num = mmal_queue_length(state->video_pool->queue);
	int q;
	for (q = 0; q < num; q++)
	{
		MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state->video_pool->queue);
		
		if (!buffer)
			vcos_log_error("Unable to get a required buffer %d from pool queue", q);
		
		if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS)
			vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
	}

	//mmal_status_to_int(status);	
		
	// Disable all our ports that are not handled by connections
	//check_disable_port(camera_still_port);

	//if (status != 0)
	//	raspicamcontrol_check_configuration(128);

	vcos_semaphore_wait(&state->capture_done_sem);
	return capture;
}
예제 #9
0
파일: RaspiVid.c 프로젝트: SlugCam/SCnode
/**
 * main
 */
int main(int argc, const char **argv)
{
   // Our main data storage vessel..
   RASPIVID_STATE state;

   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_PORT_T *camera_preview_port = NULL;
   MMAL_PORT_T *camera_video_port = NULL;
   MMAL_PORT_T *camera_still_port = NULL;
   MMAL_PORT_T *preview_input_port = NULL;
   MMAL_PORT_T *encoder_input_port = NULL;
   MMAL_PORT_T *encoder_output_port = NULL;
   FILE *output_file = NULL;

   bcm_host_init();

   // Register our application with the logging system
   vcos_log_register("RaspiVid", VCOS_LOG_CATEGORY);

   signal(SIGINT, signal_handler);

   default_status(&state);

   // Do we have any parameters
   if (argc == 1)
   {
      fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING);

      display_valid_parameters(basename(argv[0]));
      exit(0);
   }

   // Parse the command line and put options in to our status structure
   if (parse_cmdline(argc, argv, &state))
   {
      status = -1;
      exit(0);
   }

   if (state.verbose)
   {
      fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING);
      dump_status(&state);
   }

   // OK, we have a nice set of parameters. Now set up our components
   // We have three components. Camera, Preview and encoder.

   if ((status = create_camera_component(&state)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create camera component", __func__);
   }
   else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create preview component", __func__);
      destroy_camera_component(&state);
   }
   else if ((status = create_encoder_component(&state)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create encode component", __func__);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);
   }
   else
   {
      PORT_USERDATA callback_data;

      if (state.verbose)
         fprintf(stderr, "Starting component connection stage\n");

      camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
      camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
      camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
      preview_input_port  = state.preview_parameters.preview_component->input[0];
      encoder_input_port  = state.encoder_component->input[0];
      encoder_output_port = state.encoder_component->output[0];

      if (state.preview_parameters.wantPreview )
      {
         if (state.verbose)
         {
            fprintf(stderr, "Connecting camera preview port to preview input port\n");
            fprintf(stderr, "Starting video preview\n");
         }

         // Connect camera to preview
         status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection);
      }
      else
      {
         status = MMAL_SUCCESS;
      }

      if (status == MMAL_SUCCESS)
      {
         if (state.verbose)
            fprintf(stderr, "Connecting camera stills port to encoder input port\n");

         // Now connect the camera to the encoder
         status = connect_ports(camera_video_port, encoder_input_port, &state.encoder_connection);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
            goto error;
         }

         if (state.filename)
         {
            if (state.filename[0] == '-')
            {
               output_file = stdout;

               // Ensure we don't upset the output stream with diagnostics/info
               state.verbose = 0;
            }
            else
            {
               if (state.verbose)
                  fprintf(stderr, "Opening output file \"%s\"\n", state.filename);

               output_file = fopen(state.filename, "wb");
            }

            if (!output_file)
            {
               // Notify user, carry on but discarding encoded output buffers
               vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state.filename);
            }
         }

         // Set up our userdata - this is passed though to the callback where we need the information.
         callback_data.file_handle = output_file;
		 callback_data.image = Mat(Size(state.width, state.height), CV_8UC1);
         callback_data.pstate = &state;
         callback_data.abort = 0;

         encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;

         if (state.verbose)
            fprintf(stderr, "Enabling encoder output port\n");

         // Enable the encoder output port and tell it its callback function
         status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("Failed to setup encoder output");
            goto error;
         }

         if (state.demoMode)
         {
            // Run for the user specific time..
            int num_iterations = state.timeout / state.demoInterval;
            int i;

            if (state.verbose)
               fprintf(stderr, "Running in demo mode\n");

            for (i=0;state.timeout == 0 || i<num_iterations;i++)
            {
               raspicamcontrol_cycle_test(state.camera_component);
               vcos_sleep(state.demoInterval);
            }
         }
         else
         {
            // Only encode stuff if we have a filename and it opened
            if (output_file)
            {
               int wait;

               if (state.verbose)
                  fprintf(stderr, "Starting video capture\n");

               if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
               {
                  goto error;
               }

               // Send all the buffers to the encoder output port
               {
                  int num = mmal_queue_length(state.encoder_pool->queue);
                  int q;
                  for (q=0;q<num;q++)
                  {
                     MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue);

                     if (!buffer)
                        vcos_log_error("Unable to get a required buffer %d from pool queue", q);

                     if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS)
                        vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);

                  }
               }

               // Now wait until we need to stop. Whilst waiting we do need to check to see if we have aborted (for example
               // out of storage space)
               // Going to check every ABORT_INTERVAL milliseconds

               for (wait = 0; state.timeout == 0 || wait < state.timeout; wait+= ABORT_INTERVAL)
               {
                  vcos_sleep(ABORT_INTERVAL);
                  if (callback_data.abort)
                     break;
               }

               if (state.verbose)
                  fprintf(stderr, "Finished capture\n");
            }
            else
            {
               if (state.timeout)
                  vcos_sleep(state.timeout);
               else
                  for (;;) vcos_sleep(ABORT_INTERVAL);
            }
         }
      }
      else
      {
         mmal_status_to_int(status);
         vcos_log_error("%s: Failed to connect camera to preview", __func__);
      }

error:

      mmal_status_to_int(status);

      if (state.verbose)
         fprintf(stderr, "Closing down\n");

      // Disable all our ports that are not handled by connections
      check_disable_port(camera_still_port);
      check_disable_port(encoder_output_port);

      if (state.preview_parameters.wantPreview )
         mmal_connection_destroy(state.preview_connection);
      mmal_connection_destroy(state.encoder_connection);

      // Can now close our file. Note disabling ports may flush buffers which causes
      // problems if we have already closed the file!
      if (output_file && output_file != stdout)
         fclose(output_file);

      /* Disable components */
      if (state.encoder_component)
         mmal_component_disable(state.encoder_component);

      if (state.preview_parameters.preview_component)
         mmal_component_disable(state.preview_parameters.preview_component);

      if (state.camera_component)
         mmal_component_disable(state.camera_component);

      destroy_encoder_component(&state);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);

      if (state.verbose)
         fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n");
   }

   if (status != MMAL_SUCCESS)
      raspicamcontrol_check_configuration(128);

   return 0;
}
예제 #10
0
/**
*  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");
}
예제 #11
0
/**
 * main
 */
int main(int argc, const char **argv)
{
	// *** MODIFICATION: OpenCV modifications.
	// Load previous image.
	IplImage* prevImage = cvLoadImage("motion1.jpg", CV_LOAD_IMAGE_COLOR);
		
	// Create two arrays with the same number of channels than the original one.		
	avg1 = cvCreateMat(prevImage->height,prevImage->width,CV_32FC3);
	avg2 = cvCreateMat(prevImage->height,prevImage->width,CV_32FC3);
		
	// Create image of 32 bits.
	IplImage* image32 = cvCreateImage(cvSize(prevImage->width,prevImage->height), 32,3);
												
	// Convert image to 32 bits.
	cvConvertScale(prevImage,image32,1/255,0);
		
	// Set data from previous image into arrays.
	cvSetData(avg1,image32->imageData,image32->widthStep);
	cvSetData(avg2,image32->imageData,image32->widthStep);
	// *** MODIFICATION end
	
   // Our main data storage vessel..
   RASPISTILL_STATE state;

   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_PORT_T *camera_preview_port = NULL;
   MMAL_PORT_T *camera_video_port = NULL;
   MMAL_PORT_T *camera_still_port = NULL;
   MMAL_PORT_T *preview_input_port = NULL;
   MMAL_PORT_T *encoder_input_port = NULL;
   MMAL_PORT_T *encoder_output_port = NULL;

   bcm_host_init();

   // Register our application with the logging system
   vcos_log_register("fast", VCOS_LOG_CATEGORY);

   signal(SIGINT, signal_handler);

   default_status(&state);     
   
   if (state.verbose)
   {
      fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING);      
   }

   // OK, we have a nice set of parameters. Now set up our components
   // We have three components. Camera, Preview and encoder.
   // Camera and encoder are different in stills/video, but preview
   // is the same so handed off to a separate module

   if ((status = create_camera_component(&state)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create camera component", __func__);
   }
   else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create preview component", __func__);
      destroy_camera_component(&state);
   }
   else if ((status = create_encoder_component(&state)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create encode component", __func__);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);
   }
   else
   {
      PORT_USERDATA callback_data;

      if (state.verbose)
         fprintf(stderr, "Starting component connection stage\n");
         
      camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
      camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
      camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
      preview_input_port  = state.preview_parameters.preview_component->input[0];
      encoder_input_port  = state.encoder_component->input[0];
      encoder_output_port = state.encoder_component->output[0];

      if (state.preview_parameters.wantPreview )
      {
         if (state.verbose)
         {
            fprintf(stderr, "Connecting camera preview port to preview input port\n");
            fprintf(stderr, "Starting video preview\n");
         }

         // *** USER: remove preview
         // Connect camera to preview
         //status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection);

      }
      else
      {
         status = MMAL_SUCCESS;
      }

      if (status == MMAL_SUCCESS)
      {
         VCOS_STATUS_T vcos_status;

         if (state.verbose)
            fprintf(stderr, "Connecting camera stills port to encoder input port\n");

         // Now connect the camera to the encoder
         status = connect_ports(camera_still_port, encoder_input_port, &state.encoder_connection);
         

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
            goto error;
         }

         // Set up our userdata - this is passed though to the callback where we need the information.
         // Null until we open our filename
         callback_data.file_handle = NULL;
         callback_data.pstate = &state;
         vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);

         vcos_assert(vcos_status == VCOS_SUCCESS);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("Failed to setup encoder output");
            goto error;
         }
         
         FILE *output_file = NULL;
         
         int frame = 1;
         
         // Enable the encoder output port
         encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;
         
         if (state.verbose)
			fprintf(stderr, "Enabling encoder output port\n");
			
		// Enable the encoder output port and tell it its callback function
		status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);
		
		// Create an empty matrix with the size of the buffer.
		CvMat* buf = cvCreateMat(1,60000,CV_8UC1);
		
		// Keep buffer that gets frames from queue.
		MMAL_BUFFER_HEADER_T *buffer;
		
		// Image to be displayed.
		IplImage* image;
		
		// Keep number of buffers and index for the loop.
		int num, q; 
		
		while(1) 
		{
			// Send all the buffers to the encoder output port
			num = mmal_queue_length(state.encoder_pool->queue);
			
			for (q=0;q<num;q++)
			{
				buffer = mmal_queue_get(state.encoder_pool->queue);
				
				if (!buffer)
					vcos_log_error("Unable to get a required buffer %d from pool queue", q);
					
				if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS)
					vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
			} // for
			
			if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
				vcos_log_error("%s: Failed to start capture", __func__);
			
			else
			{
				// Wait for capture to complete
				// For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error
				// even though it appears to be all correct, so reverting to untimed one until figure out why its erratic
				vcos_semaphore_wait(&callback_data.complete_semaphore);
				if (state.verbose)
					fprintf(stderr, "Finished capture %d\n", frame);
			} // else
			
			// Copy buffer from camera to matrix.
			buf->data.ptr = buffer->data;
			
			// This workaround is needed for the code to work
			// *** TODO: investigate why.
			printf("Until here works\n");
			
			// Decode the image and display it.
			image = cvDecodeImage(buf, CV_LOAD_IMAGE_COLOR);
		
			// Destinations
			CvMat* res1 = cvCreateMat(image->height,image->width,CV_8UC3);
			CvMat* res2 = cvCreateMat(image->height,image->width,CV_8UC3);
		
			// Update running averages and then scale, calculate absolute values
			// and convert the result 8-bit.
			// *** USER:change the value of the weight.
			cvRunningAvg(image,avg2,0.0001, NULL);		
			cvConvertScaleAbs(avg2, res2, 1,0);
		
			cvRunningAvg(image,avg1,0.1, NULL);
			cvConvertScaleAbs(avg1, res1, 1,0);
				
			// Show images
			cvShowImage("img",image);
			cvShowImage("avg1",res1);
			cvShowImage("avg2",res2);
			cvWaitKey(20);
		
			// Update previous image.
			cvSaveImage("motion1.jpg", image, 0);
		} // end while 
		
		vcos_semaphore_delete(&callback_data.complete_semaphore);
         
      }
      else
      {
         mmal_status_to_int(status);
         vcos_log_error("%s: Failed to connect camera to preview", __func__);
      }

error:

      mmal_status_to_int(status);

      if (state.verbose)
         fprintf(stderr, "Closing down\n");

      // Disable all our ports that are not handled by connections
      check_disable_port(camera_video_port);
      check_disable_port(encoder_output_port);

      if (state.preview_parameters.wantPreview )
         mmal_connection_destroy(state.preview_connection);

      mmal_connection_destroy(state.encoder_connection);

      /* Disable components */
      if (state.encoder_component)
         mmal_component_disable(state.encoder_component);

      if (state.preview_parameters.preview_component)
         mmal_component_disable(state.preview_parameters.preview_component);

      if (state.camera_component)
         mmal_component_disable(state.camera_component);

      destroy_encoder_component(&state);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);

      if (state.verbose)
         fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n");
   }

   if (status != MMAL_SUCCESS)
      raspicamcontrol_check_configuration(128);
      
   return 0;
}
예제 #12
0
MmalStillCamera::MmalStillCamera(int imageWidth, int imageHeight, bool enableBurstMode) :
	m_imageWidth(imageWidth),
	m_imageHeight(imageHeight),
	m_callbackData(NULL),
	m_cs(),
	m_camera(NULL),
	m_preview(NULL),
	m_encoder(NULL),
	m_pool(NULL),
	m_previewPort(NULL),
	m_videoPort(NULL),
	m_stillPort(NULL),
	m_targetPort(NULL)
{
	m_callbackData = new MmalStillCallbackData(m_imageWidth, m_imageHeight, 3);

	createCameraComponent();
	std::cout << "Created camera" << std::endl;

	createPreview();
	std::cout << "Created preview" << std::endl;

	std::cout << "Target Image Width: " << VCOS_ALIGN_UP(m_imageWidth, 32) << std::endl;
	std::cout << "Target Image Height: " << VCOS_ALIGN_UP(m_imageHeight, 16) << std::endl;

	MMAL_STATUS_T status;

	m_targetPort = m_stillPort;

	// Create pool of buffer headers for the output port to consume
	m_pool = mmal_port_pool_create(m_targetPort, m_targetPort->buffer_num, m_targetPort->buffer_size);
	if (m_pool == NULL)
	{
		throw Exception("Failed to create buffer header pool for encoder output port");
	}

	MMAL_CONNECTION_T *preview_connection = NULL;
	status = connect_ports(m_previewPort, m_preview->input[0], &preview_connection);
	if (status != MMAL_SUCCESS)
	{
		throw Exception("Error connecting preview port");
	}

	m_targetPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData;
	m_callbackData->image = NULL;
	m_callbackData->pool = m_pool;

	// Enable the encoder output port and tell it its callback function
	if (mmal_port_enable(m_targetPort, EncoderBufferCallback) != MMAL_SUCCESS)
	{
		std::cerr << "Error enabling the encoder buffer callback" << std::endl;
	}

	// Send all the buffers to the encoder output port
	int num = mmal_queue_length(m_pool->queue);
	for (int q = 0; q < num; q++)
	{
		MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_pool->queue);

		if (buffer == NULL)
		{
			std::cerr << "Unable to get buffer " << q << " from the pool" << std::endl;
		}

		if (mmal_port_send_buffer(m_targetPort, buffer)!= MMAL_SUCCESS)
		{
			std::cerr << "Unable to send a buffer " << q << " to encoder output port " << std::endl;
		}
	}

	// Enable burst mode
	if (enableBurstMode)
	{
		if (mmal_port_parameter_set_boolean(m_camera->control,  MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1) != MMAL_SUCCESS)
		{
			std::cerr << "Error enabling burst mode" << std::endl;
		}

		std::cout << "Enabled burst mode for still images" << std::endl;
	}

	std::cout << "Initialized camera" << std::endl;
}
예제 #13
0
static void camera_video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {
    static int frame_count = 0;
    static struct timespec t1;
    struct timespec t2;
    uint8_t *local_overlay_buffer;

    //fprintf(stderr, "INFO:%s\n", __func__);
    if (frame_count == 0) {
        clock_gettime(CLOCK_MONOTONIC, &t1);
    }
    clock_gettime(CLOCK_MONOTONIC, &t2);

    int d = t2.tv_sec - t1.tv_sec;

    MMAL_BUFFER_HEADER_T *new_buffer;
    MMAL_BUFFER_HEADER_T *output_buffer = 0;
    PORT_USERDATA *userdata = (PORT_USERDATA *) port->userdata;

    MMAL_POOL_T *pool = userdata->camera_video_port_pool;


    frame_count++;

    output_buffer = mmal_queue_get(userdata->encoder_input_pool->queue);

    //Set pointer to  latest updated/drawn double buffer to local pointer  
    if (userdata->overlay == 0) {
        local_overlay_buffer = userdata->overlay_buffer;
    }
    else {
        local_overlay_buffer = userdata->overlay_buffer2;
    }

    //Try to some colors http://en.wikipedia.org/wiki/YUV
    int chrominance_offset = userdata->width * userdata->height;
    int v_offset = chrominance_offset / 4;
    int chroma = 0;

    if (output_buffer) {
        mmal_buffer_header_mem_lock(buffer);
        memcpy(output_buffer->data, buffer->data, buffer->length);
        // dim
        int x, y;
        for (x = 0; x < 600; x++) {
            for (y = 0; y < 100; y++) {
                if (local_overlay_buffer[(y * 600 + x) * 4] > 0) {
                    //copy luma Y
                    output_buffer->data[y * userdata->width + x ] = 0xdf;
                    //pointer to chrominance U/V
                    chroma= y / 2 * userdata->width / 2 + x / 2 + chrominance_offset;
                    //just guessing colors 
                    output_buffer->data[chroma] = 0x38 ;
                    output_buffer->data[chroma+v_offset] = 0xb8 ;
                }
            }
        }

        output_buffer->length = buffer->length;
        mmal_buffer_header_mem_unlock(buffer);
        if (mmal_port_send_buffer(userdata->encoder_input_port, output_buffer) != MMAL_SUCCESS) {
            fprintf(stderr, "ERROR: Unable to send buffer \n");
        }
    } else {
        fprintf(stderr, "ERROR: mmal_queue_get (%d)\n", output_buffer);
    }


    if (frame_count % 10 == 0) {
        // print framerate every n frame
        clock_gettime(CLOCK_MONOTONIC, &t2);
        float d = (t2.tv_sec + t2.tv_nsec / 1000000000.0) - (t1.tv_sec + t1.tv_nsec / 1000000000.0);
        float fps = 0.0;

        if (d > 0) {
            fps = frame_count / d;
        } else {
            fps = frame_count;
        }
        userdata->fps = fps;
        //fprintf(stderr, "  Frame = %d,  Framerate = %.1f fps \n", frame_count, fps);
    }


    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(pool->queue);

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

        if (!new_buffer || status != MMAL_SUCCESS) {
            fprintf(stderr, "Error: Unable to return a buffer to the video port\n");
        }
    }
}
예제 #14
0
static void encoder_buffer_callback(
    MMAL_PORT_T *port,
    MMAL_BUFFER_HEADER_T *buffer
    )
{
    MMAL_BUFFER_HEADER_T *new_buffer;

    static int buffer_count = 0;
    static sSX_CAMERA_HW_BUFFER *hw_buf = NULL;
    static unsigned index = 0;

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


    printf("callback current time = %d\n", get_time_ns());


    PORT_USERDATA *pData = (PORT_USERDATA *) port->userdata;
    assert(pData != NULL);

    int bytes_written = buffer->length;

    vcos_assert(pData->file_handle);

    assert(buffer->length > 0);

    // Get frame end.
    unsigned char frame_end = 0;
    if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
    {
        frame_end = 1;
    }

    unsigned char config = 0;
    if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
    {
        config = 1;
    }

#if 0
    printf("frame_end = %d\n", buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END);

    printf("config = %d\n", buffer->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG);

    printf("buffer received: len = %d, frame_end = %d\n",
            buffer->length, frame_end);
#endif

    if(hw_buf == NULL)
    {
        index = 0;
        hw_buf = malloc(sizeof(sSX_CAMERA_HW_BUFFER));
    }

    mmal_buffer_header_mem_lock(buffer);

    unsigned int offset = 0;
    if(   (buffer->data[0] == 0x00)
       && (buffer->data[1] == 0x00)
       && (buffer->data[2] == 0x00)
       && (buffer->data[3] == 0x01))
    {
        offset = 4;
    }

    assert((index + buffer->length) <= SX_CAMERA_HW_NAL_LEN_MAX);

    memcpy(&hw_buf->nal[index],
            buffer->data + offset,
            buffer->length - offset);

    index += (buffer->length - offset);

    mmal_buffer_header_mem_unlock(buffer);

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

    if(frame_end || config)
    {
        hw_buf->nal_len = index;

        sx_queue_push(f_nal_queue, hw_buf);

        hw_buf = NULL;

//        printf("(sx_camera_hw): Queue nal unit [len = %d]\n", index);
    }


#if 0
    printf("frame end = %d\n",
            frame_end);

    printf("data len = %d\n",
            buffer->length);

    printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
            buffer->data[0],
            buffer->data[1],
            buffer->data[2],
            buffer->data[3],
            buffer->data[4],
            buffer->data[5],
            buffer->data[6],
            buffer->data[7]);


    mmal_buffer_header_mem_lock(buffer);

    bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);

    mmal_buffer_header_mem_unlock(buffer);
#endif

    // 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);
            assert(status == MMAL_SUCCESS);
        }
    }
}
예제 #15
0
void camera_thread(
    void
    )
{
    static MMAL_STATUS_T   status;
    static RASPIVID_STATE state;
    static MMAL_PORT_T *camera_preview_port = NULL;
    static MMAL_PORT_T *camera_video_port = NULL;
    static MMAL_PORT_T *camera_still_port = NULL;
    static MMAL_PORT_T *preview_input_port = NULL;
    static MMAL_PORT_T *encoder_input_port = NULL;
    static MMAL_PORT_T *encoder_output_port = NULL;
    static FILE *output_file = NULL;


    f_nal_queue = sx_queue_create();

    bcm_host_init();

    default_status(&state);

    state.verbose = 1;

    status = create_camera_component(&state);
    assert(status == MMAL_SUCCESS);

    status = raspipreview_create(&state.preview_parameters);
    assert(status == MMAL_SUCCESS);

    status = create_encoder_component(&state);
    assert(status == MMAL_SUCCESS);

    PORT_USERDATA callback_data;

    camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
    camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
    camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
    preview_input_port  = state.preview_parameters.preview_component->input[0];
    encoder_input_port  = state.encoder_component->input[0];
    encoder_output_port = state.encoder_component->output[0];

    // Now connect the camera to the encoder
    status = connect_ports(camera_video_port,
                           encoder_input_port,
                           &state.encoder_connection);
    assert(status == MMAL_SUCCESS);

    char *filename = "output.h264";

    state.filename = filename;

    output_file = fopen(state.filename, "wb");

    // Set up our userdata - this is passed though to the callback where we need the information.
    callback_data.file_handle = output_file;
    callback_data.pstate = &state;
    callback_data.abort = 0;

    encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *) &callback_data;

    // Enable the encoder output port and tell it its callback function
    status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);
    assert(status == MMAL_SUCCESS);

    // Only encode stuff if we have a filename and it opened
    if (output_file)
    {
        int wait;

        if (state.verbose)
            fprintf(stderr, "Starting video capture\n");

        status = mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1);
        assert(status == MMAL_SUCCESS);

        // Send all the buffers to the encoder output port
        {
            int num = mmal_queue_length(state.encoder_pool->queue);
            int q;

            fprintf(stderr, "mmal_queue_len = %d\n", num);

            for (q=0;q<num;q++)
            {
                printf("start current time = %d\n", get_time_ns());

                MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue);
                assert(buffer != NULL);

                status = mmal_port_send_buffer(encoder_output_port, buffer);
                assert(status == MMAL_SUCCESS);
            }
        }

        // Now wait until we need to stop. Whilst waiting we do need to check to see if we have aborted (for example
        // out of storage space)
        // Going to check every ABORT_INTERVAL milliseconds

#if 1
        while(1)
        {
            // sleep forever.
            vcos_sleep(ABORT_INTERVAL);
        }
#endif

#if 0
        for (wait = 0; state.timeout == 0 || wait < state.timeout; wait+= ABORT_INTERVAL)
        {
            vcos_sleep(ABORT_INTERVAL);
            if (callback_data.abort)
            {
                fprintf(stderr, "333\n");

                break;
            }

            fprintf(stderr, "222\n");
        }

        fprintf(stderr, "wait = %u\n", wait);

        if (state.verbose)
            fprintf(stderr, "Finished capture\n");
#endif
    }
}
예제 #16
0
파일: codec.c 프로젝트: Adatan/vlc
static picture_t *decode(decoder_t *dec, block_t **pblock)
{
    decoder_sys_t *sys = dec->p_sys;
    block_t *block;
    MMAL_BUFFER_HEADER_T *buffer;
    bool need_flush = false;
    uint32_t len;
    uint32_t flags = 0;
    MMAL_STATUS_T status;
    picture_t *ret = NULL;

    /*
     * Configure output port if necessary
     */
    if (sys->output_format) {
        if (change_output_format(dec) < 0)
            msg_Err(dec, "Failed to change output port format");
    }

    if (!pblock)
        goto out;

    block = *pblock;

    /*
     * Check whether full flush is required
     */
    if (block && block->i_flags & BLOCK_FLAG_DISCONTINUITY) {
        flush_decoder(dec);
        block_Release(*pblock);
        return NULL;
    }

    /*
     * Send output buffers
     */
    if (atomic_load(&sys->started)) {
        buffer = mmal_queue_get(sys->decoded_pictures);
        if (buffer) {
            ret = (picture_t *)buffer->user_data;
            ret->date = buffer->pts;
            ret->b_progressive = sys->b_progressive;
            ret->b_top_field_first = sys->b_top_field_first;

            if (sys->output_pool) {
                buffer->data = NULL;
                mmal_buffer_header_reset(buffer);
                mmal_buffer_header_release(buffer);
            }
        }

        fill_output_port(dec);
    }

    if (ret)
        goto out;

    /*
     * Process input
     */
    if (!block)
        goto out;

    *pblock = NULL;

    if (block->i_flags & BLOCK_FLAG_CORRUPTED)
        flags |= MMAL_BUFFER_HEADER_FLAG_CORRUPTED;

    vlc_mutex_lock(&sys->mutex);
    while (block->i_buffer > 0) {
        buffer = mmal_queue_timedwait(sys->input_pool->queue, 2);
        if (!buffer) {
            msg_Err(dec, "Failed to retrieve buffer header for input data");
            need_flush = true;
            break;
        }
        mmal_buffer_header_reset(buffer);
        buffer->cmd = 0;
        buffer->pts = block->i_pts != 0 ? block->i_pts : block->i_dts;
        buffer->dts = block->i_dts;
        buffer->alloc_size = sys->input->buffer_size;

        len = block->i_buffer;
        if (len > buffer->alloc_size)
            len = buffer->alloc_size;

        buffer->data = block->p_buffer;
        block->p_buffer += len;
        block->i_buffer -= len;
        buffer->length = len;
        if (block->i_buffer == 0)
            buffer->user_data = block;
        buffer->flags = flags;

        status = mmal_port_send_buffer(sys->input, buffer);
        if (status != MMAL_SUCCESS) {
            msg_Err(dec, "Failed to send buffer to input port (status=%"PRIx32" %s)",
                    status, mmal_status_to_string(status));
            break;
        }
        atomic_fetch_add(&sys->input_in_transit, 1);
    }
    vlc_mutex_unlock(&sys->mutex);

out:
    if (need_flush)
        flush_decoder(dec);

    return ret;
}
예제 #17
0
int main(int argc, char **argv)
{
	MMAL_COMPONENT_T *camera =0;
	MMAL_COMPONENT_T *preview=0;
	MMAL_COMPONENT_T *encoder=0;
	MMAL_CONNECTION_T *preview_conn=0;
	MMAL_CONNECTION_T *encoder_conn=0;
	USERDATA_T callback_data;

	// bcm should be initialized before any GPU call is made
	bcm_host_init();

	setNonDefaultOptions(argc, argv);

	// Open file to save the video 
	open_new_file_handle(&callback_data, output_file_name);
	fprintf(stderr, "Output Filename: %s\n", output_file_name);

	// Create Camera, set default values and enable it
	vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera) == MMAL_SUCCESS) 
		&& "Failed creating camera component");

	vcos_assert((set_camera_component_defaults(camera)) == MMAL_SUCCESS
		&& "Failed setting camera components default values");

	vcos_assert((mmal_component_enable(camera) == MMAL_SUCCESS) 
		&& "Failed to enable camera component");

	// Create Preview, set default values and enable it
	vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview) == MMAL_SUCCESS) 
		&& "Failed creating preview component");

	vcos_assert((set_preview_component_defaults(preview) == MMAL_SUCCESS) 
		&& "Failed setting preview components default values");

	vcos_assert((mmal_component_enable(preview) == MMAL_SUCCESS) 
		&& "Failed to enable camera component");

	// Create Encoder, set defaults, enable it and create encoder pool
        vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder) == MMAL_SUCCESS)
                && "Failed to create encoder component");

        vcos_assert((encoder->input_num && encoder->output_num)
                && "Video encoder does not have input/output ports\n");

        set_encoder_component_defaults(encoder);

        vcos_assert((mmal_component_enable(encoder) == MMAL_SUCCESS)
		&& "Failed enabling encoder component");

        callback_data.pool = (MMAL_POOL_T *)mmal_port_pool_create(encoder->output[0],
                        encoder->output[0]->buffer_num, encoder->output[0]->buffer_size);

        vcos_assert(callback_data.pool && "Failed creating encoder pool\n");

	// Setup connections
	vcos_assert((mmal_connection_create(&preview_conn, camera->output[0], preview->input[0], 
		MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) 
		&& "Failed stablishing connection between camera output 0 and preview");

	vcos_assert((mmal_connection_enable(preview_conn) == MMAL_SUCCESS) 
		&& "Failed enabling connection between camera output 0 and preview");

        vcos_assert((mmal_connection_create(&encoder_conn, camera->output[1], encoder->input[0],
        //        MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS)
                MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS)
                && "Failed creating encoder connection to capture (camera output 1)");

        vcos_assert((mmal_connection_enable(encoder_conn) == MMAL_SUCCESS)
                && "Failed enabling encoder connection to capture (campera output 1)");

	encoder_conn->callback = connection_video2encoder_callback;

	// Set callback and enable encoder port
	encoder->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;
	vcos_assert(MMAL_SUCCESS == mmal_port_enable(encoder->output[0], encoder_callback));


	// Send the buffer to encode output port
	MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(callback_data.pool->queue);
	vcos_assert((mmal_port_send_buffer(encoder->output[0], buffer)== MMAL_SUCCESS)
		&& "Unable to send buffer to encoder output port");

	vcos_assert((mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 1) == MMAL_SUCCESS) 
		&& "Unable to set camera->output[1] capture parameter");

	consume_queue_on_connection(encoder_conn->out, encoder_conn->pool->queue);

	while(1)
	{
        	vcos_sleep(1000); // wait for exit call	
		if (exit_prog){
        		vcos_sleep(500); // exit called, wait for all buffers be flushed
			break;
		}
	}

	return 0;
}
예제 #18
0
/**
 *  buffer header callback function for video
 *
 * @param port Pointer to port from which callback originated
 * @param buffer mmal buffer header pointer
 */
static void video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
    MMAL_BUFFER_HEADER_T *new_buffer;
    PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata;

    if (pData)
    {

        if (buffer->length)
        {

            mmal_buffer_header_mem_lock(buffer);

            //
            // *** PR : OPEN CV Stuff here !
            //
            int w=pData->pstate->width;	// get image size
            int h=pData->pstate->height;
            int h4=h/4;

            memcpy(py->imageData,buffer->data,w*h);	// read Y

            if (pData->pstate->graymode==0)
            {
                memcpy(pu->imageData,buffer->data+w*h,w*h4); // read U
                memcpy(pv->imageData,buffer->data+w*h+w*h4,w*h4); // read v

                cvResize(pu, pu_big, CV_INTER_NN);
                cvResize(pv, pv_big, CV_INTER_NN);  //CV_INTER_LINEAR looks better but it's slower
                cvMerge(py, pu_big, pv_big, NULL, image);

                cvCvtColor(image,dstImage,CV_YCrCb2RGB);	// convert in RGB color space (slow)
                cvShowImage("camcvWin", dstImage );
            }
            else
            {
                cvShowImage("camcvWin", py); // display only gray channel
            }

            cvWaitKey(1);
            nCount++;		// count frames displayed

            mmal_buffer_header_mem_unlock(buffer);
        }
        else vcos_log_error("buffer null");

    }
    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->video_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");
    }

}
예제 #19
0
RaspiCamCvCapture * raspiCamCvCreateCameraCapture(int index)
{
	RaspiCamCvCapture * capture = (RaspiCamCvCapture*)malloc(sizeof(RaspiCamCvCapture));
	// Our main data storage vessel..
	RASPIVID_STATE * state = (RASPIVID_STATE*)malloc(sizeof(RASPIVID_STATE));
	capture->pState = state;

	MMAL_STATUS_T status = -1;
	MMAL_PORT_T *camera_video_port = NULL;
	MMAL_PORT_T *camera_video_port_2 = NULL;
	//MMAL_PORT_T *camera_still_port = NULL;
	MMAL_PORT_T *encoder_input_port = NULL;
	MMAL_PORT_T *encoder_output_port = NULL;

	bcm_host_init();

	// read default status
	default_status(state);

	int w = state->width;
	int h = state->height;

	state->py = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);		// Y component of YUV I420 frame

	if (state->graymode==0)
	{
		state->pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// U component of YUV I420 frame
		state->pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// V component of YUV I420 frame
	}
	vcos_semaphore_create(&state->capture_sem, "Capture-Sem", 0);
	vcos_semaphore_create(&state->capture_done_sem, "Capture-Done-Sem", 0);

	if (state->graymode==0)
	{
		state->pu_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
		state->pv_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
		state->yuvImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);
		state->dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); // final picture to display
	}

	//printf("point2.0\n");
	// create camera
	if (!create_camera_component(state))
	{
		vcos_log_error("%s: Failed to create camera component", __func__);
		raspiCamCvReleaseCapture(&capture);
		return NULL;
	} else if ((status = create_encoder_component(state)) != MMAL_SUCCESS)
	{
		vcos_log_error("%s: Failed to create encode component", __func__);
		destroy_camera_component(state);
		return NULL;
	}

	//printf("point2.1\n");
	//create_encoder_component(state);

	camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT];
	camera_video_port_2 = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT_2];
	//camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
	encoder_input_port  = state->encoder_component->input[0];
	encoder_output_port = state->encoder_component->output[0];

	// assign data to use for callback
	camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)state;

	// assign data to use for callback
	camera_video_port_2->userdata = (struct MMAL_PORT_USERDATA_T *)state;

	// Now connect the camera to the encoder
	status = connect_ports(camera_video_port_2, encoder_input_port, &state->encoder_connection);	

	if (state->filename)
	{
		if (state->filename[0] == '-')
		{
			state->callback_data.file_handle = stdout;
		}
		else
		{
			state->callback_data.file_handle = open_filename(state);
		}

		if (!state->callback_data.file_handle)
		{
			// Notify user, carry on but discarding encoded output buffers
			vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state->filename);
		}
	}

	// Set up our userdata - this is passed though to the callback where we need the information.
	state->callback_data.pstate = state;
	state->callback_data.abort = 0;
	encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&state->callback_data;

	// Enable the encoder output port and tell it its callback function
	status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);

	if (status != MMAL_SUCCESS)
	{
		state->encoder_connection = NULL;
		vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
		return NULL;
	}

	if (status != MMAL_SUCCESS)
	{
		vcos_log_error("Failed to setup encoder output");
		return NULL;
	}

	//mmal_port_enable(encoder_output_port, encoder_buffer_callback);

	// Only encode stuff if we have a filename and it opened
	// Note we use the copy in the callback, as the call back MIGHT change the file handle
	if (state->callback_data.file_handle)
	{
		int running = 1;

		// Send all the buffers to the encoder output port
		{
			int num = mmal_queue_length(state->encoder_pool->queue);
			int q;
			for (q=0;q<num;q++)
			{
				MMAL_BUFFER_HEADER_T *buffer2 = mmal_queue_get(state->encoder_pool->queue);

				if (!buffer2)
					vcos_log_error("Unable to get a required buffer %d from pool queue", q);

				if (mmal_port_send_buffer(encoder_output_port, buffer2)!= MMAL_SUCCESS)
					vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
			}
		}
	}


	// start capture
	if (mmal_port_parameter_set_boolean(camera_video_port_2, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
	{
		vcos_log_error("%s: Failed to start capture", __func__);
		raspiCamCvReleaseCapture(&capture);
		return NULL;
	}

	// Send all the buffers to the video port

	int num = mmal_queue_length(state->video_pool->queue);
	int q;
	for (q = 0; q < num; q++)
	{
		MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state->video_pool->queue);

		if (!buffer)
			vcos_log_error("Unable to get a required buffer %d from pool queue", q);

		if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS)
			vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
	}

	//mmal_status_to_int(status);	

	// Disable all our ports that are not handled by connections
	//check_disable_port(camera_still_port);

	//if (status != 0)
	//	raspicamcontrol_check_configuration(128);

	vcos_semaphore_wait(&state->capture_done_sem);
	return capture;
}
예제 #20
0
/**
 * main
 */
int main(int argc, const char **argv)
{
    // Our main data storage vessel..
    RASPIVID_STATE state;

    MMAL_STATUS_T status = -1;
    MMAL_PORT_T *camera_video_port = NULL;
    MMAL_PORT_T *camera_still_port = NULL;
    MMAL_PORT_T *preview_input_port = NULL;
    MMAL_PORT_T *encoder_input_port = NULL;
    MMAL_PORT_T *encoder_output_port = NULL;

    time_t timer_begin,timer_end;
    double secondsElapsed;

    bcm_host_init();
    signal(SIGINT, signal_handler);

    // read default status
    default_status(&state);

    // init windows and OpenCV Stuff
    cvNamedWindow("camcvWin", CV_WINDOW_AUTOSIZE);
    int w=state.width;
    int h=state.height;
    dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);
    py = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);		// Y component of YUV I420 frame
    pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// U component of YUV I420 frame
    pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);	// V component of YUV I420 frame
    pu_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
    pv_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1);
    image = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);	// final picture to display


    // create camera
    if (!create_camera_component(&state))
    {
        vcos_log_error("%s: Failed to create camera component", __func__);
    }
    else if (!raspipreview_create(&state.preview_parameters))
    {
        vcos_log_error("%s: Failed to create preview component", __func__);
        destroy_camera_component(&state);
    }
    else
    {
        PORT_USERDATA callback_data;

        camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
        camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];

        VCOS_STATUS_T vcos_status;

        callback_data.pstate = &state;

        vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);
        vcos_assert(vcos_status == VCOS_SUCCESS);

        // assign data to use for callback
        camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;

        // init timer
        time(&timer_begin);


        // start capture
        if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
        {
            goto error;
        }

        // Send all the buffers to the video port

        int num = mmal_queue_length(state.video_pool->queue);
        int q;
        for (q=0; q<num; q++)
        {
            MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.video_pool->queue);

            if (!buffer)
                vcos_log_error("Unable to get a required buffer %d from pool queue", q);

            if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS)
                vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
        }


        // Now wait until we need to stop
        vcos_sleep(state.timeout);

error:

        mmal_status_to_int(status);


        // Disable all our ports that are not handled by connections
        check_disable_port(camera_still_port);

        if (state.camera_component)
            mmal_component_disable(state.camera_component);

        //destroy_encoder_component(&state);
        raspipreview_destroy(&state.preview_parameters);
        destroy_camera_component(&state);

    }
    if (status != 0)
        raspicamcontrol_check_configuration(128);

    time(&timer_end);  /* get current time; same as: timer = time(NULL)  */
    cvReleaseImage(&dstImage);
    cvReleaseImage(&pu);
    cvReleaseImage(&pv);
    cvReleaseImage(&py);
    cvReleaseImage(&pu_big);
    cvReleaseImage(&pv_big);

    secondsElapsed = difftime(timer_end,timer_begin);

    printf ("%.f seconds for %d frames : FPS = %f\n", secondsElapsed,nCount,(float)((float)(nCount)/secondsElapsed));

    return 0;
}
/**
 *  buffer header callback function for video
 *
 * @param port Pointer to port from which callback originated
 * @param buffer mmal buffer header pointer
 */
static void video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
	MMAL_BUFFER_HEADER_T *new_buffer;
	RASPIVID_STATE * state = (RASPIVID_STATE *)port->userdata;		

	if (state)
	{
		if (state->finished) {
			vcos_semaphore_post(&state->capture_done_sem);
			return;
		}
		if (buffer->length)
		{
			mmal_buffer_header_mem_lock(buffer);
 
			//
			// *** PR : OPEN CV Stuff here !
			//
			int w=state->width;	// get image size
			int h=state->height;
			int h4=h/4;

			memcpy(state->py->imageData,buffer->data,w*h);	// read Y
		
			if (state->graymode==0)
			{
				memcpy(state->pu->imageData,buffer->data+w*h,w*h4); // read U
				memcpy(state->pv->imageData,buffer->data+w*h+w*h4,w*h4); // read v
			}

			vcos_semaphore_post(&state->capture_done_sem);
			vcos_semaphore_wait(&state->capture_sem);

			mmal_buffer_header_mem_unlock(buffer);
		}
		else
		{
			vcos_log_error("buffer null");
		}
	}
	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(state->video_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");
	}
}
예제 #22
0
/**
 *  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)
{
   int complete = 0;

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

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

   if (pData)
   {
      if (buffer->length)
      {
         mmal_buffer_header_mem_lock(buffer);

		//
		// *** PR : OPEN CV Stuff here !
		//
		// create a CvMat empty structure, with size of the buffer. 
		CvMat* buf = cvCreateMat(1,buffer->length,CV_8UC1);
		// copy buffer from cam to CvMat
		buf->data.ptr = buffer->data;
		// decode image (interpret jpg)
		IplImage *img = cvDecodeImage(buf, CV_LOAD_IMAGE_COLOR);
		
		// we can save it !
		cvSaveImage("foobar.bmp", img,0);
		
		// or display it 
		cvNamedWindow("camcvWin", CV_WINDOW_AUTOSIZE); 
  		cvShowImage("camcvWin", img );
		cvWaitKey(0);

  		//cvReleaseImage(&img );
  
         mmal_buffer_header_mem_unlock(buffer);
      }

      // Now flag if we have completed
      if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED))
         complete = 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;
      MMAL_BUFFER_HEADER_T *new_buffer;

      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");
   }

   if (complete)
      vcos_semaphore_post(&(pData->complete_semaphore));

}
예제 #23
0
/**
 * main
 */
int main(int argc, const char **argv)
{
   // Our main data storage vessel..
   RASPISTILLYUV_STATE state;

   MMAL_STATUS_T status;
   MMAL_PORT_T *camera_preview_port = NULL;
   MMAL_PORT_T *camera_video_port = NULL;
   MMAL_PORT_T *camera_still_port = NULL;
   MMAL_PORT_T *preview_input_port = NULL;
   FILE *output_file = NULL;

   // Register our application with the logging system
   vcos_log_register("RaspiStill", VCOS_LOG_CATEGORY);

   printf("\nRaspiStillYUV Camera App\n");
   printf(  "========================\n\n");

   signal(SIGINT, signal_handler);

   // Do we have any parameters
   if (argc == 1)
   {
      display_valid_parameters();
      exit(0);
   }

   default_status(&state);

   // Parse the command line and put options in to our status structure
   if (parse_cmdline(argc, argv, &state))
   {
      status = -1;
      exit(0);
   }

   if (state.verbose)
      dump_status(&state);

   // OK, we have a nice set of parameters. Now set up our components
   // We have two components. Camera and Preview
   // Camera is different in stills/video, but preview
   // is the same so handed off to a separate module

   if (!create_camera_component(&state))
   {
      vcos_log_error("%s: Failed to create camera component", __func__);
   }
   else if ( !raspipreview_create(&state.preview_parameters))
   {
      vcos_log_error("%s: Failed to create preview component", __func__);
      destroy_camera_component(&state);
   }
   else
   {
      PORT_USERDATA callback_data;

      if (state.verbose)
         printf("Starting component connection stage\n");

      camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
      camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
      camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
      preview_input_port  = state.preview_parameters.preview_component->input[0];

      if (state.preview_parameters.wantPreview )
      {
         if (state.verbose)
         {
            printf("Connecting camera preview port to preview input port\n");
            printf("Starting video preview\n");
         }

         // Connect camera to preview
         status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection);
      }

      if (status == MMAL_SUCCESS)
      {
         VCOS_STATUS_T vcos_status;

         if (state.filename)
         {
            if (state.verbose)
               printf("Opening output file %s\n", state.filename);

            output_file = fopen(state.filename, "wb");
            if (!output_file)
            {
               // Notify user, carry on but discarding encoded output buffers
               vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state.filename);
            }
         }

         // Set up our userdata - this is passed though to the callback where we need the information.
         callback_data.file_handle = output_file;
         callback_data.pstate = &state;

         vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);
         vcos_assert(vcos_status == VCOS_SUCCESS);

         camera_still_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;

         if (state.verbose)
            printf("Enabling camera still output port\n");

         // Enable the camera still output port and tell it its callback function
         status = mmal_port_enable(camera_still_port, camera_buffer_callback);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("Failed to setup camera output");
            goto error;
         }

         if (state.verbose)
            printf("Starting video preview\n");

         // Send all the buffers to the encoder output port
         {
            int num = mmal_queue_length(state.camera_pool->queue);
            int q;
            for (q=0;q<num;q++)
            {
               MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.camera_pool->queue);

               if (!buffer)
                  vcos_log_error("Unable to get a required buffer %d from pool queue", q);

               if (mmal_port_send_buffer(camera_still_port, buffer)!= MMAL_SUCCESS)
                  vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);

            }
         }

         // Now wait until we need to do the capture
         vcos_sleep(state.timeout);

         // And only do the capture if we have specified a filename and its opened OK
         if (output_file)
         {
            if (state.verbose)
               printf("Starting capture\n");

            // Fire the capture
            if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
            {
               vcos_log_error("%s: Failed to start capture", __func__);
            }
            else
            {
               // Wait for capture to complete
               // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error
               // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic
               vcos_semaphore_wait(&callback_data.complete_semaphore);

               if (state.verbose)
                  printf("Finished capture\n");
            }
         }

         vcos_semaphore_delete(&callback_data.complete_semaphore);
      }
      else
      {
         mmal_status_to_int(status);
         vcos_log_error("%s: Failed to connect camera to preview", __func__);
      }

error:

      mmal_status_to_int(status);

      if (state.verbose)
         printf("Closing down\n");

      if (output_file)
         fclose(output_file);

      // Disable all our ports that are not handled by connections
      check_disable_port(camera_video_port);

      if (state.preview_parameters.wantPreview )
         mmal_connection_destroy(state.preview_connection);

      /* Disable components */
      if (state.preview_parameters.preview_component)
         mmal_component_disable(state.preview_parameters.preview_component);

      if (state.camera_component)
         mmal_component_disable(state.camera_component);

      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);

      if (state.verbose)
         printf("Close down completed, all components disconnected, disabled and destroyed\n\n");
   }

   return 0;
}
예제 #24
0
/**
 * main
 */
int main(int argc, const char **argv)
{
   // Our main data storage vessel..
   RASPISTILL_STATE state;

   MMAL_STATUS_T status = -1;
   MMAL_PORT_T *camera_preview_port = NULL;
   MMAL_PORT_T *camera_video_port = NULL;
   MMAL_PORT_T *camera_still_port = NULL;
   MMAL_PORT_T *preview_input_port = NULL;
   MMAL_PORT_T *encoder_input_port = NULL;
   MMAL_PORT_T *encoder_output_port = NULL;

   bcm_host_init();


   signal(SIGINT, signal_handler);

   default_status(&state);

   if (!create_camera_component(&state))
   {
      vcos_log_error("%s: Failed to create camera component", __func__);
   }
   //else if (!raspipreview_create(&state.preview_parameters))
   //{
   //   vcos_log_error("%s: Failed to create preview component", __func__);
    //  destroy_camera_component(&state);
   //}
   else if (!create_encoder_component(&state))
   {
      vcos_log_error("%s: Failed to create encode component", __func__);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);
   }
   else
   {
      PORT_USERDATA callback_data;

		// *** PR : we don't want preview
      camera_preview_port = NULL;//state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
      camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
      camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
      preview_input_port  = state.preview_parameters.preview_component->input[0];
      encoder_input_port  = state.encoder_component->input[0];
      encoder_output_port = state.encoder_component->output[0];

      if (state.preview_parameters.wantPreview )
      {
         if (state.verbose)
         {
            fprintf(stderr, "Connecting camera preview port to preview input port\n");
            fprintf(stderr, "Starting video preview\n");
         }
		// PR : we don't want preview
        // Connect camera to preview
        // status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection);
      }
          VCOS_STATUS_T vcos_status;

         if (state.verbose)
            fprintf(stderr, "Connecting camera stills port to encoder input port\n");

         // Now connect the camera to the encoder
         status = connect_ports(camera_still_port, encoder_input_port, &state.encoder_connection);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
            goto error;
         }

         // Set up our userdata - this is passed though to the callback where we need the information.
         // Null until we open our filename
         callback_data.file_handle = NULL;
         callback_data.pstate = &state;
         vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);

         vcos_assert(vcos_status == VCOS_SUCCESS);

         encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;

         if (state.verbose)
            fprintf(stderr, "Enabling encoder output port\n");

         // Enable the encoder output port and tell it its callback function
         status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("Failed to setup encoder output");
            goto error;
         }

                {
            int num_iterations =  state.timelapse ? state.timeout / state.timelapse : 1;
            int frame;
            for (frame = 1;frame<=num_iterations; frame++)
            {
               if (state.timelapse)
                  vcos_sleep(state.timelapse);
               else
                  vcos_sleep(state.timeout);

                  // Send all the buffers to the encoder output port
                  int num = mmal_queue_length(state.encoder_pool->queue);
                  int q;

                  for (q=0;q<num;q++)
                  {
                     MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue);

                     if (!buffer)
                        vcos_log_error("Unable to get a required buffer %d from pool queue", q);

                     if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS)
                        vcos_log_error("Unable to send a buffer to encoder output port (%d)", q);
                  }

                  
                  if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
                  {
                     vcos_log_error("%s: Failed to start capture", __func__);
                  }
                  else
                  {
                     // Wait for capture to complete
                     // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error
                     // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic
                     vcos_semaphore_wait(&callback_data.complete_semaphore);
                     
                   }

                                

            } // end for (frame)

            vcos_semaphore_delete(&callback_data.complete_semaphore);
         }
      
error:

      mmal_status_to_int(status);

   
      // Disable all our ports that are not handled by connections
      check_disable_port(camera_video_port);
      check_disable_port(encoder_output_port);

		// PR : we don't want preview
      //if (state.preview_parameters.wantPreview )
        // mmal_connection_destroy(state.preview_connection);

      mmal_connection_destroy(state.encoder_connection);

      /* Disable components */
      if (state.encoder_component)
         mmal_component_disable(state.encoder_component);

      if (state.preview_parameters.preview_component)
         mmal_component_disable(state.preview_parameters.preview_component);

      if (state.camera_component)
         mmal_component_disable(state.camera_component);

      destroy_encoder_component(&state);
      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);

      if (state.verbose)
         fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n");
   }
   if (status != 0)
      raspicamcontrol_check_configuration(128);



   return 0;
}
예제 #25
0
int main(int argc, char **argv)
{
   MMAL_STATUS_T status = MMAL_EINVAL;
   MMAL_COMPONENT_T *decoder = 0;
   MMAL_POOL_T *pool_in = 0, *pool_out = 0;
   unsigned int count;

   if (argc < 2)
   {
      fprintf(stderr, "invalid arguments\n");
      return -1;
   }

#ifndef WIN32
   // TODO verify that we dont really need to call bcm_host_init
   bcm_host_init();
#endif

   vcos_semaphore_create(&context.semaphore, "example", 1);

   SOURCE_OPEN(argv[1]);

   /* Create the decoder component.
    * This specific component exposes 2 ports (1 input and 1 output). Like most components
    * its expects the format of its input port to be set by the client in order for it to
    * know what kind of data it will be fed. */
   status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder);
   CHECK_STATUS(status, "failed to create decoder");

   /* Set format of video decoder input port */
   MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
   format_in->type = MMAL_ES_TYPE_VIDEO;
   format_in->encoding = MMAL_ENCODING_H264;
   format_in->es->video.width = 1280;
   format_in->es->video.height = 720;
   format_in->es->video.frame_rate.num = 30;
   format_in->es->video.frame_rate.den = 1;
   format_in->es->video.par.num = 1;
   format_in->es->video.par.den = 1;
   /* If the data is known to be framed then the following flag should be set:
    * format_in->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; */

   SOURCE_READ_CODEC_CONFIG_DATA(codec_header_bytes, codec_header_bytes_size);
   status = mmal_format_extradata_alloc(format_in, codec_header_bytes_size);
   CHECK_STATUS(status, "failed to allocate extradata");
   format_in->extradata_size = codec_header_bytes_size;
   if (format_in->extradata_size)
      memcpy(format_in->extradata, codec_header_bytes, format_in->extradata_size);

   status = mmal_port_format_commit(decoder->input[0]);
   CHECK_STATUS(status, "failed to commit format");

   /* Display the output port format */
   MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
   fprintf(stderr, "%s\n", decoder->output[0]->name);
   fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding);
   fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate,
           !!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED));
   fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata);
   fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n",
           format_out->es->video.width, format_out->es->video.height,
           format_out->es->video.crop.x, format_out->es->video.crop.y,
           format_out->es->video.crop.width, format_out->es->video.crop.height);

   /* The format of both ports is now set so we can get their buffer requirements and create
    * our buffer headers. We use the buffer pool API to create these. */
   decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min;
   decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min;
   decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min;
   decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min;
   pool_in = mmal_pool_create(decoder->input[0]->buffer_num,
                              decoder->input[0]->buffer_size);
   pool_out = mmal_pool_create(decoder->output[0]->buffer_num,
                               decoder->output[0]->buffer_size);

   /* Create a queue to store our decoded video frames. The callback we will get when
    * a frame has been decoded will put the frame into this queue. */
   context.queue = mmal_queue_create();

   /* Store a reference to our context in each port (will be used during callbacks) */
   decoder->input[0]->userdata = (void *)&context;
   decoder->output[0]->userdata = (void *)&context;

   /* Enable all the input port and the output port.
    * The callback specified here is the function which will be called when the buffer header
    * we sent to the component has been processed. */
   status = mmal_port_enable(decoder->input[0], input_callback);
   CHECK_STATUS(status, "failed to enable input port");
   status = mmal_port_enable(decoder->output[0], output_callback);
   CHECK_STATUS(status, "failed to enable output port");

   /* Component won't start processing data until it is enabled. */
   status = mmal_component_enable(decoder);
   CHECK_STATUS(status, "failed to enable component");

   /* Start decoding */
   fprintf(stderr, "start decoding\n");

   /* This is the main processing loop */
   for (count = 0; count < 500; count++)
   {
      MMAL_BUFFER_HEADER_T *buffer;

      /* Wait for buffer headers to be available on either of the decoder ports */
      vcos_semaphore_wait(&context.semaphore);

      /* Send data to decode to the input port of the video decoder */
      if ((buffer = mmal_queue_get(pool_in->queue)) != NULL)
      {
         SOURCE_READ_DATA_INTO_BUFFER(buffer);
         if (!buffer->length)
            break;

         fprintf(stderr, "sending %i bytes\n", (int)buffer->length);
         status = mmal_port_send_buffer(decoder->input[0], buffer);
         CHECK_STATUS(status, "failed to send buffer");
      }

      /* Get our decoded frames */
      while ((buffer = mmal_queue_get(context.queue)) != NULL)
      {
         /* We have a frame, do something with it (why not display it for instance?).
          * Once we're done with it, we release it. It will automatically go back
          * to its original pool so it can be reused for a new video frame.
          */
         fprintf(stderr, "decoded frame\n");
         mmal_buffer_header_release(buffer);
      }

      /* Send empty buffers to the output port of the decoder */
      while ((buffer = mmal_queue_get(pool_out->queue)) != NULL)
      {
         status = mmal_port_send_buffer(decoder->output[0], buffer);
         CHECK_STATUS(status, "failed to send buffer");
      }
   }

   /* Stop decoding */
   fprintf(stderr, "stop decoding\n");

   /* Stop everything. Not strictly necessary since mmal_component_destroy()
    * will do that anyway */
   mmal_port_disable(decoder->input[0]);
   mmal_port_disable(decoder->output[0]);
   mmal_component_disable(decoder);

 error:
   /* Cleanup everything */
   if (decoder)
      mmal_component_destroy(decoder);
   if (pool_in)
      mmal_pool_destroy(pool_in);
   if (pool_out)
      mmal_pool_destroy(pool_out);
   if (context.queue)
      mmal_queue_destroy(context.queue);

   SOURCE_CLOSE();
   vcos_semaphore_delete(&context.semaphore);
   return status == MMAL_SUCCESS ? 0 : -1;
}
예제 #26
0
파일: MMALCodec.cpp 프로젝트: Avbrella/xbmc
int CMMALVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
{
  //if (g_advancedSettings.CanLogComponent(LOGVIDEO))
  //  CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f dts_queue(%d) ready_queue(%d) busy_queue(%d)",
  //    CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_dts_queue.size(), m_output_ready.size(), m_output_busy);

  unsigned int demuxer_bytes = 0;
  uint8_t *demuxer_content = NULL;
  MMAL_BUFFER_HEADER_T *buffer;
  MMAL_STATUS_T status;

  while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer)
    Recycle(buffer);
  // we need to queue then de-queue the demux packet, seems silly but
  // mmal might not have an input buffer available when we are called
  // and we must store the demuxer packet and try again later.
  // try to send any/all demux packets to mmal decoder.
  unsigned space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size;
  if (pData && m_demux_queue.empty() && space >= (unsigned int)iSize)
  {
    demuxer_bytes = iSize;
    demuxer_content = pData;
  }
  else if (pData && iSize)
  {
    mmal_demux_packet demux_packet;
    demux_packet.dts = dts;
    demux_packet.pts = pts;
    demux_packet.size = iSize;
    demux_packet.buff = new uint8_t[iSize];
    memcpy(demux_packet.buff, pData, iSize);
    m_demux_queue_length += demux_packet.size;
    m_demux_queue.push(demux_packet);
  }

  uint8_t *buffer_to_free = NULL;

  while (1)
  {
     while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer)
       Recycle(buffer);

     space = mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size;
     if (!demuxer_bytes && !m_demux_queue.empty())
     {
       mmal_demux_packet &demux_packet = m_demux_queue.front();
       if (space >= (unsigned int)demux_packet.size)
       {
         // need to lock here to retrieve an input buffer and pop the queue
         m_demux_queue_length -= demux_packet.size;
         m_demux_queue.pop();
         demuxer_bytes = (unsigned int)demux_packet.size;
         demuxer_content = demux_packet.buff;
         buffer_to_free = demux_packet.buff;
         dts = demux_packet.dts;
         pts = demux_packet.pts;
       }
     }
     if (demuxer_content)
     {
       // 500ms timeout
       buffer = mmal_queue_timedwait(m_dec_input_pool->queue, 500);
       if (!buffer)
       {
         CLog::Log(LOGERROR, "%s::%s - mmal_queue_get failed", CLASSNAME, __func__);
         return VC_ERROR;
       }

       mmal_buffer_header_reset(buffer);
       buffer->cmd = 0;
       if (m_startframe && pts == DVD_NOPTS_VALUE)
         pts = 0;
       buffer->pts = pts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pts;
       buffer->dts = dts == DVD_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : dts;
       buffer->length = demuxer_bytes > buffer->alloc_size ? buffer->alloc_size : demuxer_bytes;
       buffer->user_data = (void *)m_decode_frame_number;
       // set a flag so we can identify primary frames from generated frames (deinterlace)
       buffer->flags = MMAL_BUFFER_HEADER_FLAG_USER0;

       // Request decode only (maintain ref frames, but don't return a picture)
       if (m_drop_state)
         buffer->flags |= MMAL_BUFFER_HEADER_FLAG_DECODEONLY;

       memcpy(buffer->data, demuxer_content, buffer->length);
       demuxer_bytes   -= buffer->length;
       demuxer_content += buffer->length;

       if (demuxer_bytes == 0)
         buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;

       if (g_advancedSettings.CanLogComponent(LOGVIDEO))
         CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d/%-6d dts:%.3f pts:%.3f flags:%x dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)",
            CLASSNAME, __func__, buffer, buffer->length, demuxer_bytes, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, buffer->flags, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
       assert((int)buffer->length > 0);
       status = mmal_port_send_buffer(m_dec_input, buffer);
       if (status != MMAL_SUCCESS)
       {
         CLog::Log(LOGERROR, "%s::%s Failed send buffer to decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status));
         return VC_ERROR;
       }

       if (demuxer_bytes == 0)
       {
         m_decode_frame_number++;
         m_startframe = true;
         if (m_drop_state)
         {
           m_droppedPics += m_deint ? 2:1;
         }
         else
         {
           // only push if we are successful with feeding mmal
           pthread_mutex_lock(&m_output_mutex);
           m_dts_queue.push(dts);
           assert(m_dts_queue.size() < 5000);
           pthread_mutex_unlock(&m_output_mutex);
         }
         if (m_changed_count_dec != m_changed_count)
         {
           if (g_advancedSettings.CanLogComponent(LOGVIDEO))
             CLog::Log(LOGDEBUG, "%s::%s format changed frame:%d(%d)", CLASSNAME, __func__, m_changed_count_dec, m_changed_count);
           m_changed_count_dec = m_changed_count;
           if (!change_dec_output_format())
           {
             CLog::Log(LOGERROR, "%s::%s - change_dec_output_format() failed", CLASSNAME, __func__);
             return VC_ERROR;
           }
         }
         EDEINTERLACEMODE deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
         EINTERLACEMETHOD interlace_method = g_renderManager.AutoInterlaceMethod(CMediaSettings::Get().GetCurrentVideoSettings().m_InterlaceMethod);

         bool deinterlace = m_interlace_mode != MMAL_InterlaceProgressive;

         if (deinterlace_request == VS_DEINTERLACEMODE_OFF)
           deinterlace = false;
         else if (deinterlace_request == VS_DEINTERLACEMODE_FORCE)
           deinterlace = true;

         if (((deinterlace && interlace_method != m_interlace_method) || !deinterlace) && m_deint)
           DestroyDeinterlace();
         if (deinterlace && !m_deint)
           CreateDeinterlace(interlace_method);

         if (buffer_to_free)
         {
           delete [] buffer_to_free;
           buffer_to_free = NULL;
           demuxer_content = NULL;
           continue;
         }
         while (buffer = mmal_queue_get(m_dec_output_pool->queue), buffer)
           Recycle(buffer);
       }
    }
    if (!demuxer_bytes)
      break;
  }
  int ret = 0;
  if (!m_output_ready.empty())
  {
    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
      CLog::Log(LOGDEBUG, "%s::%s - got space for output: demux_queue(%d) space(%d)", CLASSNAME, __func__, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
    ret |= VC_PICTURE;
  }
  if (mmal_queue_length(m_dec_input_pool->queue) > 0 && !m_demux_queue_length)
  {
    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
      CLog::Log(LOGDEBUG, "%s::%s -  got output picture:%d", CLASSNAME, __func__, m_output_ready.size());
    ret |= VC_BUFFER;
  }
  if (!ret)
  {
    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
      CLog::Log(LOGDEBUG, "%s::%s - Nothing to do: dts_queue(%d) ready_queue(%d) busy_queue(%d) demux_queue(%d) space(%d)",
        CLASSNAME, __func__, m_dts_queue.size(), m_output_ready.size(), m_output_busy, m_demux_queue_length, mmal_queue_length(m_dec_input_pool->queue) * m_dec_input->buffer_size);
    Sleep(10); // otherwise we busy spin
  }
  return ret;
}
예제 #27
0
/**
 * main
 */
int main(int argc, const char **argv)
{
   // Our main data storage vessel..
   RASPISTILLYUV_STATE state;
   int exit_code = EX_OK;

   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_PORT_T *camera_preview_port = NULL;
   MMAL_PORT_T *camera_video_port = NULL;
   MMAL_PORT_T *camera_still_port = NULL;
   MMAL_PORT_T *preview_input_port = NULL;
   FILE *output_file = NULL;

   bcm_host_init();

   // Register our application with the logging system
   vcos_log_register("RaspiStill", VCOS_LOG_CATEGORY);

   signal(SIGINT, signal_handler);

   // Disable USR1 for the moment - may be reenabled if go in to signal capture mode
   signal(SIGUSR1, SIG_IGN);

   default_status(&state);

   // Do we have any parameters
   if (argc == 1)
   {
      fprintf(stdout, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING);

      display_valid_parameters(basename(argv[0]));
      exit(EX_USAGE);
   }

   default_status(&state);

   // Parse the command line and put options in to our status structure
   if (parse_cmdline(argc, argv, &state))
   {
      status = -1;
      exit(EX_USAGE);
   }

   if (state.verbose)
   {
      fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING);
      dump_status(&state);
   }

   // OK, we have a nice set of parameters. Now set up our components
   // We have two components. Camera and Preview
   // Camera is different in stills/video, but preview
   // is the same so handed off to a separate module

   if ((status = create_camera_component(&state)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create camera component", __func__);
      exit_code = EX_SOFTWARE;
   }
   else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS)
   {
      vcos_log_error("%s: Failed to create preview component", __func__);
      destroy_camera_component(&state);
      exit_code = EX_SOFTWARE;
   }
   else
   {
      PORT_USERDATA callback_data;

      if (state.verbose)
         fprintf(stderr, "Starting component connection stage\n");

      camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
      camera_video_port   = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT];
      camera_still_port   = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT];

      // Note we are lucky that the preview and null sink components use the same input port
      // so we can simple do this without conditionals
      preview_input_port  = state.preview_parameters.preview_component->input[0];

      // Connect camera to preview (which might be a null_sink if no preview required)
      status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection);

      if (status == MMAL_SUCCESS)
      {
         VCOS_STATUS_T vcos_status;

         // Set up our userdata - this is passed though to the callback where we need the information.
         // Null until we open our filename
         callback_data.file_handle = NULL;
         callback_data.pstate = &state;

         vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);
         vcos_assert(vcos_status == VCOS_SUCCESS);

         camera_still_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;

         if (state.verbose)
            fprintf(stderr, "Enabling camera still output port\n");

         // Enable the camera still output port and tell it its callback function
         status = mmal_port_enable(camera_still_port, camera_buffer_callback);

         if (status != MMAL_SUCCESS)
         {
            vcos_log_error("Failed to setup camera output");
            goto error;
         }

         if (state.verbose)
            fprintf(stderr, "Starting video preview\n");


         int frame, keep_looping = 1;
         FILE *output_file = NULL;
         char *use_filename = NULL;      // Temporary filename while image being written
         char *final_filename = NULL;    // Name that file gets once writing complete

         frame = 0;

         while (keep_looping)
         {
             keep_looping = wait_for_next_frame(&state, &frame);

            // Open the file
            if (state.filename)
            {
               if (state.filename[0] == '-')
               {
                  output_file = stdout;

                  // Ensure we don't upset the output stream with diagnostics/info
                  state.verbose = 0;
               }
               else
               {
                  vcos_assert(use_filename == NULL && final_filename == NULL);
                  status = create_filenames(&final_filename, &use_filename, state.filename, frame);
                  if (status  != MMAL_SUCCESS)
                  {
                     vcos_log_error("Unable to create filenames");
                     goto error;
                  }

                  if (state.verbose)
                     fprintf(stderr, "Opening output file %s\n", final_filename);
                     // Technically it is opening the temp~ filename which will be ranamed to the final filename

                  output_file = fopen(use_filename, "wb");

                  if (!output_file)
                  {
                     // Notify user, carry on but discarding encoded output buffers
                     vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, use_filename);
                  }
               }

               callback_data.file_handle = output_file;
            }

            if (output_file)
            {
               int num, q;

               // There is a possibility that shutter needs to be set each loop.
               if (mmal_status_to_int(mmal_port_parameter_set_uint32(state.camera_component->control, MMAL_PARAMETER_SHUTTER_SPEED, state.camera_parameters.shutter_speed) != MMAL_SUCCESS))
                  vcos_log_error("Unable to set shutter speed");


               // Send all the buffers to the camera output port
               num = mmal_queue_length(state.camera_pool->queue);

               for (q=0;q<num;q++)
               {
                  MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.camera_pool->queue);

                  if (!buffer)
                     vcos_log_error("Unable to get a required buffer %d from pool queue", q);

                  if (mmal_port_send_buffer(camera_still_port, buffer)!= MMAL_SUCCESS)
                     vcos_log_error("Unable to send a buffer to camera output port (%d)", q);
               }

               if (state.burstCaptureMode && frame==1)
               {
                  mmal_port_parameter_set_boolean(state.camera_component->control,  MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1);
               }

               if (state.verbose)
                  fprintf(stderr, "Starting capture %d\n", frame);

               if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
               {
                  vcos_log_error("%s: Failed to start capture", __func__);
               }
               else
               {
                  // Wait for capture to complete
                  // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error
                  // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic
                  vcos_semaphore_wait(&callback_data.complete_semaphore);
                  if (state.verbose)
                     fprintf(stderr, "Finished capture %d\n", frame);
               }

               // Ensure we don't die if get callback with no open file
               callback_data.file_handle = NULL;

               if (output_file != stdout)
               {
                  rename_file(&state, output_file, final_filename, use_filename, frame);
               }
            }

            if (use_filename)
            {
               free(use_filename);
               use_filename = NULL;
            }
            if (final_filename)
            {
               free(final_filename);
               final_filename = NULL;
            }
         } // end for (frame)
         
         vcos_semaphore_delete(&callback_data.complete_semaphore);
      }
      else
      {
         mmal_status_to_int(status);
         vcos_log_error("%s: Failed to connect camera to preview", __func__);
      }

error:

      mmal_status_to_int(status);

      if (state.verbose)
         fprintf(stderr, "Closing down\n");

      if (output_file)
         fclose(output_file);

      // Disable all our ports that are not handled by connections
      check_disable_port(camera_video_port);

      if (state.preview_connection)
         mmal_connection_destroy(state.preview_connection);

      /* Disable components */
      if (state.preview_parameters.preview_component)
         mmal_component_disable(state.preview_parameters.preview_component);

      if (state.camera_component)
         mmal_component_disable(state.camera_component);

      raspipreview_destroy(&state.preview_parameters);
      destroy_camera_component(&state);

      if (state.verbose)
         fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n");
   }

   if (status != MMAL_SUCCESS)
      raspicamcontrol_check_configuration(128);

   return exit_code;
}
예제 #28
0
/** Start playback on an instance of mmalplay.
 * Note: this is test code. Do not use it in your app. It *will* change or even be removed without notice.
 */
MMAL_STATUS_T mmalplay_play(MMALPLAY_T *ctx)
{
   MMAL_STATUS_T status = MMAL_SUCCESS;
   unsigned int i;

   LOG_TRACE("%p, %s", ctx, ctx->uri);

   ctx->time_playback = vcos_getmicrosecs();

   /* Start the clocks */
   if (ctx->video_clock)
      mmal_port_parameter_set_boolean(ctx->video_clock, MMAL_PARAMETER_CLOCK_ACTIVE, MMAL_TRUE);
   if (ctx->audio_clock)
      mmal_port_parameter_set_boolean(ctx->audio_clock, MMAL_PARAMETER_CLOCK_ACTIVE, MMAL_TRUE);

   while(1)
   {
      MMAL_BUFFER_HEADER_T *buffer;

      vcos_semaphore_wait(&ctx->event);
      if (ctx->stop || ctx->status != MMAL_SUCCESS)
      {
         status = ctx->status;
         break;
      }

      /* Loop through all the connections */
      for (i = 0; i < ctx->connection_num; i++)
      {
         MMAL_CONNECTION_T *connection = ctx->connection[i];

         if (connection->flags & MMAL_CONNECTION_FLAG_TUNNELLING)
            continue; /* Nothing else to do in tunnelling mode */

         /* Send any queued buffer to the next component */
         buffer = mmal_queue_get(connection->queue);
         while (buffer)
         {
            if (buffer->cmd)
            {
               status = mmalplay_event_handle(connection, connection->out, buffer);
               if (status != MMAL_SUCCESS)
                  goto error;
               buffer = mmal_queue_get(connection->queue);
               continue;
            }

            /* Code specific to handling of the video output port */
            if (connection->out == ctx->video_out_port)
            {
               if (buffer->length)
                  ctx->decoded_frames++;

               if (ctx->options.stepping)
                  getchar();
            }

            status = mmal_port_send_buffer(connection->in, buffer);
            if (status != MMAL_SUCCESS)
            {
               LOG_ERROR("mmal_port_send_buffer failed (%i)", status);
               mmal_queue_put_back(connection->queue, buffer);
               goto error;
            }
            buffer = mmal_queue_get(connection->queue);
         }

         /* Send empty buffers to the output port of the connection */
         buffer = connection->pool ? mmal_queue_get(connection->pool->queue) : NULL;
         while (buffer)
         {
            status = mmal_port_send_buffer(connection->out, buffer);
            if (status != MMAL_SUCCESS)
            {
               LOG_ERROR("mmal_port_send_buffer failed (%i)", status);
               mmal_queue_put_back(connection->pool->queue, buffer);
               goto error;
            }
            buffer = mmal_queue_get(connection->pool->queue);
         }
      }
   }

 error:
   ctx->time_playback = vcos_getmicrosecs() - ctx->time_playback;

   /* For still images we want to pause a bit once they are displayed */
   if (ctx->is_still_image && status == MMAL_SUCCESS)
      vcos_sleep(MMALPLAY_STILL_IMAGE_PAUSE);

   return status;
}
예제 #29
0
// Fetch a decoded buffer and place it into the frame parameter.
static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_BUFFER_HEADER_T *buffer = NULL;
    MMAL_STATUS_T status = 0;
    int ret = 0;

    if (ctx->eos_received)
        goto done;

    while (1) {
        // To ensure decoding in lockstep with a constant delay between fed packets
        // and output frames, we always wait until an output buffer is available.
        // Except during start we don't know after how many input packets the decoder
        // is going to return the first buffer, and we can't distinguish decoder
        // being busy from decoder waiting for input. So just poll at the start and
        // keep feeding new data to the buffer.
        // We are pretty sure the decoder will produce output if we sent more input
        // frames than what a H.264 decoder could logically delay. This avoids too
        // excessive buffering.
        // We also wait if we sent eos, but didn't receive it yet (think of decoding
        // stream with a very low number of frames).
        if (avpriv_atomic_int_get(&ctx->packets_buffered) > MAX_DELAYED_FRAMES ||
            (ctx->packets_sent && ctx->eos_sent)) {
            // MMAL will ignore broken input packets, which means the frame we
            // expect here may never arrive. Dealing with this correctly is
            // complicated, so here's a hack to avoid that it freezes forever
            // in this unlikely situation.
            buffer = mmal_queue_timedwait(ctx->queue_decoded_frames, 100);
            if (!buffer) {
                av_log(avctx, AV_LOG_ERROR, "Did not get output frame from MMAL.\n");
                ret = AVERROR_UNKNOWN;
                goto done;
            }
        } else {
            buffer = mmal_queue_get(ctx->queue_decoded_frames);
            if (!buffer)
                goto done;
        }

        ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);
        if (ctx->eos_received)
            goto done;

        if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
            MMAL_COMPONENT_T *decoder = ctx->decoder;
            MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);
            MMAL_BUFFER_HEADER_T *stale_buffer;

            av_log(avctx, AV_LOG_INFO, "Changing output format.\n");

            if ((status = mmal_port_disable(decoder->output[0])))
                goto done;

            while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))
                mmal_buffer_header_release(stale_buffer);

            mmal_format_copy(decoder->output[0]->format, ev->format);

            if ((ret = ffmal_update_format(avctx)) < 0)
                goto done;

            if ((status = mmal_port_enable(decoder->output[0], output_callback)))
                goto done;

            if ((ret = ffmmal_fill_output_port(avctx)) < 0)
                goto done;

            if ((ret = ffmmal_fill_input_port(avctx)) < 0)
                goto done;

            mmal_buffer_header_release(buffer);
            continue;
        } else if (buffer->cmd) {
            char s[20];
            av_get_codec_tag_string(s, sizeof(s), buffer->cmd);
            av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", s);
            goto done;
        } else if (buffer->length == 0) {
            // Unused output buffer that got drained after format change.
            mmal_buffer_header_release(buffer);
            continue;
        }

        ctx->frames_output++;

        if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0)
            goto done;

        *got_frame = 1;
        break;
    }

done:
    if (buffer)
        mmal_buffer_header_release(buffer);
    if (status && ret >= 0)
        ret = AVERROR_UNKNOWN;
    return ret;
}
예제 #30
0
파일: codec.c 프로젝트: Adatan/vlc
static int send_output_buffer(decoder_t *dec)
{
    decoder_sys_t *sys = dec->p_sys;
    MMAL_BUFFER_HEADER_T *buffer;
    picture_sys_t *p_sys;
    picture_t *picture;
    MMAL_STATUS_T status;
    unsigned buffer_size = 0;
    int ret = 0;

    if (!sys->output->is_enabled)
        return VLC_EGENERIC;

    /* If local output pool is allocated, use it - this is only the case for
     * non-opaque modes */
    if (sys->output_pool) {
        buffer = mmal_queue_get(sys->output_pool->queue);
        if (!buffer) {
            msg_Warn(dec, "Failed to get new buffer");
            return VLC_EGENERIC;
        }
    }

    picture = decoder_NewPicture(dec);
    if (!picture) {
        msg_Warn(dec, "Failed to get new picture");
        ret = -1;
        goto err;
    }

    p_sys = picture->p_sys;
    for (int i = 0; i < picture->i_planes; i++)
        buffer_size += picture->p[i].i_lines * picture->p[i].i_pitch;

    if (sys->output_pool) {
        mmal_buffer_header_reset(buffer);
        buffer->user_data = picture;
        buffer->alloc_size = sys->output->buffer_size;
        if (buffer_size < sys->output->buffer_size) {
            msg_Err(dec, "Retrieved picture with too small data block (%d < %d)",
                    buffer_size, sys->output->buffer_size);
            ret = VLC_EGENERIC;
            goto err;
        }

        if (!sys->opaque)
            buffer->data = picture->p[0].p_pixels;
    } else {
        buffer = p_sys->buffer;
        if (!buffer) {
            msg_Warn(dec, "Picture has no buffer attached");
            picture_Release(picture);
            return VLC_EGENERIC;
        }
        buffer->data = p_sys->buffer->data;
    }
    buffer->cmd = 0;

    status = mmal_port_send_buffer(sys->output, buffer);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to send buffer to output port (status=%"PRIx32" %s)",
                status, mmal_status_to_string(status));
        ret = -1;
        goto err;
    }
    atomic_fetch_add(&sys->output_in_transit, 1);

    return ret;

err:
    if (picture)
        picture_Release(picture);
    if (sys->output_pool && buffer) {
        buffer->data = NULL;
        mmal_buffer_header_release(buffer);
    }
    return ret;
}