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