static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
{
  GstTypeFindElement *typefind;
  GstFlowReturn res = GST_FLOW_OK;

  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  switch (typefind->mode) {
    case MODE_ERROR:
      /* we should already have called GST_ELEMENT_ERROR */
      return GST_FLOW_ERROR;
    case MODE_NORMAL:
      gst_buffer_set_caps (buffer, typefind->caps);
      return gst_pad_push (typefind->src, buffer);
    case MODE_TYPEFIND:{
      if (typefind->store)
        typefind->store = gst_buffer_join (typefind->store, buffer);
      else
        typefind->store = buffer;

      res = gst_type_find_element_chain_do_typefinding (typefind);

      if (typefind->mode == MODE_ERROR)
        res = GST_FLOW_ERROR;

      break;
    }
    default:
      g_assert_not_reached ();
      return GST_FLOW_ERROR;
  }

  return res;
}
Exemple #2
0
static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
{
    res = gst_type_find_element_chain_do_typefinding (typefind);
    {
        GstCaps *caps;
        caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
          typefind->store, &probability);
        // gstreamer/libs/gst/base/gsttypefindhelper.c
        // All available typefinders will be called on the data in order of rank. If
        // a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
        // typefinding is stopped immediately and the found caps will be returned
        // right away. Otherwise, all available typefind functions will the tried,
        // and the caps with the highest probability will be returned
        {
            type_list = gst_type_find_factory_get_list ();
            type_list = g_list_sort (type_list, type_find_factory_rank_cmp);

            gst_type_find_factory_call_function (helper.factory, &find);
            {
                // find function from factory
                new_factory =
                    GST_TYPE_FIND_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory)));
                new_factory->function (find, new_factory->user_data);
                gst_object_unref (new_factory);
            } // gst_type_find_factory_call_function()
        } // gst_type_find_helper_for_buffer()

        /* probability is good enough too, so let's make it known ... */
        g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
            probability, caps);

        // stop typefind
        stop_typefinding (typefind);
        {
            // TODO: why set itself to NULL?
            gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);

            // reset state to normal
            typefind->mode = MODE_NORMAL;

            // send cache event and buffers
            gst_type_find_element_send_cached_events (typefind);
            gst_pad_push (typefind->src, typefind->store);
        }
    } // gst_type_find_element_chain_do_typefinding()
}
static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  GstTypeFindElement *typefind;
  GstFlowReturn res = GST_FLOW_OK;

  typefind = GST_TYPE_FIND_ELEMENT (parent);

  GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode);

  switch (typefind->mode) {
    case MODE_ERROR:
      /* we should already have called GST_ELEMENT_ERROR */
      return GST_FLOW_ERROR;
    case MODE_NORMAL:
      /* don't take object lock as typefind->caps should not change anymore */
      return gst_pad_push (typefind->src, buffer);
    case MODE_TYPEFIND:
    {
      GST_OBJECT_LOCK (typefind);
      if (typefind->initial_offset == GST_BUFFER_OFFSET_NONE)
        typefind->initial_offset = GST_BUFFER_OFFSET (buffer);
      gst_adapter_push (typefind->adapter, buffer);
      GST_OBJECT_UNLOCK (typefind);

      res = gst_type_find_element_chain_do_typefinding (typefind, TRUE, FALSE);

      if (typefind->mode == MODE_ERROR)
        res = GST_FLOW_ERROR;

      break;
    }
    default:
      g_assert_not_reached ();
      return GST_FLOW_ERROR;
  }

  return res;
}
static gboolean
gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  gboolean res = FALSE;
  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);

  GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
      GST_EVENT_TYPE_NAME (event), typefind->mode);

  switch (typefind->mode) {
    case MODE_TYPEFIND:
      switch (GST_EVENT_TYPE (event)) {
        case GST_EVENT_CAPS:
        {
          GstCaps *caps;

          /* Parse and push out our caps and data */
          gst_event_parse_caps (event, &caps);
          res = gst_type_find_element_setcaps (typefind, caps);

          gst_event_unref (event);
          break;
        }
        case GST_EVENT_GAP:
        {
          GST_FIXME_OBJECT (typefind,
              "GAP events during typefinding not handled properly");

          /* FIXME: These would need to be inserted in the stream at
           * the right position between buffers, but we combine all
           * buffers with a GstAdapter. Drop the GAP event for now,
           * which will only cause an implicit GAP between buffers.
           */
          gst_event_unref (event);
          res = TRUE;
          break;
        }
        case GST_EVENT_EOS:
        {
          GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
          gst_type_find_element_chain_do_typefinding (typefind, FALSE, TRUE);

          res = gst_pad_push_event (typefind->src, event);
          break;
        }
        case GST_EVENT_FLUSH_STOP:{
          GList *l;

          GST_OBJECT_LOCK (typefind);

          for (l = typefind->cached_events; l; l = l->next) {
            if (GST_EVENT_IS_STICKY (l->data) &&
                GST_EVENT_TYPE (l->data) != GST_EVENT_SEGMENT &&
                GST_EVENT_TYPE (l->data) != GST_EVENT_EOS) {
              gst_pad_store_sticky_event (typefind->src, l->data);
            }
            gst_event_unref (l->data);
          }

          g_list_free (typefind->cached_events);
          typefind->cached_events = NULL;
          gst_adapter_clear (typefind->adapter);
          GST_OBJECT_UNLOCK (typefind);
          /* fall through */
        }
        case GST_EVENT_FLUSH_START:
          res = gst_pad_push_event (typefind->src, event);
          break;
        default:
          /* Forward events that would happen before the caps event
           * directly instead of storing them. There's no reason not
           * to send them directly and we should only store events
           * for later sending that would need to come after the caps
           * event */
          if (GST_EVENT_TYPE (event) < GST_EVENT_CAPS) {
            res = gst_pad_push_event (typefind->src, event);
          } else {
            GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
                GST_EVENT_TYPE_NAME (event));
            GST_OBJECT_LOCK (typefind);
            typefind->cached_events =
                g_list_append (typefind->cached_events, event);
            GST_OBJECT_UNLOCK (typefind);
            res = TRUE;
          }
          break;
      }
      break;
    case MODE_NORMAL:
      res = gst_pad_push_event (typefind->src, event);
      break;
    case MODE_ERROR:
      break;
    default:
      g_assert_not_reached ();
  }
  return res;
}
static gboolean
gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  gboolean res = FALSE;
  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);

  GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
      GST_EVENT_TYPE_NAME (event), typefind->mode);

  switch (typefind->mode) {
    case MODE_TYPEFIND:
      switch (GST_EVENT_TYPE (event)) {
        case GST_EVENT_CAPS:
        {
          GstCaps *caps;

          /* first pass the caps event downstream */
          res = gst_pad_push_event (typefind->src, gst_event_ref (event));

          /* then parse and push out our data */
          gst_event_parse_caps (event, &caps);
          res = gst_type_find_element_setcaps (typefind, caps);

          gst_event_unref (event);
          break;
        }
        case GST_EVENT_EOS:
        {
          GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
          gst_type_find_element_chain_do_typefinding (typefind, FALSE);

          res = gst_pad_push_event (typefind->src, event);
          break;
        }
        case GST_EVENT_FLUSH_STOP:
          GST_OBJECT_LOCK (typefind);
          g_list_foreach (typefind->cached_events,
              (GFunc) gst_mini_object_unref, NULL);
          g_list_free (typefind->cached_events);
          typefind->cached_events = NULL;
          gst_adapter_clear (typefind->adapter);
          GST_OBJECT_UNLOCK (typefind);
          /* fall through */
        case GST_EVENT_FLUSH_START:
          res = gst_pad_push_event (typefind->src, event);
          break;
        default:
          GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
              GST_EVENT_TYPE_NAME (event));
          GST_OBJECT_LOCK (typefind);
          typefind->cached_events =
              g_list_append (typefind->cached_events, event);
          GST_OBJECT_UNLOCK (typefind);
          res = TRUE;
          break;
      }
      break;
    case MODE_NORMAL:
      res = gst_pad_push_event (typefind->src, event);
      break;
    case MODE_ERROR:
      break;
    default:
      g_assert_not_reached ();
  }
  return res;
}