Ejemplo n.º 1
0
void PiCam::video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {
    PiCam* cam = (PiCam*) port->userdata;
    if (buffer->length) {
	    mmal_buffer_header_mem_lock(buffer);
        memcpy(cam->frame.data, buffer->data, 3*cam->width*cam->height);
        //memcpy(cam->frame.data, buffer->data, cam->width*cam->height);
        mmal_buffer_header_mem_unlock(buffer);
        cam->callback(cam->frame);
        //cv::waitKey(1);
    }
    
    // release buffer back to the pool
    mmal_buffer_header_release(buffer);

    /*
    if (vcos_semaphore_trywait(&(cam->frame_semaphore)) != VCOS_SUCCESS) {
        vcos_semaphore_post(&(cam->frame_semaphore));
    }
    */


    // 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(cam->videoPool->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");
    }
}
Ejemplo n.º 2
0
static void encoder_output_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {
    MMAL_BUFFER_HEADER_T *new_buffer;
    PORT_USERDATA *userdata = (PORT_USERDATA *) port->userdata;
    MMAL_POOL_T *pool = userdata->encoder_output_pool;
    //fprintf(stderr, "INFO:%s\n", __func__);

    mmal_buffer_header_mem_lock(buffer);
    fwrite(buffer->data, 1, buffer->length, stdout);
    mmal_buffer_header_mem_unlock(buffer);

    mmal_buffer_header_release(buffer);
    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, "Unable to return a buffer to the video port\n");
        }
    }
}
Ejemplo n.º 3
0
static void encoder_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
        USERDATA_T *data;

        vcos_assert((data = (USERDATA_T *)port->userdata) != NULL
			&& "No data associated with this buffer");

        vcos_assert((buffer && buffer->length > 0)
		&& "buffer == NULL or buffer has size 0");

	mmal_buffer_header_mem_lock(buffer);
	vcos_assert((fwrite(buffer->data, 1, buffer->length, data->file_handle) == buffer->length) 
		&& "Failed writing buffer to file (different size returned)");
	mmal_buffer_header_mem_unlock(buffer);

        mmal_buffer_header_release(buffer);

	// send one buffer back
        if (port->is_enabled)
        {
                MMAL_BUFFER_HEADER_T *new_buffer;
                if ((new_buffer = mmal_queue_get(data->pool->queue)) != NULL )
                        vcos_assert((mmal_port_send_buffer(port, new_buffer) == MMAL_SUCCESS)
                                && "Unable to return buffer to encoder port");
        }
}
Ejemplo n.º 4
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)
   {
      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;
      }

      // 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_SUCCESS;
      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));

}
Ejemplo n.º 5
0
/* Send a payload buffer to a connected port/client */
static MMAL_STATUS_T mmal_port_clock_forward_payload(MMAL_PORT_T *port, const MMAL_CLOCK_PAYLOAD_T *payload)
{
   MMAL_STATUS_T status;
   MMAL_BUFFER_HEADER_T *buffer;

   buffer = mmal_queue_get(port->priv->module->queue);
   if (!buffer)
   {
      LOG_ERROR("no free buffers available");
      return MMAL_ENOSPC;
   }

   status = mmal_buffer_header_mem_lock(buffer);
   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("failed to lock buffer %s", mmal_status_to_string(status));
      mmal_queue_put_back(port->priv->module->queue, buffer);
      goto end;
   }
   buffer->length = sizeof(MMAL_CLOCK_PAYLOAD_T);
   memcpy(buffer->data, payload, buffer->length);
   mmal_buffer_header_mem_unlock(buffer);

   mmal_port_buffer_header_callback(port, buffer);

end:
   return status;
}
Ejemplo n.º 6
0
/* This will output a frame that can be used for OpenCV */
IplImage* cvQueryRPiFrame(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)
		{
			/*Convert buffer to RGB IplImage*/
						
			mmal_buffer_header_mem_lock(buffer);

			int w=pData->pstate->width;	// get image size
			int h=pData->pstate->height;
			int h4=h/4;
			
			memcpy(yCSI_CAM->imageData,buffer->data,w*h);
			memcpy(uCSI_CAM->imageData,buffer->data+w*h,w*h4);
			memcpy(vCSI_CAM->imageData,buffer->data+w*h+w*h4,w*h4);
			
			cvResize(uCSI_CAM, uCSI_CAM_BIG, CV_INTER_NN);
			cvResize(vCSI_CAM, vCSI_CAM_BIG, CV_INTER_NN);  //CV_INTER_LINEAR looks better but it's slower
			cvMerge(yCSI_CAM, uCSI_CAM_BIG, vCSI_CAM_BIG, NULL, CSI_CAM_IMAGE);
	
			cvCvtColor(CSI_CAM_IMAGE,CSI_CAM_DSTIMAGE,CV_YCrCb2RGB);	// convert in RGB color space (slow)
			
			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");
   }
   
   return CSI_CAM_DSTIMAGE;
}
Ejemplo n.º 7
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 pixelSize = state->monochrome ? 1 : 3;
			memcpy(state->dstImage->imageData,buffer->data,w*h*pixelSize);	

			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");
	}
}
Ejemplo n.º 8
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)
   {
      if (buffer->length)
      {
         mmal_buffer_header_mem_lock(buffer);
         int i;
         for( i = 0; i < buffer->length; i++ )
            pData->data_dump[i] = buffer->data[i];

         mmal_buffer_header_mem_unlock(buffer);
      }

      // 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));
   }
}
Ejemplo n.º 9
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;

   // 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;

      vcos_assert(pData->file_handle);

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

         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");
   }
}
Ejemplo n.º 10
0
static void jpegencoder_buffer_callback (MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {

  int bytes_written = buffer->length;
  char *filename_temp, *filename_temp2;

  if(mjpeg_cnt == 0) {
    if(!jpegoutput_file) {
      asprintf(&filename_temp, jpeg_filename, image_cnt);
      asprintf(&filename_temp2, "%s.part", filename_temp);
      jpegoutput_file = fopen(filename_temp2, "wb");
      free(filename_temp);
      free(filename_temp2);
      if(!jpegoutput_file) error("Could not open mjpeg-destination");
    }
    if(buffer->length) {
      mmal_buffer_header_mem_lock(buffer);
      bytes_written = fwrite(buffer->data, 1, buffer->length, jpegoutput_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) {
    mjpeg_cnt++;
    if(mjpeg_cnt == divider) {
      fclose(jpegoutput_file);
      jpegoutput_file = NULL;
      asprintf(&filename_temp, jpeg_filename, image_cnt);
      asprintf(&filename_temp2, "%s.part", filename_temp);
      rename(filename_temp2, filename_temp);
      free(filename_temp);
      free(filename_temp2);
      image_cnt++;
      mjpeg_cnt = 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_jpegencoder->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");
  }

}
Ejemplo n.º 11
0
void Private_Impl::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;

    bool hasGrabbed = false;
    
    //pData->_mutex.lock();
    std::unique_lock<std::mutex> lck ( pData->_mutex );
    if ( pData ) {
        if ( pData->wantToGrab &&  buffer->length ) {
            mmal_buffer_header_mem_lock ( buffer );
            //printf("pdata buff length%d\n",pData->_buffData.size);
            pData->_buffData.resize ( buffer->length );


            memcpy ( pData->_buffData.data, buffer->data, buffer->length );
            pData->npts = buffer->pts;
            //tst=buffer->pts;
            pData->wantToGrab = false;
            hasGrabbed = true;
            mmal_buffer_header_mem_unlock ( buffer );
        }

    }
    //pData->_mutex.unlock();
    // if ( hasGrabbed ) pData->Thcond.BroadCast(); //wake up waiting client

    // 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 )
            printf ( "Unable to return a buffer to the encoder port\n" );
    }

    if ( pData->pstate->shutterSpeed != 0 )
        mmal_port_parameter_set_uint32 ( pData->pstate->camera_component->control, MMAL_PARAMETER_SHUTTER_SPEED, pData->pstate->shutterSpeed ) ;
    if ( hasGrabbed ) pData->Thcond.BroadCast(); //wake up waiting client

}
Ejemplo n.º 12
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)
{
   MMAL_STATUS_T status;

   // 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);

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

         mmal_buffer_header_mem_unlock(buffer);
      }

      // What about error conditions?
      if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_EOS | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED))
      {
         vcos_semaphore_post(&(pData->complete_semaphore));
      }
   }
   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_BUFFER_HEADER_T *new_buffer = mmal_queue_get(pData->pstate->camera_pool->queue);

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

      if (status != MMAL_SUCCESS)
         vcos_log_error("Unable to return the buffer to the camera still port");
   }
}
Ejemplo n.º 13
0
static void
h264_header_save(MMAL_BUFFER_HEADER_T *mmalbuf)
	{
	VideoCircularBuffer *vcb = &video_circular_buffer;

	if (vcb->h264_header_position + mmalbuf->length > H264_MAX_HEADER_SIZE)
		log_printf("h264 header bytes error.\n");
	else
		{
		/* Save header bytes to write to .mp4 video files
		*/
		mmal_buffer_header_mem_lock(mmalbuf);
		memcpy(vcb->h264_header + vcb->h264_header_position,
					mmalbuf->data, mmalbuf->length);
		mmal_buffer_header_mem_unlock(mmalbuf);
		vcb->h264_header_position += mmalbuf->length;
		}
	}
Ejemplo n.º 14
0
void
still_jpeg_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
	{
	CameraObject			*data = (CameraObject *) port->userdata;
	int						n;
	static int		bytes_written;

	if (buffer->length && still_jpeg_encoder.file)
		{
		mmal_buffer_header_mem_lock(buffer);
		n = fwrite(buffer->data, 1, buffer->length, still_jpeg_encoder.file);
		bytes_written += n;
		mmal_buffer_header_mem_unlock(buffer);
		if (n != buffer->length)
			{
			log_printf("still_jpeg_callback: %s file write error.  %m\n", data->name);
			exit(1);
			}
		}
	if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
		{
		fclose(still_jpeg_encoder.file);
		if (pikrellcam.still_capture_event)
			event_add("still capture command", pikrellcam.t_now, 0,
					event_still_capture_cmd,
					pikrellcam.on_still_capture_cmd);
		else if (pikrellcam.timelapse_capture_event)
			{
			if (bytes_written > 0)
				time_lapse.sequence += 1;
			else if (pikrellcam.timelapse_jpeg_last)
				{
				unlink(pikrellcam.timelapse_jpeg_last);
				dup_string(&pikrellcam.timelapse_jpeg_last, "failed");
				}
			}
		pikrellcam.still_capture_event = FALSE;
		pikrellcam.timelapse_capture_event = FALSE;
		bytes_written = 0;
		pikrellcam.state_modified = TRUE;
		still_jpeg_encoder.file = NULL;
		}
	return_buffer_to_port(port, buffer);
	}
static void buffer_callback ( MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer ) {
    RASPICAM_USERDATA *userdata = ( RASPICAM_USERDATA* ) port->userdata;
    if ( userdata == NULL || userdata->cameraBoard == NULL ) {

    } else {
        unsigned int flags = buffer->flags;
        mmal_buffer_header_mem_lock ( buffer );
        for ( unsigned int i = 0; i < buffer->length; i++, userdata->bufferPosition++ ) {
            if ( userdata->offset >= userdata->length ) {
                cout << userdata->cameraBoard->API_NAME << ": Buffer provided was too small! Failed to copy data into buffer.\n";
                userdata->cameraBoard = NULL;
                break;
            } else {
                if ( userdata->cameraBoard->getEncoding() == RASPICAM_ENCODING_RGB ) {
                    // Determines if the byte is an RGB value
                    if ( userdata->bufferPosition >= 54 ) {
                        userdata->data[userdata->offset] = buffer->data[i];
                        userdata->offset++;
                    }
                } else {
                    userdata->data[userdata->offset] = buffer->data[i];
                    userdata->offset++;
                }
            }
        }
        mmal_buffer_header_mem_unlock ( buffer );
        unsigned int END_FLAG = 0;
        END_FLAG |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
        END_FLAG |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
        END_FLAG &= flags;
        if ( END_FLAG != 0 ) {
            if ( userdata->mutex == NULL ) {
                userdata->imageCallback ( userdata->data, userdata->startingOffset, userdata->length - userdata->startingOffset );
            } else {
                sem_post ( userdata->mutex );
            }
        }
    }
    mmal_buffer_header_release ( buffer );
    if ( port->is_enabled ) {
        MMAL_BUFFER_HEADER_T *new_buffer = mmal_queue_get ( userdata->encoderPool->queue );
        if ( new_buffer ) mmal_port_send_buffer ( port, new_buffer );
    }
}
Ejemplo n.º 16
0
/* Process buffers received from other clock ports */
static MMAL_STATUS_T mmal_port_clock_process_buffer(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_CLOCK_PAYLOAD_T payload;

   if (buffer->length != sizeof(MMAL_CLOCK_PAYLOAD_T))
   {
      LOG_ERROR("invalid buffer length %d", buffer->length);
      return MMAL_EINVAL;
   }

   mmal_buffer_header_mem_lock(buffer);
   memcpy(&payload, buffer->data, sizeof(MMAL_CLOCK_PAYLOAD_T));
   mmal_buffer_header_mem_unlock(buffer);

   if (payload.magic != MMAL_CLOCK_PAYLOAD_MAGIC)
   {
      LOG_ERROR("buffer corrupt (magic %4.4s)", (char*)&payload.magic);
      return MMAL_EINVAL;
   }

   LOG_TRACE("port %s length %d id %4.4s time %"PRIi64,
         port->name, buffer->length, (char*)&payload.id, payload.time);

   switch (payload.id)
   {
   case MMAL_CLOCK_PAYLOAD_TIME:
      mmal_clock_media_time_set(port->priv->module->clock, payload.time);
      break;
   case MMAL_CLOCK_PAYLOAD_SCALE:
      mmal_clock_scale_set(port->priv->module->clock, payload.data.scale);
      break;
   default:
      LOG_ERROR("invalid id %4.4s", (char*)&payload.id);
      status = MMAL_EINVAL;
      break;
   }

   /* Finished with the buffer, so return it */
   buffer->length = 0;
   mmal_port_buffer_header_callback(port, buffer);

   return status;
}
Ejemplo n.º 17
0
void CCameraOutput::EndReadFrame()
{
	if(LockedBuffer)
	{
		// unlock and then release buffer back to the pool from whence it came
		mmal_buffer_header_mem_unlock(LockedBuffer);
		mmal_buffer_header_release(LockedBuffer);
		LockedBuffer = NULL;

		// and send it back to the port (if still open)
		if (BufferPort->is_enabled)
		{
			MMAL_STATUS_T status;
			MMAL_BUFFER_HEADER_T *new_buffer;
			new_buffer = mmal_queue_get(BufferPool->queue);
			if (new_buffer)
				status = mmal_port_send_buffer(BufferPort, new_buffer);
			if (!new_buffer || status != MMAL_SUCCESS)
				printf("Unable to return a buffer to the video port\n");
		}	
	}
}
Ejemplo n.º 18
0
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");
  }

}
Ejemplo n.º 19
0
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");
  }

}
Ejemplo n.º 20
0
  /* In pikrellcam, this callback receives resized I420 frames before
  |  sending them on to a jpeg encoder component which generates the
  |  mjpeg.jpg stream image.  Here we send the frame data to the motion display
  |  routine for possible drawing of region outlines, motion vectors
  |  and/or various status text.  Motion detection was done in the h264
  |  callback and a flag is set there so these two paths can be synchronized
  |  so motion vectors can be drawn on the right frame.
  */
void
I420_video_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
	{
	CameraObject          *obj = (CameraObject *) port->userdata;
	MMAL_BUFFER_HEADER_T  *buffer_in;
	static struct timeval timer;
	int                   utime;
	static int            encoder_busy_count;

	if (   buffer->length > 0
	    && motion_frame_event
	   )
		{
		motion_frame_event = FALSE;

		/* Do not send buffer to encoder if it has not received the previous
		|  one we sent unless this is the frame we want for a preview save.
		|  In that case, we may be sending a buffer to preview save before
		|  the previous buffer is handled.  This is accounted for below.
		*/
		if (   mjpeg_encoder_send_count == mjpeg_encoder_recv_count
		    || motion_frame.do_preview_save
		   )
			{
			if (obj->callback_port_in && obj->callback_pool_in)
				{
				buffer_in = mmal_queue_get(obj->callback_pool_in->queue);
				if (   buffer_in
				    && obj->callback_port_in->buffer_size >= buffer->length
				   )
					{
					mmal_buffer_header_mem_lock(buffer);
					memcpy(buffer_in->data, buffer->data, buffer->length);
					buffer_in->length = buffer->length;
					mmal_buffer_header_mem_unlock(buffer);
					display_draw(buffer_in->data);

					if (motion_frame.do_preview_save)
						{
						/* If mjpeg encoder has not received previous buffer,
						|  then the buffer to save will be the second buffer
						|  it gets from now. Otherwise it's the next buffer.
						*/
						pthread_mutex_lock(&mjpeg_encoder_count_lock);
						if (mjpeg_encoder_send_count == mjpeg_encoder_recv_count)
							mjpeg_do_preview_save = 1;
						else
							mjpeg_do_preview_save = 2;
						pthread_mutex_unlock(&mjpeg_encoder_count_lock);
						if (mjpeg_do_preview_save == 2 && pikrellcam.debug)
							printf("%s: encoder not clear -> preview save delayed\n",
								fname_base(pikrellcam.video_pathname));
						}
					motion_frame.do_preview_save = FALSE;
					++mjpeg_encoder_send_count;
					mmal_port_send_buffer(obj->callback_port_in, buffer_in);
					}
				}
			}
		else
			{
			++encoder_busy_count;
			if (pikrellcam.debug)
				printf("encoder not clear (%d) -> skipping mjpeg frame.\n",
					   encoder_busy_count);
			if (encoder_busy_count > 2)	/* Frame maybe dropped ??, move on */
				{
				if (pikrellcam.debug)
					printf("  Syncing recv/send counts.\n");
				encoder_busy_count = 0;
				mjpeg_encoder_recv_count = mjpeg_encoder_send_count;
				}
			}
		if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
			{
			if (pikrellcam.debug_fps && (utime = micro_elapsed_time(&timer)) > 0)
				printf("%s fps %d\n", obj->name, 1000000 / utime);
			}
		}
	return_buffer_to_port(port, buffer);
	}
Ejemplo n.º 21
0
void
video_h264_encoder_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *mmalbuf)
	{
	VideoCircularBuffer *vcb = &video_circular_buffer;
	MotionFrame		*mf = &motion_frame;
	KeyFrame		*kf;
	int				i, end_space, t_elapsed, event = 0;
	int				t_usec, dt_frame;
	boolean			force_stop;
	time_t			t_cur = pikrellcam.t_now;
	static int		fps_count, pause_frame_count_adjust;
	static time_t	t_sec, t_prev;
	uint64_t		t64_now;
	static int		t_annotate, t_key_frame;
	static struct timeval	tv;
	static uint64_t	t0_stc, pts_prev;
	static boolean	prev_pause;

	if (vcb->state == VCB_STATE_RESTARTING)
		{
		if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
			h264_header_save(mmalbuf);
		fps_count = 0;
		return_buffer_to_port(port, mmalbuf);
		return;
		}

	if (mmalbuf->pts > 0)
		{
		if (pikrellcam.t_now > tv.tv_sec + 10)
			{	/* Rarely, but time skew can change if ntp updates. */
			gettimeofday(&tv, NULL);
			mmal_port_parameter_get_uint64(port, MMAL_PARAMETER_SYSTEM_TIME, &t0_stc);
			t0_stc = (uint64_t) tv.tv_sec * 1000000LL + (uint64_t) tv.tv_usec - t0_stc;
			}

		/* Skew adjust to the system clock to get second transitions.
		|  Annotate times need to be set early to get displayed time synced
		|  with system time.  Needs >2 frames + offset to get it to work over
		|  range of fps values.
		|  Key frames can be delivered one frame after a request, so request
		|  within 1 1/2 frames before second time transitions.
		*/
		t64_now = t0_stc + mmalbuf->pts;
		t_sec = (int) (t64_now / 1000000LL);
		t_usec = (int) (t64_now % 1000000LL);
		dt_frame = 1000000 / pikrellcam.camera_adjust.video_fps;

		if (   t_annotate < t_sec
		    && t_usec > 900000 - 5 * dt_frame / 2
		   )
			{
			t_annotate = t_sec;
			annotate_text_update(t_annotate + 1);
			}

		if (   (vcb->state == VCB_STATE_NONE || vcb->pause)
		    && t_key_frame < t_sec
		    && t_usec > 1000000 - 3 * dt_frame / 2
		   )
			{
			t_key_frame = t_sec;
			mmal_port_parameter_set_boolean(port,
						MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, 1);
			}
		if (   (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
		         && t_cur < t_sec
		        )
			t_cur = t_sec;
		}

	pthread_mutex_lock(&vcb->mutex);
	
	if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG)
		h264_header_save(mmalbuf);
	else if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO)
		{
		if (++fps_count >= pikrellcam.mjpeg_divider)
			{
			motion_frame_event = TRUE;		/* synchronize with i420 callback */
			fps_count = 0;
			mmal_buffer_header_mem_lock(mmalbuf);
			memcpy(motion_frame.vectors, mmalbuf->data, motion_frame.vectors_size);
			mmal_buffer_header_mem_unlock(mmalbuf);
			motion_frame_process(vcb, &motion_frame);
			}
		}
	else
		{
		if (  (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME)
		    && !vcb->in_keyframe
		   )
			{
			/* Keep key_frame[cur_frame_index] always pointing to the latest
			|  keyframe (this one) in the video buffer.  Then adjust the
			|  key_frame[pre_frame_index] to point to a keyframe
			|  in the video buffer that is pre_capture time behind.
			|  If paused, always keep tail pointing to the latest keyframe.
			*/
			vcb->in_keyframe = TRUE;
			vcb->cur_frame_index = (vcb->cur_frame_index + 1) % KEYFRAME_SIZE;
			kf = &vcb->key_frame[vcb->cur_frame_index];
			kf->position = vcb->head;
			kf->frame_count = 0;
			pause_frame_count_adjust = 0;
			if (vcb->pause && vcb->state == VCB_STATE_MANUAL_RECORD)
				{
				vcb->tail = vcb->head;
				pts_prev = mmalbuf->pts;
				pause_frame_count_adjust = 0;
				}
			kf->t_frame = t_cur;
			kf->frame_pts = mmalbuf->pts;
			while (t_cur - vcb->key_frame[vcb->pre_frame_index].t_frame
						 > pikrellcam.motion_times.pre_capture)
				{
				vcb->pre_frame_index = (vcb->pre_frame_index + 1) % KEYFRAME_SIZE;
				if (vcb->pre_frame_index == vcb->cur_frame_index)
					break;
				}
			}
		if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
			{
			vcb->in_keyframe = FALSE;
			i = vcb->pre_frame_index; 
			while (1)
				{
				vcb->key_frame[i].frame_count += 1;
				if (i++ == vcb->cur_frame_index)
					break;
				i %= KEYFRAME_SIZE;
				}
			if (   vcb->state == VCB_STATE_MOTION_RECORD
			    || vcb->state == VCB_STATE_MANUAL_RECORD
			   )
				{
				if (!vcb->pause)
					vcb->frame_count += 1;
				else
					pause_frame_count_adjust += 1;
				}
			}

		if (t_cur > t_prev)
			{
			if (!vcb->pause)
				++vcb->record_elapsed_time;
			t_prev = t_cur;
			}

		if (vcb->state == VCB_STATE_MOTION_RECORD_START)
			{
			/* Write mp4 header and set tail to beginning of pre_capture
			|  video data, then write the entire pre_capture time data.
			|  The keyframe data we collected above keeps a pointer to
			|  video data close to the pre_capture time we want.
			*/
			fwrite(vcb->h264_header, 1, vcb->h264_header_position, vcb->file);
			pikrellcam.video_header_size = vcb->h264_header_position;
			pikrellcam.video_size = vcb->h264_header_position;

			vcb->tail = vcb->key_frame[vcb->record_start_frame_index].position;
			vcb_video_write(vcb);
			vcb->frame_count = vcb->key_frame[vcb->record_start_frame_index].frame_count;
			vcb->video_frame_count = vcb->frame_count;
			motion_event_write(vcb, mf);
			vcb->state = VCB_STATE_MOTION_RECORD;
			if (mf->external_trigger_time_limit > 0)
				{
				vcb->motion_sync_time = t_cur + mf->external_trigger_time_limit;
				vcb->max_record_time = mf->external_trigger_time_limit;
				}
			else
				{
				vcb->motion_sync_time = t_cur + pikrellcam.motion_times.post_capture;
				vcb->max_record_time = pikrellcam.motion_record_time_limit;
				}

			/* Schedule any motion begin command.
			*/
			event |= EVENT_MOTION_BEGIN;
			}

		if (vcb->state == VCB_STATE_MANUAL_RECORD_START)
			{
			/* Write mp4 header and set tail to most recent keyframe.
			|  So manual records may have up to about a sec pre_capture.
			*/
			fwrite(vcb->h264_header, 1, vcb->h264_header_position, vcb->file);
			pikrellcam.video_header_size = vcb->h264_header_position;
			pikrellcam.video_size = vcb->h264_header_position;

			vcb->tail = vcb->key_frame[vcb->record_start_frame_index].position;

			vcb_video_write(vcb);
			vcb->frame_count = vcb->key_frame[vcb->record_start_frame_index].frame_count;
			pts_prev = 0;
			vcb->state = VCB_STATE_MANUAL_RECORD;
			event |= EVENT_PREVIEW_SAVE;
			}

		if (h264_conn_status == H264_TCP_SEND_HEADER) 
			tcp_send_h264_header(vcb->h264_header, vcb->h264_header_position);

		/* Save video data into the circular buffer.
		*/
		mmal_buffer_header_mem_lock(mmalbuf);
		end_space = vcb->size - vcb->head;
		if (mmalbuf->length <= end_space)
			{
			memcpy(vcb->data + vcb->head, mmalbuf->data, mmalbuf->length);
			if(h264_conn_status == H264_TCP_SEND_DATA) 
				tcp_send_h264_data("data 1",vcb->data + vcb->head, mmalbuf->length);
			}
		else
			{
			memcpy(vcb->data + vcb->head, mmalbuf->data, end_space);
			memcpy(vcb->data, mmalbuf->data + end_space, mmalbuf->length - end_space);
			if (h264_conn_status == H264_TCP_SEND_DATA) 
      			{
				tcp_send_h264_data("data 2",vcb->data + vcb->head, end_space);
				tcp_send_h264_data("data 3",vcb->data, mmalbuf->length - end_space);
				}
			}
		vcb->head = (vcb->head + mmalbuf->length) % vcb->size;
		mmal_buffer_header_mem_unlock(mmalbuf);

		/* And write video data to a video file according to record state.
		|  Record time limit (if any) does not include pre capture times or
		|  manual paused time which is accounted for in record_elapsed_time.
		*/
		force_stop = FALSE;
		if (vcb->max_record_time > 0)
			{
			t_elapsed = vcb->record_elapsed_time;
			if (vcb->state == VCB_STATE_MOTION_RECORD)
				t_elapsed -= (mf->external_trigger_pre_capture > 0) ?
							  mf->external_trigger_pre_capture
							: pikrellcam.motion_times.pre_capture;
			else
				t_elapsed -= vcb->manual_pre_capture;

			if (t_elapsed >= vcb->max_record_time)
				force_stop = TRUE;
			}

		if (vcb->state == VCB_STATE_MANUAL_RECORD)
			{
			if (!vcb->pause)
				{
				if (mmalbuf->pts > 0)
					{
					if (pts_prev > 0)
						vcb->last_pts += mmalbuf->pts - pts_prev;
					else
						vcb->last_pts = mmalbuf->pts;
					pts_prev = mmalbuf->pts;
					}
				if (prev_pause)
					{
					vcb->frame_count += pause_frame_count_adjust;
					pause_frame_count_adjust = 0;
					}
				vcb->video_frame_count = vcb->frame_count;
				vcb_video_write(vcb);	/* Continuously write video data */
				}
			prev_pause = vcb->pause;
	
			if (force_stop)
				video_record_stop(vcb);
			}
		else if (vcb->state == VCB_STATE_MOTION_RECORD)
			{
			/* Always write until we reach motion_sync time (which is last
			|  motion detect time + post_capture time), then hold during
			|  event_gap time.  Motion events during event_gap time will bump
			|  motion_sync_time and event_gap expiration time higher thus
			|  triggering more writes up to the new sync_time.
			|  If there is not another motion event, event_gap time will be
			|  reached and we stop recording with the post_capture time
			|  already written.
			*/
			if (t_cur <= vcb->motion_sync_time)
				{
				if (mmalbuf->pts > 0)
					vcb->last_pts = mmalbuf->pts;
				vcb->video_frame_count = vcb->frame_count;
				vcb_video_write(vcb);
				}
			if (   force_stop
		        || (   mf->external_trigger_time_limit == 0
			        && t_cur >= vcb->motion_last_detect_time + pikrellcam.motion_times.event_gap
			       )
		       )
				{
				/* For motion recording, preview_save_mode "first" has been
				|  handled in motion_frame_process().  But if not "first",
				|  there is a preview save waiting to be handled.
				*/
				video_record_stop(vcb);
				event |= EVENT_MOTION_END;
				if (strcmp(pikrellcam.motion_preview_save_mode, "first") != 0)
					event |= EVENT_MOTION_PREVIEW_SAVE_CMD;
				}
			}
		}
	pthread_mutex_unlock(&vcb->mutex);
	return_buffer_to_port(port, mmalbuf);

	/* This handles preview saves for manual records for possible future use.
	|  preview_save_cmd does not apply for manual records.
	|  All preview saves for motion records are scheduled in motion_frame_process().
	|  preview_save_cmd for save mode "best" is handled in video_record_stop().
	*/
	if (event & EVENT_PREVIEW_SAVE)
		event_add("manual preview save", pikrellcam.t_now, 0,
					event_preview_save, NULL);

	if (   (event & EVENT_MOTION_BEGIN)
	    && *pikrellcam.on_motion_begin_cmd != '\0'
	   )
		event_add("motion begin", pikrellcam.t_now, 0,
					exec_no_wait, pikrellcam.on_motion_begin_cmd);
	/* motion end event and preview dispose are handled in video_record_stop()
	*/
	}
Ejemplo n.º 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)
{
	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");
}
Ejemplo n.º 23
0
static void video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
	//fprintf(stderr,"#");fflush(stderr);

	MMAL_BUFFER_HEADER_T *new_buffer;
	RASPIVID_STATE * state = (RASPIVID_STATE *)port->userdata;

	counter++;

	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*3);	// read BGR

			/*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
			}*/

			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
			}

			//fprintf(stderr,"a");fflush(stderr);
			vcos_semaphore_post(&state->capture_done_sem);
			//fprintf(stderr,"b");fflush(stderr);
			vcos_semaphore_wait(&state->capture_sem);
			//fprintf(stderr,"c");fflush(stderr);

			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");
	}
}
Ejemplo n.º 24
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));

}
Ejemplo n.º 25
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 = 0;
      int bytes_to_write = buffer->length;

      if (pData->pstate->onlyLuma)
         bytes_to_write = port->format->es->video.width * port->format->es->video.height;

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

         bytes_written = fwrite(buffer->data, 1, bytes_to_write, 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 (buffer->length && bytes_written != bytes_to_write)
      {
         vcos_log_error("Unable to write buffer to file - aborting %d vs %d", bytes_written, bytes_to_write);
         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));
   }
}
Ejemplo n.º 26
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");
    }

}
// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//
static void camera_video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
    PORT_USERDATA *userdata = (PORT_USERDATA *) port->userdata;

    static struct timespec t1;
    struct timespec t2;

    static int frame_count = 0;
    static int frame_post_count = 0;

    if (frame_count == 0) {
        clock_gettime(CLOCK_MONOTONIC, &t1);
    }
    frame_count++;

    //if(1){
    if( (CALC_FPS) && (frame_count % (VIDEO_FPS*2) == 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->video_fps = fps;
      //fprintf(stderr, "  Frame = %d, Frame Post %d, Framerate = %.0f fps \n", frame_count, frame_post_count, fps);
    }

    //if(1){
    if(userdata->motion > 0){   
      MMAL_BUFFER_HEADER_T *output_buffer = mmal_queue_get(userdata->encoder_input_pool->queue);
      if(output_buffer){
	  
	  /*if( (CALC_FPS) && (frame_count % (VIDEO_FPS*2) == 0) )
		  {
			fprintf(stderr,  "image: mmal_queue_get have valid buffer, output_buffer->data=0x%02X, output_buffer->length=%d, output_buffer->alloc_size=%d, buffer->length=%d \n", output_buffer->data, output_buffer->length, output_buffer->alloc_size, buffer->length );
		  }*/
	  
        mmal_buffer_header_mem_lock(buffer);
        memcpy(output_buffer->data, buffer->data, buffer->length);
        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");
        }
      }
      userdata->motion--;
    }
    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_POOL_T *pool = userdata->camera_video_port_pool;
        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, "[%s]Unable to return a buffer to the video port\n", __func__);
        }
    }
}
Ejemplo n.º 28
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 camera_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) {
    MMAL_BUFFER_HEADER_T *new_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 && pData->pstate->isInit) {
        int bytes_written = buffer->length;
        if (buffer->length) {
            mmal_buffer_header_mem_lock(buffer);
            memcpy(&(pData->buffer[pData->frame & 1][pData->id]), buffer->data, buffer->length);
            pData->id += bytes_written;
            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;
        }
        if (buffer->flags & (MMAL_BUFFER_HEADER_FLAG_FRAME_END | MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED))
            complete = 1;

        if (complete) {
            sensor_msgs::Image msg;
            msg.header.seq = pData->frame;
            msg.header.frame_id = tf_prefix;
            msg.header.frame_id.append("/camera");
            msg.header.stamp = ros::Time::now();
            msg.height = pData->pstate->height;
            msg.width = pData->pstate->width;
            msg.encoding = "bgra8";
            msg.is_bigendian = 0;
            msg.step = pData->pstate->width*4;
            msg.data.insert(msg.data.end(), pData->buffer[pData->frame & 1], &(pData->buffer[pData->frame & 1][pData->id]));
            image_pub.publish(msg);
            c_info.header.seq = pData->frame;
            c_info.header.stamp = msg.header.stamp;
            c_info.header.frame_id = msg.header.frame_id;
            camera_info_pub.publish(c_info);
            pData->frame++;
            pData->id = 0;
        }
    } 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->camera_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");
    } else {
        ROS_INFO("oups");
    }
}
Ejemplo n.º 29
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);
        }
    }
}
Ejemplo n.º 30
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");
        }
    }
}