_gst_query_initialize ();
_gst_caps_initialize ();
_gst_meta_init ();
- gst_context_get_type ();
g_type_class_ref (gst_object_get_type ());
g_type_class_ref (gst_pad_get_type ());
}
}
+ if (flags & GST_BUFFER_COPY_CAPS) {
+ gst_caps_replace (&GST_BUFFER_CAPS (dest), GST_BUFFER_CAPS (src));
+ }
+
if (flags & GST_BUFFER_COPY_MEMORY) {
GstMemory *mem;
gsize skip, left, len, i, bsize;
GST_CAT_LOG (GST_CAT_BUFFER, "finalize %p", buffer);
- gst_context_replace (&GST_BUFFER_CONTEXT (buffer), NULL);
+ gst_caps_replace (&GST_BUFFER_CAPS (buffer), NULL);
/* free metadata */
for (walk = GST_BUFFER_META (buffer); walk; walk = next) {
(GstMiniObjectFreeFunction) _gst_buffer_free;
GST_BUFFER (buffer)->pool = NULL;
- GST_BUFFER_CONTEXT (buffer) = NULL;
+ GST_BUFFER_CAPS (buffer) = NULL;
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
}
/**
- * gst_buffer_get_context:
+ * gst_buffer_get_caps:
* @buffer: a #GstBuffer.
*
- * Gets the context of the buffer. This can be NULL if there
- * is no context attached to this buffer.
+ * Gets the media type of the buffer. This can be NULL if there
+ * is no media type attached to this buffer.
*
- * Returns: (transfer full): a reference to the #GstContext. unref after usage.
- * Returns NULL if there was no context on this buffer.
+ * Returns: (transfer full): a reference to the #GstCaps. unref after usage.
+ * Returns NULL if there were no caps on this buffer.
*/
/* this is not made atomic because if the buffer were reffed from multiple
* threads, it would have a refcount > 2 and thus be immutable.
*/
-GstContext *
-gst_buffer_get_context (GstBuffer * buffer)
+GstCaps *
+gst_buffer_get_caps (GstBuffer * buffer)
{
- GstContext *ret;
+ GstCaps *ret;
g_return_val_if_fail (buffer != NULL, NULL);
- ret = GST_BUFFER_CONTEXT (buffer);
+ ret = GST_BUFFER_CAPS (buffer);
if (ret)
- gst_context_ref (ret);
+ gst_caps_ref (ret);
return ret;
}
/**
- * gst_buffer_set_context:
+ * gst_buffer_set_caps:
* @buffer: a #GstBuffer.
- * @context: (transfer none): a #GstContext.
+ * @caps: (transfer none): a #GstCaps.
*
- * Sets the media type on the buffer. The refcount of the context will
- * be increased and any previous context on the buffer will be
+ * Sets the media type on the buffer. The refcount of the caps will
+ * be increased and any previous caps on the buffer will be
* unreffed.
*/
/* this is not made atomic because if the buffer were reffed from multiple
* threads, it would have a refcount > 2 and thus be immutable.
*/
void
-gst_buffer_set_context (GstBuffer * buffer, GstContext * context)
+gst_buffer_set_caps (GstBuffer * buffer, GstCaps * caps)
{
g_return_if_fail (buffer != NULL);
- g_return_if_fail (gst_buffer_is_writable (buffer));
+ g_return_if_fail (caps == NULL || GST_CAPS_IS_SIMPLE (caps));
- gst_context_replace (&GST_BUFFER_CONTEXT (buffer), context);
+#if GST_VERSION_NANO == 1
+ /* we enable this extra debugging in git versions only for now */
+ g_warn_if_fail (gst_buffer_is_writable (buffer));
+ /* FIXME: would be nice to also check if caps are fixed here, but expensive */
+#endif
+
+ gst_caps_replace (&GST_BUFFER_CAPS (buffer), caps);
}
/**
* gst_buffer_copy_region:
* @parent: a #GstBuffer.
- * @offset: the offset into parent #GstBuffer at which the new sub-buffer
+ * @offset: the offset into parent #GstBuffer at which the new sub-buffer
* begins.
* @size: the size of the new #GstBuffer sub-buffer, in bytes.
*
* Creates a sub-buffer from @parent at @offset and @size.
* This sub-buffer uses the actual memory space of the parent buffer.
* This function will copy the offset and timestamp fields when the
- * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and
+ * offset is 0. If not, they will be set to #GST_CLOCK_TIME_NONE and
* #GST_BUFFER_OFFSET_NONE.
* If @offset equals 0 and @size equals the total size of @buffer, the
* duration and offset end fields are also copied. If not they will be set
else
return NULL;
}
-
-GstCaps *
-gst_buffer_caps (GstBuffer * buffer)
-{
- GstContext *context;
- GstEvent *event;
- GstCaps *caps = NULL;
-
- if (!(context = GST_BUFFER_CONTEXT (buffer)))
- return NULL;
-
- if (!(event = gst_context_get (context, GST_EVENT_CAPS)))
- return NULL;
-
- gst_event_parse_caps (event, &caps);
- gst_event_unref (event);
-
- return caps;
-}
#ifndef __GST_BUFFER_H__
#define __GST_BUFFER_H__
-typedef struct _GstBuffer GstBuffer;
-typedef struct _GstBufferPool GstBufferPool;
-
#include <gst/gstminiobject.h>
#include <gst/gstclock.h>
-#include <gst/gstcontext.h>
+#include <gst/gstcaps.h>
#include <gst/gstmemory.h>
G_BEGIN_DECLS
extern GType _gst_buffer_type;
+typedef struct _GstBuffer GstBuffer;
+typedef struct _GstBufferPool GstBufferPool;
+
/**
* GST_BUFFER_TRACE_NAME:
*
*/
#define GST_BUFFER_DURATION(buf) (GST_BUFFER_CAST(buf)->duration)
/**
- * GST_BUFFER_CONTEXT:
+ * GST_BUFFER_CAPS:
* @buf: a #GstBuffer.
*
- * The context for this buffer.
+ * The caps for this buffer.
*/
-#define GST_BUFFER_CONTEXT(buf) (GST_BUFFER_CAST(buf)->context)
+#define GST_BUFFER_CAPS(buf) (GST_BUFFER_CAST(buf)->caps)
/**
* GST_BUFFER_OFFSET:
* @buf: a #GstBuffer.
/*< public >*/ /* with COW */
GstBufferPool *pool;
/* the media type of this buffer */
- GstContext *context;
+ GstCaps *caps;
/* timestamp */
GstClockTime timestamp;
* @GST_BUFFER_COPY_FLAGS: flag indicating that buffer flags should be copied
* @GST_BUFFER_COPY_TIMESTAMPS: flag indicating that buffer timestamp, duration,
* offset and offset_end should be copied
+ * @GST_BUFFER_COPY_CAPS: flag indicating that buffer caps should be copied
* @GST_BUFFER_COPY_MEMORY: flag indicating that buffer memory should be copied
* and appended to already existing memory
* @GST_BUFFER_COPY_MERGE: flag indicating that buffer memory should be
GST_BUFFER_COPY_NONE = 0,
GST_BUFFER_COPY_FLAGS = (1 << 0),
GST_BUFFER_COPY_TIMESTAMPS = (1 << 1),
+ GST_BUFFER_COPY_CAPS = (1 << 2),
GST_BUFFER_COPY_MEMORY = (1 << 3),
GST_BUFFER_COPY_MERGE = (1 << 4)
} GstBufferCopyFlags;
* Combination of all possible metadata fields that can be copied with
* gst_buffer_copy_into().
*/
-#define GST_BUFFER_COPY_METADATA (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS)
+#define GST_BUFFER_COPY_METADATA (GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_CAPS)
/**
* GST_BUFFER_COPY_ALL:
GST_MINI_OBJECT_CAST (nbuf)); \
} G_STMT_END
-GstContext* gst_buffer_get_context (GstBuffer *buffer);
-void gst_buffer_set_context (GstBuffer *buffer, GstContext *context);
+GstCaps* gst_buffer_get_caps (GstBuffer *buffer);
+void gst_buffer_set_caps (GstBuffer *buffer, GstCaps *caps);
/* creating a region */
GstBuffer* gst_buffer_copy_region (GstBuffer *parent, GstBufferCopyFlags flags,
*/
#define gst_value_get_buffer(v) GST_BUFFER_CAST (g_value_get_boxed(v))
-/* shortcuts */
-GstCaps * gst_buffer_caps (GstBuffer *buffer);
-
G_END_DECLS
#endif /* __GST_BUFFER_H__ */
static void
_gst_context_free (GstContext * context)
{
- GST_LOG ("freeing context %p", context);
-
g_return_if_fail (context != NULL);
g_return_if_fail (GST_IS_CONTEXT (context));
+ GST_LOG ("freeing context %p", context);
+
gst_context_clear (context);
g_slice_free1 (GST_MINI_OBJECT_SIZE (context), context);
for (i = 0; i < GST_EVENT_MAX_STICKY; i++)
gst_event_replace (&context->events[i], NULL);
}
-
-/**
- * gst_context_foreach:
- * @context: a #GstContext
- * @func: a #GFunc
- * @user_data: user data
- *
- * Call @func with the non NULL event and @user_data.
- */
-void
-gst_context_foreach (GstContext * context, GFunc func, gpointer user_data)
-{
- guint i;
- GstEvent *event;
-
- for (i = 0; i < GST_EVENT_MAX_STICKY; i++)
- if ((event = context->events[i]))
- func (event, user_data);
-}
#ifndef __GST_CONTEXT_H__
#define __GST_CONTEXT_H__
-typedef struct _GstContext GstContext;
-
#include <gst/gstminiobject.h>
#include <gst/gstevent.h>
#define GST_CONTEXT_TRACE_NAME "GstContext"
+typedef struct _GstContext GstContext;
#define GST_TYPE_CONTEXT (gst_context_get_type())
#define GST_IS_CONTEXT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_CONTEXT))
GstContext * gst_context_new (void);
-/* updating and setting events */
void gst_context_update (GstContext *context, GstEvent *event);
GstEvent * gst_context_get (GstContext *context, GstEventType type);
void gst_context_clear (GstContext *context);
-/* foreach */
-void gst_context_foreach (GstContext *context, GFunc func, gpointer user_data);
-
G_END_DECLS
#endif /* __GST_CONTEXT_H__ */
#ifndef __GST_EVENT_H__
#define __GST_EVENT_H__
-typedef struct _GstEvent GstEvent;
-
#include <gst/gstminiobject.h>
#include <gst/gstformat.h>
#include <gst/gstobject.h>
#include <gst/gstclock.h>
-#include <gst/gstcaps.h>
#include <gst/gststructure.h>
#include <gst/gsttaglist.h>
*/
#define GST_EVENT_TRACE_NAME "GstEvent"
+typedef struct _GstEvent GstEvent;
+
#define GST_TYPE_EVENT (gst_event_get_type())
#define GST_IS_EVENT(obj) (GST_IS_MINI_OBJECT_TYPE (obj, GST_TYPE_EVENT))
#define GST_EVENT(obj) ((GstEvent *)(obj))
static void
on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
{
- /* FIXME, add new signal for notifying when the context caps change */
-#if 0
GstCaps *caps;
gboolean changed;
if (caps)
gst_caps_unref (caps);
-#endif
}
static void
on_src_target_notify (GstPad * target, GParamSpec * unused, gpointer user_data)
{
- /* FIXME, add new signal for notifying when the context caps change */
-#if 0
GstProxyPad *proxypad;
GstGhostPad *gpad;
GstCaps *caps;
done:
if (caps)
gst_caps_unref (caps);
-#endif
}
static gboolean
struct _GstPadPushCache
{
GstPad *peer; /* reffed peer pad */
+ GstCaps *caps; /* caps for this link */
};
static GstPadPushCache _pad_cache_invalid = { NULL, };
g_static_rec_mutex_init (pad->stream_rec_lock);
pad->block_cond = g_cond_new ();
+
+ pad->context = gst_context_new ();
}
static void
pad->block_data = NULL;
}
-
- if (GST_PAD_CONTEXT (pad))
- gst_context_replace (&GST_PAD_CONTEXT (pad), NULL);
-
+ gst_context_clear (pad->context);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
pad->block_cond = NULL;
}
+ gst_context_unref (pad->context);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/* ensures that streaming stops */
GST_PAD_STREAM_LOCK (pad);
GST_DEBUG_OBJECT (pad, "stopped streaming");
- if (pad->context)
- gst_context_clear (pad->context);
+ gst_context_clear (pad->context);
GST_PAD_STREAM_UNLOCK (pad);
break;
}
}
}
-typedef struct
+static gboolean
+gst_pad_configure_sink (GstPad * pad, GstCaps * caps)
{
- GstPadEventFunction eventfunc;
- GstPad *pad;
- GstFlowReturn ret;
-} ContextData;
+ gboolean res;
-static void
-context_func (GstEvent * event, ContextData * data)
-{
- data->eventfunc (data->pad, gst_event_ref (event));
- /* FIXME, update return value when we can */
-}
+ /* See if pad accepts the caps */
+ if (!gst_caps_can_intersect (caps, gst_pad_get_pad_template_caps (pad)))
+ goto not_accepted;
-static GstFlowReturn
-gst_pad_configure_sink (GstPad * pad, GstContext * context)
-{
- ContextData data;
+ /* set caps on pad if call succeeds */
+ res = gst_pad_set_caps (pad, caps);
+ /* no need to unref the caps here, set_caps takes a ref and
+ * our ref goes away when we leave this function. */
- if (G_UNLIKELY ((data.eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL))
- goto no_function;
+ return res;
- data.ret = GST_FLOW_OK;
- data.pad = pad;
- gst_context_foreach (context, (GFunc) context_func, &data);
+not_accepted:
+ {
+ GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+ "caps %" GST_PTR_FORMAT " not accepted", caps);
+ return FALSE;
+ }
+}
- /* set context on pad if all succeeds */
- gst_context_replace (&GST_PAD_CONTEXT (pad), context);
+/* returns TRUE if the src pad could be configured to accept the given caps */
+static gboolean
+gst_pad_configure_src (GstPad * pad, GstCaps * caps, gboolean dosetcaps)
+{
+ gboolean res;
- return data.ret;
+ if (dosetcaps) {
+ /* See if pad accepts the caps */
+ if (!gst_pad_accept_caps (pad, caps))
+ goto not_accepted;
-no_function:
+ res = gst_pad_set_caps (pad, caps);
+ } else {
+ res = TRUE;
+ }
+ return res;
+
+not_accepted:
{
- g_warning ("pad %s:%s has no event handler, file a bug.",
- GST_DEBUG_PAD_NAME (pad));
- return GST_FLOW_ERROR;
+ GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
+ "caps %" GST_PTR_FORMAT " not accepted", caps);
+ return FALSE;
}
}
}
}
-static GstContext *
-gst_pad_data_get_context (gboolean is_buffer, void *data)
+static GstCaps *
+gst_pad_data_get_caps (gboolean is_buffer, void *data)
{
- GstContext *context;
+ GstCaps *caps;
if (G_LIKELY (is_buffer)) {
- context = GST_BUFFER_CONTEXT (data);
+ caps = GST_BUFFER_CAPS (data);
} else {
GstBuffer *buf;
if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0)))
- context = GST_BUFFER_CONTEXT (buf);
+ caps = GST_BUFFER_CAPS (buf);
else
- context = NULL;
+ caps = NULL;
}
- return context;
+ return caps;
}
/* this is the chain function that does not perform the additional argument
*/
static inline GstFlowReturn
gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
- GstContext * context, GstPadPushCache * cache)
+ GstPadPushCache * cache)
{
- gboolean context_changed;
+ GstCaps *caps;
+ gboolean caps_changed;
GstFlowReturn ret;
gboolean emit_signal;
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
- context_changed = context && context != GST_PAD_CONTEXT (pad);
+ caps = gst_pad_data_get_caps (is_buffer, data);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
+
emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
+
+#if 0
+ if (G_UNLIKELY (GST_PAD_IS_STICKY_PENDING (pad))) {
+ GstPadEventFunction eventfunc;
+
+ if (G_LIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)))) {
+ GstEvent *events[GST_EVENT_MAX_STICKY];
+ GstEvent *event;
+ guint i;
+
+ /* need to make a copy because when we release the object lock, things
+ * could just change */
+ for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
+ if ((event = pad->sticky[i]))
+ events[i] = gst_event_ref (event);
+ else
+ events[i] = NULL;
+ }
+ /* clear the flag */
+ GST_OBJECT_FLAG_UNSET (pad, GST_PAD_STICKY_PENDING);
+ GST_OBJECT_UNLOCK (pad);
+
+ /* and push */
+ GST_DEBUG_OBJECT (pad, "pushing sticky events");
+ for (i = 0; i < GST_EVENT_MAX_STICKY; i++) {
+ if ((event = events[i]))
+ eventfunc (pad, event);
+ }
+ /* and restart, we released the lock things might have changed */
+ goto again;
+ }
+ }
+#endif
+
GST_OBJECT_UNLOCK (pad);
/* see if the signal should be emited, we emit before caps nego as
}
/* we got a new datatype on the pad, see if it can handle it */
- if (G_UNLIKELY (context_changed)) {
- GST_DEBUG_OBJECT (pad, "context changed to %p", context);
- if (G_UNLIKELY (gst_pad_configure_sink (pad, context) != GST_FLOW_OK))
+ if (G_UNLIKELY (caps_changed)) {
+ GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
+ if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
goto not_negotiated;
}
if (cache) {
cache->peer = gst_object_ref (pad);
+ cache->caps = caps ? gst_caps_ref (caps) : NULL;
}
ret = chainfunc (pad, GST_BUFFER_CAST (data));
for (i = 0; i < len; i++) {
buffer = gst_buffer_list_get (list, i);
- context = GST_BUFFER_CONTEXT (buffer);
ret =
gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_ref (buffer),
- context, NULL);
+ NULL);
if (ret != GST_FLOW_OK)
break;
}
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
- return gst_pad_chain_data_unchecked (pad, TRUE, buffer,
- GST_BUFFER_CONTEXT (buffer), NULL);
+ return gst_pad_chain_data_unchecked (pad, TRUE, buffer, NULL);
}
/**
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
- return gst_pad_chain_data_unchecked (pad, FALSE, list,
- gst_pad_data_get_context (FALSE, list), NULL);
+ return gst_pad_chain_data_unchecked (pad, FALSE, list, NULL);
}
static GstFlowReturn
gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
- GstContext * context, GstPadPushCache * cache)
+ GstPadPushCache * cache)
{
GstPad *peer;
GstFlowReturn ret;
- gboolean context_changed;
+ GstCaps *caps;
+ gboolean caps_changed;
GST_OBJECT_LOCK (pad);
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
goto not_linked;
- /* Before pushing the buffer to the peer pad, ensure that context
- * is set on the buffer */
- context_changed = context != GST_PAD_CONTEXT (pad);
+ /* Before pushing the buffer to the peer pad, ensure that caps
+ * are set on this pad */
+ caps = gst_pad_data_get_caps (is_buffer, data);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
/* take ref to peer pad before releasing the lock */
gst_object_ref (peer);
GST_OBJECT_UNLOCK (pad);
/* we got a new datatype from the pad, it had better handle it */
- if (G_UNLIKELY (context_changed)) {
- GST_DEBUG_OBJECT (pad, "setting context %p on buffer", context);
-
- data = gst_mini_object_make_writable (GST_MINI_OBJECT_CAST (data));
-
- if (is_buffer)
- gst_buffer_set_context (GST_BUFFER_CAST (data), context);
+ if (G_UNLIKELY (caps_changed)) {
+ GST_DEBUG_OBJECT (pad,
+ "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
+ GST_PAD_CAPS (pad), caps, caps);
+ if (G_UNLIKELY (!gst_pad_set_caps (pad, caps)))
+ goto not_negotiated;
}
- ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, context, cache);
+ ret = gst_pad_chain_data_unchecked (peer, is_buffer, data, cache);
gst_object_unref (peer);
for (i = 0; i < len; i++) {
buffer = gst_buffer_list_get (list, i);
- ret = gst_pad_push_data (pad, TRUE, gst_buffer_ref (buffer),
- GST_BUFFER_CONTEXT (buffer), NULL);
+ ret = gst_pad_push_data (pad, TRUE, gst_buffer_ref (buffer), NULL);
if (ret != GST_FLOW_OK)
break;
}
GST_OBJECT_UNLOCK (pad);
return GST_FLOW_NOT_LINKED;
}
+not_negotiated:
+ {
+ gst_pad_data_unref (is_buffer, data);
+ gst_object_unref (peer);
+ GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "element pushed data then refused to accept the caps");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
static inline GstPadPushCache *
pad_free_cache (GstPadPushCache * cache)
{
gst_object_unref (cache->peer);
+ if (cache->caps)
+ gst_caps_unref (cache->caps);
g_slice_free (GstPadPushCache, cache);
}
GstFlowReturn ret;
gpointer *cache_ptr;
GstPad *peer;
+ GstCaps *caps;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
if (G_UNLIKELY (cache == NULL))
goto slow_path;
+ /* check caps */
+ caps = GST_BUFFER_CAPS (buffer);
+ if (G_UNLIKELY (caps && caps != cache->caps)) {
+ pad_free_cache (cache);
+ goto slow_path;
+ }
+
peer = cache->peer;
GST_PAD_STREAM_LOCK (peer);
GST_LOG_OBJECT (pad, "Taking slow path");
- ret =
- gst_pad_push_data (pad, TRUE, buffer, GST_BUFFER_CONTEXT (buffer),
- &scache);
+ ret = gst_pad_push_data (pad, TRUE, buffer, &scache);
if (scache.peer) {
GstPadPushCache *ncache;
GstFlowReturn
gst_pad_push_list (GstPad * pad, GstBufferList * list)
{
+ GstBuffer *buf;
GstPadPushCache *cache;
GstFlowReturn ret;
gpointer *cache_ptr;
GstPad *peer;
+ GstCaps *caps;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
if (G_UNLIKELY (cache == NULL))
goto slow_path;
+ /* check caps */
+ if ((buf = gst_buffer_list_get (list, 0)))
+ caps = GST_BUFFER_CAPS (buf);
+ else
+ caps = NULL;
+
+ if (G_UNLIKELY (caps && caps != cache->caps)) {
+ pad_free_cache (cache);
+ goto slow_path;
+ }
+
peer = cache->peer;
GST_PAD_STREAM_LOCK (peer);
GST_LOG_OBJECT (pad, "Taking slow path");
- ret = gst_pad_push_data (pad, FALSE, list,
- gst_pad_data_get_context (FALSE, list), &scache);
+ ret = gst_pad_push_data (pad, FALSE, list, &scache);
if (scache.peer) {
GstPadPushCache *ncache;
GstFlowReturn ret;
GstPadGetRangeFunction getrangefunc;
gboolean emit_signal;
- GstContext *context;
- gboolean context_changed;
+ GstCaps *caps;
+ gboolean caps_changed;
GST_PAD_STREAM_LOCK (pad);
goto get_range_failed;
GST_OBJECT_LOCK (pad);
- /* Before pushing the buffer to the peer pad, ensure that context
- * is set on this buffer */
- context = GST_PAD_CONTEXT (pad);
- context_changed = context != GST_BUFFER_CONTEXT (*buffer);
+ /* Before pushing the buffer to the peer pad, ensure that caps
+ * are set on this pad */
+ caps = GST_BUFFER_CAPS (*buffer);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
GST_OBJECT_UNLOCK (pad);
- if (G_UNLIKELY (context_changed)) {
- GST_DEBUG_OBJECT (pad, "set context on buffer %p", *buffer);
-
- *buffer = gst_buffer_make_writable (*buffer);
- gst_buffer_set_context (*buffer, context);
+ if (G_UNLIKELY (caps_changed)) {
+ GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
+ /* this should usually work because the element produced the buffer */
+ if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
+ goto not_negotiated;
}
return ret;
pad, "getrange failed, flow: %s", gst_flow_get_name (ret));
return ret;
}
+not_negotiated:
+ {
+ gst_buffer_unref (*buffer);
+ *buffer = NULL;
+ GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
+ "getrange returned buffer of unaccaptable caps");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
/**
GstPad *peer;
GstFlowReturn ret;
gboolean emit_signal;
- GstContext *context;
- gboolean context_changed;
+ GstCaps *caps;
+ gboolean caps_changed;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
GST_OBJECT_LOCK (pad);
/* Before pushing the buffer to the peer pad, ensure that caps
* are set on this pad */
- context = GST_BUFFER_CONTEXT (*buffer);
- context_changed = context && context != GST_PAD_CONTEXT (pad);
+ caps = GST_BUFFER_CAPS (*buffer);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
GST_OBJECT_UNLOCK (pad);
/* we got a new datatype on the pad, see if it can handle it */
- if (G_UNLIKELY (context_changed)) {
- GST_DEBUG_OBJECT (pad, "context changed to %p", context);
- if (G_UNLIKELY (gst_pad_configure_sink (pad, context) != GST_FLOW_OK))
+ if (G_UNLIKELY (caps_changed)) {
+ GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
+ if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
goto not_negotiated;
}
return ret;
/* store the event on the pad, but only on srcpads */
if (GST_PAD_IS_SRC (pad) && GST_EVENT_IS_STICKY (event)) {
- if (pad->context)
- pad->context = gst_context_make_writable (pad->context);
- else
- pad->context = gst_context_new ();
-
- g_assert (GST_IS_CONTEXT (GST_PAD_CONTEXT (pad)));
-
+ pad->context = gst_context_make_writable (pad->context);
gst_context_update (pad->context, event);
}
* The caps for this pad.
*/
#define GST_PAD_CAPS(pad) (GST_PAD_CAST(pad)->caps)
-#define GST_PAD_CONTEXT(pad) (GST_PAD_CAST(pad)->context)
#define GST_PAD_GETCAPSFUNC(pad) (GST_PAD_CAST(pad)->getcapsfunc)
#define GST_PAD_SETCAPSFUNC(pad) (GST_PAD_CAST(pad)->setcapsfunc)
#define GST_PAD_ACCEPTCAPSFUNC(pad) (GST_PAD_CAST(pad)->acceptcapsfunc)
while ((queued_frame = g_queue_pop_head (&parse->priv->queued_frames))) {
queued_frame->buffer = gst_buffer_make_writable (queued_frame->buffer);
- gst_buffer_set_context (queued_frame->buffer,
- GST_PAD_CONTEXT (GST_BASE_PARSE_SRC_PAD (parse)));
+ gst_buffer_set_caps (queued_frame->buffer,
+ GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)));
gst_base_parse_push_frame (parse, queued_frame);
gst_base_parse_frame_free (queued_frame);
}
/* decorate */
buffer = gst_buffer_make_writable (buffer);
- gst_buffer_set_context (buffer, GST_PAD_CONTEXT (parse->srcpad));
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
parse->priv->seen_keyframe |= parse->priv->is_video &&
!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
GST_BUFFER_TIMESTAMP (*buf) = 0;
}
- /* set pad context on the buffer if the buffer had no caps */
- if (GST_BUFFER_CONTEXT (*buf) == NULL) {
+ /* set pad caps on the buffer if the buffer had no caps */
+ if (GST_BUFFER_CAPS (*buf) == NULL) {
*buf = gst_buffer_make_writable (*buf);
- gst_buffer_set_context (*buf, GST_PAD_CONTEXT (src->srcpad));
+ gst_buffer_set_caps (*buf, GST_PAD_CAPS (src->srcpad));
}
/* now sync before pushing the buffer */
return ret;
}
-#if 0
/* check if caps @in on @pad can be transformed to @out on the other pad.
* We don't have a vmethod to test this yet so we have to do a somewhat less
* efficient check for this.
return FALSE;
}
}
-#endif
/* given a fixed @caps on @pad, create the best possible caps for the
* other pad.
return types;
}
-#if 0
static void
compute_upstream_suggestion (GstBaseTransform * trans, gsize expsize,
GstCaps * caps)
gst_caps_unref (othercaps);
}
}
-#endif
/* Allocate a buffer using gst_pad_alloc_buffer
*
GstBaseTransformClass *bclass;
GstBaseTransformPrivate *priv;
GstFlowReturn ret = GST_FLOW_OK;
- gsize insize, outsize;
- gboolean discard, copymeta;
- GstCaps *oldcaps, *outcaps;
+ gsize insize, outsize, newsize, expsize;
+ gboolean discard, setcaps, copymeta;
+ GstCaps *incaps, *oldcaps, *newcaps, *outcaps;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
oldcaps);
*out_buf = gst_buffer_new_and_alloc (outsize);
+ gst_buffer_set_caps (*out_buf, oldcaps);
#if 0
ret = gst_pad_alloc_buffer (trans->srcpad,
GST_BUFFER_OFFSET (in_buf), outsize, oldcaps, out_buf);
if (*out_buf == NULL)
goto no_buffer;
+ /* check if we got different caps on this new output buffer */
+ newcaps = GST_BUFFER_CAPS (*out_buf);
+ newsize = gst_buffer_get_size (*out_buf);
+
+ if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) {
+ GstCaps *othercaps;
+ gboolean can_convert;
+
+ GST_DEBUG_OBJECT (trans, "received new caps %" GST_PTR_FORMAT, newcaps);
+
+ incaps = GST_PAD_CAPS (trans->sinkpad);
+
+ /* check if we can convert the current incaps to the new target caps */
+ can_convert =
+ gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
+ newcaps);
+
+ if (!can_convert) {
+ GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
+
+ gst_base_transform_transform_size (trans,
+ GST_PAD_SINK, incaps, insize, newcaps, &expsize);
+
+ compute_upstream_suggestion (trans, expsize, newcaps);
+
+ /* we got a suggested caps but we can't transform to it. See if there is
+ * another downstream format that we can transform to */
+ othercaps =
+ gst_base_transform_find_transform (trans, trans->sinkpad, incaps);
+
+ if (othercaps && !gst_caps_is_empty (othercaps)) {
+ GST_DEBUG_OBJECT (trans, "we found target caps %" GST_PTR_FORMAT,
+ othercaps);
+ *out_buf = gst_buffer_make_writable (*out_buf);
+ gst_buffer_set_caps (*out_buf, othercaps);
+ gst_caps_unref (othercaps);
+ newcaps = GST_BUFFER_CAPS (*out_buf);
+ can_convert = TRUE;
+ } else if (othercaps)
+ gst_caps_unref (othercaps);
+ }
+
+ /* it's possible that the buffer we got is of the wrong size, get the
+ * expected size here, we will check the size if we are going to use the
+ * buffer later on. */
+ gst_base_transform_transform_size (trans,
+ GST_PAD_SINK, incaps, insize, newcaps, &expsize);
+
+ if (can_convert) {
+ GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
+
+ /* subclass might want to add fields to the caps */
+ if (bclass->fixate_caps != NULL) {
+ newcaps = gst_caps_copy (newcaps);
+
+ GST_DEBUG_OBJECT (trans, "doing fixate %" GST_PTR_FORMAT
+ " using caps %" GST_PTR_FORMAT
+ " on pad %s:%s using fixate_caps vmethod", newcaps, incaps,
+ GST_DEBUG_PAD_NAME (trans->srcpad));
+ bclass->fixate_caps (trans, GST_PAD_SINK, incaps, newcaps);
+
+ *out_buf = gst_buffer_make_writable (*out_buf);
+ gst_buffer_set_caps (*out_buf, newcaps);
+ gst_caps_unref (newcaps);
+ newcaps = GST_BUFFER_CAPS (*out_buf);
+ }
+
+ /* caps not empty, try to renegotiate to the new format */
+ if (!gst_base_transform_configure_caps (trans, incaps, newcaps)) {
+ /* not sure we need to fail hard here, we can simply continue our
+ * conversion with what we negotiated before */
+ goto failed_configure;
+ }
+ /* new format configure, and use the new output buffer */
+ gst_pad_set_caps (trans->srcpad, newcaps);
+ discard = FALSE;
+ /* clear previous cached sink-pad caps, so buffer_alloc knows that
+ * it needs to revisit the decision about whether to proxy or not: */
+ gst_caps_replace (&priv->sink_alloc, NULL);
+ /* if we got a buffer of the wrong size, discard it now and make sure we
+ * allocate a propertly sized buffer later. */
+ if (newsize != expsize) {
+ if (in_buf != *out_buf)
+ gst_buffer_unref (*out_buf);
+ *out_buf = NULL;
+ }
+ outsize = expsize;
+ } else {
+ compute_upstream_suggestion (trans, expsize, newcaps);
+
+ if (in_buf != *out_buf)
+ gst_buffer_unref (*out_buf);
+ *out_buf = NULL;
+ }
+ } else if (outsize != newsize) {
+ GST_WARNING_OBJECT (trans, "Caps did not change but allocated size does "
+ "not match expected size (%d != %d)", newsize, outsize);
+ if (in_buf != *out_buf)
+ gst_buffer_unref (*out_buf);
+ *out_buf = NULL;
+ }
+
/* these are the final output caps */
outcaps = GST_PAD_CAPS (trans->srcpad);
}
}
+ /* check if we need to make things writable. We need this when we need to
+ * update the caps or the metadata on the output buffer. */
+ newcaps = GST_BUFFER_CAPS (*out_buf);
+ /* we check the pointers as a quick check and then go to the more involved
+ * check. This is needed when we receive different pointers on the sinkpad
+ * that mean the same caps. What we then want to do is prefer those caps over
+ * the ones on the srcpad and set the srcpad caps to the buffer caps */
+ setcaps = !newcaps || ((newcaps != outcaps)
+ && (!gst_caps_is_equal (newcaps, outcaps)));
/* we need to modify the metadata when the element is not gap aware,
* passthrough is not used and the gap flag is set */
copymeta |= !trans->priv->gap_aware && !trans->passthrough
&& (GST_MINI_OBJECT_FLAGS (*out_buf) & GST_BUFFER_FLAG_GAP);
- if (copymeta) {
- GST_DEBUG_OBJECT (trans, "copymeta %d", copymeta);
+ if (setcaps || copymeta) {
+ GST_DEBUG_OBJECT (trans, "setcaps %d, copymeta %d", setcaps, copymeta);
if (!gst_buffer_is_writable (*out_buf)) {
GST_DEBUG_OBJECT (trans, "buffer %p not writable", *out_buf);
if (in_buf == *out_buf)
*out_buf = gst_buffer_make_writable (*out_buf);
}
/* when we get here, the metadata should be writable */
+ if (setcaps)
+ gst_buffer_set_caps (*out_buf, outcaps);
if (copymeta)
gst_buffer_copy_into (*out_buf, in_buf,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
GST_ERROR_OBJECT (trans, "unknown output size");
return GST_FLOW_ERROR;
}
+failed_configure:
+ {
+ GST_WARNING_OBJECT (trans, "failed to configure caps");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
/* Given @caps calcultate the size of one unit.
{
GstBaseTransformClass *bclass;
GstFlowReturn ret = GST_FLOW_OK;
- gboolean want_in_place;
+ gboolean want_in_place, reconfigure;
GstClockTime running_time;
GstClockTime timestamp;
+ GstCaps *incaps;
gsize insize;
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
-#if 0
if (G_LIKELY ((incaps = GST_BUFFER_CAPS (inbuf)))) {
GST_OBJECT_LOCK (trans);
reconfigure = trans->priv->reconfigure;
goto not_negotiated;
}
}
-#endif
insize = gst_buffer_get_size (inbuf);
if (ret != GST_FLOW_OK)
goto error;
- caps = gst_buffer_caps (buffer);
+ caps = GST_BUFFER_CAPS (buffer);
if (caps && !gst_caps_is_empty (caps) && !gst_caps_is_any (caps)) {
GST_DEBUG ("buffer has caps %" GST_PTR_FORMAT ", suggest max probability",
gst_check_element_push_buffer_list (const gchar * element_name,
GList * buffer_in, GList * buffer_out, GstFlowReturn last_flow_return)
{
- //GstCaps *sink_caps;
- //GstCaps *src_caps = NULL;
+ GstCaps *sink_caps;
+ GstCaps *src_caps = NULL;
GstElement *element;
GstPad *pad_peer;
GstPad *sink_pad = NULL;
buffer = GST_BUFFER (buffer_in->data);
fail_unless (GST_IS_BUFFER (buffer), "There should be a buffer in buffer_in");
- //src_caps = gst_buffer_caps (buffer);
+ src_caps = GST_BUFFER_CAPS (buffer);
src_pad = gst_pad_new (NULL, GST_PAD_SRC);
- //gst_pad_set_caps (src_pad, src_caps);
+ gst_pad_set_caps (src_pad, src_caps);
pad_peer = gst_element_get_static_pad (element, "sink");
fail_if (pad_peer == NULL);
fail_unless (gst_pad_link (src_pad, pad_peer) == GST_PAD_LINK_OK,
GST_DEBUG ("src pad activated");
/* don't create the sink_pad if there is no buffer_out list */
if (buffer_out != NULL) {
- //gchar *temp;
+ gchar *temp;
GST_DEBUG ("buffer out detected, creating the sink pad");
/* get the sink caps */
- //sink_caps = gst_buffer_caps (GST_BUFFER (buffer_out->data));
- //fail_unless (GST_IS_CAPS (sink_caps), "buffer out don't have caps");
- //temp = gst_caps_to_string (sink_caps);
+ sink_caps = GST_BUFFER_CAPS (GST_BUFFER (buffer_out->data));
+ fail_unless (GST_IS_CAPS (sink_caps), "buffer out don't have caps");
+ temp = gst_caps_to_string (sink_caps);
- //GST_DEBUG ("sink caps requested by buffer out: '%s'", temp);
- //g_free (temp);
- //fail_unless (gst_caps_is_fixed (sink_caps), "we need fixed caps");
+ GST_DEBUG ("sink caps requested by buffer out: '%s'", temp);
+ g_free (temp);
+ fail_unless (gst_caps_is_fixed (sink_caps), "we need fixed caps");
/* get the sink pad */
sink_pad = gst_pad_new (NULL, GST_PAD_SINK);
fail_unless (GST_IS_PAD (sink_pad));
- //gst_pad_set_caps (sink_pad, sink_caps);
+ gst_pad_set_caps (sink_pad, sink_caps);
/* get the peer pad */
pad_peer = gst_element_get_static_pad (element, "src");
fail_unless (gst_pad_link (pad_peer, sink_pad) == GST_PAD_LINK_OK,
newdata = gst_buffer_map (new, &newsize, NULL, GST_MAP_READ);
origdata = gst_buffer_map (orig, &origsize, NULL, GST_MAP_READ);
- GST_LOG ("orig buffer: size %u", origsize);
- GST_LOG ("new buffer: size %u", newsize);
+ GST_LOG ("orig buffer: size %u, caps %" GST_PTR_FORMAT,
+ origsize, GST_BUFFER_CAPS (orig));
+ GST_LOG ("new buffer: size %u, caps %" GST_PTR_FORMAT,
+ newsize, GST_BUFFER_CAPS (new));
GST_MEMDUMP ("orig buffer", origdata, origsize);
GST_MEMDUMP ("new buffer", newdata, newsize);
fail_unless (origsize == newsize, "size of the buffers are not the same");
fail_unless (memcmp (origdata, newdata, newsize) == 0,
"data is not the same");
- //gst_check_caps_equal (GST_BUFFER_CAPS (orig), GST_BUFFER_CAPS (new));
+ gst_check_caps_equal (GST_BUFFER_CAPS (orig), GST_BUFFER_CAPS (new));
gst_buffer_unmap (orig, origdata, origsize);
gst_buffer_unmap (new, newdata, newsize);
{
GstFlowReturn ret = GST_FLOW_OK;
- *buf = input;
- gst_buffer_ref (input);
-
-#if 0
if (GST_BUFFER_CAPS (input) != NULL) {
/* Output buffer already has caps */
GST_LOG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)");
g_free (caps_str);
}
}
-#endif
return ret;
}
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
GstEvent *event = NULL;
GstClockTime newts;
- //GstCaps *padcaps;
+ GstCaps *padcaps;
GST_DEBUG_OBJECT (funnel, "received buffer %p", buffer);
if (!gst_pad_push_event (funnel->srcpad, event))
GST_WARNING_OBJECT (funnel, "Could not push out newsegment event");
}
-#if 0
+
GST_OBJECT_LOCK (pad);
- padcontext = GST_PAD_CONTEXT (funnel->srcpad);
+ padcaps = GST_PAD_CAPS (funnel->srcpad);
GST_OBJECT_UNLOCK (pad);
- if (GST_BUFFER_CONTEXT (buffer) && GST_BUFFER_CONTEXT (buffer) != padcontext) {
- if (!gst_pad_set_context (funnel->srcpad, GST_BUFFER_CONTEXT (buffer))) {
+ if (GST_BUFFER_CAPS (buffer) && GST_BUFFER_CAPS (buffer) != padcaps) {
+ if (!gst_pad_set_caps (funnel->srcpad, GST_BUFFER_CAPS (buffer))) {
res = GST_FLOW_NOT_NEGOTIATED;
goto out;
}
}
-#endif
res = gst_pad_push (funnel->srcpad, buffer);
GST_LOG_OBJECT (funnel, "handled buffer %s", gst_flow_get_name (res));
+out:
gst_object_unref (funnel);
return res;
GstClockTime start_time;
GstSegment *seg;
GstEvent *close_event = NULL, *start_event = NULL;
+ GstCaps *caps;
sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
selpad = GST_SELECTOR_PAD_CAST (pad);
/* forward */
GST_LOG_OBJECT (pad, "Forwarding buffer %p", buf);
-#if 0
if ((caps = GST_BUFFER_CAPS (buf))) {
if (GST_PAD_CAPS (sel->srcpad) != caps)
gst_pad_set_caps (sel->srcpad, caps);
}
-#endif
res = gst_pad_push (sel->srcpad, buf);
selpad->pushed = TRUE;
if (GST_IS_BUFFER (object)) {
GstBuffer *buffer;
GstClockTime timestamp, duration;
+ GstCaps *caps;
buffer = GST_BUFFER_CAST (object);
timestamp = GST_BUFFER_TIMESTAMP (buffer);
duration = GST_BUFFER_DURATION (buffer);
+ caps = GST_BUFFER_CAPS (buffer);
apply_buffer (mq, sq, timestamp, duration, &sq->src_segment);
"SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT,
sq->id, buffer, GST_TIME_ARGS (timestamp));
+ /* Set caps on pad before pushing, this avoids core calling the acceptcaps
+ * function on the srcpad, which will call acceptcaps upstream, which might
+ * not accept these caps (anymore). */
+ if (caps && caps != GST_PAD_CAPS (sq->srcpad))
+ gst_pad_set_caps (sq->srcpad, caps);
+
result = gst_pad_push (sq->srcpad, buffer);
} else if (GST_IS_EVENT (object)) {
GstEvent *event;
next:
if (is_buffer) {
GstBuffer *buffer;
+ GstCaps *caps;
buffer = GST_BUFFER_CAST (data);
queue->head_needs_discont = FALSE;
}
+ caps = GST_BUFFER_CAPS (buffer);
+
GST_QUEUE_MUTEX_UNLOCK (queue);
+ /* set the right caps on the pad now. We do this before pushing the buffer
+ * because the pad_push call will check (using acceptcaps) if the buffer can
+ * be set on the pad, which might fail because this will be propagated
+ * upstream. Also note that if the buffer has NULL caps, it means that the
+ * caps did not change, so we don't have to change caps on the pad. */
+ if (caps && caps != GST_PAD_CAPS (queue->srcpad))
+ gst_pad_set_caps (queue->srcpad, caps);
if (queue->push_newsegment) {
gst_queue_push_newsegment (queue);
if (is_buffer) {
GstBuffer *buffer;
+ GstCaps *caps;
buffer = GST_BUFFER_CAST (data);
+ caps = GST_BUFFER_CAPS (buffer);
+
+ /* set caps before pushing the buffer so that core does not try to do
+ * something fancy to check if this is possible. */
+ if (caps && caps != GST_PAD_CAPS (queue->srcpad))
+ gst_pad_set_caps (queue->srcpad, caps);
result = gst_pad_push (queue->srcpad, buffer);
goto no_data;
buffer = gst_adapter_take_buffer (typefind->adapter, avail);
+ buffer = gst_buffer_make_writable (buffer);
+
+ gst_buffer_set_caps (buffer, typefind->caps);
GST_OBJECT_UNLOCK (typefind);
if (!push_cached_buffers) {
goto no_data;
buffer = gst_adapter_take_buffer (typefind->adapter, avail);
+ buffer = gst_buffer_make_writable (buffer);
+ gst_buffer_set_caps (buffer, typefind->caps);
GST_OBJECT_UNLOCK (typefind);
GST_DEBUG_OBJECT (typefind, "Pushing buffer: %d", avail);
/* 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 */
+ buffer = gst_buffer_make_writable (buffer);
+ gst_buffer_set_caps (buffer, typefind->caps);
return gst_pad_push (typefind->src, buffer);
case MODE_TYPEFIND:
{
ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
+ if (ret == GST_FLOW_OK && buffer && *buffer) {
+ /* don't take object lock as typefind->caps should not change anymore */
+ /* we assume that pulled buffers are meta-data writable */
+ gst_buffer_set_caps (*buffer, typefind->caps);
+ }
+
return ret;
}
/* setup dummy buffer */
caps = gst_caps_from_string ("application/x-unknown");
buf = gst_buffer_new_and_alloc (1);
+ gst_buffer_set_caps (buf, caps);
gst_caps_unref (caps);
while (l != NULL) {
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
buffer = gst_buffer_new ();
- //gst_buffer_set_caps (buffer, caps);
+ gst_buffer_set_caps (buffer, caps);
/* First check if everything works in normal state */
fail_unless (gst_pad_push (mysrc, gst_buffer_ref (buffer)) == GST_FLOW_OK);
#include <gst/check/gstcheck.h>
+GST_START_TEST (test_caps)
+{
+ GstBuffer *buffer;
+ GstCaps *caps, *caps2;
+
+ buffer = gst_buffer_new_and_alloc (4);
+ caps = gst_caps_from_string ("audio/x-raw-int");
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+
+ fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
+
+ gst_buffer_set_caps (buffer, caps);
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
+
+ fail_unless (GST_BUFFER_CAPS (buffer) == caps);
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
+
+ fail_unless (gst_buffer_get_caps (buffer) == caps);
+ gst_caps_unref (caps);
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 2);
+
+ caps2 = gst_caps_from_string ("audio/x-raw-float");
+ ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
+
+ gst_buffer_set_caps (buffer, caps2);
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+ ASSERT_CAPS_REFCOUNT (caps2, "caps2", 2);
+
+ gst_buffer_set_caps (buffer, NULL);
+ ASSERT_CAPS_REFCOUNT (caps, "caps", 1);
+ ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
+
+ /* clean up, with caps2 still set as caps */
+ gst_buffer_set_caps (buffer, caps2);
+ ASSERT_CAPS_REFCOUNT (caps2, "caps2", 2);
+ gst_buffer_unref (buffer);
+ ASSERT_CAPS_REFCOUNT (caps2, "caps2", 1);
+ gst_caps_unref (caps);
+ gst_caps_unref (caps2);
+}
+
+GST_END_TEST;
+
+
GST_START_TEST (test_subbuffer)
{
GstBuffer *buffer, *sub;
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_caps);
tcase_add_test (tc_chain, test_subbuffer);
tcase_add_test (tc_chain, test_subbuffer_make_writable);
tcase_add_test (tc_chain, test_make_writable);
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (1000);
+ gst_buffer_set_caps (buffer, c1); /* doesn't give away our c1 ref */
gst_caps_unref (c1);
gst_buffer_unref (buffer); /* Should now drop both references */
/* Should fail if src pad caps are incompatible with sink pad caps */
gst_pad_set_caps (src, caps);
+ gst_buffer_set_caps (buffer, caps);
gst_buffer_ref (buffer);
fail_unless (gst_pad_push (src, buffer) == GST_FLOW_NOT_NEGOTIATED);
ASSERT_MINI_OBJECT_REFCOUNT (buffer, "buffer", 1);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
/* caps should not have been set */
- //fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
+ fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
gst_buffer_unref (buffer);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 10);
/* caps should not have been set */
- //fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
+ fail_unless (GST_BUFFER_CAPS (buffer) == NULL);
gst_buffer_unref (buffer);
GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, caps);
+ gst_buffer_set_caps (buffer, caps);
buffer_alloc_pt1_called = FALSE;
set_caps_pt2_called = FALSE;
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
gst_buffer_unref (buffer);
GST_DEBUG_OBJECT (trans, "buffer with caps, size 10");
buffer = gst_buffer_new_and_alloc (10);
- //gst_buffer_set_caps (buffer, caps);
+ gst_buffer_set_caps (buffer, caps);
buffer_alloc_pt1_called = FALSE;
set_caps_pt2_called = FALSE;
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 10);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
gst_buffer_unref (buffer);
GST_DEBUG_OBJECT (trans, "buffer with caps, size 20");
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, caps);
+ gst_buffer_set_caps (buffer, caps);
transform_ip_1_called = FALSE;
transform_ip_1_writable = FALSE;
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
gst_buffer_unref (buffer);
#if 0
GST_DEBUG_OBJECT (trans, "buffer with caps extra ref, size 20");
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, caps);
+ gst_buffer_set_caps (buffer, caps);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps));
/* output buffer has refcount 1 */
//fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
/* try to push a buffer with caps */
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 40);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 40);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
/* output buffer has refcount 1 */
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
/* try to push a buffer with caps */
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
/* output buffer has refcount 1 */
//fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
/* try to push a buffer with caps */
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
gst_buffer_unref (buffer);
buffer = gst_buffer_new_and_alloc (20);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
/* take additional ref to make it non-writable */
gst_buffer_ref (buffer);
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
fail_unless (gst_buffer_get_size (buffer) == 20);
- //fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
+ fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps));
/* output buffer has refcount 1 */
fail_unless (GST_MINI_OBJECT_REFCOUNT_VALUE (buffer) == 1);
GST_DEBUG_OBJECT (trans,
"buffer with in passthrough with caps %" GST_PTR_FORMAT, incaps);
buffer = gst_buffer_new_and_alloc (10);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
/* don't suggest anything else */
buffer_alloc_ct2_case = 1;
buffer = gst_test_trans_pop (trans);
fail_unless (buffer != NULL);
/* FIXME changing src caps should produce converted buffer */
- //GST_DEBUG_OBJECT (trans, "received caps %" GST_PTR_FORMAT,
- // GST_BUFFER_CAPS (buffer));
+ GST_DEBUG_OBJECT (trans, "received caps %" GST_PTR_FORMAT,
+ GST_BUFFER_CAPS (buffer));
//fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), outcaps));
//fail_unless (gst_buffer_get_size (buffer) == 20);
GST_DEBUG_OBJECT (trans, "buffer with caps %" GST_PTR_FORMAT, incaps);
buffer = gst_buffer_new_and_alloc (10);
- //gst_buffer_set_caps (buffer, incaps);
+ gst_buffer_set_caps (buffer, incaps);
/* don't suggest anything else */
buffer_alloc_ct2_suggest = FALSE;
img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
if (img) {
gchar *caps_str;
- GstCaps *caps;
- caps = gst_buffer_caps (img);
- caps_str = caps ? gst_caps_to_string (caps) : g_strdup ("unknown");
+ caps_str = GST_BUFFER_CAPS (img) ?
+ gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
str = g_strdup_printf ("buffer of %" G_GSIZE_FORMAT " bytes, type: %s",
gst_buffer_get_size (img), caps_str);
g_free (caps_str);
- if (caps)
- gst_caps_unref (caps);
} else {
str = g_strdup ("NULL buffer");
}