Пример #1
0
static void ffmmal_stop_decoder(AVCodecContext *avctx)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_COMPONENT_T *decoder = ctx->decoder;
    MMAL_BUFFER_HEADER_T *buffer;

    mmal_port_disable(decoder->input[0]);
    mmal_port_disable(decoder->output[0]);
    mmal_port_disable(decoder->control);

    mmal_port_flush(decoder->input[0]);
    mmal_port_flush(decoder->output[0]);
    mmal_port_flush(decoder->control);

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

    while (ctx->waiting_buffers) {
        FFBufferEntry *buffer = ctx->waiting_buffers;

        ctx->waiting_buffers = buffer->next;

        if (buffer->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END)
            avpriv_atomic_int_add_and_fetch(&ctx->packets_buffered, -1);

        av_buffer_unref(&buffer->ref);
        av_free(buffer);
    }
    ctx->waiting_buffers_tail = NULL;

    av_assert0(avpriv_atomic_int_get(&ctx->packets_buffered) == 0);

    ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = ctx->extradata_sent = 0;
}
Пример #2
0
static void ffmmal_stop_decoder(AVCodecContext *avctx)
{
    MMALDecodeContext *ctx = avctx->priv_data;
    MMAL_COMPONENT_T *decoder = ctx->decoder;
    MMAL_BUFFER_HEADER_T *buffer;

    mmal_port_disable(decoder->input[0]);
    mmal_port_disable(decoder->output[0]);
    mmal_port_disable(decoder->control);

    mmal_port_flush(decoder->input[0]);
    mmal_port_flush(decoder->output[0]);
    mmal_port_flush(decoder->control);

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

    while (ctx->waiting_buffers) {
        FFBufferEntry *buffer = ctx->waiting_buffers;

        ctx->waiting_buffers = buffer->next;

        av_buffer_unref(&buffer->ref);
        av_free(buffer);
    }
    ctx->waiting_buffers_tail = NULL;

    ctx->frames_output = ctx->eos_received = ctx->eos_sent = ctx->packets_sent = 0;
}
Пример #3
0
static void flush(filter_t *filter)
{
    filter_sys_t *sys = filter->p_sys;
    MMAL_BUFFER_HEADER_T *buffer;

    msg_Dbg(filter, "flush deinterlace filter");

    if (atomic_load(&sys->input_in_transit) ||
            atomic_load(&sys->output_in_transit)) {

        msg_Dbg(filter, "flush: flush ports (input: %d, output: %d in transit)",
                sys->input_in_transit, sys->output_in_transit);
        mmal_port_flush(sys->output);
        mmal_port_flush(sys->input);

        msg_Dbg(filter, "flush: wait for all buffers to be returned");
        vlc_mutex_lock(&sys->buffer_cond_mutex);
        while (atomic_load(&sys->input_in_transit) ||
                atomic_load(&sys->output_in_transit)) {
            vlc_cond_wait(&sys->buffer_cond, &sys->buffer_cond_mutex);
        }
        vlc_mutex_unlock(&sys->buffer_cond_mutex);
    }

    while ((buffer = mmal_queue_get(sys->filtered_pictures))) {
        picture_t *pic = (picture_t *)buffer->user_data;
        msg_Dbg(filter, "flush: release already filtered pic %p",
                (void *)pic);
        picture_Release(pic);
    }
    msg_Dbg(filter, "flush: done");
}
Пример #4
0
Файл: codec.c Проект: Adatan/vlc
static int flush_decoder(decoder_t *dec)
{
    decoder_sys_t *sys = dec->p_sys;
    MMAL_BUFFER_HEADER_T *buffer;
    MMAL_STATUS_T status;
    int ret = 0;

    msg_Dbg(dec, "Flushing decoder ports...");
    mmal_port_disable(sys->output);
    mmal_port_disable(sys->input);
    mmal_port_flush(sys->output);
    mmal_port_flush(sys->input);

    /* Reload extradata if available */
    if (dec->fmt_in.i_codec == VLC_CODEC_H264) {
        if (dec->fmt_in.i_extra > 0) {
            status = mmal_format_extradata_alloc(sys->input->format,
                    dec->fmt_in.i_extra);
            if (status == MMAL_SUCCESS) {
                memcpy(sys->input->format->extradata, dec->fmt_in.p_extra,
                        dec->fmt_in.i_extra);
                sys->input->format->extradata_size = dec->fmt_in.i_extra;
            } else {
                msg_Err(dec, "Failed to allocate extra format data on input port %s (status=%"PRIx32" %s)",
                        sys->input->name, status, mmal_status_to_string(status));
            }
        }
    }

    status = mmal_port_format_commit(sys->input);
    if (status != MMAL_SUCCESS) {
        msg_Err(dec, "Failed to commit format for input port %s (status=%"PRIx32" %s)",
                sys->input->name, status, mmal_status_to_string(status));
    }

    mmal_port_enable(sys->output, output_port_cb);
    mmal_port_enable(sys->input, input_port_cb);

    while (atomic_load(&sys->output_in_transit))
        vlc_sem_wait(&sys->sem);

    /* Free pictures which are decoded but have not yet been sent
     * out to the core */
    while ((buffer = mmal_queue_get(sys->decoded_pictures))) {
        picture_t *pic = (picture_t *)buffer->user_data;
        picture_Release(pic);

        if (sys->output_pool) {
            buffer->user_data = NULL;
            buffer->alloc_size = 0;
            buffer->data = NULL;
            mmal_buffer_header_release(buffer);
        }
    }
    msg_Dbg(dec, "Ports flushed, returning to normal operation");

    return ret;
}
Пример #5
0
static void disable_renderer(struct gl_hwdec *hw)
{
    struct priv *p = hw->priv;

    if (p->renderer_enabled) {
        mmal_port_disable(p->renderer->control);
        mmal_port_disable(p->renderer->input[0]);

        mmal_port_flush(p->renderer->control);
        mmal_port_flush(p->renderer->input[0]);

        mmal_component_disable(p->renderer);
    }
    mmal_pool_destroy(p->swpool);
    p->swpool = NULL;
    p->renderer_enabled = false;
}
Пример #6
0
void CMMALRenderer::UnInitMMAL()
{
  CSingleLock lock(m_sharedSection);
  CLog::Log(LOGDEBUG, "%s::%s pool(%p)", CLASSNAME, __func__, m_vout_input_pool);
  if (m_queue)
  {
    StopThread(true);
    mmal_queue_destroy(m_queue);
    m_queue = nullptr;
  }
  if (m_vout)
  {
    mmal_component_disable(m_vout);
  }

  if (m_vout_input)
  {
    mmal_port_flush(m_vout_input);
    mmal_port_disable(m_vout_input);
  }

  ReleaseBuffers();

  if (m_vout_input_pool)
  {
    mmal_port_pool_destroy(m_vout_input, m_vout_input_pool);
    m_vout_input_pool = NULL;
  }
  m_vout_input = NULL;

  if (m_vout)
  {
    mmal_component_release(m_vout);
    m_vout = NULL;
  }

  m_src_rect.SetRect(0, 0, 0, 0);
  m_dst_rect.SetRect(0, 0, 0, 0);
  m_video_stereo_mode = RENDER_STEREO_MODE_OFF;
  m_display_stereo_mode = RENDER_STEREO_MODE_OFF;
  m_StereoInvert = false;
  m_format = RENDER_FMT_NONE;

  m_bConfigured = false;
  m_bMMALConfigured = false;
}
Пример #7
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;
}
Пример #8
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;
}