コード例 #1
0
ファイル: playback.c プロジェクト: 4leavedclover/userland
static MMAL_STATUS_T mmalplay_event_handle(MMAL_CONNECTION_T *connection, MMAL_PORT_T *port,
   MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_STATUS_T status = MMAL_SUCCESS;

   LOG_INFO("%s(%p) received event %4.4s (%i bytes)", port->name, port,
            (char *)&buffer->cmd, (int)buffer->length);

   if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED && port->type == MMAL_PORT_TYPE_OUTPUT)
   {
      MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(buffer);
      if (event)
      {
         LOG_INFO("----------Port format changed----------");
         log_format(port->format, port);
         LOG_INFO("-----------------to---------------------");
         log_format(event->format, 0);
         LOG_INFO(" buffers num (opt %i, min %i), size (opt %i, min: %i)",
                  event->buffer_num_recommended, event->buffer_num_min,
                  event->buffer_size_recommended, event->buffer_size_min);
         LOG_INFO("----------------------------------------");
      }

      status = mmal_connection_event_format_changed(connection, buffer);
   }

   mmal_buffer_header_release(buffer);
   return status;
}
コード例 #2
0
ファイル: mmal_port.c プロジェクト: 4leavedclover/userland
/** Connected output port buffer callback */
static void mmal_port_connected_output_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
   MMAL_PORT_T* connected_port = port->priv->core->connected_port;
   MMAL_STATUS_T status;

   LOG_TRACE("buffer %p from connected output port %p: data %p, alloc_size %u, length %u",
             buffer, port, buffer->data, buffer->alloc_size, buffer->length);

   if (buffer->cmd)
   {
      MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(buffer);

      /* Handle format changed events */
      if (event)
      {
         /* Apply the change */
         status = mmal_format_full_copy(port->format, event->format);
         if (status == MMAL_SUCCESS)
            status = mmal_port_format_commit(port);
         if (status != MMAL_SUCCESS)
            LOG_ERROR("format commit failed on port %s (%i)", port->name, status);

         /* Forward to the connected port */
         if (status == MMAL_SUCCESS)
            status = mmal_port_send_buffer(connected_port, buffer);

         if (status != MMAL_SUCCESS)
         {
            mmal_event_error_send(port->component, status);
            mmal_buffer_header_release(buffer);
         }
         return; /* Event handled */
      }

      /* FIXME Release other event buffers for now, until we can deal with shared memory issues */
      mmal_buffer_header_release(buffer);
   }
   else
   {
      if (port->is_enabled)
      {
         /* Forward data buffers to the connected input port */
         status = mmal_port_send_buffer(connected_port, buffer);
         if (status != MMAL_SUCCESS)
         {
            LOG_ERROR("%s could not send buffer on port %s (%s)",
                      port->name, connected_port->name, mmal_status_to_string(status));
            mmal_buffer_header_release(buffer);
         }
      }
      else
      {
         /* This port is disabled. Buffer will be a flushed buffer, so
          * return to the pool rather than delivering it.
          */
         mmal_buffer_header_release(buffer);
      }
   }
}
コード例 #3
0
ファイル: MMALCodec.cpp プロジェクト: Avbrella/xbmc
void CMMALVideo::PortSettingsChanged(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
  MMAL_EVENT_FORMAT_CHANGED_T *fmt = mmal_event_format_changed_get(buffer);
  mmal_format_copy(m_es_format, fmt->format);
  m_changed_count++;

  if (m_es_format->es->video.crop.width && m_es_format->es->video.crop.height)
  {
    if (m_es_format->es->video.par.num && m_es_format->es->video.par.den)
      m_aspect_ratio = (float)(m_es_format->es->video.par.num * m_es_format->es->video.crop.width) / (m_es_format->es->video.par.den * m_es_format->es->video.crop.height);
    m_decoded_width = m_es_format->es->video.crop.width;
    m_decoded_height = m_es_format->es->video.crop.height;
    if (g_advancedSettings.CanLogComponent(LOGVIDEO))
      CLog::Log(LOGDEBUG, "%s::%s format changed: %dx%d %.2f frame:%d", CLASSNAME, __func__, m_decoded_width, m_decoded_height, m_aspect_ratio, m_changed_count);
  }
  else
    CLog::Log(LOGERROR, "%s::%s format changed: Unexpected %dx%d", CLASSNAME, __func__, m_es_format->es->video.crop.width, m_es_format->es->video.crop.height);
}
コード例 #4
0
ファイル: codec.c プロジェクト: Adatan/vlc
static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
    decoder_t *dec = (decoder_t *)port->userdata;
    decoder_sys_t *sys = dec->p_sys;
    picture_t *picture;
    MMAL_EVENT_FORMAT_CHANGED_T *fmt;
    MMAL_ES_FORMAT_T *format;

    if (buffer->cmd == 0) {
        if (buffer->length > 0) {
            mmal_queue_put(sys->decoded_pictures, buffer);
        } else {
            picture = (picture_t *)buffer->user_data;
            picture_Release(picture);
            if (sys->output_pool) {
                buffer->user_data = NULL;
                buffer->alloc_size = 0;
                buffer->data = NULL;
                mmal_buffer_header_release(buffer);
            }
        }
        atomic_fetch_sub(&sys->output_in_transit, 1);
        vlc_sem_post(&sys->sem);
    } else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
        fmt = mmal_event_format_changed_get(buffer);

        format = mmal_format_alloc();
        mmal_format_full_copy(format, fmt->format);

        if (sys->opaque)
            format->encoding = MMAL_ENCODING_OPAQUE;

        sys->output_format = format;

        mmal_buffer_header_release(buffer);
    } else {
        mmal_buffer_header_release(buffer);
    }
}
コード例 #5
0
ファイル: mmaldec.c プロジェクト: atomnuker/FFmpeg-Daala
// Fetch a decoded buffer and place it into the frame parameter.
static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_BUFFER_HEADER_T *buffer = NULL;
    MMAL_STATUS_T status = 0;
    int ret = 0;

    if (ctx->eos_received)
        goto done;

    while (1) {
        // To ensure decoding in lockstep with a constant delay between fed packets
        // and output frames, we always wait until an output buffer is available.
        // Except during start we don't know after how many input packets the decoder
        // is going to return the first buffer, and we can't distinguish decoder
        // being busy from decoder waiting for input. So just poll at the start and
        // keep feeding new data to the buffer.
        // We are pretty sure the decoder will produce output if we sent more input
        // frames than what a H.264 decoder could logically delay. This avoids too
        // excessive buffering.
        // We also wait if we sent eos, but didn't receive it yet (think of decoding
        // stream with a very low number of frames).
        if (avpriv_atomic_int_get(&ctx->packets_buffered) > MAX_DELAYED_FRAMES ||
            (ctx->packets_sent && ctx->eos_sent)) {
            // MMAL will ignore broken input packets, which means the frame we
            // expect here may never arrive. Dealing with this correctly is
            // complicated, so here's a hack to avoid that it freezes forever
            // in this unlikely situation.
            buffer = mmal_queue_timedwait(ctx->queue_decoded_frames, 100);
            if (!buffer) {
                av_log(avctx, AV_LOG_ERROR, "Did not get output frame from MMAL.\n");
                ret = AVERROR_UNKNOWN;
                goto done;
            }
        } else {
            buffer = mmal_queue_get(ctx->queue_decoded_frames);
            if (!buffer)
                goto done;
        }

        ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);
        if (ctx->eos_received)
            goto done;

        if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
            MMAL_COMPONENT_T *decoder = ctx->decoder;
            MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);
            MMAL_BUFFER_HEADER_T *stale_buffer;

            av_log(avctx, AV_LOG_INFO, "Changing output format.\n");

            if ((status = mmal_port_disable(decoder->output[0])))
                goto done;

            while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))
                mmal_buffer_header_release(stale_buffer);

            mmal_format_copy(decoder->output[0]->format, ev->format);

            if ((ret = ffmal_update_format(avctx)) < 0)
                goto done;

            if ((status = mmal_port_enable(decoder->output[0], output_callback)))
                goto done;

            if ((ret = ffmmal_fill_output_port(avctx)) < 0)
                goto done;

            if ((ret = ffmmal_fill_input_port(avctx)) < 0)
                goto done;

            mmal_buffer_header_release(buffer);
            continue;
        } else if (buffer->cmd) {
            char s[20];
            av_get_codec_tag_string(s, sizeof(s), buffer->cmd);
            av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", s);
            goto done;
        } else if (buffer->length == 0) {
            // Unused output buffer that got drained after format change.
            mmal_buffer_header_release(buffer);
            continue;
        }

        ctx->frames_output++;

        if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0)
            goto done;

        *got_frame = 1;
        break;
    }

done:
    if (buffer)
        mmal_buffer_header_release(buffer);
    if (status && ret >= 0)
        ret = AVERROR_UNKNOWN;
    return ret;
}
コード例 #6
0
ファイル: brcmimage.cpp プロジェクト: gdachs/OpenELEC.Plex
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;
}
コード例 #7
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;
}