Esempio n. 1
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;
}
Esempio n. 2
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. 3
0
/** Send a buffer header to a port */
static MMAL_STATUS_T splitter_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_COMPONENT_T *component = port->component;
   MMAL_COMPONENT_MODULE_T *module = component->priv->module;
   MMAL_PORT_T *in_port, *out_port;
   MMAL_BUFFER_HEADER_T *in;
   MMAL_STATUS_T status;
   unsigned int i;

   mmal_queue_put(port->priv->module->queue, buffer);

   if (module->error)
      return MMAL_SUCCESS; /* Just do nothing */

   /* Get input buffer header */
   in_port = component->input[0];
   in = mmal_queue_get(in_port->priv->module->queue);
   if (!in)
      return MMAL_SUCCESS; /* Nothing to do */

   for (i = 0; i < component->output_num; i++)
   {
      out_port = component->output[i];
      status = splitter_send_output(in, out_port);

      if (status != MMAL_SUCCESS && status != MMAL_EAGAIN)
         goto error;

      if (status == MMAL_SUCCESS)
         module->sent_flags |= (1<<i);
   }

   /* Check if we're done with the input buffer */
   if ((module->sent_flags & module->enabled_flags) == module->enabled_flags)
   {
      in->length = 0; /* Consume the input buffer */
      mmal_port_buffer_header_callback(in_port, in);
      module->sent_flags = 0;
      return MMAL_SUCCESS;
   }

   /* We're not done yet so put the buffer back in the queue */
   mmal_queue_put(in_port->priv->module->queue, in);
   return MMAL_SUCCESS;

 error:
   mmal_queue_put(in_port->priv->module->queue, in);

   status = mmal_event_error_send(port->component, status);
   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("unable to send an error event buffer (%i)", (int)status);
      return MMAL_SUCCESS;
   }
   module->error = 1;
   return MMAL_SUCCESS;
}
Esempio n. 4
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. 5
0
static MMAL_STATUS_T mmal_port_clock_flush(MMAL_PORT_T *port)
{
   MMAL_BUFFER_HEADER_T *buffer;

   /* Flush empty buffers */
   buffer = mmal_queue_get(port->priv->module->queue);
   while (buffer)
   {
      mmal_port_buffer_header_callback(port, buffer);
      buffer = mmal_queue_get(port->priv->module->queue);
   }

   return MMAL_SUCCESS;
}
Esempio n. 6
0
/** Flush a port */
static MMAL_STATUS_T sdl_port_flush(MMAL_PORT_T *port)
{
   MMAL_COMPONENT_T *component = port->component;
   MMAL_COMPONENT_MODULE_T *module = component->priv->module;
   MMAL_BUFFER_HEADER_T *buffer;

   /* Flush buffers that our component is holding on to.
    * If the reading thread is holding onto a buffer it will send it back ASAP as well
    * so no need to care about that.  */
   while((buffer = mmal_queue_get(module->queue)))
      mmal_port_buffer_header_callback(port, buffer);

   return MMAL_SUCCESS;
}
Esempio n. 7
0
/** Flush a port */
static MMAL_STATUS_T splitter_port_flush(MMAL_PORT_T *port)
{
   MMAL_PORT_MODULE_T *port_module = port->priv->module;
   MMAL_BUFFER_HEADER_T *buffer;

   /* Flush buffers that our component is holding on to */
   buffer = mmal_queue_get(port_module->queue);
   while(buffer)
   {
      mmal_port_buffer_header_callback(port, buffer);
      buffer = mmal_queue_get(port_module->queue);
   }

   if (port->type == MMAL_PORT_TYPE_INPUT)
      port->component->priv->module->sent_flags = 0;

   return MMAL_SUCCESS;
}
Esempio n. 8
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;
}
Esempio n. 9
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;
}
Esempio n. 10
0
static MMAL_BOOL_T sdl_do_processing(MMAL_COMPONENT_T *component)
{
   MMAL_PORT_T *port = component->input[0];
   MMAL_COMPONENT_MODULE_T *module = component->priv->module;
   unsigned int width = port->format->es->video.width;
   unsigned int height = port->format->es->video.height;
   MMAL_BUFFER_HEADER_T *buffer;
   uint8_t *src_plane[3];
   uint32_t *src_pitch;
   unsigned int i, line;
   MMAL_BOOL_T eos;
   SDL_Rect rect;

   buffer = mmal_queue_get(module->queue);
   if (!buffer)
	   return 0;

   eos = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS;

   /* Handle event buffers */
   if (buffer->cmd)
   {
      MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(buffer);
      if (event)
      {
         mmal_format_copy(port->format, event->format);
         module->status = port->priv->pf_set_format(port);
         if (module->status != MMAL_SUCCESS)
         {
            LOG_ERROR("format not set on port %p", port);
            if (mmal_event_error_send(port->component, module->status) != MMAL_SUCCESS)
               LOG_ERROR("unable to send an error event buffer");
         }
      }
      else
      {
         LOG_ERROR("discarding event %i on port %p", (int)buffer->cmd, port);
      }

      buffer->length = 0;
      mmal_port_buffer_header_callback(port, buffer);
      return 1;
   }

   if (module->status != MMAL_SUCCESS)
      return 1;

   /* Ignore empty buffers */
   if (!buffer->length)
      goto end;

   // FIXME: sanity check the size of the buffer

   /* Blit the buffer onto the overlay. */
   src_pitch = buffer->type->video.pitch;
   src_plane[0] = buffer->data + buffer->type->video.offset[0];
   src_plane[1] = buffer->data + buffer->type->video.offset[2];
   src_plane[2] = buffer->data + buffer->type->video.offset[1];

   SDL_LockYUVOverlay(module->sdl_overlay);
   for (i=0; i<3; i++)
   {
      uint8_t *src = src_plane[i];
      uint8_t *dst = module->sdl_overlay->pixels[i];

      if(i == 1) {width /= 2; height /= 2;}
      for(line = 0; line < height; line++)
      {
         memcpy(dst, src, width);
         src += src_pitch[i];
         dst += module->sdl_overlay->pitches[i];
      }
   }
   SDL_UnlockYUVOverlay(module->sdl_overlay);

   width = port->format->es->video.width;
   height = port->format->es->video.height;
   rect.x = module->display_region.x;
   rect.w = module->display_region.width;
   height = rect.w * height / width;
   rect.y = module->display_region.y + (module->display_region.height - height) / 2;
   rect.h = height;

   SDL_DisplayYUVOverlay(module->sdl_overlay, &rect);

 end:
   buffer->offset = buffer->length = 0;
   mmal_port_buffer_header_callback(port, buffer);

   /* Generate EOS events */
   if (eos)
      mmal_event_eos_send(port);

   return 1;
}