Commit c4751ec8 authored by Wim Taymans's avatar Wim Taymans

Revert "context: use context on buffers instead of caps"

This reverts commit 9ef1346b.

Way to much for one commit and I'm not sure we want to get rid of the pad caps
just like that. It's nice to have the buffer and its type in onw nice bundle
without having to drag the complete context with it.
parent 419f48d0
......@@ -670,7 +670,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
_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 ());
......
......@@ -306,6 +306,10 @@ gst_buffer_copy_into (GstBuffer * dest, GstBuffer * src,
}
}
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;
......@@ -398,7 +402,7 @@ _gst_buffer_free (GstBuffer * buffer)
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) {
......@@ -440,7 +444,7 @@ gst_buffer_init (GstBufferImpl * buffer, gsize size)
(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;
......@@ -1053,65 +1057,71 @@ gst_buffer_memcmp (GstBuffer * buffer, gsize offset, gconstpointer mem,
}
/**
* 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
......@@ -1499,22 +1509,3 @@ gst_buffer_iterate_meta (GstBuffer * buffer, gpointer * state)
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;
}
......@@ -24,18 +24,18 @@
#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:
*
......@@ -112,12 +112,12 @@ extern GType _gst_buffer_type;
*/
#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.
......@@ -260,7 +260,7 @@ struct _GstBuffer {
/*< public >*/ /* with COW */
GstBufferPool *pool;
/* the media type of this buffer */
GstContext *context;
GstCaps *caps;
/* timestamp */
GstClockTime timestamp;
......@@ -386,6 +386,7 @@ gst_buffer_copy (const GstBuffer * buf)
* @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
......@@ -398,6 +399,7 @@ typedef enum {
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;
......@@ -408,7 +410,7 @@ typedef enum {
* 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:
......@@ -467,8 +469,8 @@ G_STMT_START { \
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,
......@@ -516,9 +518,6 @@ GstMeta * gst_buffer_iterate_meta (GstBuffer *buffer, gpointer *st
*/
#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__ */
......@@ -60,11 +60,11 @@ gst_context_get_type (void)
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);
......@@ -181,22 +181,3 @@ gst_context_clear (GstContext * 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);
}
......@@ -23,8 +23,6 @@
#ifndef __GST_CONTEXT_H__
#define __GST_CONTEXT_H__
typedef struct _GstContext GstContext;
#include <gst/gstminiobject.h>
#include <gst/gstevent.h>
......@@ -32,6 +30,7 @@ G_BEGIN_DECLS
#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))
......@@ -135,15 +134,11 @@ gst_context_copy (const GstContext * 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__ */
......@@ -25,13 +25,10 @@
#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>
......@@ -170,6 +167,8 @@ typedef enum {
*/
#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))
......
......@@ -623,8 +623,6 @@ gst_ghost_pad_do_unlink (GstPad * pad)
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;
......@@ -648,14 +646,11 @@ on_int_notify (GstPad * internal, GParamSpec * unused, GstGhostPad * pad)
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;
......@@ -707,7 +702,6 @@ on_src_target_notify (GstPad * target, GParamSpec * unused, gpointer user_data)
done:
if (caps)
gst_caps_unref (caps);
#endif
}
static gboolean
......
......@@ -100,6 +100,7 @@ typedef struct _GstPadPushCache GstPadPushCache;
struct _GstPadPushCache
{
GstPad *peer; /* reffed peer pad */
GstCaps *caps; /* caps for this link */
};
static GstPadPushCache _pad_cache_invalid = { NULL, };
......@@ -370,6 +371,8 @@ gst_pad_init (GstPad * pad)
g_static_rec_mutex_init (pad->stream_rec_lock);
pad->block_cond = g_cond_new ();
pad->context = gst_context_new ();
}
static void
......@@ -403,10 +406,7 @@ gst_pad_dispose (GObject * object)
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);
}
......@@ -434,6 +434,8 @@ gst_pad_finalize (GObject * object)
pad->block_cond = NULL;
}
gst_context_unref (pad->context);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
......@@ -618,8 +620,7 @@ post_activate (GstPad * pad, GstActivateMode new_mode)
/* 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;
}
......@@ -2604,42 +2605,52 @@ could_not_set:
}
}
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;
}
}
......@@ -3397,22 +3408,22 @@ gst_pad_data_unref (gboolean is_buffer, void *data)
}
}
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
......@@ -3420,9 +3431,10 @@ gst_pad_data_get_context (gboolean is_buffer, void *data)
*/
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;
......@@ -3432,8 +3444,44 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
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
......@@ -3451,9 +3499,9 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
}
/* 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;
}
......@@ -3474,6 +3522,7 @@ gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data,
if (cache) {
cache->peer = gst_object_ref (pad);
cache->caps = caps ? gst_caps_ref (caps) : NULL;
}
ret = chainfunc (pad, GST_BUFFER_CAST (data));
......@@ -3517,10 +3566,9 @@ chain_groups:
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;
}
......@@ -3601,8 +3649,7 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
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);
}
/**
......@@ -3641,17 +3688,17 @@ gst_pad_chain_list (GstPad * pad, GstBufferList * list)
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);
......@@ -3683,25 +3730,25 @@ gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data,
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);