Esempio n. 1
0
/** Send a buffer header to a port */
MMAL_STATUS_T mmal_port_send_buffer(MMAL_PORT_T *port,
   MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_STATUS_T status;

   if (!port || !port->priv)
   {
      LOG_ERROR("invalid port");
      return MMAL_EINVAL;
   }

#ifdef ENABLE_MMAL_EXTRA_LOGGING
   LOG_TRACE("%s(%i:%i) port %p, buffer %p (%p,%i,%i)",
             port->component->name, (int)port->type, (int)port->index, port, buffer,
             buffer ? buffer->data: 0, buffer ? (int)buffer->offset : 0,
             buffer ? (int)buffer->length : 0);
#endif

   if (!buffer->data && !(port->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH))
   {
      LOG_ERROR("%s(%p) received invalid buffer header", port->name, port);
      return MMAL_EINVAL;
   }

   if (!port->priv->pf_send)
      return MMAL_ENOSYS;

   LOCK_SENDING(port);

   if (!port->is_enabled)
   {
      UNLOCK_SENDING(port);
      return MMAL_EINVAL;
   }

   if (port->type == MMAL_PORT_TYPE_OUTPUT && buffer->length)
   {
      LOG_DEBUG("given an output buffer with length != 0");
      buffer->length = 0;
   }

   IN_TRANSIT_INCREMENT(port);
   status = port->priv->pf_send(port, buffer);

   if (status != MMAL_SUCCESS)
   {
      IN_TRANSIT_DECREMENT(port);
      LOG_ERROR("%s: send failed: %s", port->name, mmal_status_to_string(status));
   }
   else
   {
      mmal_port_update_port_stats(port, MMAL_CORE_STATS_RX);
   }

   UNLOCK_SENDING(port);
   return status;
}
Esempio n. 2
0
static MMAL_STATUS_T mmal_port_disable_internal(MMAL_PORT_T *port)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_BUFFER_HEADER_T *buffer;

   LOCK_PORT(port);

   if (!port->is_enabled)
      goto end;

   LOCK_SENDING(port);
   port->is_enabled = 0;
   UNLOCK_SENDING(port);

   mmal_component_action_lock(port->component);

   if (core->pool_for_connection)
      mmal_pool_callback_set(core->pool_for_connection, NULL, NULL);

   status = port->priv->pf_disable(port);

   mmal_component_action_unlock(port->component);

   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("port %p could not be disabled (%s)", port->name, mmal_status_to_string(status));
      LOCK_SENDING(port);
      port->is_enabled = 1;
      UNLOCK_SENDING(port);
      goto end;
   }

   /* Flush our internal queue */
   buffer = port->priv->core->queue_first;
   while (buffer)
   {
      MMAL_BUFFER_HEADER_T *next = buffer->next;
      mmal_port_buffer_header_callback(port, buffer);
      buffer = next;
   }
   port->priv->core->queue_first = 0;
   port->priv->core->queue_last = &port->priv->core->queue_first;

   /* Wait for all the buffers to have come back from the component */
   LOG_DEBUG("%s waiting for %i buffers left in transit", port->name, (int)IN_TRANSIT_COUNT(port));
   IN_TRANSIT_WAIT(port);
   LOG_DEBUG("%s has no buffers left in transit", port->name);

   port->priv->core->buffer_header_callback = NULL;

 end:
   UNLOCK_PORT(port);
   return status;
}
Esempio n. 3
0
/** Flush a port */
MMAL_STATUS_T mmal_port_flush(MMAL_PORT_T *port)
{
   MMAL_BUFFER_HEADER_T *buffer = 0;
   MMAL_STATUS_T status;

   if (!port || !port->priv)
      return MMAL_EINVAL;

   LOG_TRACE("%s(%i:%i) port %p", port->component->name,
             (int)port->type, (int)port->index, port);

   if (!port->priv->pf_flush)
      return MMAL_ENOSYS;

   mmal_component_action_lock(port->component);
   LOCK_SENDING(port);
   status = port->priv->pf_flush(port);
   if (status == MMAL_SUCCESS)
   {
      /* Flush our internal queue */
      buffer = port->priv->core->queue_first;
      port->priv->core->queue_first = 0;
      port->priv->core->queue_last = &port->priv->core->queue_first;
   }
   UNLOCK_SENDING(port);
   mmal_component_action_unlock(port->component);

   while (buffer)
   {
      MMAL_BUFFER_HEADER_T *next = buffer->next;
      mmal_port_buffer_header_callback(port, buffer);
      buffer = next;
   }
   return status;
}
Esempio n. 4
0
static MMAL_STATUS_T mmal_port_disable_locked(MMAL_PORT_T *port)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_STATUS_T status;

   if (!port->is_enabled)
   {
      LOG_ERROR("port %p is not enabled", port);
      return MMAL_EINVAL;
   }

   LOCK_SENDING(port);
   port->is_enabled = 0;
   UNLOCK_SENDING(port);

   mmal_component_action_lock(port->component);

   if (core->pool_for_connection)
      mmal_pool_callback_set(core->pool_for_connection, NULL, NULL);

   status = port->priv->pf_disable(port);

   mmal_component_action_unlock(port->component);

   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("port %p could not be disabled (%s)", port->name, mmal_status_to_string(status));
      LOCK_SENDING(port);
      port->is_enabled = 1;
      UNLOCK_SENDING(port);
      return status;
   }

   /* Wait for all the buffers to have come back from the component */
   LOG_DEBUG("%s waiting for %i buffers left in transit", port->name, (int)IN_TRANSIT_COUNT(port));
   IN_TRANSIT_WAIT(port);
   LOG_DEBUG("%s has no buffers left in transit", port->name);

   port->priv->core->buffer_header_callback = NULL;

   if (core->connected_port && port->type == MMAL_PORT_TYPE_OUTPUT)
      mmal_port_disable(core->connected_port);

   return status;
}
Esempio n. 5
0
/** Flush a port */
MMAL_STATUS_T mmal_port_flush(MMAL_PORT_T *port)
{
   MMAL_STATUS_T status;

   if (!port || !port->priv)
      return MMAL_EINVAL;

   LOG_TRACE("%s(%i:%i) port %p", port->component->name,
             (int)port->type, (int)port->index, port);

   if (!port->priv->pf_flush)
      return MMAL_ENOSYS;

   LOCK_SENDING(port);
   status = port->priv->pf_flush(port);
   UNLOCK_SENDING(port);
   return status;
}
Esempio n. 6
0
MMAL_STATUS_T mmal_port_pause(MMAL_PORT_T *port, MMAL_BOOL_T pause)
{
   MMAL_STATUS_T status = MMAL_SUCCESS;

   LOCK_SENDING(port);

   /* When resuming from pause, we send all our queued buffers to the port */
   if (!pause && port->is_enabled)
   {
      MMAL_BUFFER_HEADER_T *buffer = port->priv->core->queue_first;
      while (buffer)
      {
         MMAL_BUFFER_HEADER_T *next = buffer->next;
         status = port->priv->pf_send(port, buffer);
         if (status != MMAL_SUCCESS)
         {
            buffer->next = next;
            break;
         }
         buffer = next;
      }

      /* If for some reason we could not send one of the buffers, we just
       * leave all the buffers in our internal queue and return an error. */
      if (status != MMAL_SUCCESS)
      {
         port->priv->core->queue_first = buffer;
      }
      else
      {
         port->priv->core->queue_first = 0;
         port->priv->core->queue_last = &port->priv->core->queue_first;
      }
   }

   if (status == MMAL_SUCCESS)
      port->priv->core->is_paused = pause;

   UNLOCK_SENDING(port);
   return status;
}
Esempio n. 7
0
static MMAL_STATUS_T mmal_port_enable_internal(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;

   LOCK_PORT(port);

   if (port->is_enabled)
      goto end;

   /* Sanity check the buffer requirements */
   if (port->buffer_num < port->buffer_num_min)
   {
      LOG_ERROR("buffer_num too small (%i/%i)", (int)port->buffer_num, (int)port->buffer_num_min);
      status = MMAL_EINVAL;
      goto end;
   }
   if (port->buffer_size < port->buffer_size_min)
   {
      LOG_ERROR("buffer_size too small (%i/%i)", (int)port->buffer_size, (int)port->buffer_size_min);
      status = MMAL_EINVAL;
      goto end;
   }

   core->buffer_header_callback = cb;
   status = port->priv->pf_enable(port, cb);
   if (status != MMAL_SUCCESS)
      goto end;

   LOCK_SENDING(port);
   port->is_enabled = 1;
   UNLOCK_SENDING(port);

end:
   UNLOCK_PORT(port);
   return status;
}
Esempio n. 8
0
/** Send a buffer header to a port */
MMAL_STATUS_T mmal_port_send_buffer(MMAL_PORT_T *port,
   MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_STATUS_T status = MMAL_SUCCESS;

   if (!port || !port->priv)
   {
      LOG_ERROR("invalid port");
      return MMAL_EINVAL;
   }

#ifdef ENABLE_MMAL_EXTRA_LOGGING
   LOG_TRACE("%s(%i:%i) port %p, buffer %p (%p,%i,%i)",
             port->component->name, (int)port->type, (int)port->index, port, buffer,
             buffer ? buffer->data: 0, buffer ? (int)buffer->offset : 0,
             buffer ? (int)buffer->length : 0);
#endif

   if (!buffer->data && !(port->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH))
   {
      LOG_ERROR("%s(%p) received invalid buffer header", port->name, port);
      return MMAL_EINVAL;
   }

   if (!port->priv->pf_send)
      return MMAL_ENOSYS;

   LOCK_SENDING(port);

   if (!port->is_enabled)
   {
      UNLOCK_SENDING(port);
      return MMAL_EINVAL;
   }

   if (port->type == MMAL_PORT_TYPE_OUTPUT && buffer->length)
   {
      LOG_DEBUG("given an output buffer with length != 0");
      buffer->length = 0;
   }

   /* coverity[lock] transit_sema is used for signalling, and is not a lock */
   /* coverity[lock_order] since transit_sema is not a lock, there is no ordering conflict */
   IN_TRANSIT_INCREMENT(port);

   if (port->priv->core->is_paused)
   {
      /* Add buffer to our internal queue */
      buffer->next = NULL;
      *port->priv->core->queue_last = buffer;
      port->priv->core->queue_last = &buffer->next;
   }
   else
   {
      /* Send buffer to component */
      status = port->priv->pf_send(port, buffer);
   }

   if (status != MMAL_SUCCESS)
   {
      IN_TRANSIT_DECREMENT(port);
      LOG_ERROR("%s: send failed: %s", port->name, mmal_status_to_string(status));
   }
   else
   {
      mmal_port_update_port_stats(port, MMAL_CORE_STATS_RX);
   }

   UNLOCK_SENDING(port);
   return status;
}
Esempio n. 9
0
static MMAL_STATUS_T mmal_port_enable_locked(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_PORT_T* connected_port = core->connected_port;
   MMAL_STATUS_T status;

   if (port->is_enabled)
   {
      LOG_DEBUG("already enabled");
      return MMAL_EINVAL;
   }

   /* Ensure that the buffer numbers and sizes used are the maxima between connected ports. */
   if (connected_port && port->type == MMAL_PORT_TYPE_OUTPUT)
   {
      LOCK_PORT(connected_port);

      if (connected_port->buffer_num > port->buffer_num)
         port->buffer_num = connected_port->buffer_num;
      if (connected_port->buffer_size > port->buffer_size)
         port->buffer_size = connected_port->buffer_size;

      UNLOCK_PORT(connected_port);
   }

   /* Sanity check the buffer requirements */
   if (port->buffer_num < port->buffer_num_min)
   {
      LOG_ERROR("buffer_num too small (%i/%i)", (int)port->buffer_num, (int)port->buffer_num_min);
      return MMAL_EINVAL;
   }
   if (port->buffer_size < port->buffer_size_min)
   {
      LOG_ERROR("buffer_size too small (%i/%i)", (int)port->buffer_size, (int)port->buffer_size_min);
      return MMAL_EINVAL;
   }

   if (!connected_port == !cb)
   {
      /* Callback must be NULL if connected port is not NULL */
      LOG_ERROR("connected port %p, callback %p not allowed", connected_port, cb);
      return MMAL_EINVAL;
   }

   core->buffer_header_callback = cb;
   status = port->priv->pf_enable(port, cb);
   if (status != MMAL_SUCCESS)
      return status;

   LOCK_SENDING(port);
   port->is_enabled = 1;
   UNLOCK_SENDING(port);

   //FIXME: move before is_enabled is set ?
   if (connected_port)
   {
      if (port->type == MMAL_PORT_TYPE_INPUT)
         core->buffer_header_callback = mmal_port_connected_input_cb;
      else
         status = mmal_port_enable_locked_connected(port, connected_port);
   }

   return status;
}