Пример #1
0
static GstFlowReturn
gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind)
{
  GstTypeFindProbability probability;
  GstCaps *caps;

  if (GST_BUFFER_SIZE (typefind->store) < TYPE_FIND_MIN_SIZE) {
    GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
        "(%u bytes)", GST_BUFFER_SIZE (typefind->store));
    return GST_FLOW_OK;
  }

  caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
      typefind->store, &probability);

  if (caps == NULL && GST_BUFFER_SIZE (typefind->store) > TYPE_FIND_MAX_SIZE) {
    GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
    stop_typefinding (typefind);
    return GST_FLOW_ERROR;
  } else if (caps == NULL) {
    GST_DEBUG_OBJECT (typefind, "no caps found with %u bytes of data, "
        "waiting for more data", GST_BUFFER_SIZE (typefind->store));
    return GST_FLOW_OK;
  }

  /* found a type */
  if (probability < typefind->min_probability) {
    GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
        "probability is %u which is lower than the required minimum of %u",
        caps, probability, typefind->min_probability);

    gst_caps_replace (&caps, NULL);

    if (GST_BUFFER_SIZE (typefind->store) >= TYPE_FIND_MAX_SIZE) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
      stop_typefinding (typefind);
      return GST_FLOW_ERROR;
    }

    GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
    return GST_FLOW_OK;
  }

  /* 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);

  /* .. and send out the accumulated data */
  stop_typefinding (typefind);
  gst_caps_unref (caps);
  return GST_FLOW_OK;
}
static gboolean
gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent,
    GstPadMode mode, gboolean active)
{
  gboolean res;
  GstTypeFindElement *typefind;

  typefind = GST_TYPE_FIND_ELEMENT (parent);

  switch (mode) {
    case GST_PAD_MODE_PULL:
      if (active) {
        gst_segment_init (&typefind->segment, GST_FORMAT_BYTES);
        typefind->need_segment = TRUE;
        typefind->need_stream_start = TRUE;
        typefind->offset = 0;
        res = TRUE;
      } else {
        res = gst_pad_stop_task (pad);
      }
      break;
    case GST_PAD_MODE_PUSH:
      if (active)
        start_typefinding (typefind);
      else
        stop_typefinding (typefind);

      res = TRUE;
      break;
    default:
      res = FALSE;
      break;
  }
  return res;
}
Пример #3
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 gboolean
gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps)
{
  /* don't operate on ANY caps */
  if (gst_caps_is_any (caps))
    return TRUE;

  gst_type_find_element_emit_have_type (typefind, GST_TYPE_FIND_MAXIMUM, caps);

  /* Shortcircuit typefinding if we get caps */
  GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
      "upstream: %" GST_PTR_FORMAT, caps);

  stop_typefinding (typefind);

  return TRUE;
}
static GstFlowReturn
gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
    gboolean check_avail, gboolean at_eos)
{
  GstTypeFindProbability probability;
  GstCaps *caps = NULL;
  gsize avail;
  const guint8 *data;
  gboolean have_min, have_max;

  GST_OBJECT_LOCK (typefind);
  if (typefind->force_caps) {
    caps = gst_caps_ref (typefind->force_caps);
    probability = GST_TYPE_FIND_MAXIMUM;
  }

  if (!caps) {
    avail = gst_adapter_available (typefind->adapter);

    if (check_avail) {
      have_min = avail >= TYPE_FIND_MIN_SIZE;
      have_max = avail >= TYPE_FIND_MAX_SIZE;
    } else {
      have_min = avail > 0;
      have_max = TRUE;
    }

    if (!have_min)
      goto not_enough_data;

    /* map all available data */
    data = gst_adapter_map (typefind->adapter, avail);
    caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
        data, avail, &probability);
    gst_adapter_unmap (typefind->adapter);

    if (caps == NULL && have_max)
      goto no_type_found;
    else if (caps == NULL)
      goto wait_for_data;

    /* found a type */
    if (probability < typefind->min_probability)
      goto low_probability;
  }

  GST_OBJECT_UNLOCK (typefind);

  /* probability is good enough too, so let's make it known ... emiting this
   * signal calls our object handler which sets the caps. */
  gst_type_find_element_emit_have_type (typefind, probability, caps);

  /* .. and send out the accumulated data */
  stop_typefinding (typefind);
  gst_caps_unref (caps);

  return GST_FLOW_OK;

not_enough_data:
  {
    GST_OBJECT_UNLOCK (typefind);

    if (at_eos) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
          (_("Stream doesn't contain enough data.")),
          ("Can't typefind stream"));
      return GST_FLOW_ERROR;
    } else {
      GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
          "(%" G_GSIZE_FORMAT " bytes)", avail);
      return GST_FLOW_OK;
    }
  }
no_type_found:
  {
    GST_OBJECT_UNLOCK (typefind);
    GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
    stop_typefinding (typefind);
    return GST_FLOW_ERROR;
  }
wait_for_data:
  {
    GST_OBJECT_UNLOCK (typefind);

    if (at_eos) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
          (_("Stream doesn't contain enough data.")),
          ("Can't typefind stream"));
      return GST_FLOW_ERROR;
    } else {
      GST_DEBUG_OBJECT (typefind,
          "no caps found with %" G_GSIZE_FORMAT " bytes of data, "
          "waiting for more data", avail);
      return GST_FLOW_OK;
    }
  }
low_probability:
  {
    GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
        "probability is %u which is lower than the required minimum of %u",
        caps, probability, typefind->min_probability);

    gst_caps_unref (caps);

    if (have_max)
      goto no_type_found;

    GST_OBJECT_UNLOCK (typefind);
    GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
    return GST_FLOW_OK;
  }
}
Пример #6
0
static gboolean
gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
{
  gboolean res = FALSE;
  GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  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_EOS:{
          GstTypeFindProbability prob = 0;
          GstCaps *caps = NULL;

          GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");

          /* we might not have started typefinding yet because there was not
           * enough data so far; just give it a shot now and see what we get */
          if (typefind->store) {
            caps = gst_type_find_helper_for_buffer (GST_OBJECT (typefind),
                typefind->store, &prob);

            if (caps && prob >= typefind->min_probability) {
              g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
                  0, prob, caps);
            } else {
              GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
                  (NULL), (NULL));
            }
            gst_caps_replace (&caps, NULL);
          } else {
            /* keep message in sync with the one in the pad activate function */
            GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
                (_("Stream contains no data.")),
                ("Can't typefind empty stream"));
          }

          stop_typefinding (typefind);
          res = gst_pad_push_event (typefind->src, event);
          break;
        }
        case GST_EVENT_FLUSH_STOP:
          g_list_foreach (typefind->cached_events,
              (GFunc) gst_mini_object_unref, NULL);
          g_list_free (typefind->cached_events);
          typefind->cached_events = NULL;
          gst_buffer_replace (&typefind->store, NULL);
          /* 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));
          typefind->cached_events =
              g_list_append (typefind->cached_events, event);
          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;
}