diff options
Diffstat (limited to 'gst')
-rw-r--r-- | gst/adder/Makefile.am | 6 | ||||
-rw-r--r-- | gst/adder/gstadder.c | 129 | ||||
-rw-r--r-- | gst/audiorate/gstaudiorate.c | 10 | ||||
-rw-r--r-- | gst/playback/gstdecodebin2.c | 39 | ||||
-rw-r--r-- | gst/playback/gstplaybin2.c | 12 | ||||
-rw-r--r-- | gst/playback/gsturidecodebin.c | 20 |
6 files changed, 145 insertions, 71 deletions
diff --git a/gst/adder/Makefile.am b/gst/adder/Makefile.am index cf4005d07..7ec0a40e2 100644 --- a/gst/adder/Makefile.am +++ b/gst/adder/Makefile.am @@ -1,10 +1,12 @@ plugin_LTLIBRARIES = libgstadder.la libgstadder_la_SOURCES = gstadder.c -libgstadder_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstadder_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) #$(LIBOIL_CFLAGS) libgstadder_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstadder_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) +libgstadder_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) #$(LIBOIL_LIBS) libgstadder_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/adder/gstadder.c b/gst/adder/gstadder.c index 1d17d0bfc..4dc9fd42e 100644 --- a/gst/adder/gstadder.c +++ b/gst/adder/gstadder.c @@ -136,6 +136,8 @@ static void gst_adder_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn gst_adder_change_state (GstElement * element, GstStateChange transition); +static GstBuffer *gst_adder_do_clip (GstCollectPads * pads, + GstCollectData * data, GstBuffer * buffer, gpointer user_data); static GstFlowReturn gst_adder_collected (GstCollectPads * pads, gpointer user_data); @@ -780,7 +782,7 @@ gst_adder_sink_event (GstPad * pad, GstEvent * event) case GST_EVENT_FLUSH_STOP: /* we received a flush-stop. The collect_event function will push the * event past our element. We simply forward all flush-stop events, even - * when no flush-stop was pendingk, this is required because collectpads + * when no flush-stop was pending, this is required because collectpads * does not provide an API to handle-but-not-forward the flush-stop. * We unset the pending flush-stop flag so that we don't send anymore * flush-stop from the collect function later. @@ -798,7 +800,7 @@ gst_adder_sink_event (GstPad * pad, GstEvent * event) break; case GST_EVENT_TAG: GST_OBJECT_LOCK (adder->collect); - /* collectpads is a pile of horse manure. */ + /* collect tags here so we can push them out when we collect data */ adder->pending_events = g_list_append (adder->pending_events, event); GST_OBJECT_UNLOCK (adder->collect); goto beach; @@ -882,6 +884,8 @@ gst_adder_init (GstAdder * adder) adder->collect = gst_collect_pads_new (); gst_collect_pads_set_function (adder->collect, GST_DEBUG_FUNCPTR (gst_adder_collected), adder); + gst_collect_pads_set_clip_function (adder->collect, + GST_DEBUG_FUNCPTR (gst_adder_do_clip), adder); } static void @@ -1023,6 +1027,18 @@ gst_adder_release_pad (GstElement * element, GstPad * pad) gst_element_remove_pad (element, pad); } +static GstBuffer * +gst_adder_do_clip (GstCollectPads * pads, GstCollectData * data, + GstBuffer * buffer, gpointer user_data) +{ + GstAdder *adder = GST_ADDER (user_data); + + buffer = gst_audio_buffer_clip (buffer, &data->segment, adder->rate, + adder->bps); + + return buffer; +} + static GstFlowReturn gst_adder_collected (GstCollectPads * pads, gpointer user_data) { @@ -1043,12 +1059,11 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data) * mix into a temp (float) buffer and scale afterwards as well */ GstAdder *adder; - GSList *collected; + GSList *collected, *next = NULL; GstFlowReturn ret; - GstBuffer *outbuf = NULL; + GstBuffer *outbuf = NULL, *gapbuf = NULL; gpointer outdata = NULL; guint outsize; - gboolean empty = TRUE; adder = GST_ADDER (user_data); @@ -1064,20 +1079,26 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data) /* get available bytes for reading, this can be 0 which could mean empty * buffers or EOS, which we will catch when we loop over the pads. */ outsize = gst_collect_pads_available (pads); + /* can only happen when no pads to collect or all EOS */ + if (outsize == 0) + goto eos; GST_LOG_OBJECT (adder, "starting to cycle through channels, %d bytes available (bps = %d)", outsize, adder->bps); - for (collected = pads->data; collected; collected = g_slist_next (collected)) { + for (collected = pads->data; collected; collected = next) { GstCollectData *collect_data; GstBuffer *inbuf; - guint8 *indata; - guint insize; + gboolean is_gap; + + /* take next to see if this is the last collectdata */ + next = g_slist_next (collected); collect_data = (GstCollectData *) collected->data; - /* get a subbuffer of size bytes */ + /* get a buffer of size bytes, if we get a buffer, it is at least outsize + * bytes big. */ inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize); /* NULL means EOS or an empty buffer so we still need to flush in * case of an empty buffer. */ @@ -1086,55 +1107,69 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data) continue; } - indata = GST_BUFFER_DATA (inbuf); - insize = GST_BUFFER_SIZE (inbuf); + is_gap = GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP); + /* Try to make an output buffer */ if (outbuf == NULL) { - GST_LOG_OBJECT (adder, "channel %p: making output buffer of %d bytes", - collect_data, outsize); + /* if this is a gap buffer but we have some more pads to check, skip it. + * If we are at the last buffer, take it, regardless if it is a GAP + * buffer or not. */ + if (is_gap && next) { + GST_DEBUG_OBJECT (adder, "skipping, non-last GAP buffer"); + /* we keep the GAP buffer, if we don't have anymore buffers (all pads + * EOS, we can use this one as the output buffer. */ + if (gapbuf == NULL) + gapbuf = inbuf; + else + gst_buffer_unref (inbuf); + continue; + } - /* first buffer, alloc outsize. - * FIXME: we can easily subbuffer and _make_writable. - * FIXME: only create empty buffer for first non-gap buffer, so that we - * only use adder function when really adding - */ - outbuf = gst_buffer_new_and_alloc (outsize); + GST_LOG_OBJECT (adder, "channel %p: preparing output buffer of %d bytes", + collect_data, outsize); + /* make data and metadata writable, can simply return the inbuf when we + * are the only one referencing this buffer. If this is the last (and + * only) GAP buffer, it will automatically copy the GAP flag. */ + outbuf = gst_buffer_make_writable (inbuf); outdata = GST_BUFFER_DATA (outbuf); gst_buffer_set_caps (outbuf, GST_PAD_CAPS (adder->srcpad)); - - if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { - GST_LOG_OBJECT (adder, "channel %p: copying %d bytes from data %p", - collect_data, insize, indata); - /* clear if we are only going to fill a partial buffer */ - if (G_UNLIKELY (outsize > insize)) - memset ((guint8 *) outdata + insize, 0, outsize - insize); - /* and copy the data into it */ - memcpy (outdata, indata, insize); - empty = FALSE; - } else { - /* clear whole buffer */ - GST_LOG_OBJECT (adder, "channel %p: zeroing %d bytes from data %p", - collect_data, insize, indata); - memset (outdata, 0, outsize); - } } else { - if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { + if (!is_gap) { + /* we had a previous output buffer, mix this non-GAP buffer */ + guint8 *indata; + guint insize; + + indata = GST_BUFFER_DATA (inbuf); + insize = GST_BUFFER_SIZE (inbuf); + + /* all buffers should have outsize, there are no short buffers because we + * asked for the max size above */ + g_assert (insize == outsize); + GST_LOG_OBJECT (adder, "channel %p: mixing %d bytes from data %p", collect_data, insize, indata); + /* further buffers, need to add them */ adder->func ((gpointer) outdata, (gpointer) indata, insize); - empty = FALSE; } else { - GST_LOG_OBJECT (adder, "channel %p: skipping %d bytes from data %p", - collect_data, insize, indata); + /* skip gap buffer */ + GST_LOG_OBJECT (adder, "channel %p: skipping GAP buffer", collect_data); } + gst_buffer_unref (inbuf); } - gst_buffer_unref (inbuf); } - /* can only happen when no pads to collect or all EOS */ - if (outbuf == NULL) - goto eos; + if (outbuf == NULL) { + /* no output buffer, reuse one of the GAP buffers then if we have one */ + if (gapbuf) { + GST_LOG_OBJECT (adder, "reusing GAP buffer %p", gapbuf); + outbuf = gapbuf; + } else + /* assume EOS otherwise, this should not happen, really */ + goto eos; + } else if (gapbuf) + /* we had an output buffer, unref the gapbuffer we kept */ + gst_buffer_unref (gapbuf); /* our timestamping is very simple, just an ever incrementing * counter, the new segment time will take care of their respective @@ -1199,13 +1234,9 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data) GST_BUFFER_DURATION (outbuf) = adder->timestamp - GST_BUFFER_TIMESTAMP (outbuf); - /* if we only processed silence, mark output again as silence */ - if (empty) - GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); - /* send it out */ - GST_LOG_OBJECT (adder, "pushing outbuf, timestamp %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); + GST_LOG_OBJECT (adder, "pushing outbuf %p, timestamp %" GST_TIME_FORMAT, + outbuf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); ret = gst_pad_push (adder->srcpad, outbuf); GST_LOG_OBJECT (adder, "pushed outbuf, result = %s", gst_flow_get_name (ret)); diff --git a/gst/audiorate/gstaudiorate.c b/gst/audiorate/gstaudiorate.c index 2fbd5f8e5..0adf8e18b 100644 --- a/gst/audiorate/gstaudiorate.c +++ b/gst/audiorate/gstaudiorate.c @@ -199,6 +199,14 @@ gst_audio_rate_class_init (GstAudioRateClass * klass) g_param_spec_boolean ("silent", "silent", "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAudioRate:tolerance + * + * The difference between incoming timestamp and next timestamp must exceed + * the given value for audiorate to add or drop samples. + * + * Since: 0.10.26 + **/ g_object_class_install_property (object_class, ARG_TOLERANCE, g_param_spec_uint64 ("tolerance", "tolerance", "Only act if timestamp jitter/imperfection exceeds indicated tolerance (ns)", @@ -664,10 +672,10 @@ gst_audio_rate_chain (GstPad * pad, GstBuffer * buf) } } +send: if (GST_BUFFER_SIZE (buf) == 0) goto beach; -send: /* Now calculate parameters for whichever buffer (either the original * or truncated one) we're pushing. */ GST_BUFFER_OFFSET (buf) = audiorate->next_offset; diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c index 09b59b1d7..95cc645fe 100644 --- a/gst/playback/gstdecodebin2.c +++ b/gst/playback/gstdecodebin2.c @@ -1469,12 +1469,12 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, "is a demuxer, connecting the pad through multiqueue '%s'", GST_OBJECT_NAME (chain->parent->multiqueue)); - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad))) goto beach; src = chain->parent->multiqueue; pad = mqpad; - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); } /* 2. Try to create an element and link to it */ @@ -1488,7 +1488,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, /* Set dpad target to pad again, it might've been unset * below but we came back here because something failed */ - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); /* take first factory */ factory = g_value_get_object (g_value_array_get_nth (factories, 0)); @@ -1519,7 +1519,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, } /* 2.0. Unlink pad */ - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); /* 2.1. Try to create an element */ if ((element = gst_element_factory_create (factory, NULL)) == NULL) { @@ -1754,11 +1754,11 @@ expose_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, if (chain->parent && !chain->elements && src != chain->parent->multiqueue) { GST_LOG_OBJECT (src, "connecting the pad through multiqueue"); - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad))) goto beach; pad = mqpad; - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); } gst_decode_pad_activate (dpad, chain); @@ -2190,7 +2190,7 @@ gst_decode_chain_free_internal (GstDecodeChain * chain, gboolean hide) chain->endcaps = NULL; } - GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hided" : "Freed"), + GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hidden" : "Freed"), chain); CHAIN_MUTEX_UNLOCK (chain); if (!hide) { @@ -2735,8 +2735,8 @@ sort_end_pads (GstDecodePad * da, GstDecodePad * db) GstStructure *sa, *sb; const gchar *namea, *nameb; - capsa = gst_pad_get_caps_reffed (GST_PAD (da)); - capsb = gst_pad_get_caps_reffed (GST_PAD (db)); + capsa = gst_pad_get_caps_reffed (GST_PAD_CAST (da)); + capsb = gst_pad_get_caps_reffed (GST_PAD_CAST (db)); sa = gst_caps_get_structure ((const GstCaps *) capsa, 0); sb = gst_caps_get_structure ((const GstCaps *) capsb, 0); @@ -2989,7 +2989,7 @@ gst_decode_bin_expose (GstDecodeBin * dbin) /* 2. activate and add */ if (!dpad->exposed - && !gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD (dpad))) { + && !gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD_CAST (dpad))) { /* not really fatal, we can try to add the other pads */ g_warning ("error adding pad to decodebin2"); continue; @@ -3167,10 +3167,11 @@ gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked) gst_pad_set_blocked_async_full (opad, blocked, (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad), (GDestroyNotify) gst_object_unref); + if (blocked) { if (dbin->shutdown) { /* deactivate to force flushing state to prevent NOT_LINKED errors */ - gst_pad_set_active (GST_PAD (dpad), FALSE); + gst_pad_set_active (GST_PAD_CAST (dpad), FALSE); } else { gst_object_ref (dpad); dbin->blocked_pads = g_list_prepend (dbin->blocked_pads, dpad); @@ -3191,7 +3192,7 @@ out: static void gst_decode_pad_add_drained_check (GstDecodePad * dpad) { - gst_pad_add_event_probe (GST_PAD (dpad), + gst_pad_add_event_probe (GST_PAD_CAST (dpad), G_CALLBACK (source_pad_event_probe), dpad); } @@ -3201,7 +3202,7 @@ gst_decode_pad_activate (GstDecodePad * dpad, GstDecodeChain * chain) g_return_if_fail (chain != NULL); dpad->chain = chain; - gst_pad_set_active (GST_PAD (dpad), TRUE); + gst_pad_set_active (GST_PAD_CAST (dpad), TRUE); gst_decode_pad_set_blocked (dpad, TRUE); gst_decode_pad_add_drained_check (dpad); } @@ -3221,11 +3222,12 @@ gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, GstDecodeChain * chain) { GstDecodePad *dpad; + GST_DEBUG_OBJECT (dbin, "making new decodepad"); dpad = g_object_new (GST_TYPE_DECODE_PAD, "direction", GST_PAD_DIRECTION (pad), NULL); - gst_ghost_pad_construct (GST_GHOST_PAD (dpad)); - gst_ghost_pad_set_target (GST_GHOST_PAD (dpad), pad); + gst_ghost_pad_construct (GST_GHOST_PAD_CAST (dpad)); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); dpad->chain = chain; dpad->dbin = dbin; @@ -3305,10 +3307,13 @@ unblock_pads (GstDecodeBin * dbin) { GList *tmp; + GST_LOG_OBJECT (dbin, "unblocking pads"); + for (tmp = dbin->blocked_pads; tmp; tmp = tmp->next) { GstDecodePad *dpad = (GstDecodePad *) tmp->data; - GstPad *opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad)); + GstPad *opad; + opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad)); if (!opad) continue; @@ -3317,7 +3322,7 @@ unblock_pads (GstDecodeBin * dbin) (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad), (GDestroyNotify) gst_object_unref); /* make flushing, prevent NOT_LINKED */ - GST_PAD_SET_FLUSHING (GST_PAD (dpad)); + GST_PAD_SET_FLUSHING (GST_PAD_CAST (dpad)); gst_object_unref (dpad); gst_object_unref (opad); GST_DEBUG_OBJECT (dpad, "unblocked"); diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index d8adb49cc..a9f71f2e9 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -3182,7 +3182,6 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target) else g_object_set (uridecodebin, "download", FALSE, NULL); - /* configure subtitle encoding */ g_object_set (uridecodebin, "subtitle-encoding", playbin->encoding, NULL); /* configure uri */ @@ -3368,6 +3367,17 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group) } if (select->selector) { + gint n; + + /* release and unref requests pad from the selector */ + for (n = 0; n < select->channels->len; n++) { + GstPad *sinkpad = g_ptr_array_index (select->channels, n); + + gst_element_release_request_pad (select->selector, sinkpad); + gst_object_unref (sinkpad); + } + g_ptr_array_set_size (select->channels, 0); + gst_element_set_state (select->selector, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (playbin), select->selector); select->selector = NULL; diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c index 5bbbe1fa9..28b985023 100644 --- a/gst/playback/gsturidecodebin.c +++ b/gst/playback/gsturidecodebin.c @@ -86,6 +86,7 @@ struct _GstURIDecodeBin gboolean use_buffering; GstElement *source; + GstElement *queue; GstElement *typefind; guint have_type_id; /* have-type signal id from typefind */ GSList *decodebins; @@ -1076,7 +1077,7 @@ analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw, GstPad *sinkpad; /* insert a queue element right before the raw pad */ - outelem = gst_element_factory_make ("queue2", "queue"); + outelem = gst_element_factory_make ("queue2", NULL); gst_bin_add (GST_BIN_CAST (decoder), outelem); sinkpad = gst_element_get_static_pad (outelem, "sink"); @@ -1084,6 +1085,9 @@ analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw, gst_object_unref (sinkpad); gst_object_unref (pad); + /* save queue pointer so we can remove it later */ + decoder->queue = outelem; + /* get the new raw srcpad */ pad = gst_element_get_static_pad (outelem, "src"); } else { @@ -1482,10 +1486,12 @@ could_not_link: { GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, (NULL), ("Can't link source to typefind element")); + gst_bin_remove (GST_BIN_CAST (decoder), typefind); return FALSE; } } +/* remove source and all related elements */ static void remove_source (GstURIDecodeBin * bin) { @@ -1506,6 +1512,18 @@ remove_source (GstURIDecodeBin * bin) } bin->source = NULL; } + if (bin->queue) { + GST_DEBUG_OBJECT (bin, "removing old queue element"); + gst_element_set_state (bin->queue, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), bin->queue); + bin->queue = NULL; + } + if (bin->typefind) { + GST_DEBUG_OBJECT (bin, "removing old typefind element"); + gst_element_set_state (bin->typefind, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), bin->typefind); + bin->typefind = NULL; + } } /* is called when a dynamic source element created a new pad. */ |