示例#1
0
static gboolean
handle_event (GstBaseSrc * gst_base, GstEvent * event)
{
  GstOmxBaseSrc *self;

  self = GST_OMX_BASE_SRC (gst_base);

  GST_LOG_OBJECT (self, "begin");

  GST_DEBUG_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
      /* Close the output port. */
      g_omx_core_set_done (self->gomx);
      break;

    case GST_EVENT_NEWSEGMENT:
      break;

    default:
      break;
  }

  GST_LOG_OBJECT (self, "end");

  return true;
}
static gboolean
handle_event (GstBaseSink *gst_base,
              GstEvent *event)
{
    GstOmxBaseSink *self;
    GOmxCore *gomx;
    GOmxPort *in_port;

    self = GST_OMX_BASE_SINK (gst_base);
    gomx = self->gomx;
    in_port = self->in_port;

    GST_LOG_OBJECT (self, "begin");

    GST_DEBUG_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));

    switch (GST_EVENT_TYPE (event))
    {
        case GST_EVENT_EOS:
            /* Close the inpurt port. */
            g_omx_core_set_done (gomx);
            break;

        case GST_EVENT_FLUSH_START:
            /* unlock loops */
            g_omx_port_pause (in_port);

            /* flush all buffers */
            OMX_SendCommand (gomx->omx_handle, OMX_CommandFlush, OMX_ALL, NULL);
            break;

        case GST_EVENT_FLUSH_STOP:
            g_sem_down (gomx->flush_sem);

            g_omx_port_resume (in_port);
            break;

        default:
            break;
    }

    GST_LOG_OBJECT (self, "end");

    return TRUE;
}
示例#3
0
static GstFlowReturn
create (GstBaseSrc * gst_base,
    guint64 offset, guint length, GstBuffer ** ret_buf)
{
  GOmxCore *gomx;
  GOmxPort *out_port;
  GstOmxBaseSrc *self;
  GstFlowReturn ret = GST_FLOW_OK;

  self = GST_OMX_BASE_SRC (gst_base);

  gomx = self->gomx;

  GST_LOG_OBJECT (self, "begin");

  GST_LOG_OBJECT (self, "state: %d", gomx->omx_state);

  if (gomx->omx_state == OMX_StateLoaded) {
    GST_INFO_OBJECT (self, "omx: prepare");

    setup_ports (self);
    g_omx_core_prepare (self->gomx);
  }

  out_port = self->out_port;

  while (out_port->enabled) {
    switch (gomx->omx_state) {
      case OMX_StateIdle:
      {
        GST_INFO_OBJECT (self, "omx: play");
        g_omx_core_start (gomx);
      }
        break;
      default:
        break;
    }

    switch (gomx->omx_state) {
      case OMX_StateExecuting:
        /* OK */
        break;
      default:
        GST_ERROR_OBJECT (self, "Whoa! very wrong");
        break;
    }

    {
      OMX_BUFFERHEADERTYPE *omx_buffer;

      GST_LOG_OBJECT (self, "request_buffer");
      omx_buffer = g_omx_port_request_buffer (out_port);

      if (omx_buffer) {
        GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, offset=%lu",
            omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nOffset);

        if (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS) {
          GST_INFO_OBJECT (self, "got eos");
          g_omx_core_set_done (gomx);
          break;
        }

        if (omx_buffer->nFilledLen > 0) {
          GstBuffer *buf;

          if (out_port->enabled) {
            GstCaps *caps = NULL;

            caps = gst_pad_get_negotiated_caps (gst_base->srcpad);

            if (!caps) {
                            /** @todo We shouldn't be doing this. */
              GST_WARNING_OBJECT (self, "somebody didn't do his work");
              gomx->settings_changed_cb (gomx);
            } else {
              GST_LOG_OBJECT (self, "caps already fixed");
              gst_caps_unref (caps);
            }
          }

          buf = omx_buffer->pAppPrivate;

          if (buf && !(omx_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
            GST_BUFFER_SIZE (buf) = omx_buffer->nFilledLen;
#if 0
            if (self->use_timestamps) {
              GST_BUFFER_TIMESTAMP (buf) =
                  omx_buffer->nTimeStamp * (GST_SECOND / OMX_TICKS_PER_SECOND);
            }
#endif

            omx_buffer->pAppPrivate = NULL;
            omx_buffer->pBuffer = NULL;
            omx_buffer->nFilledLen = 0;

            *ret_buf = buf;

            gst_buffer_unref (buf);
          } else {
            /* This is only meant for the first OpenMAX buffers,
             * which need to be pre-allocated. */
            /* Also for the very last one. */
            gst_pad_alloc_buffer_and_set_caps (gst_base->srcpad,
                GST_BUFFER_OFFSET_NONE,
                omx_buffer->nFilledLen, GST_PAD_CAPS (gst_base->srcpad), &buf);

            if (buf) {
              GST_WARNING_OBJECT (self, "couldn't zero-copy");
              memcpy (GST_BUFFER_DATA (buf),
                  omx_buffer->pBuffer + omx_buffer->nOffset,
                  omx_buffer->nFilledLen);
#if 0
              if (self->use_timestamps) {
                GST_BUFFER_TIMESTAMP (buf) =
                    omx_buffer->nTimeStamp * (GST_SECOND /
                    OMX_TICKS_PER_SECOND);
              }
#endif

              omx_buffer->nFilledLen = 0;
              g_free (omx_buffer->pBuffer);
              omx_buffer->pBuffer = NULL;

              *ret_buf = buf;
            } else {
              GST_ERROR_OBJECT (self, "whoa!");
            }
          }

          if (!omx_buffer->pBuffer) {
            GstBuffer *new_buf;
            GstFlowReturn result;

            GST_LOG_OBJECT (self, "allocate buffer");
            result = gst_pad_alloc_buffer_and_set_caps (gst_base->srcpad,
                GST_BUFFER_OFFSET_NONE,
                omx_buffer->nAllocLen,
                GST_PAD_CAPS (gst_base->srcpad), &new_buf);

            if (result == GST_FLOW_OK) {
              gst_buffer_ref (new_buf);
              omx_buffer->pAppPrivate = new_buf;

              omx_buffer->pBuffer = GST_BUFFER_DATA (new_buf);
              omx_buffer->nAllocLen = GST_BUFFER_SIZE (new_buf);
            } else {
              GST_WARNING_OBJECT (self, "could not allocate buffer");
              omx_buffer->pBuffer = g_malloc (omx_buffer->nAllocLen);
            }
          }

          GST_LOG_OBJECT (self, "release_buffer");
          g_omx_port_release_buffer (out_port, omx_buffer);
          break;
        } else {
          GST_WARNING_OBJECT (self, "empty buffer");
          GST_LOG_OBJECT (self, "release_buffer");
          g_omx_port_release_buffer (out_port, omx_buffer);
          continue;
        }
      } else {
        GST_WARNING_OBJECT (self, "null buffer");
        /* ret = GST_FLOW_ERROR; */
        break;
      }
    }
  }

  if (!out_port->enabled) {
    GST_WARNING_OBJECT (self, "done");
    ret = GST_FLOW_UNEXPECTED;
  }

  GST_LOG_OBJECT (self, "end");

  return ret;
}
示例#4
0
static OMX_ERRORTYPE
EventHandler (OMX_HANDLETYPE omx_handle,
              OMX_PTR app_data,
              OMX_EVENTTYPE event,
              OMX_U32 data_1,
              OMX_U32 data_2,
              OMX_PTR event_data)
{
    GOmxCore *core;

    core = (GOmxCore *) app_data;

    switch (event)
    {
        case OMX_EventCmdComplete:
            {
                OMX_COMMANDTYPE cmd;

                cmd = (OMX_COMMANDTYPE) data_1;

                GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);

                switch (cmd)
                {
                    case OMX_CommandStateSet:
                        complete_change_state (core, data_2);
                        break;
                    case OMX_CommandFlush:
                        g_sem_up (core->flush_sem);
                        break;
                    case OMX_CommandPortDisable:
                    case OMX_CommandPortEnable:
                        g_sem_up (core->port_sem);
                    default:
                        break;
                }
                break;
            }
        case OMX_EventBufferFlag:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
                if (data_2 & OMX_BUFFERFLAG_EOS)
                {
                    g_omx_core_set_done (core);
                }
                break;
            }
        case OMX_EventPortSettingsChanged:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventPortSettingsChanged");
                /** @todo only on the relevant port. */
                if (core->settings_changed_cb)
                {
                    core->settings_changed_cb (core);
                }
                break;
            }
        case OMX_EventError:
            {
                core->omx_error = data_1;
                GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
                                  omx_error_to_str (data_1), data_1);
                /* component might leave us waiting for buffers, unblock */
                g_omx_core_flush_start (core);
                /* unlock wait_for_state */
                g_mutex_lock (core->omx_state_mutex);
                g_cond_signal (core->omx_state_condition);
                g_mutex_unlock (core->omx_state_mutex);
                break;
            }
        default:
            break;
    }

    return OMX_ErrorNone;
}
示例#5
0
static gboolean
pad_event (GstPad *pad,
           GstEvent *event)
{
    GstOmxBaseFilter *self;
    GOmxCore *gomx;
    GOmxPort *in_port;
    GOmxPort *out_port;
    gboolean ret;

    self = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));
    gomx = self->gomx;
    in_port = self->in_port;
    out_port = self->out_port;

    GST_LOG_OBJECT (self, "begin");

    GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));

    switch (GST_EVENT_TYPE (event))
    {
        case GST_EVENT_EOS:
            if (self->initialized)
            {
                /* send buffer with eos flag */
                /** @todo move to util */
                {
                    OMX_BUFFERHEADERTYPE *omx_buffer;

                    GST_LOG_OBJECT (self, "request buffer");
                    omx_buffer = g_omx_port_request_buffer (in_port);

                    if (G_LIKELY (omx_buffer))
                    {
                        omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;

                        GST_LOG_OBJECT (self, "release_buffer");
                        /* foo_buffer_untaint (omx_buffer); */
                        g_omx_port_release_buffer (in_port, omx_buffer);
                    }
                    else
                    {
                        g_omx_core_set_done (gomx);
                    }
                }

                /* Wait for the output port to get the EOS. */
                g_omx_core_wait_for_done (gomx);
            }

            ret = gst_pad_push_event (self->srcpad, event);
            break;

        case GST_EVENT_FLUSH_START:
            gst_pad_push_event (self->srcpad, event);
            self->last_pad_push_return = GST_FLOW_WRONG_STATE;

            g_omx_core_flush_start (gomx);

            gst_pad_pause_task (self->srcpad);

            ret = TRUE;
            break;

        case GST_EVENT_FLUSH_STOP:
            gst_pad_push_event (self->srcpad, event);
            self->last_pad_push_return = GST_FLOW_OK;

            g_omx_core_flush_stop (gomx);

            gst_pad_start_task (self->srcpad, output_loop, self->srcpad);

            ret = TRUE;
            break;

        case GST_EVENT_NEWSEGMENT:
            ret = gst_pad_push_event (self->srcpad, event);
            break;

        default:
            ret = gst_pad_push_event (self->srcpad, event);
            break;
    }

    GST_LOG_OBJECT (self, "end");

    return ret;
}
示例#6
0
static void
output_loop (gpointer data)
{
    GstPad *pad;
    GOmxCore *gomx;
    GOmxPort *out_port;
    GstOmxBaseFilter *self;
    GstFlowReturn ret = GST_FLOW_OK;

    pad = data;
    self = GST_OMX_BASE_FILTER (gst_pad_get_parent (pad));
    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");

    if (!self->initialized)
    {
        g_error ("not initialized");
        return;
    }

    out_port = self->out_port;

    if (G_LIKELY (out_port->enabled))
    {
        OMX_BUFFERHEADERTYPE *omx_buffer = NULL;

        GST_LOG_OBJECT (self, "request buffer");
        omx_buffer = g_omx_port_request_buffer (out_port);

        GST_LOG_OBJECT (self, "omx_buffer: %p", omx_buffer);

        if (G_UNLIKELY (!omx_buffer))
        {
            GST_WARNING_OBJECT (self, "null buffer: leaving");
            goto leave;
        }

        GST_DEBUG_OBJECT (self, "omx_buffer: size=%lu, len=%lu, flags=%lu, offset=%lu, timestamp=%lld",
                          omx_buffer->nAllocLen, omx_buffer->nFilledLen, omx_buffer->nFlags,
                          omx_buffer->nOffset, omx_buffer->nTimeStamp);

        if (G_LIKELY (omx_buffer->nFilledLen > 0))
        {
            GstBuffer *buf;

#if 1
            /** @todo remove this check */
            if (G_LIKELY (self->in_port->enabled))
            {
                GstCaps *caps = NULL;

                caps = gst_pad_get_negotiated_caps (self->srcpad);

                if (!caps)
                {
                    /** @todo We shouldn't be doing this. */
                    GST_WARNING_OBJECT (self, "faking settings changed notification");
                    if (gomx->settings_changed_cb)
                        gomx->settings_changed_cb (gomx);
                }
                else
                {
                    GST_LOG_OBJECT (self, "caps already fixed: %" GST_PTR_FORMAT, caps);
                    gst_caps_unref (caps);
                }
            }
#endif

            /* buf is always null when the output buffer pointer isn't shared. */
            buf = omx_buffer->pAppPrivate;

            if (buf && !(omx_buffer->nFlags & OMX_BUFFERFLAG_EOS))
            {
                GST_BUFFER_SIZE (buf) = omx_buffer->nFilledLen;
                if (self->use_timestamps)
                {
                    GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (omx_buffer->nTimeStamp,
                                                                            GST_SECOND,
                                                                            OMX_TICKS_PER_SECOND);
                }

                omx_buffer->pAppPrivate = NULL;
                omx_buffer->pBuffer = NULL;

                ret = push_buffer (self, buf);

                gst_buffer_unref (buf);
            }
            else
            {
                /* This is only meant for the first OpenMAX buffers,
                 * which need to be pre-allocated. */
                /* Also for the very last one. */
                gst_pad_alloc_buffer_and_set_caps (self->srcpad,
                                                   GST_BUFFER_OFFSET_NONE,
                                                   omx_buffer->nFilledLen,
                                                   GST_PAD_CAPS (self->srcpad),
                                                   &buf);

                if (G_LIKELY (buf))
                {
                    memcpy (GST_BUFFER_DATA (buf), omx_buffer->pBuffer + omx_buffer->nOffset, omx_buffer->nFilledLen);
                    if (self->use_timestamps)
                    {

                        GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int (omx_buffer->nTimeStamp,
                                                                                GST_SECOND,
                                                                                OMX_TICKS_PER_SECOND);
                    }

                    if (self->share_output_buffer)
                    {
                        GST_WARNING_OBJECT (self, "couldn't zero-copy");
                        g_free (omx_buffer->pBuffer);
                        omx_buffer->pBuffer = NULL;
                    }

                    ret = push_buffer (self, buf);
                }
                else
                {
                    GST_WARNING_OBJECT (self, "couldn't allocate buffer of size %d",
                                        omx_buffer->nFilledLen);
                }
            }
        }
        else
        {
            GST_WARNING_OBJECT (self, "empty buffer");
        }

        if (G_UNLIKELY (omx_buffer->nFlags & OMX_BUFFERFLAG_EOS))
        {
            GST_DEBUG_OBJECT (self, "got eos");
            g_omx_core_set_done (gomx);
            goto leave;
        }

        if (self->share_output_buffer &&
            !omx_buffer->pBuffer &&
            omx_buffer->nOffset == 0)
        {
            GstBuffer *buf;
            GstFlowReturn result;

            GST_LOG_OBJECT (self, "allocate buffer");
            result = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
                                                        GST_BUFFER_OFFSET_NONE,
                                                        omx_buffer->nAllocLen,
                                                        GST_PAD_CAPS (self->srcpad),
                                                        &buf);

            if (G_LIKELY (result == GST_FLOW_OK))
            {
                gst_buffer_ref (buf);
                omx_buffer->pAppPrivate = buf;

                omx_buffer->pBuffer = GST_BUFFER_DATA (buf);
                omx_buffer->nAllocLen = GST_BUFFER_SIZE (buf);
            }
            else
            {
                GST_WARNING_OBJECT (self, "could not pad allocate buffer, using malloc");
                omx_buffer->pBuffer = g_malloc (omx_buffer->nAllocLen);
            }
        }

        if (self->share_output_buffer &&
            !omx_buffer->pBuffer)
        {
            GST_ERROR_OBJECT (self, "no input buffer to share");
        }

        omx_buffer->nFilledLen = 0;
        GST_LOG_OBJECT (self, "release_buffer");
        g_omx_port_release_buffer (out_port, omx_buffer);
    }

leave:

    self->last_pad_push_return = ret;

    if (ret != GST_FLOW_OK)
    {
        GST_INFO_OBJECT (self, "pause task, reason:  %s",
                         gst_flow_get_name (ret));
        gst_pad_pause_task (self->srcpad);
    }

    GST_LOG_OBJECT (self, "end");

    gst_object_unref (self);
}
/* protected helper method which can be used by derived classes:
 */
GstFlowReturn
gst_omx_base_src_create_from_port (GstOmxBaseSrc *self,
                                   GOmxPort *out_port,
                                   GstBuffer **ret_buf)
{
    GOmxCore *gomx;
    GstFlowReturn ret = GST_FLOW_OK;

    gomx = self->gomx;

    GST_LOG_OBJECT (self, "begin");

    if (out_port->enabled)
    {
        if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle))
        {
            GST_INFO_OBJECT (self, "omx: play");
            g_omx_core_start (gomx);
        }

        if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting))
        {
            GST_ERROR_OBJECT (self, "Whoa! very wrong");
            ret = GST_FLOW_ERROR;
            goto beach;
        }

        while (out_port->enabled)
        {
            gpointer obj = g_omx_port_recv (out_port);

            if (G_UNLIKELY (!obj))
            {
                ret = GST_FLOW_ERROR;
                break;
            }

            if (G_LIKELY (GST_IS_BUFFER (obj)))
            {
                GstBuffer *buf = GST_BUFFER (obj);
                if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0))
                {
                    PRINT_BUFFER (self, buf);
                    *ret_buf = buf;
                    break;
                }
            }
            else if (GST_IS_EVENT (obj))
            {
                GST_INFO_OBJECT (self, "got eos");
                g_omx_core_set_done (gomx);
                break;
            }
        }
    }

    if (!out_port->enabled)
    {
        GST_WARNING_OBJECT (self, "done");
        ret = GST_FLOW_UNEXPECTED;
    }

beach:

    GST_LOG_OBJECT (self, "end");

    return ret;
}
示例#8
0
static OMX_ERRORTYPE
EventHandler (OMX_HANDLETYPE omx_handle,
              OMX_PTR app_data,
              OMX_EVENTTYPE event,
              OMX_U32 data_1,
              OMX_U32 data_2,
              OMX_PTR event_data)
{
    GOmxCore *core;

    core = (GOmxCore *) app_data;

    switch (event)
    {
        case OMX_EventCmdComplete:
            {
                OMX_COMMANDTYPE cmd;

                cmd = (OMX_COMMANDTYPE) data_1;

                GST_DEBUG_OBJECT (core->object, "OMX_EventCmdComplete: %d", cmd);

                switch (cmd)
                {
                    case OMX_CommandStateSet:
                        complete_change_state (core, data_2);
                        break;
                    case OMX_CommandFlush:
                        g_sem_up (core->flush_sem);
                        break;
                    case OMX_CommandPortDisable:
                    case OMX_CommandPortEnable:
                        g_sem_up (core->port_sem);
                    default:
                        break;
                }
                break;
            }
        case OMX_EventBufferFlag:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventBufferFlag");
                if (data_2 & OMX_BUFFERFLAG_EOS)
                {
                    g_omx_core_set_done (core);
                }
                break;
            }
        case OMX_EventPortSettingsChanged:
            {
                GST_DEBUG_OBJECT (core->object, "OMX_EventPortSettingsChanged");
                /** @todo only on the relevant port. */
                if (core->settings_changed_cb)
                {
                    core->settings_changed_cb (core);
                }
                break;
            }
        case OMX_EventIndexSettingChanged:
            {
                GST_DEBUG_OBJECT (core->object,
                        "OMX_EventIndexSettingsChanged");
                if (core->index_settings_changed_cb)
                {
                    core->index_settings_changed_cb (core, data_1, data_2);
                }
                break;
            }
        case OMX_EventError:
            {
                core->omx_error = data_1;
                GST_ERROR_OBJECT (core->object, "unrecoverable error: %s (0x%lx)",
                                  g_omx_error_to_str (data_1), data_1);
                /* component might leave us waiting for buffers, unblock */
                g_omx_core_flush_start (core);
                /* unlock wait_for_state */
                g_mutex_lock (core->omx_state_mutex);
                g_cond_signal (core->omx_state_condition);
                g_mutex_unlock (core->omx_state_mutex);
                break;
            }
#ifdef USE_OMXTICORE
        case OMX_TI_EventBufferRefCount:
            {
                OMX_BUFFERHEADERTYPE *omx_buffer = (OMX_BUFFERHEADERTYPE *)data_1;
                GOmxPort *port = get_port (core, omx_buffer->nOutputPortIndex);

                GST_DEBUG_OBJECT (core->object, "unref: omx_buffer=%p, pAppPrivate=%p, pBuffer=%p",
                        omx_buffer, omx_buffer->pAppPrivate, omx_buffer->pBuffer);

                g_mutex_lock (core->omx_state_mutex);
                omx_buffer->nFlags |= GST_BUFFERFLAG_UNREF_CHECK;
                g_mutex_unlock (core->omx_state_mutex);

                g_omx_port_push_buffer (port, omx_buffer);
                break;
            }
#endif
        default:
            GST_WARNING_OBJECT (core->object, "unhandled event: %d", event);
            break;
    }

    return OMX_ErrorNone;
}