예제 #1
0
static MMAL_STATUS_T mmal_port_connection_enable(MMAL_PORT_T *port, MMAL_PORT_T *connected_port)
{
   MMAL_PORT_T *output = port->type == MMAL_PORT_TYPE_OUTPUT ? port : connected_port;
   MMAL_PORT_T *input = connected_port->type == MMAL_PORT_TYPE_INPUT ? connected_port : port;
   MMAL_PORT_T *pool_port = (output->capabilities & MMAL_PORT_CAPABILITY_ALLOCATION) ? output : input;
   MMAL_PORT_PRIVATE_CORE_T *pool_core = pool_port->priv->core;
   uint32_t buffer_size, buffer_num;
   MMAL_POOL_T *pool;

   /* At this point both ports hold the connection lock */

   /* Ensure that the buffer numbers and sizes used are the maxima between connected ports. */
   buffer_num  = MMAL_MAX(port->buffer_num,  connected_port->buffer_num);
   buffer_size = MMAL_MAX(port->buffer_size, connected_port->buffer_size);
   port->buffer_num  = connected_port->buffer_num  = buffer_num;
   port->buffer_size = connected_port->buffer_size = buffer_size;

   if (output->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
      buffer_size = 0;

   if (!port->priv->core->core_owns_connection)
      return MMAL_SUCCESS;

   pool = mmal_port_pool_create(pool_port, buffer_num, buffer_size);
   if (!pool)
   {
      LOG_ERROR("failed to create pool for connection");
      return MMAL_ENOMEM;
   }

   pool_core->pool_for_connection = pool;
   mmal_pool_callback_set(pool, mmal_port_connected_pool_cb, output);
   return MMAL_SUCCESS;
}
예제 #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;
}
예제 #3
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;
}
예제 #4
0
static MMAL_STATUS_T mmal_port_enable_locked_connected(MMAL_PORT_T* output, MMAL_PORT_T* input)
{
   MMAL_PORT_PRIVATE_CORE_T* output_core = output->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;

   output_core->buffer_header_callback = mmal_port_connected_output_cb;

   /* Output port already locked, lock input port */
   LOCK_PORT(input);

   /* Disable connected port if its buffer config needs to change */
   if (input->is_enabled &&
         (input->buffer_size != output->buffer_size ||
          input->buffer_num != output->buffer_num))
   {
      status = mmal_port_disable_locked(input);
      if (status != MMAL_SUCCESS)
         goto finish;
   }

   /* Ensure the connected port has the same buffer configuration */
   input->buffer_size = output->buffer_size;
   input->buffer_num = output->buffer_num;

   /* Enable other end of the connection, if not already enabled */
   if (!input->is_enabled)
   {
      status = mmal_port_enable_locked(input, NULL);
      if (status != MMAL_SUCCESS)
         goto finish;
   }

   if (output_core->allocate_pool)
   {
      MMAL_POOL_T* pool = NULL;
      /* Decide which port will be used to allocate the pool */
      MMAL_PORT_T* pool_port = (output->capabilities & MMAL_PORT_CAPABILITY_ALLOCATION) ? output : input;
      MMAL_PORT_PRIVATE_CORE_T* pool_core = pool_port->priv->core;
      uint32_t buffer_size = pool_port->buffer_size;

      /* No need to allocate payload memory for pass-through ports */
      if (output->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
         buffer_size = 0;

      UNLOCK_PORT(input);
      if (pool_port == output)
         UNLOCK_PORT(output);

      /* Port pool creation must be done without the lock held */
      pool = mmal_port_pool_create(pool_port, pool_port->buffer_num, buffer_size);

      if (pool_port == output)
         LOCK_PORT(output);
      LOCK_PORT(input);

      if (!pool)
      {
         status = MMAL_ENOMEM;
         goto finish;
      }

      pool_core->pool_for_connection = pool;
      mmal_pool_callback_set(pool_core->pool_for_connection, mmal_port_connected_pool_cb, output);

      /* Put the buffers into the output port */
      status = mmal_port_populate_from_pool(output, pool_port->priv->core->pool_for_connection);
   }

finish:
   /* At this point, both locks must be held */

   if (status != MMAL_SUCCESS && input->is_enabled)
      mmal_port_disable_locked(input);

   UNLOCK_PORT(input);

   if (status != MMAL_SUCCESS)
      mmal_port_disable_locked(output);

   return status;
}