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; }
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; } }
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; }