Exemplo n.º 1
0
/* Parse a string of the form: "fourcc:widthxheight" */
static int get_format(const char *name, uint32_t *fourcc, unsigned int *width, unsigned int *height)
{
   char *delim, fcc[4] = {' ', ' ', ' ', ' '};
   unsigned int value_u1, value_u2;
   size_t size;

   *width = *height = 0;
   *fourcc = MMAL_ENCODING_UNKNOWN;

   /* Fourcc is the first element */
   delim = strchr(name, ':');
   size = delim ? (size_t)(delim - name) : strlen(name);
   memcpy(fcc, name, MMAL_MIN(size, sizeof(fcc)));

   if (size == sizeof("yuv420")-1 && !memcmp(name, "yuv420", size))
      *fourcc = MMAL_ENCODING_I420;
   else if (size == sizeof("yuvuv")-1 && !memcmp(name, "yuvuv", size))
      *fourcc = MMAL_ENCODING_YUVUV128;
   else if (size == sizeof("opaque")-1 && !memcmp(name, "opaque", size))
      *fourcc = MMAL_ENCODING_OPAQUE;
   else if (size > 0 && size <= 4)
      *fourcc = MMAL_FOURCC(fcc[0], fcc[1], fcc[2], fcc[3]);
   else
      return 1;

   if (!delim)
      return 0; /* Nothing more to parse */

   /* Width/height are next */
   /* coverity[secure_coding] Only reading integers, so can't overflow */
   if (sscanf(delim+1, "%ux%u", &value_u1, &value_u2) != 2)
      return 1;

   *width = value_u1;
   *height = value_u2;
   return 0;
}
Exemplo n.º 2
0
/** Create an instance of mmalplay.
 * Note: this is test code. Do not use it in your app. It *will* change or even be removed without notice.
 */
MMALPLAY_T *mmalplay_create(const char *uri, MMALPLAY_OPTIONS_T *opts, MMAL_STATUS_T *pstatus)
{
   MMAL_STATUS_T status = MMAL_SUCCESS, status_audio, status_video, status_clock;
   MMALPLAY_T *ctx;
   MMAL_COMPONENT_T *component;
   MMALPLAY_CONNECTIONS_T connections;
   unsigned int i;

   LOG_TRACE("%s", uri);

   if (pstatus) *pstatus = MMAL_ENOMEM;

   /* Allocate and initialise context */
   ctx = malloc(sizeof(MMALPLAY_T));
   if (!ctx)
      return NULL;
   memset(ctx, 0, sizeof(*ctx));
   memset(&connections, 0, sizeof(connections));
   if (vcos_semaphore_create(&ctx->event, "MMALTest", 1) != VCOS_SUCCESS)
   {
      free(ctx);
      return NULL;
   }

   ctx->uri = uri;
   if (opts)
      ctx->options = *opts;

   ctx->options.output_num = MMAL_MAX(ctx->options.output_num, 1);
   ctx->options.output_num = MMAL_MIN(ctx->options.output_num, MMALPLAY_MAX_RENDERERS);
   connections.num = 0;

   /* Create and setup the container reader component */
   component = mmalplay_component_create(ctx, MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &status);
   if (!component)
      goto error;

   status_video = mmalplay_pipeline_video_create(ctx, ctx->reader_video, &connections);
   status_audio = mmalplay_pipeline_audio_create(ctx, ctx->reader_audio, &connections);
   status_clock = mmalplay_pipeline_clock_create(ctx, &connections);
   if (status_video != MMAL_SUCCESS && status_audio != MMAL_SUCCESS && status_clock != MMAL_SUCCESS)
   {
      status = status_video;
      goto error;
   }

   /* Create our connections */
   for (i = 0; i < connections.num; i++)
   {
      status = mmalplay_connection_create(ctx, connections.connection[i].out, connections.connection[i].in,
            connections.connection[i].flags);
      if (status != MMAL_SUCCESS)
         goto error;
   }

   /* Enable our connections */
   for (i = 0; i < ctx->connection_num; i++)
   {
      status = mmal_connection_enable(ctx->connection[i]);
      if (status != MMAL_SUCCESS)
         goto error;
   }

   if (pstatus) *pstatus = MMAL_SUCCESS;
   return ctx;

 error:
   mmalplay_destroy(ctx);
   if (status == MMAL_SUCCESS) status = MMAL_ENOSPC;
   if (pstatus) *pstatus = status;
   return NULL;
}
Exemplo n.º 3
0
static BRCMIMAGE_STATUS_T brcmimage_decode(BRCMIMAGE_T *ctx,
   BRCMIMAGE_REQUEST_T *jd)
{
   BRCMIMAGE_STATUS_T err;
   MMAL_STATUS_T status;
   MMAL_BUFFER_HEADER_T *in, *out;
   MMAL_BOOL_T eos = MMAL_FALSE;
   const uint8_t *inBuf = jd->input;
   unsigned int slices = 0, inBufSize = jd->input_size;
   MMAL_PORT_T *port_in = ctx->mmal->input[0];
   MMAL_PORT_T *port_out = ctx->mmal->output[0];
   LOG_DEBUG("decode %i bytes\n", jd->input_size);

   jd->output_size = 0;
   err = brcmimage_configure_decoder(ctx, jd);
   if (err != BRCMIMAGE_SUCCESS)
      return err;

   while (!eos)
   {
      /* Send as many chunks of data to decode as we can */
      while (inBufSize)
      {
         status = mmal_wrapper_buffer_get_empty(port_in, &in, 0);
         if (status == MMAL_EAGAIN)
            break;
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to get empty buffer (%i)", status);

         in->data = (uint8_t *)inBuf;
         in->length = MMAL_MIN(port_in->buffer_size, inBufSize);
         in->alloc_size = in->length;
         inBufSize -= in->length;
         inBuf += in->length;
         in->flags = inBufSize ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS;
         LOG_DEBUG("send decode in (%i bytes)\n", in->length);
         status = mmal_port_send_buffer(port_in, in);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to send input buffer");
      }

      /* Check for decoded data */
      status = mmal_wrapper_buffer_get_full(port_out, &out, 0);
      if (status == MMAL_EAGAIN)
      {
         WAIT(ctx);
         continue;
      }
      CHECK_MMAL_STATUS(status, EXECUTE, "error decoding");

      /* Check if a new format has been auto-detected by the decoder */
      if (out->cmd == MMAL_EVENT_FORMAT_CHANGED)
      {
         MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(out);

         if (event)
            mmal_format_copy(port_out->format, event->format);
         mmal_buffer_header_release(out);

         if (!event)
            status = MMAL_EINVAL;
         CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event");

         LOG_DEBUG("new format (%4.4s:%ux%u|%ux%u)\n", (char *)&event->format->encoding,
            event->format->es->video.crop.width, event->format->es->video.crop.height,
            event->format->es->video.width, event->format->es->video.height);

         /* re-setup the output port for the new format */
         status = mmal_wrapper_port_disable(port_out);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to disable output port");

         ctx->slice_height = event->format->es->video.height;
         if (ENABLE_SLICE_MODE && !jd->output_handle)
         {
            /* setup slice mode */
            if (port_out->format->encoding == MMAL_ENCODING_I420 ||
               port_out->format->encoding == MMAL_ENCODING_I422)
            {
               if (port_out->format->encoding == MMAL_ENCODING_I420)
                  port_out->format->encoding = MMAL_ENCODING_I420_SLICE;
               if (port_out->format->encoding == MMAL_ENCODING_I422)
                  port_out->format->encoding = MMAL_ENCODING_I422_SLICE;
               ctx->slice_height = 16;
               port_out->buffer_num = 3;
            }
         }

         LOG_DEBUG("using slice size %u\n", ctx->slice_height);
         status = mmal_port_format_commit(port_out);
         CHECK_MMAL_STATUS(status, EXECUTE, "invalid format change event");
         port_out->buffer_size = port_out->buffer_size_min;
         if (jd->output_handle)
            status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_USE_SHARED_MEMORY);
         else
            status = mmal_wrapper_port_enable(port_out, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to enable output port");

         /* send all our output buffers to the decoder */
         while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS)
         {
            if (jd->output_handle)
            {
               out->data = (uint8_t*)jd->output_handle;
               out->alloc_size = jd->output_alloc_size;
            }
            status = mmal_port_send_buffer(port_out, out);
            CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer");
         }

         continue;
      }

      /* We have part of our output frame */
      jd->width = port_out->format->es->video.crop.width;
      if (!jd->width)
         jd->width = port_out->format->es->video.width;
      if (jd->output_handle)
         jd->buffer_width = port_out->format->es->video.width;
      if (!jd->buffer_width)
         jd->buffer_width = jd->width;
      jd->height = port_out->format->es->video.crop.height;
      if (!jd->height)
         jd->height = port_out->format->es->video.height;
      if (jd->output_handle)
         jd->buffer_height = port_out->format->es->video.height;
      if (!jd->buffer_height)
         jd->buffer_height = jd->height;

      if (jd->output_handle)
      {
         jd->output_size += out->length;
      }
      else
      {
         jd->output_size = brcmimage_copy_pixels(jd->output, jd->output_alloc_size,
            out->data, out->length, jd->pixel_format,
            jd->buffer_width, jd->buffer_height,
            port_out->format->es->video.width,
            ctx->slice_height, slices * ctx->slice_height, 0);
         slices++;
      }

      eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
      out->length = 0;
      if (eos)
      {
         mmal_buffer_header_release(out);
      }
      else
      {
         status = mmal_port_send_buffer(port_out, out);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to send output buffer");
      }

      if (!jd->output_size)
         status = MMAL_EINVAL;
      CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "invalid output buffer");
   }

   LOG_DEBUG("decoded W:%ixH%i:(W%ixH%i):%i in %i slices\n",
      jd->width, jd->height, jd->buffer_width, jd->buffer_height,
      jd->pixel_format, slices);
   mmal_port_flush(port_in);

   return BRCMIMAGE_SUCCESS;

 error:
   mmal_port_flush(port_in);
   return err;
}
Exemplo n.º 4
0
static BRCMIMAGE_STATUS_T brcmimage_encode(BRCMIMAGE_T *ctx,
   BRCMIMAGE_REQUEST_T *je)
{
   BRCMIMAGE_STATUS_T err;
   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_BUFFER_HEADER_T *in, *out;
   MMAL_BOOL_T eos = MMAL_FALSE;
   const uint8_t *outBuf = je->output;
   unsigned int loop = 0, slices = 0, outBufSize = je->output_alloc_size;
   MMAL_PORT_T *port_in = ctx->mmal->input[0];
   MMAL_PORT_T *port_out = ctx->mmal->output[0];

   je->output_size = 0;
   err = brcmimage_configure_encoder(ctx, je);
   if (err != BRCMIMAGE_SUCCESS)
      return err;

   /* Then we read the encoded data back from the encoder */

   while (!eos && status == MMAL_SUCCESS)
   {
      /* send buffers to be filled */
      while (mmal_wrapper_buffer_get_empty(port_out, &out, 0) == MMAL_SUCCESS)
      {
         out->data = (uint8_t *)outBuf;
         out->alloc_size = MMAL_MIN(port_out->buffer_size, outBufSize);
         outBufSize -= out->alloc_size;
         outBuf += out->alloc_size;
         status = mmal_port_send_buffer(port_out, out);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer");
      }

      /* Send slices to be encoded */
      if (slices * ctx->slice_height < port_in->format->es->video.height &&
          mmal_wrapper_buffer_get_empty(port_in, &in, 0) == MMAL_SUCCESS)
      {
         if (je->input_handle)
         {
            in->data = (uint8_t *)je->input_handle;
            in->length = in->alloc_size = je->input_size;
         }
         else
         {
            in->length = brcmimage_copy_pixels(in->data, in->alloc_size,
               je->input, je->input_size, je->pixel_format,
               port_in->format->es->video.width,
               ctx->slice_height, je->buffer_width, je->buffer_height,
               slices * ctx->slice_height, 1);
            if (!in->length)
               status = MMAL_EINVAL;
            CHECK_MMAL_STATUS(status, INPUT_BUFFER, "input buffer too small");
         }

         slices++;
         if (slices * ctx->slice_height >= port_in->format->es->video.height)
             in->flags = MMAL_BUFFER_HEADER_FLAG_EOS;
         status = mmal_port_send_buffer(port_in, in);
         CHECK_MMAL_STATUS(status, EXECUTE, "failed to send buffer");
      }

      status = mmal_wrapper_buffer_get_full(port_out, &out, 0);
      if (status == MMAL_EAGAIN)
      {
         status = MMAL_SUCCESS;
         WAIT(ctx);
         continue;
      }
      CHECK_MMAL_STATUS(status, EXECUTE, "failed to get full buffer");

      LOG_DEBUG("received %i bytes\n", out->length);
      je->output_size += out->length;
      eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS;

      /* Detect when the encoder is running out of space for its output */
      if (++loop >= port_out->buffer_num && !eos && !out->length)
      {
         LOG_ERROR("no more output space for encoder");
         status = MMAL_EINVAL;
      }

      mmal_buffer_header_release(out);
   }

   /* Check if buffer was too small */
   CHECK_MMAL_STATUS(status, OUTPUT_BUFFER, "output buffer too small");

   LOG_DEBUG("encoded W:%ixH:%i:%i (%i bytes) in %i slices\n",
         je->width, je->height, je->pixel_format, je->output_size, slices);
   mmal_port_flush(port_out);
   return BRCMIMAGE_SUCCESS;

 error:
   mmal_wrapper_port_disable(port_in);
   mmal_wrapper_port_disable(port_out);
   return err;
}