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