diff options
Diffstat (limited to 'plugins/elements/gsttypefindelement.c')
-rw-r--r-- | plugins/elements/gsttypefindelement.c | 269 |
1 files changed, 123 insertions, 146 deletions
diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index fc38031..ebbb6e7 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -15,8 +15,8 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /** * SECTION:element-typefind @@ -543,10 +543,14 @@ stop_typefinding (GstTypeFindElement * typefind) gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0); - push_cached_buffers = (state >= GST_STATE_PAUSED); + push_cached_buffers = (state >= GST_STATE_PAUSED && typefind->caps); GST_DEBUG_OBJECT (typefind, "stopping typefinding%s", - push_cached_buffers ? " and pushing cached buffers" : ""); + push_cached_buffers ? " and pushing cached events and buffers" : ""); + + typefind->mode = MODE_NORMAL; + if (push_cached_buffers) + gst_type_find_element_send_cached_events (typefind); GST_OBJECT_LOCK (typefind); avail = gst_adapter_available (typefind->adapter); @@ -561,8 +565,6 @@ stop_typefinding (GstTypeFindElement * typefind) } else { GstPad *peer = gst_pad_get_peer (typefind->src); - typefind->mode = MODE_NORMAL; - /* make sure the user gets a meaningful error message in this case, * which is not a core bug or bug of any kind (as the default error * message emitted by gstpad.c otherwise would make you think) */ @@ -578,7 +580,6 @@ stop_typefinding (GstTypeFindElement * typefind) typefind->mode = MODE_ERROR; /* make the chain function error out */ gst_buffer_unref (buffer); } else { - gst_type_find_element_send_cached_events (typefind); gst_pad_push (typefind->src, buffer); } if (peer) @@ -612,16 +613,26 @@ gst_type_find_element_sink_event (GstPad * pad, GstObject * parent, { 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 */ + /* 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; + } case GST_EVENT_EOS: { GST_INFO_OBJECT (typefind, "Got EOS and no type found yet"); @@ -643,13 +654,22 @@ gst_type_find_element_sink_event (GstPad * pad, GstObject * parent, 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; + /* 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; @@ -695,35 +715,12 @@ gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps) GST_TYPE_FIND_MAXIMUM, caps); /* Shortcircuit typefinding if we get caps */ - if (typefind->mode == MODE_TYPEFIND) { - GstBuffer *buffer; - gsize avail; - - GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from " - "upstream buffer: %" GST_PTR_FORMAT, caps); - typefind->mode = MODE_NORMAL; + GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from " + "upstream: %" GST_PTR_FORMAT, caps); - gst_type_find_element_send_cached_events (typefind); - GST_OBJECT_LOCK (typefind); - avail = gst_adapter_available (typefind->adapter); - if (avail == 0) - goto no_data; - - buffer = gst_adapter_take_buffer (typefind->adapter, avail); - GST_OBJECT_UNLOCK (typefind); - - GST_DEBUG_OBJECT (typefind, "Pushing buffer: %" G_GSIZE_FORMAT, avail); - gst_pad_push (typefind->src, buffer); - } + stop_typefinding (typefind); return TRUE; - -no_data: - { - GST_DEBUG_OBJECT (typefind, "no data to push"); - GST_OBJECT_UNLOCK (typefind); - return TRUE; - } } static gchar * @@ -852,39 +849,47 @@ gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind, gboolean check_avail) { GstTypeFindProbability probability; - GstCaps *caps; + GstCaps *caps = NULL; gsize avail; const guint8 *data; gboolean have_min, have_max; GST_OBJECT_LOCK (typefind); - 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 (typefind->force_caps) { + caps = gst_caps_ref (typefind->force_caps); + probability = GST_TYPE_FIND_MAXIMUM; } - if (!have_min) - goto not_enough_data; + 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; + } - /* 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 (!have_min) + goto not_enough_data; - if (caps == NULL && have_max) - goto no_type_found; - else if (caps == NULL) - goto wait_for_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; + } - /* 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 @@ -966,14 +971,6 @@ gst_type_find_element_activate_src_mode (GstPad * pad, GstObject * parent, * activation might happen from the streaming thread. */ gst_pad_pause_task (typefind->sink); res = gst_pad_activate_mode (typefind->sink, mode, active); - if (active && res && typefind->caps) { - GstCaps *caps; - GST_OBJECT_LOCK (typefind); - caps = gst_caps_ref (typefind->caps); - GST_OBJECT_UNLOCK (typefind); - res = gst_pad_set_caps (typefind->src, caps); - gst_caps_unref (caps); - } break; default: res = TRUE; @@ -990,47 +987,69 @@ gst_type_find_element_loop (GstPad * pad) typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); + if (typefind->need_stream_start) { + gchar *stream_id; + + stream_id = gst_pad_create_stream_id (typefind->src, + GST_ELEMENT_CAST (typefind), NULL); + + GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START"); + gst_pad_push_event (typefind->src, gst_event_new_stream_start (stream_id)); + + typefind->need_stream_start = FALSE; + g_free (stream_id); + } + if (typefind->mode == MODE_TYPEFIND) { - GstPad *peer; + GstPad *peer = NULL; GstCaps *found_caps = NULL; GstTypeFindProbability probability = GST_TYPE_FIND_NONE; GST_DEBUG_OBJECT (typefind, "find type in pull mode"); - peer = gst_pad_get_peer (pad); - if (peer) { - gint64 size; - gchar *ext; + GST_OBJECT_LOCK (typefind); + if (typefind->force_caps) { + found_caps = gst_caps_ref (typefind->force_caps); + probability = GST_TYPE_FIND_MAXIMUM; + } + GST_OBJECT_UNLOCK (typefind); - if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) { - GST_WARNING_OBJECT (typefind, "Could not query upstream length!"); - gst_object_unref (peer); + if (!found_caps) { + peer = gst_pad_get_peer (pad); + if (peer) { + gint64 size; + gchar *ext; - ret = GST_FLOW_ERROR; - goto pause; - } + if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) { + GST_WARNING_OBJECT (typefind, "Could not query upstream length!"); + gst_object_unref (peer); - /* the size if 0, we cannot continue */ - if (size == 0) { - /* keep message in sync with message in sink event handler */ - GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, - (_("Stream contains no data.")), ("Can't typefind empty stream")); - gst_object_unref (peer); - ret = GST_FLOW_ERROR; - goto pause; - } - ext = gst_type_find_get_extension (typefind, pad); + ret = GST_FLOW_ERROR; + goto pause; + } - found_caps = - gst_type_find_helper_get_range (GST_OBJECT_CAST (peer), - GST_OBJECT_PARENT (peer), - (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)), - (guint64) size, ext, &probability); - g_free (ext); + /* the size if 0, we cannot continue */ + if (size == 0) { + /* keep message in sync with message in sink event handler */ + GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, + (_("Stream contains no data.")), ("Can't typefind empty stream")); + gst_object_unref (peer); + ret = GST_FLOW_ERROR; + goto pause; + } + ext = gst_type_find_get_extension (typefind, pad); - GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps); + found_caps = + gst_type_find_helper_get_range (GST_OBJECT_CAST (peer), + GST_OBJECT_PARENT (peer), + (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)), + (guint64) size, ext, &probability); + g_free (ext); - gst_object_unref (peer); + GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps); + + gst_object_unref (peer); + } } if (!found_caps || probability < typefind->min_probability) { @@ -1055,21 +1074,6 @@ gst_type_find_element_loop (GstPad * pad) } else if (typefind->mode == MODE_NORMAL) { GstBuffer *outbuf = NULL; - if (typefind->need_stream_start) { - gchar *stream_id; - - stream_id = - gst_pad_create_stream_id (typefind->src, GST_ELEMENT_CAST (typefind), - NULL); - - GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START"); - gst_pad_push_event (typefind->src, - gst_event_new_stream_start (stream_id)); - - typefind->need_stream_start = FALSE; - g_free (stream_id); - } - if (typefind->need_segment) { typefind->need_segment = FALSE; gst_pad_push_event (typefind->src, @@ -1176,37 +1180,10 @@ gst_type_find_element_activate_sink_mode (GstPad * pad, GstObject * parent, static gboolean gst_type_find_element_activate_sink (GstPad * pad, GstObject * parent) { - GstTypeFindElement *typefind; GstQuery *query; gboolean pull_mode; - GstCaps *found_caps = NULL; - GstTypeFindProbability probability = GST_TYPE_FIND_NONE; GstSchedulingFlags sched_flags; - typefind = GST_TYPE_FIND_ELEMENT (parent); - - /* if we have force caps, use those */ - GST_OBJECT_LOCK (typefind); - if (typefind->force_caps) { - found_caps = gst_caps_ref (typefind->force_caps); - probability = GST_TYPE_FIND_MAXIMUM; - GST_OBJECT_UNLOCK (typefind); - - GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); - g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], - 0, probability, found_caps); - gst_caps_unref (found_caps); - typefind->mode = MODE_NORMAL; - /* the signal above could have made a downstream element activate - * the pad in pull mode, we check if the pad is already active now and if - * so, we are done */ - if (gst_pad_is_active (pad)) - return TRUE; - - goto typefind_push; - } - GST_OBJECT_UNLOCK (typefind); - query = gst_query_new_scheduling (); if (!gst_pad_peer_query (pad, query)) { |