#include <stdlib.h>
#include <string.h>
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include <gst/gst_private.h>
#include <gst/glib-compat-private.h>
#include "gstbasesrc.h"
#include "gsttypefindhelper.h"
-#include <gst/gstmarshal.h>
#include <gst/gst-i18n-lib.h>
GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
#define GST_CAT_DEFAULT gst_base_src_debug
-#define GST_LIVE_GET_LOCK(elem) (GST_BASE_SRC_CAST(elem)->live_lock)
+#define GST_LIVE_GET_LOCK(elem) (&GST_BASE_SRC_CAST(elem)->live_lock)
#define GST_LIVE_LOCK(elem) g_mutex_lock(GST_LIVE_GET_LOCK(elem))
#define GST_LIVE_TRYLOCK(elem) g_mutex_trylock(GST_LIVE_GET_LOCK(elem))
#define GST_LIVE_UNLOCK(elem) g_mutex_unlock(GST_LIVE_GET_LOCK(elem))
-#define GST_LIVE_GET_COND(elem) (GST_BASE_SRC_CAST(elem)->live_cond)
+#define GST_LIVE_GET_COND(elem) (&GST_BASE_SRC_CAST(elem)->live_cond)
#define GST_LIVE_WAIT(elem) g_cond_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem))
-#define GST_LIVE_TIMED_WAIT(elem, timeval) g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem),\
- timeval)
+#define GST_LIVE_WAIT_UNTIL(elem, end_time) g_cond_timed_wait (GST_LIVE_GET_COND (elem), GST_LIVE_GET_LOCK (elem), end_time)
#define GST_LIVE_SIGNAL(elem) g_cond_signal (GST_LIVE_GET_COND (elem));
#define GST_LIVE_BROADCAST(elem) g_cond_broadcast (GST_LIVE_GET_COND (elem));
GstFlowReturn start_result;
gboolean async;
+ /* if a stream-start event should be sent */
+ gboolean stream_start_pending;
+
/* if segment should be sent */
gboolean segment_pending;
GstClockTime earliest_time;
GstBufferPool *pool;
- const GstAllocator *allocator;
+ GstAllocator *allocator;
guint prefix;
guint alignment;
};
static GstCaps *gst_base_src_default_get_caps (GstBaseSrc * bsrc,
GstCaps * filter);
-static void gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps);
-static void gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps);
+static GstCaps *gst_base_src_default_fixate (GstBaseSrc * src, GstCaps * caps);
+static GstCaps *gst_base_src_fixate (GstBaseSrc * src, GstCaps * caps);
static gboolean gst_base_src_is_random_access (GstBaseSrc * src);
static gboolean gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
basesrc->priv = GST_BASE_SRC_GET_PRIVATE (basesrc);
basesrc->is_live = FALSE;
- basesrc->live_lock = g_mutex_new ();
- basesrc->live_cond = g_cond_new ();
+ g_mutex_init (&basesrc->live_lock);
+ g_cond_init (&basesrc->live_cond);
basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
basesrc->num_buffers_left = -1;
basesrc->priv->do_timestamp = DEFAULT_DO_TIMESTAMP;
g_atomic_int_set (&basesrc->priv->have_events, FALSE);
- basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+ basesrc->priv->start_result = GST_FLOW_FLUSHING;
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
GST_OBJECT_FLAG_SET (basesrc, GST_ELEMENT_FLAG_SOURCE);
basesrc = GST_BASE_SRC (object);
- g_mutex_free (basesrc->live_lock);
- g_cond_free (basesrc->live_cond);
+ g_mutex_clear (&basesrc->live_lock);
+ g_cond_clear (&basesrc->live_cond);
event_p = &basesrc->pending_seek;
gst_event_replace (event_p, NULL);
* This function will block until a state change to PLAYING happens (in which
* case this function returns #GST_FLOW_OK) or the processing must be stopped due
* to a state change to READY or a FLUSH event (in which case this function
- * returns #GST_FLOW_WRONG_STATE).
+ * returns #GST_FLOW_FLUSHING).
*
* Since: 0.10.12
*
flushing:
{
GST_DEBUG_OBJECT (src, "we are flushing");
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
}
return res;
}
+static gboolean
+gst_base_src_send_stream_start (GstBaseSrc * src)
+{
+ gboolean ret = TRUE;
+
+ if (src->priv->stream_start_pending) {
+ ret = gst_pad_push_event (src->srcpad, gst_event_new_stream_start ());
+ src->priv->stream_start_pending = FALSE;
+ }
+
+ return ret;
+}
+
/**
* gst_base_src_set_caps:
* @src: a #GstBaseSrc
bclass = GST_BASE_SRC_GET_CLASS (src);
+ gst_base_src_send_stream_start (src);
gst_pad_push_event (src->srcpad, gst_event_new_caps (caps));
if (bclass->set_caps)
return caps;
}
-static void
+static GstCaps *
gst_base_src_default_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{
GST_DEBUG_OBJECT (bsrc, "using default caps fixate function");
- gst_caps_fixate (caps);
+ return gst_caps_fixate (caps);
}
-static void
+static GstCaps *
gst_base_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{
GstBaseSrcClass *bclass;
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->fixate)
- bclass->fixate (bsrc, caps);
+ caps = bclass->fixate (bsrc, caps);
+
+ return caps;
}
static gboolean
bclass = GST_BASE_SRC_GET_CLASS (src);
if (bclass->get_caps) {
gst_query_parse_caps (query, &filter);
- caps = bclass->get_caps (src, filter);
- gst_query_set_caps_result (query, caps);
- gst_caps_unref (caps);
- res = TRUE;
+ if ((caps = bclass->get_caps (src, filter))) {
+ gst_query_set_caps_result (query, caps);
+ gst_caps_unref (caps);
+ res = TRUE;
+ } else {
+ res = FALSE;
+ }
} else
res = FALSE;
break;
}
}
- if (G_UNLIKELY (!GST_BASE_SRC_IS_STARTED (src)))
+ if (G_UNLIKELY (!GST_BASE_SRC_IS_STARTED (src)
+ && !GST_BASE_SRC_IS_STARTING (src)))
goto not_started;
if (G_UNLIKELY (!bclass->create))
* get rid of the produced buffer. */
GST_DEBUG_OBJECT (src,
"clock was unscheduled (%d), returning WRONG_STATE", status);
- ret = GST_FLOW_WRONG_STATE;
+ ret = GST_FLOW_FLUSHING;
} else {
/* If we are running when this happens, we quickly switched between
* pause and playing. We try to produce a new buffer */
not_started:
{
GST_DEBUG_OBJECT (src, "getrange but not started");
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
no_function:
{
GST_DEBUG_OBJECT (src, "we are flushing");
gst_buffer_unref (*buf);
*buf = NULL;
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
eos:
{
flushing:
{
GST_DEBUG_OBJECT (src, "we are flushing");
- res = GST_FLOW_WRONG_STATE;
+ res = GST_FLOW_FLUSHING;
goto done;
}
}
src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
+ gst_base_src_send_stream_start (src);
+
/* check if we need to renegotiate */
if (gst_pad_check_reconfigure (pad)) {
if (!gst_base_src_negotiate (src))
{
GST_DEBUG_OBJECT (src, "we are flushing");
GST_LIVE_UNLOCK (src);
- ret = GST_FLOW_WRONG_STATE;
+ ret = GST_FLOW_FLUSHING;
goto pause;
}
pause:
static gboolean
gst_base_src_set_allocation (GstBaseSrc * basesrc, GstBufferPool * pool,
- const GstAllocator * allocator, guint prefix, guint alignment)
+ GstAllocator * allocator, guint prefix, guint alignment)
{
+ GstAllocator *oldalloc;
GstBufferPool *oldpool;
GstBaseSrcPrivate *priv = basesrc->priv;
oldpool = priv->pool;
priv->pool = pool;
+ oldalloc = priv->allocator;
priv->allocator = allocator;
priv->prefix = prefix;
}
gst_object_unref (oldpool);
}
+ if (oldalloc) {
+ gst_allocator_unref (oldalloc);
+ }
return TRUE;
/* ERRORS */
gboolean result = TRUE;
GstQuery *query;
GstBufferPool *pool = NULL;
- const GstAllocator *allocator = NULL;
+ GstAllocator *allocator = NULL;
guint size, min, max, prefix, alignment;
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
&alignment, &pool);
if (size == 0) {
- const gchar *mem = NULL;
-
/* no size, we have variable size buffers */
if (gst_query_get_n_allocation_memories (query) > 0) {
- mem = gst_query_parse_nth_allocation_memory (query, 0);
+ if ((allocator = gst_query_parse_nth_allocation_memory (query, 0)))
+ gst_allocator_ref (allocator);
}
- GST_DEBUG_OBJECT (basesrc, "0 size, getting allocator %s",
- GST_STR_NULL (mem));
- allocator = gst_allocator_find (mem);
+ GST_DEBUG_OBJECT (basesrc, "0 size, using allocator %p", allocator);
} else if (pool == NULL) {
/* fixed size, we can use a bufferpool */
GstStructure *config;
* nego is not needed */
result = TRUE;
} else {
- caps = gst_caps_make_writable (caps);
- gst_base_src_fixate (basesrc, caps);
+ caps = gst_base_src_fixate (basesrc, caps);
GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_fixed (caps)) {
/* yay, fixed caps, use those then, it's possible that the subclass does
if (GST_BASE_SRC_IS_STARTED (basesrc))
goto was_started;
- basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+ basesrc->priv->start_result = GST_FLOW_FLUSHING;
GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTING);
basesrc->num_buffers_left = basesrc->num_buffers;
basesrc->running = FALSE;
GstFormat format;
GstPadMode mode;
GstEvent *event;
- GstBaseSrcClass *bclass;
-
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
if (ret != GST_FLOW_OK)
goto error;
have_size = FALSE;
size = -1;
if (format == GST_FORMAT_BYTES) {
- bclass = GST_BASE_SRC_GET_CLASS (basesrc);
+ GstBaseSrcClass *bclass = GST_BASE_SRC_GET_CLASS (basesrc);
if (bclass->get_size) {
if (!(have_size = bclass->get_size (basesrc, &size)))
* we are not yet PLAYING */
gst_base_src_set_flushing (basesrc, FALSE, FALSE, FALSE, NULL);
+ gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (basesrc));
+
GST_OBJECT_LOCK (basesrc->srcpad);
mode = GST_PAD_MODE (basesrc->srcpad);
GST_OBJECT_UNLOCK (basesrc->srcpad);
goto no_get_range;
}
- gst_pad_mark_reconfigure (GST_BASE_SRC_PAD (basesrc));
-
GST_LIVE_LOCK (basesrc);
GST_OBJECT_FLAG_SET (basesrc, GST_BASE_SRC_FLAG_STARTED);
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
}
/**
- * gst_base_src_start_complete:
+ * gst_base_src_start_wait:
* @src: base source instance
* @ret: a #GstFlowReturn
*
{
GST_DEBUG_OBJECT (basesrc, "we are flushing");
GST_LIVE_UNLOCK (basesrc);
- return GST_FLOW_WRONG_STATE;
+ return GST_FLOW_FLUSHING;
}
}
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTING);
GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_FLAG_STARTED);
- basesrc->priv->start_result = GST_FLOW_WRONG_STATE;
+ basesrc->priv->start_result = GST_FLOW_FLUSHING;
GST_LIVE_SIGNAL (basesrc);
GST_LIVE_UNLOCK (basesrc);
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
+ basesrc->priv->stream_start_pending = TRUE;
no_preroll = gst_base_src_is_live (basesrc);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
* already did this */
g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
gst_event_replace (&basesrc->pending_seek, NULL);
+ basesrc->priv->stream_start_pending = FALSE;
break;
}
case GST_STATE_CHANGE_READY_TO_NULL: