Commit 22939b07 authored by Wim Taymans's avatar Wim Taymans
Browse files
parents 8266d201 fe970cb8
common @ 14cec891
Subproject commit 47cb23af8902d358b73d3b60ab9ea4a74d6a114f
Subproject commit 14cec891e98eb39780f67e89a1b821a839c7e370
......@@ -1119,6 +1119,9 @@ gst_rtcp_packet_fb_set_media_ssrc
gst_rtcp_ntp_to_unix
gst_rtcp_unix_to_ntp
gst_rtcp_sdes_name_to_type
gst_rtcp_sdes_type_to_name
<SUBSECTION Standard>
</SECTION>
......
......@@ -98,6 +98,11 @@ struct _GstTheoraEnc
guint64 timestamp_offset;
gint speed_level;
gboolean vp3_compatible;
gboolean drop_frames;
gboolean cap_overflow;
gboolean cap_underflow;
int rate_buffer;
};
struct _GstTheoraEncClass
......
......@@ -104,6 +104,11 @@ _ilog (unsigned int v)
#define THEORA_DEF_KEYFRAME_FREQ 64
#define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
#define THEORA_DEF_SPEEDLEVEL 1
#define THEORA_DEF_VP3_COMPATIBLE FALSE
#define THEORA_DEF_DROP_FRAMES TRUE
#define THEORA_DEF_CAP_OVERFLOW TRUE
#define THEORA_DEF_CAP_UNDERFLOW FALSE
#define THEORA_DEF_RATE_BUFFER 0
enum
{
ARG_0,
......@@ -120,6 +125,11 @@ enum
ARG_NOISE_SENSITIVITY,
ARG_SHARPNESS,
ARG_SPEEDLEVEL,
ARG_VP3_COMPATIBLE,
ARG_DROP_FRAMES,
ARG_CAP_OVERFLOW,
ARG_CAP_UNDERFLOW,
ARG_RATE_BUFFER,
/* FILL ME */
};
......@@ -273,6 +283,38 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
"encoding. This property requires libtheora version >= 1.0",
0, 2, THEORA_DEF_SPEEDLEVEL,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_VP3_COMPATIBLE,
g_param_spec_boolean ("vp3-compatible", "VP3 Compatible",
"Disables non-VP3 compatible features."
" This property requires libtheora version >= 1.1",
THEORA_DEF_VP3_COMPATIBLE,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_DROP_FRAMES,
g_param_spec_boolean ("drop-frames", "VP3 Compatible",
"Allow or disallow frame dropping."
" This property requires libtheora version >= 1.1",
THEORA_DEF_DROP_FRAMES,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_CAP_OVERFLOW,
g_param_spec_boolean ("cap-overflow", "VP3 Compatible",
"Enable capping of bit reservoir overflows."
" This property requires libtheora version >= 1.1",
THEORA_DEF_CAP_OVERFLOW,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_CAP_UNDERFLOW,
g_param_spec_boolean ("cap-underflow", "VP3 Compatible",
"Enable capping of bit reservoir underflows."
" This property requires libtheora version >= 1.1",
THEORA_DEF_CAP_UNDERFLOW,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, ARG_RATE_BUFFER,
g_param_spec_int ("rate-buffer", "Rate Control Buffer",
"Sets the size of the rate control buffer, in units of frames. "
"The default value of 0 instructs the encoder to automatically "
"select an appropriate value."
" This property requires libtheora version >= 1.1",
0, 1000, THEORA_DEF_RATE_BUFFER,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = theora_enc_change_state;
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
......@@ -305,6 +347,11 @@ gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
enc->expected_ts = GST_CLOCK_TIME_NONE;
enc->speed_level = THEORA_DEF_SPEEDLEVEL;
enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE;
enc->drop_frames = THEORA_DEF_DROP_FRAMES;
enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW;
enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW;
enc->rate_buffer = THEORA_DEF_RATE_BUFFER;
}
static void
......@@ -325,6 +372,7 @@ static void
theora_enc_reset (GstTheoraEnc * enc)
{
ogg_uint32_t keyframe_force;
int rate_flags;
if (enc->encoder)
th_encode_free (enc->encoder);
......@@ -335,6 +383,31 @@ theora_enc_reset (GstTheoraEnc * enc)
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level,
sizeof (enc->speed_level));
#endif
#ifdef TH_ENCCTL_SET_VP3_COMPATIBLE
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_VP3_COMPATIBLE,
&enc->vp3_compatible, sizeof (enc->vp3_compatible));
#endif
rate_flags = 0;
#ifdef TH_ENCCTL_SET_RATE_FLAGS
if (enc->drop_frames)
rate_flags |= TH_RATECTL_DROP_FRAMES;
if (enc->drop_frames)
rate_flags |= TH_RATECTL_CAP_OVERFLOW;
if (enc->drop_frames)
rate_flags |= TH_RATECTL_CAP_UNDERFLOW;
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_FLAGS,
&rate_flags, sizeof (rate_flags));
#endif
#ifdef TH_ENCCTL_SET_RATE_BUFFER
if (enc->rate_buffer) {
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_BUFFER,
&enc->rate_buffer, sizeof (enc->rate_buffer));
} else {
/* FIXME */
}
#endif
keyframe_force = enc->keyframe_auto ?
enc->keyframe_force : enc->keyframe_freq;
......@@ -1082,6 +1155,31 @@ theora_enc_set_property (GObject * object, guint prop_id,
case ARG_SPEEDLEVEL:
#ifdef TH_ENCCTL_SET_SPLEVEL
enc->speed_level = g_value_get_int (value);
#endif
break;
case ARG_VP3_COMPATIBLE:
#ifdef TH_ENCCTL_SET_VP3_COMPATIBLE
enc->vp3_compatible = g_value_get_boolean (value);
#endif
break;
case ARG_DROP_FRAMES:
#ifdef TH_ENCCTL_SET_RATE_FLAGS
enc->drop_frames = g_value_get_boolean (value);
#endif
break;
case ARG_CAP_OVERFLOW:
#ifdef TH_ENCCTL_SET_RATE_FLAGS
enc->cap_overflow = g_value_get_boolean (value);
#endif
break;
case ARG_CAP_UNDERFLOW:
#ifdef TH_ENCCTL_SET_RATE_FLAGS
enc->cap_underflow = g_value_get_boolean (value);
#endif
break;
case ARG_RATE_BUFFER:
#ifdef TH_ENCCTL_SET_RATE_BUFFER
enc->rate_buffer = g_value_get_int (value);
#endif
break;
default:
......@@ -1136,6 +1234,21 @@ theora_enc_get_property (GObject * object, guint prop_id,
case ARG_SPEEDLEVEL:
g_value_set_int (value, enc->speed_level);
break;
case ARG_VP3_COMPATIBLE:
g_value_set_boolean (value, enc->vp3_compatible);
break;
case ARG_DROP_FRAMES:
g_value_set_boolean (value, enc->drop_frames);
break;
case ARG_CAP_OVERFLOW:
g_value_set_boolean (value, enc->cap_overflow);
break;
case ARG_CAP_UNDERFLOW:
g_value_set_boolean (value, enc->cap_underflow);
break;
case ARG_RATE_BUFFER:
g_value_set_int (value, enc->rate_buffer);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
......
......@@ -88,9 +88,9 @@ enum
/* FIXME, enable pull mode when clock slaving and trick modes are figured out */
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
/* when timestamps or clock slaving drift for more than 10ms we resync. This is
/* when timestamps or clock slaving drift for more than 20ms we resync. This is
* a reasonable default */
#define DEFAULT_DRIFT_TOLERANCE ((20 * GST_MSECOND) / GST_USECOND)
#define DEFAULT_DRIFT_TOLERANCE ((40 * GST_MSECOND) / GST_USECOND)
enum
{
......
......@@ -1853,3 +1853,93 @@ gst_rtcp_unix_to_ntp (guint64 unixtime)
return ntptime;
}
/**
* gst_rtcp_sdes_type_to_name:
* @type: a #GstRTCPSDESType
*
* Converts @type to the string equivalent. The string is typically used as a
* key in a #GstStructure containing SDES items.
*
* Returns: the string equivalent of @type
*
* Since: 0.10.26
*/
const gchar *
gst_rtcp_sdes_type_to_name (GstRTCPSDESType type)
{
const gchar *result;
switch (type) {
case GST_RTCP_SDES_CNAME:
result = "cname";
break;
case GST_RTCP_SDES_NAME:
result = "name";
break;
case GST_RTCP_SDES_EMAIL:
result = "email";
break;
case GST_RTCP_SDES_PHONE:
result = "phone";
break;
case GST_RTCP_SDES_LOC:
result = "location";
break;
case GST_RTCP_SDES_TOOL:
result = "tool";
break;
case GST_RTCP_SDES_NOTE:
result = "note";
break;
case GST_RTCP_SDES_PRIV:
result = "priv";
break;
default:
result = NULL;
break;
}
return result;
}
/**
* gst_rtcp_sdes_name_to_type:
* @name: a SDES name
*
* Convert @name into a @GstRTCPSDESType. @name is typically a key in a
* #GstStructure containing SDES items.
*
* Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name
* is a private sdes item.
*
* Since: 0.10.26
*/
GstRTCPSDESType
gst_rtcp_sdes_name_to_type (const gchar * name)
{
if (name == NULL || strlen (name) == 0)
return GST_RTCP_SDES_INVALID;
if (strcmp ("cname", name) == 0)
return GST_RTCP_SDES_CNAME;
if (strcmp ("name", name) == 0)
return GST_RTCP_SDES_NAME;
if (strcmp ("email", name) == 0)
return GST_RTCP_SDES_EMAIL;
if (strcmp ("phone", name) == 0)
return GST_RTCP_SDES_PHONE;
if (strcmp ("location", name) == 0)
return GST_RTCP_SDES_LOC;
if (strcmp ("tool", name) == 0)
return GST_RTCP_SDES_TOOL;
if (strcmp ("note", name) == 0)
return GST_RTCP_SDES_NOTE;
return GST_RTCP_SDES_PRIV;
}
......@@ -274,6 +274,9 @@ void gst_rtcp_packet_fb_set_type (GstRTCPPacket *packet, Gs
guint64 gst_rtcp_ntp_to_unix (guint64 ntptime);
guint64 gst_rtcp_unix_to_ntp (guint64 unixtime);
const gchar * gst_rtcp_sdes_type_to_name (GstRTCPSDESType type);
GstRTCPSDESType gst_rtcp_sdes_name_to_type (const gchar *name);
G_END_DECLS
#endif /* __GST_RTCPBUFFER_H__ */
......
......@@ -356,7 +356,7 @@ gst_tag_get_language_name (const gchar * language_code)
*
* Language codes are case-sensitive and expected to be lower case.
*
* Returns two-letter ISO-639-1 language code string that maps to @lang_code,
* Returns: two-letter ISO-639-1 language code string that maps to @lang_code,
* or NULL if no mapping is known. The returned string must not be
* modified or freed.
*
......@@ -438,7 +438,7 @@ gst_tag_get_language_code_iso_639_2X (const gchar * lang_code, guint8 flags)
*
* Language codes are case-sensitive and expected to be lower case.
*
* Returns three-letter ISO-639-2 language code string that maps to @lang_code,
* Returns: three-letter ISO-639-2 language code string that maps to @lang_code,
* or NULL if no mapping is known. The returned string must not be
* modified or freed.
*
......@@ -474,7 +474,7 @@ gst_tag_get_language_code_iso_639_2T (const gchar * lang_code)
*
* Language codes are case-sensitive and expected to be lower case.
*
* Returns three-letter ISO-639-2 language code string that maps to @lang_code,
* Returns: three-letter ISO-639-2 language code string that maps to @lang_code,
* or NULL if no mapping is known. The returned string must not be
* modified or freed.
*
......
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
......
......@@ -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));
......
......@@ -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;
......
......@@ -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);