remove moved dirs

Original commit message from CVS:
remove moved dirs
This commit is contained in:
Thomas Vander Stichele 2005-11-29 18:03:52 +00:00
parent 233e55299e
commit 8c96632081
29 changed files with 0 additions and 8476 deletions

View file

@ -1,12 +0,0 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs
*.bb
*.bbg
*.da
*.def
*.gcno

View file

@ -1,46 +0,0 @@
# FIXME:
# need to get gstbufferstore.[ch] into its own lib, preferably
# libs/gst/bufferstore
# This requires building libs/gst before this dir, which we currently don't
# do.
plugin_LTLIBRARIES = libgstelements.la
if HAVE_SYS_SOCKET_H
GSTFDSRC = gstfdsrc.c
else
GSTFDSRC =
endif
libgstelements_la_DEPENDENCIES = ../libgstreamer-@GST_MAJORMINOR@.la
libgstelements_la_SOURCES = \
gstbufferstore.c \
gstcapsfilter.c \
gstfakesrc.c \
gstfakesink.c \
$(GSTFDSRC) \
gstfilesink.c \
gstfilesrc.c \
gstidentity.c \
gstelements.c \
gsttee.c \
gsttypefindelement.c
libgstelements_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstelements_la_LIBADD = \
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS)
libgstelements_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = \
gstbufferstore.h \
gstfakesink.h \
gstfakesrc.h \
gstfdsrc.h \
gstfilesink.h \
gstfilesrc.h \
gstidentity.h \
gsttee.h \
gsttypefindelement.h
EXTRA_DIST = gstfdsrc.c

View file

@ -1,468 +0,0 @@
/* GStreamer
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* gstbufferstore.c: keep an easily accessible list of all buffers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gstbufferstore.h"
#include <gst/gstutils.h>
#include <string.h>
GST_DEBUG_CATEGORY_STATIC (gst_buffer_store_debug);
#define GST_CAT_DEFAULT gst_buffer_store_debug
enum
{
CLEARED,
BUFFER_ADDED,
LAST_SIGNAL
};
enum
{
ARG_0
};
static void gst_buffer_store_dispose (GObject * object);
static gboolean gst_buffer_store_add_buffer_func (GstBufferStore * store,
GstBuffer * buffer);
static void gst_buffer_store_cleared_func (GstBufferStore * store);
static guint gst_buffer_store_signals[LAST_SIGNAL] = { 0 };
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_buffer_store_debug, "GstBufferStore", 0, "buffer store helper");
GST_BOILERPLATE_FULL (GstBufferStore, gst_buffer_store, GObject, G_TYPE_OBJECT,
_do_init);
G_GNUC_UNUSED static void
debug_buffers (GstBufferStore * store)
{
GList *walk = store->buffers;
g_printerr ("BUFFERS in store:\n");
while (walk) {
g_print ("%15" G_GUINT64_FORMAT " - %7u\n", GST_BUFFER_OFFSET (walk->data),
GST_BUFFER_SIZE (walk->data));
walk = g_list_next (walk);
}
g_printerr ("\n");
}
static gboolean
continue_accu (GSignalInvocationHint * ihint, GValue * return_accu,
const GValue * handler_return, gpointer data)
{
gboolean do_continue = g_value_get_boolean (handler_return);
g_value_set_boolean (return_accu, do_continue);
return do_continue;
}
static void
gst_buffer_store_base_init (gpointer g_class)
{
}
static void
gst_buffer_store_class_init (GstBufferStoreClass * store_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (store_class);
gobject_class->dispose = gst_buffer_store_dispose;
gst_buffer_store_signals[CLEARED] = g_signal_new ("cleared",
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstBufferStoreClass, cleared), NULL, NULL,
gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
gst_buffer_store_signals[BUFFER_ADDED] = g_signal_new ("buffer-added",
G_TYPE_FROM_CLASS (store_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstBufferStoreClass, buffer_added), continue_accu, NULL,
gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_BUFFER);
store_class->cleared = gst_buffer_store_cleared_func;
store_class->buffer_added = gst_buffer_store_add_buffer_func;
}
static void
gst_buffer_store_init (GstBufferStore * store, GstBufferStoreClass * g_class)
{
store->buffers = NULL;
}
static void
gst_buffer_store_dispose (GObject * object)
{
GstBufferStore *store = GST_BUFFER_STORE (object);
gst_buffer_store_clear (store);
parent_class->dispose (object);
}
static gboolean
gst_buffer_store_add_buffer_func (GstBufferStore * store, GstBuffer * buffer)
{
g_assert (buffer != NULL);
if (!GST_BUFFER_OFFSET_IS_VALID (buffer) &&
store->buffers && GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
/* we assumed valid offsets, but suddenly they are not anymore */
GST_DEBUG_OBJECT (store,
"attempting to add buffer %p with invalid offset to store with valid offset, abort",
buffer);
return FALSE;
} else if (!store->buffers
|| !GST_BUFFER_OFFSET_IS_VALID (store->buffers->data)) {
/* the starting buffer had an invalid offset, in that case we assume continuous buffers */
GST_LOG_OBJECT (store, "adding buffer %p with invalid offset and size %u",
buffer, GST_BUFFER_SIZE (buffer));
gst_mini_object_ref (GST_MINI_OBJECT (buffer));
store->buffers = g_list_append (store->buffers, buffer);
return TRUE;
} else {
/* both list and buffer have valid offsets, we can really go wild */
GList *walk, *current_list = NULL;
GstBuffer *current;
g_assert (GST_BUFFER_OFFSET_IS_VALID (buffer));
GST_LOG_OBJECT (store,
"attempting to add buffer %p with offset %" G_GUINT64_FORMAT
" and size %u", buffer, GST_BUFFER_OFFSET (buffer),
GST_BUFFER_SIZE (buffer));
/* we keep a sorted list of non-overlapping buffers */
walk = store->buffers;
while (walk) {
current = GST_BUFFER (walk->data);
current_list = walk;
walk = g_list_next (walk);
if (GST_BUFFER_OFFSET (current) < GST_BUFFER_OFFSET (buffer)) {
continue;
} else if (GST_BUFFER_OFFSET (current) == GST_BUFFER_OFFSET (buffer)) {
guint needed_size;
if (walk) {
needed_size = MIN (GST_BUFFER_SIZE (buffer),
GST_BUFFER_OFFSET (walk->data) - GST_BUFFER_OFFSET (current));
} else {
needed_size = GST_BUFFER_SIZE (buffer);
}
if (needed_size <= GST_BUFFER_SIZE (current)) {
buffer = NULL;
break;
} else {
if (needed_size < GST_BUFFER_SIZE (buffer)) {
/* need to create subbuffer to not have overlapping data */
GstBuffer *sub = gst_buffer_create_sub (buffer, 0, needed_size);
g_assert (sub);
buffer = sub;
} else {
gst_mini_object_ref (GST_MINI_OBJECT (buffer));
}
/* replace current buffer with new one */
GST_INFO_OBJECT (store,
"replacing buffer %p with buffer %p with offset %" G_GINT64_FORMAT
" and size %u", current_list->data, buffer,
GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
gst_mini_object_unref (GST_MINI_OBJECT (current_list->data));
current_list->data = buffer;
buffer = NULL;
break;
}
} else if (GST_BUFFER_OFFSET (current) > GST_BUFFER_OFFSET (buffer)) {
GList *previous = g_list_previous (current_list);
guint64 start_offset = previous ?
GST_BUFFER_OFFSET (previous->data) +
GST_BUFFER_SIZE (previous->data) : 0;
if (start_offset == GST_BUFFER_OFFSET (current)) {
buffer = NULL;
break;
} else {
/* we have data to insert */
if (start_offset > GST_BUFFER_OFFSET (buffer) ||
GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) >
GST_BUFFER_OFFSET (current)) {
GstBuffer *sub;
/* need a subbuffer */
start_offset = GST_BUFFER_OFFSET (buffer) > start_offset ? 0 :
start_offset - GST_BUFFER_OFFSET (buffer);
sub = gst_buffer_create_sub (buffer, start_offset,
MIN (GST_BUFFER_SIZE (buffer) - start_offset,
GST_BUFFER_OFFSET (current) - start_offset -
GST_BUFFER_OFFSET (buffer)));
g_assert (sub);
GST_BUFFER_OFFSET (sub) = start_offset + GST_BUFFER_OFFSET (buffer);
buffer = sub;
} else {
gst_mini_object_ref (GST_MINI_OBJECT (buffer));
}
GST_INFO_OBJECT (store,
"adding buffer %p with offset %" G_GINT64_FORMAT " and size %u",
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
store->buffers =
g_list_insert_before (store->buffers, current_list, buffer);
buffer = NULL;
break;
}
}
}
if (buffer) {
gst_mini_object_ref (GST_MINI_OBJECT (buffer));
GST_INFO_OBJECT (store,
"adding buffer %p with offset %" G_GINT64_FORMAT " and size %u",
buffer, GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer));
if (current_list) {
g_list_append (current_list, buffer);
} else {
g_assert (store->buffers == NULL);
store->buffers = g_list_prepend (NULL, buffer);
}
}
return TRUE;
}
}
static void
gst_buffer_store_cleared_func (GstBufferStore * store)
{
g_list_foreach (store->buffers, (GFunc) gst_mini_object_unref, NULL);
g_list_free (store->buffers);
store->buffers = NULL;
}
/**
* gst_buffer_store_new:
*
* Creates a new bufferstore.
*
* Returns: the new bufferstore.
*/
GstBufferStore *
gst_buffer_store_new (void)
{
return GST_BUFFER_STORE (g_object_new (GST_TYPE_BUFFER_STORE, NULL));
}
/**
* gst_buffer_store_clear:
* @store: a bufferstore
*
* Clears the buffer store. All buffers are removed and the buffer store
* behaves like it was just created.
*/
/* FIXME: call this function _reset ? */
void
gst_buffer_store_clear (GstBufferStore * store)
{
g_return_if_fail (GST_IS_BUFFER_STORE (store));
g_signal_emit (store, gst_buffer_store_signals[CLEARED], 0, NULL);
}
/**
* gst_buffer_store_add_buffer:
* @store: a bufferstore
* @buffer: the buffer to add
*
* Adds a buffer to the buffer store.
*
* Returns: TRUE, if the buffer was added, FALSE if an error occured.
*/
gboolean
gst_buffer_store_add_buffer (GstBufferStore * store, GstBuffer * buffer)
{
gboolean ret;
g_return_val_if_fail (GST_IS_BUFFER_STORE (store), FALSE);
g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
if (store->buffers &&
GST_BUFFER_OFFSET_IS_VALID (store->buffers->data) &&
!GST_BUFFER_OFFSET_IS_VALID (buffer))
return FALSE;
g_signal_emit (store, gst_buffer_store_signals[BUFFER_ADDED], 0, buffer,
&ret);
return ret;
}
/**
* gst_buffer_store_get_buffer:
* @store: a bufferstore
* @offset: starting offset of returned buffer
* @size: size of returned buffer
*
* Returns a buffer that corresponds to the given area of data. If part of the
* data is not available inside the store, NULL is returned. You have to unref
* the buffer after use.
*
* Returns: a buffer with the requested data or NULL if the data was not
* available.
*/
GstBuffer *
gst_buffer_store_get_buffer (GstBufferStore * store, guint64 offset, guint size)
{
GstBuffer *current;
GList *walk;
guint8 *data;
guint tmp;
gboolean have_offset;
guint64 cur_offset = 0;
GstBuffer *ret = NULL;
g_return_val_if_fail (GST_IS_BUFFER_STORE (store), NULL);
walk = store->buffers;
if (!walk)
return NULL;
if (GST_BUFFER_OFFSET_IS_VALID (walk->data)) {
have_offset = TRUE;
} else {
have_offset = FALSE;
}
while (walk) {
current = GST_BUFFER (walk->data);
if (have_offset) {
cur_offset = GST_BUFFER_OFFSET (current);
}
walk = g_list_next (walk);
if (cur_offset > offset) {
/* #include <windows.h>
do_nothing_loop (); */
} else if (cur_offset == offset && GST_BUFFER_SIZE (current) == size) {
GST_LOG_OBJECT (store,
"found matching buffer %p for offset %" G_GUINT64_FORMAT
" and size %u", current, offset, size);
ret = current;
gst_mini_object_ref (GST_MINI_OBJECT (ret));
GST_LOG_OBJECT (store, "refcount %d", GST_MINI_OBJECT (ret)->refcount);
break;
} else if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
if (cur_offset + GST_BUFFER_SIZE (current) >= offset + size) {
ret = gst_buffer_create_sub (current, offset - cur_offset, size);
GST_LOG_OBJECT (store,
"created subbuffer %p from buffer %p for offset %llu and size %u",
ret, current, offset, size);
break;
}
/* uh, the requested data spans some buffers */
ret = gst_buffer_new_and_alloc (size);
GST_BUFFER_OFFSET (ret) = offset;
GST_LOG_OBJECT (store, "created buffer %p for offset %" G_GUINT64_FORMAT
" and size %u, will fill with data now", ret, offset, size);
data = GST_BUFFER_DATA (ret);
tmp = GST_BUFFER_SIZE (current) - offset + cur_offset;
memcpy (data, GST_BUFFER_DATA (current) + offset - cur_offset, tmp);
data += tmp;
size -= tmp;
while (size) {
if (walk == NULL ||
(have_offset &&
GST_BUFFER_OFFSET (current) + GST_BUFFER_SIZE (current) !=
GST_BUFFER_OFFSET (walk->data))) {
GST_DEBUG_OBJECT (store,
"not all data for offset %" G_GUINT64_FORMAT
" and remaining size %u available, aborting", offset, size);
gst_mini_object_unref (GST_MINI_OBJECT (ret));
ret = NULL;
goto out;
}
current = GST_BUFFER (walk->data);
walk = g_list_next (walk);
tmp = MIN (GST_BUFFER_SIZE (current), size);
memcpy (data, GST_BUFFER_DATA (current), tmp);
data += tmp;
size -= tmp;
}
goto out;
}
if (!have_offset) {
cur_offset += GST_BUFFER_SIZE (current);
}
}
out:
return ret;
}
/**
* gst_buffer_store_get_size:
* @store: a bufferstore
* @offset: desired offset
*
* Calculates the number of bytes available starting from offset. This allows
* to query a buffer with the returned size.
*
* Returns: the number of continuous bytes in the bufferstore starting at
* offset.
*/
guint
gst_buffer_store_get_size (GstBufferStore * store, guint64 offset)
{
GList *walk;
gboolean have_offset;
gboolean counting = FALSE;
guint64 cur_offset = 0;
GstBuffer *current = NULL;
guint ret = 0;
g_return_val_if_fail (GST_IS_BUFFER_STORE (store), 0);
walk = store->buffers;
if (!walk)
return 0;
if (GST_BUFFER_OFFSET_IS_VALID (walk->data)) {
have_offset = TRUE;
} else {
have_offset = FALSE;
}
while (walk) {
if (have_offset && counting &&
cur_offset + GST_BUFFER_SIZE (current) !=
GST_BUFFER_OFFSET (walk->data)) {
break;
}
current = GST_BUFFER (walk->data);
if (have_offset) {
cur_offset = GST_BUFFER_OFFSET (current);
}
walk = g_list_next (walk);
if (counting) {
ret += GST_BUFFER_SIZE (current);
} else {
if (cur_offset > offset)
return 0;
if (cur_offset + GST_BUFFER_SIZE (current) > offset) {
/* we have at least some bytes */
ret = cur_offset + GST_BUFFER_SIZE (current) - offset;
counting = TRUE;
}
}
if (!have_offset) {
cur_offset += GST_BUFFER_SIZE (current);
}
}
return ret;
}

View file

@ -1,73 +0,0 @@
/* GStreamer
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* gstbufferstore.h: keep an easily accessible list of all buffers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_BUFFER_STORE_H__
#define __GST_BUFFER_STORE_H__
#include <gst/gstbuffer.h>
#include <gst/gstinfo.h>
#include <gst/gstmarshal.h>
G_BEGIN_DECLS
#define GST_TYPE_BUFFER_STORE (gst_buffer_store_get_type ())
#define GST_BUFFER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_BUFFER_STORE, GstBufferStore))
#define GST_IS_BUFFER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_BUFFER_STORE))
#define GST_BUFFER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_BUFFER_STORE, GstBufferStoreClass))
#define GST_IS_BUFFER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_BUFFER_STORE))
#define GST_BUFFER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BUFFER_STORE, GstBufferStoreClass))
typedef struct _GstBufferStore GstBufferStore;
typedef struct _GstBufferStoreClass GstBufferStoreClass;
struct _GstBufferStore {
GObject object;
GList * buffers;
};
struct _GstBufferStoreClass {
GObjectClass parent_class;
/* signals */
void (* cleared) (GstBufferStore * store);
gboolean (* buffer_added) (GstBufferStore * store,
GstBuffer * buffer);
};
GType gst_buffer_store_get_type (void);
GstBufferStore * gst_buffer_store_new (void);
void gst_buffer_store_clear (GstBufferStore * store);
gboolean gst_buffer_store_add_buffer (GstBufferStore * store,
GstBuffer * buffer);
GstBuffer * gst_buffer_store_get_buffer (GstBufferStore * store,
guint64 offset,
guint size);
guint gst_buffer_store_get_size (GstBufferStore * store,
guint64 offset);
G_END_DECLS
#endif /* __GST_BUFFER_STORE_H__ */

View file

@ -1,280 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
* 2005 David Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "../gst-i18n-lib.h"
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
static GstElementDetails gst_capsfilter_details =
GST_ELEMENT_DETAILS ("CapsFilter",
"Generic",
"Pass data without modification, limiting formats",
"David Schleef <ds@schleef.org>");
#define GST_TYPE_CAPSFILTER \
(gst_capsfilter_get_type())
#define GST_CAPSFILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAPSFILTER,GstCapsFilter))
#define GST_CAPSFILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAPSFILTER,GstCapsFilterClass))
#define GST_IS_CAPSFILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAPSFILTER))
#define GST_IS_CAPSFILTER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAPSFILTER))
typedef struct _GstCapsFilter GstCapsFilter;
typedef struct _GstCapsFilterClass GstCapsFilterClass;
struct _GstCapsFilter
{
GstBaseTransform trans;
GstCaps *filter_caps;
};
struct _GstCapsFilterClass
{
GstBaseTransformClass trans_class;
};
GType gst_capsfilter_get_type (void);
enum
{
PROP_0,
PROP_FILTER_CAPS
};
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_capsfilter_debug);
#define GST_CAT_DEFAULT gst_capsfilter_debug
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_capsfilter_debug, "capsfilter", 0, \
"capsfilter element");
GST_BOILERPLATE_FULL (GstCapsFilter, gst_capsfilter, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, _do_init);
static void gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_capsfilter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_capsfilter_dispose (GObject * object);
static GstCaps *gst_capsfilter_transform_caps (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps);
static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
GstBuffer * buf);
static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
static void
gst_capsfilter_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (element_class, &gst_capsfilter_details);
}
static void
gst_capsfilter_class_init (GstCapsFilterClass * klass)
{
GObjectClass *gobject_class;
GstBaseTransformClass *trans_class;
gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_capsfilter_set_property;
gobject_class->get_property = gst_capsfilter_get_property;
gobject_class->dispose = gst_capsfilter_dispose;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTER_CAPS,
g_param_spec_boxed ("caps", _("Filter caps"),
_("Restrict the possible allowed capabilities (NULL means ANY)"),
GST_TYPE_CAPS, G_PARAM_READWRITE));
trans_class = (GstBaseTransformClass *) klass;
trans_class->transform_caps = gst_capsfilter_transform_caps;
trans_class->transform_ip = gst_capsfilter_transform_ip;
trans_class->prepare_output_buffer = gst_capsfilter_prepare_buf;
}
static void
gst_capsfilter_init (GstCapsFilter * filter, GstCapsFilterClass * g_class)
{
filter->filter_caps = gst_caps_new_any ();
}
static void
gst_capsfilter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:{
GstCaps *new_caps;
GstCaps *old_caps;
const GstCaps *new_caps_val = gst_value_get_caps (value);
if (new_caps_val == NULL) {
new_caps = gst_caps_new_any ();
} else {
new_caps = gst_caps_copy (new_caps_val);
}
old_caps = capsfilter->filter_caps;
capsfilter->filter_caps = new_caps;
gst_caps_unref (old_caps);
GST_DEBUG_OBJECT (capsfilter, "set new caps %" GST_PTR_FORMAT, new_caps);
/* FIXME: Need to activate these caps on the pads */
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_capsfilter_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstCapsFilter *capsfilter = GST_CAPSFILTER (object);
switch (prop_id) {
case PROP_FILTER_CAPS:
gst_value_set_caps (value, capsfilter->filter_caps);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_capsfilter_dispose (GObject * object)
{
GstCapsFilter *filter = GST_CAPSFILTER (object);
gst_caps_replace (&filter->filter_caps, NULL);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static GstCaps *
gst_capsfilter_transform_caps (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps)
{
GstCapsFilter *capsfilter = GST_CAPSFILTER (base);
GstCaps *ret;
ret = gst_caps_intersect (caps, capsfilter->filter_caps);
return ret;
}
static GstFlowReturn
gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
{
/* No actual work here. It's all done in the prepare output buffer
* func. */
return GST_FLOW_OK;
}
/* Output buffer preparation... if the buffer has no caps, and
* our allowed output caps is fixed, then give the caps to the
* buffer.
* This ensures that outgoing buffers have caps if we can, so
* that pipelines like:
* gst-launch filesrc location=rawsamples.raw !
* audio/x-raw-int,width=16,depth=16,rate=48000,channels=2,
* endianness=4321,signed='(boolean)'true ! alsasink
* will work.
*/
static GstFlowReturn
gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
gint size, GstCaps * caps, GstBuffer ** buf)
{
if (GST_BUFFER_CAPS (input) != NULL) {
/* Output buffer already has caps */
GST_DEBUG_OBJECT (trans, "Input buffer already has caps");
gst_buffer_ref (input);
*buf = input;
} else {
/* Buffer has no caps. See if the output pad only supports fixed caps */
GstCaps *out_caps;
out_caps = GST_PAD_CAPS (trans->srcpad);
if (out_caps != NULL) {
gst_caps_ref (out_caps);
} else {
out_caps = gst_pad_get_allowed_caps (trans->srcpad);
g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR);
}
if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) {
GST_DEBUG_OBJECT (trans, "Have fixed output caps %"
GST_PTR_FORMAT " to apply to buffer with no caps", out_caps);
if (gst_buffer_is_writable (input)) {
gst_buffer_ref (input);
*buf = input;
} else {
GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps");
*buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input));
}
GST_BUFFER_CAPS (*buf) = out_caps;
if (GST_PAD_CAPS (trans->srcpad) == NULL)
gst_pad_set_caps (trans->srcpad, out_caps);
} else {
gst_caps_unref (out_caps);
}
}
return GST_FLOW_OK;
}

View file

@ -1,84 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstelements.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gst/gst.h>
#include "gstfakesink.h"
#include "gstfakesrc.h"
#include "gstfdsrc.h"
#include "gstfilesink.h"
#include "gstfilesrc.h"
#include "gstidentity.h"
#include "gsttee.h"
#include "gsttypefindelement.h"
struct _elements_entry
{
gchar *name;
guint rank;
GType (*type) (void);
};
/* this declaration is here because there's no gstcapsfilter.h */
extern GType gst_capsfilter_get_type (void);
static struct _elements_entry _elements[] = {
{"capsfilter", GST_RANK_NONE, gst_capsfilter_get_type},
{"fakesrc", GST_RANK_NONE, gst_fake_src_get_type},
{"fakesink", GST_RANK_NONE, gst_fake_sink_get_type},
#if HAVE_SYS_SOCKET_H
{"fdsrc", GST_RANK_NONE, gst_fdsrc_get_type},
#endif
{"filesrc", GST_RANK_NONE, gst_file_src_get_type},
{"identity", GST_RANK_NONE, gst_identity_get_type},
{"filesink", GST_RANK_NONE, gst_file_sink_get_type},
{"tee", GST_RANK_NONE, gst_tee_get_type},
{"typefind", GST_RANK_NONE, gst_type_find_element_get_type},
{NULL, 0},
};
static gboolean
plugin_init (GstPlugin * plugin)
{
struct _elements_entry *my_elements = _elements;
while ((*my_elements).name) {
if (!gst_element_register (plugin, (*my_elements).name, (*my_elements).rank,
((*my_elements).type) ()))
return FALSE;
my_elements++;
}
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"gstelements",
"standard GStreamer elements",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);

View file

@ -1,437 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstfakesink.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:gstfakesink
* @short_description: black hole for data
* @see_also: #GstFakeSrc
*
* Dummy sink that swallows everything.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gstfakesink.h"
#include <gst/gstmarshal.h>
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_fake_sink_debug);
#define GST_CAT_DEFAULT gst_fake_sink_debug
static GstElementDetails gst_fake_sink_details =
GST_ELEMENT_DETAILS ("Fake Sink",
"Sink",
"Black hole for data",
"Erik Walthinsen <omega@cse.ogi.edu>, "
"Wim Taymans <wim@fluendo.com>, "
"Mr. 'frag-me-more' Vanderwingo <wingo@fluendo.com>");
/* FakeSink signals and args */
enum
{
/* FILL ME */
SIGNAL_HANDOFF,
LAST_SIGNAL
};
#define DEFAULT_SYNC FALSE
#define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE
#define DEFAULT_SILENT FALSE
#define DEFAULT_DUMP FALSE
#define DEFAULT_SIGNAL_HANDOFFS FALSE
#define DEFAULT_LAST_MESSAGE NULL
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
enum
{
PROP_0,
PROP_STATE_ERROR,
PROP_SILENT,
PROP_DUMP,
PROP_SIGNAL_HANDOFFS,
PROP_LAST_MESSAGE,
PROP_CAN_ACTIVATE_PUSH,
PROP_CAN_ACTIVATE_PULL
};
#define GST_TYPE_FAKE_SINK_STATE_ERROR (gst_fake_sink_state_error_get_type())
static GType
gst_fake_sink_state_error_get_type (void)
{
static GType fakesink_state_error_type = 0;
static GEnumValue fakesink_state_error[] = {
{FAKE_SINK_STATE_ERROR_NONE, "No state change errors", "none"},
{FAKE_SINK_STATE_ERROR_NULL_READY,
"Fail state change from NULL to READY", "null-to-ready"},
{FAKE_SINK_STATE_ERROR_READY_PAUSED,
"Fail state change from READY to PAUSED", "ready-to-paused"},
{FAKE_SINK_STATE_ERROR_PAUSED_PLAYING,
"Fail state change from PAUSED to PLAYING", "paused-to-playing"},
{FAKE_SINK_STATE_ERROR_PLAYING_PAUSED,
"Fail state change from PLAYING to PAUSED", "playing-to-paused"},
{FAKE_SINK_STATE_ERROR_PAUSED_READY,
"Fail state change from PAUSED to READY", "paused-to-ready"},
{FAKE_SINK_STATE_ERROR_READY_NULL,
"Fail state change from READY to NULL", "ready-to-null"},
{0, NULL, NULL},
};
if (!fakesink_state_error_type) {
fakesink_state_error_type =
g_enum_register_static ("GstFakeSinkStateError", fakesink_state_error);
}
return fakesink_state_error_type;
}
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_fake_sink_debug, "fakesink", 0, "fakesink element");
GST_BOILERPLATE_FULL (GstFakeSink, gst_fake_sink, GstBaseSink,
GST_TYPE_BASE_SINK, _do_init);
static void gst_fake_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_fake_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstStateChangeReturn gst_fake_sink_change_state (GstElement * element,
GstStateChange transition);
static GstFlowReturn gst_fake_sink_preroll (GstBaseSink * bsink,
GstBuffer * buffer);
static GstFlowReturn gst_fake_sink_render (GstBaseSink * bsink,
GstBuffer * buffer);
static gboolean gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event);
static guint gst_fake_sink_signals[LAST_SIGNAL] = { 0 };
static void
gst_fake_sink_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (gstelement_class, &gst_fake_sink_details);
}
static void
gst_fake_sink_class_init (GstFakeSinkClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSinkClass *gstbase_sink_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbase_sink_class = (GstBaseSinkClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fake_sink_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fake_sink_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATE_ERROR,
g_param_spec_enum ("state_error", "State Error",
"Generate a state change error", GST_TYPE_FAKE_SINK_STATE_ERROR,
DEFAULT_STATE_ERROR, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last_message", "Last Message",
"The message describing current status", DEFAULT_LAST_MESSAGE,
G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_HANDOFFS,
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
"Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "Silent",
"Don't produce last_message events", DEFAULT_SILENT,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
DEFAULT_DUMP, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_CAN_ACTIVATE_PUSH,
g_param_spec_boolean ("can-activate-push", "Can activate push",
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_CAN_ACTIVATE_PULL,
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
G_PARAM_READWRITE));
/**
* GstFakeSink::handoff:
* @fakesink: the fakesink instance
* @buffer: the buffer that just has been received
* @pad: the pad that received it
*
* This signal gets emitted before unreffing the buffer.
*/
gst_fake_sink_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstFakeSinkClass, handoff), NULL, NULL,
gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
GST_TYPE_BUFFER, GST_TYPE_PAD);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_fake_sink_change_state);
gstbase_sink_class->event = GST_DEBUG_FUNCPTR (gst_fake_sink_event);
gstbase_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_fake_sink_preroll);
gstbase_sink_class->render = GST_DEBUG_FUNCPTR (gst_fake_sink_render);
}
static void
gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class)
{
fakesink->silent = DEFAULT_SILENT;
fakesink->dump = DEFAULT_DUMP;
GST_BASE_SINK (fakesink)->sync = DEFAULT_SYNC;
fakesink->last_message = g_strdup (DEFAULT_LAST_MESSAGE);
fakesink->state_error = DEFAULT_STATE_ERROR;
fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
}
static void
gst_fake_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstFakeSink *sink;
sink = GST_FAKE_SINK (object);
switch (prop_id) {
case PROP_SILENT:
sink->silent = g_value_get_boolean (value);
break;
case PROP_STATE_ERROR:
sink->state_error = g_value_get_enum (value);
break;
case PROP_DUMP:
sink->dump = g_value_get_boolean (value);
break;
case PROP_SIGNAL_HANDOFFS:
sink->signal_handoffs = g_value_get_boolean (value);
break;
case PROP_CAN_ACTIVATE_PUSH:
GST_BASE_SINK (sink)->can_activate_push = g_value_get_boolean (value);
break;
case PROP_CAN_ACTIVATE_PULL:
GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstFakeSink *sink;
sink = GST_FAKE_SINK (object);
switch (prop_id) {
case PROP_STATE_ERROR:
g_value_set_enum (value, sink->state_error);
break;
case PROP_SILENT:
g_value_set_boolean (value, sink->silent);
break;
case PROP_DUMP:
g_value_set_boolean (value, sink->dump);
break;
case PROP_SIGNAL_HANDOFFS:
g_value_set_boolean (value, sink->signal_handoffs);
break;
case PROP_LAST_MESSAGE:
GST_OBJECT_LOCK (sink);
g_value_set_string (value, sink->last_message);
GST_OBJECT_UNLOCK (sink);
break;
case PROP_CAN_ACTIVATE_PUSH:
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_push);
break;
case PROP_CAN_ACTIVATE_PULL:
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_fake_sink_event (GstBaseSink * bsink, GstEvent * event)
{
GstFakeSink *sink = GST_FAKE_SINK (bsink);
if (!sink->silent) {
const GstStructure *s;
gchar *sstr;
GST_OBJECT_LOCK (sink);
g_free (sink->last_message);
if ((s = gst_event_get_structure (event)))
sstr = gst_structure_to_string (s);
else
sstr = g_strdup ("");
sink->last_message =
g_strdup_printf ("event ******* E (type: %d, %s) %p",
GST_EVENT_TYPE (event), sstr, event);
g_free (sstr);
GST_OBJECT_UNLOCK (sink);
g_object_notify (G_OBJECT (sink), "last_message");
}
return TRUE;
}
static GstFlowReturn
gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
{
GstFakeSink *sink = GST_FAKE_SINK (bsink);
if (!sink->silent) {
GST_OBJECT_LOCK (sink);
g_free (sink->last_message);
sink->last_message = g_strdup_printf ("preroll ******* ");
GST_OBJECT_UNLOCK (sink);
g_object_notify (G_OBJECT (sink), "last_message");
}
return GST_FLOW_OK;
}
static GstFlowReturn
gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
GstFakeSink *sink = GST_FAKE_SINK (bsink);
if (!sink->silent) {
gchar ts_str[64], dur_str[64];
GST_OBJECT_LOCK (sink);
g_free (sink->last_message);
if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
} else {
g_strlcpy (ts_str, "none", sizeof (ts_str));
}
if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
} else {
g_strlcpy (dur_str, "none", sizeof (dur_str));
}
sink->last_message =
g_strdup_printf ("chain ******* < (%5d bytes, timestamp: %s"
", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
G_GINT64_FORMAT ", flags: %d) %p", GST_BUFFER_SIZE (buf), ts_str,
dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
GST_MINI_OBJECT (buf)->flags, buf);
GST_OBJECT_UNLOCK (sink);
g_object_notify (G_OBJECT (sink), "last_message");
}
if (sink->signal_handoffs)
g_signal_emit (G_OBJECT (sink), gst_fake_sink_signals[SIGNAL_HANDOFF], 0,
buf, bsink->sinkpad);
if (sink->dump) {
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
}
return GST_FLOW_OK;
}
static GstStateChangeReturn
gst_fake_sink_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstFakeSink *fakesink = GST_FAKE_SINK (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_NULL_READY)
goto error;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_PAUSED)
goto error;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_PLAYING)
goto error;
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PLAYING_PAUSED)
goto error;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_READY)
goto error;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_NULL)
goto error;
GST_OBJECT_LOCK (fakesink);
g_free (fakesink->last_message);
fakesink->last_message = NULL;
GST_OBJECT_UNLOCK (fakesink);
break;
default:
break;
}
return ret;
/* ERROR */
error:
GST_ELEMENT_ERROR (element, CORE, STATE_CHANGE, (NULL), (NULL));
return GST_STATE_CHANGE_FAILURE;
}

View file

@ -1,95 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfakesink.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FAKE_SINK_H__
#define __GST_FAKE_SINK_H__
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
#define GST_TYPE_FAKE_SINK \
(gst_fake_sink_get_type())
#define GST_FAKE_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FAKE_SINK,GstFakeSink))
#define GST_FAKE_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FAKE_SINK,GstFakeSinkClass))
#define GST_IS_FAKE_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAKE_SINK))
#define GST_IS_FAKE_SINK_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKE_SINK))
/**
* GstFakeSinkStateError:
* @FAKE_SINK_STATE_ERROR_NONE: no error
* @FAKE_SINK_STATE_ERROR_NULL_READY: cause the NULL to READY state change to fail
* @FAKE_SINK_STATE_ERROR_READY_PAUSED: cause the READY to PAUSED state change to fail:
* @FAKE_SINK_STATE_ERROR_PAUSED_PLAYING: cause the PAUSED to PLAYING state change to fail:
* @FAKE_SINK_STATE_ERROR_PLAYING_PAUSED: cause the PLAYING to PAUSED state change to fail:
* @FAKE_SINK_STATE_ERROR_PAUSED_READY: cause the PAUSED to READY state change to fail:
* @FAKE_SINK_STATE_ERROR_READY_NULL: cause the READY to NULL state change to fail:
*
* Possible state change errors for the state-error property.
*/
typedef enum {
FAKE_SINK_STATE_ERROR_NONE = 0,
FAKE_SINK_STATE_ERROR_NULL_READY,
FAKE_SINK_STATE_ERROR_READY_PAUSED,
FAKE_SINK_STATE_ERROR_PAUSED_PLAYING,
FAKE_SINK_STATE_ERROR_PLAYING_PAUSED,
FAKE_SINK_STATE_ERROR_PAUSED_READY,
FAKE_SINK_STATE_ERROR_READY_NULL
} GstFakeSinkStateError;
typedef struct _GstFakeSink GstFakeSink;
typedef struct _GstFakeSinkClass GstFakeSinkClass;
/**
* GstFakeSink:
*
* The opaque #GstFakeSink data structure.
*/
struct _GstFakeSink {
GstBaseSink element;
gboolean silent;
gboolean dump;
gboolean signal_handoffs;
GstFakeSinkStateError state_error;
gchar *last_message;
};
struct _GstFakeSinkClass {
GstBaseSinkClass parent_class;
/* signals */
void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
};
GType gst_fake_sink_get_type (void);
G_END_DECLS
#endif /* __GST_FAKE_SINK_H__ */

View file

@ -1,804 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfakesrc.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:gstfakesrc
* @short_description: Push empty (no data) buffers around
* @see_also: #GstFakeSink
*
* Dummy source that generates empty buffers.
*/
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gstfakesrc.h"
#include <gst/gstmarshal.h>
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_fake_src_debug);
#define GST_CAT_DEFAULT gst_fake_src_debug
static GstElementDetails gst_fake_src_details =
GST_ELEMENT_DETAILS ("Fake Source",
"Source",
"Push empty (no data) buffers around",
"Erik Walthinsen <omega@cse.ogi.edu>, "
"Wim Taymans <wim.taymans@chello.be>");
/* FakeSrc signals and args */
enum
{
/* FILL ME */
SIGNAL_HANDOFF,
LAST_SIGNAL
};
#define DEFAULT_OUTPUT FAKE_SRC_FIRST_LAST_LOOP
#define DEFAULT_DATA FAKE_SRC_DATA_ALLOCATE
#define DEFAULT_SIZETYPE FAKE_SRC_SIZETYPE_EMPTY
#define DEFAULT_SIZEMIN 0
#define DEFAULT_SIZEMAX 4096
#define DEFAULT_FILLTYPE FAKE_SRC_FILLTYPE_ZERO
#define DEFAULT_DATARATE 0
#define DEFAULT_SYNC FALSE
#define DEFAULT_PATTERN NULL
#define DEFAULT_EOS FALSE
#define DEFAULT_SIGNAL_HANDOFFS FALSE
#define DEFAULT_SILENT FALSE
#define DEFAULT_DUMP FALSE
#define DEFAULT_PARENTSIZE 4096*10
#define DEFAULT_CAN_ACTIVATE_PULL TRUE
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
enum
{
PROP_0,
PROP_OUTPUT,
PROP_DATA,
PROP_SIZETYPE,
PROP_SIZEMIN,
PROP_SIZEMAX,
PROP_FILLTYPE,
PROP_DATARATE,
PROP_SYNC,
PROP_PATTERN,
PROP_EOS,
PROP_SIGNAL_HANDOFFS,
PROP_SILENT,
PROP_DUMP,
PROP_PARENTSIZE,
PROP_LAST_MESSAGE,
PROP_CAN_ACTIVATE_PULL,
PROP_CAN_ACTIVATE_PUSH,
PROP_IS_LIVE
};
/* not implemented
#define GST_TYPE_FAKE_SRC_OUTPUT (gst_fake_src_output_get_type())
static GType
gst_fake_src_output_get_type (void)
{
static GType fakesrc_output_type = 0;
static GEnumValue fakesrc_output[] = {
{FAKE_SRC_FIRST_LAST_LOOP, "1", "First-Last loop"},
{FAKE_SRC_LAST_FIRST_LOOP, "2", "Last-First loop"},
{FAKE_SRC_PING_PONG, "3", "Ping-Pong"},
{FAKE_SRC_ORDERED_RANDOM, "4", "Ordered Random"},
{FAKE_SRC_RANDOM, "5", "Random"},
{FAKE_SRC_PATTERN_LOOP, "6", "Patttern loop"},
{FAKE_SRC_PING_PONG_PATTERN, "7", "Ping-Pong Pattern"},
{FAKE_SRC_GET_ALWAYS_SUCEEDS, "8", "'_get' Always succeeds"},
{0, NULL, NULL},
};
if (!fakesrc_output_type) {
fakesrc_output_type =
g_enum_register_static ("GstFakeSrcOutput", fakesrc_output);
}
return fakesrc_output_type;
}
*/
#define GST_TYPE_FAKE_SRC_DATA (gst_fake_src_data_get_type())
static GType
gst_fake_src_data_get_type (void)
{
static GType fakesrc_data_type = 0;
static GEnumValue fakesrc_data[] = {
{FAKE_SRC_DATA_ALLOCATE, "Allocate data", "allocate"},
{FAKE_SRC_DATA_SUBBUFFER, "Subbuffer data", "subbuffer"},
{0, NULL, NULL},
};
if (!fakesrc_data_type) {
fakesrc_data_type =
g_enum_register_static ("GstFakeSrcDataType", fakesrc_data);
}
return fakesrc_data_type;
}
#define GST_TYPE_FAKE_SRC_SIZETYPE (gst_fake_src_sizetype_get_type())
static GType
gst_fake_src_sizetype_get_type (void)
{
static GType fakesrc_sizetype_type = 0;
static GEnumValue fakesrc_sizetype[] = {
{FAKE_SRC_SIZETYPE_EMPTY, "Send empty buffers", "empty"},
{FAKE_SRC_SIZETYPE_FIXED, "Fixed size buffers (sizemax sized)", "fixed"},
{FAKE_SRC_SIZETYPE_RANDOM,
"Random sized buffers (sizemin <= size <= sizemax)", "random"},
{0, NULL, NULL},
};
if (!fakesrc_sizetype_type) {
fakesrc_sizetype_type =
g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
}
return fakesrc_sizetype_type;
}
#define GST_TYPE_FAKE_SRC_FILLTYPE (gst_fake_src_filltype_get_type())
static GType
gst_fake_src_filltype_get_type (void)
{
static GType fakesrc_filltype_type = 0;
static GEnumValue fakesrc_filltype[] = {
{FAKE_SRC_FILLTYPE_NOTHING, "Leave data as malloced", "nothing"},
{FAKE_SRC_FILLTYPE_ZERO, "Fill buffers with zeros", "zero"},
{FAKE_SRC_FILLTYPE_RANDOM, "Fill buffers with random crap", "random"},
{FAKE_SRC_FILLTYPE_PATTERN, "Fill buffers with pattern 0x00 -> 0xff",
"pattern"},
{FAKE_SRC_FILLTYPE_PATTERN_CONT,
"Fill buffers with pattern 0x00 -> 0xff that spans buffers",
"pattern-span"},
{0, NULL, NULL},
};
if (!fakesrc_filltype_type) {
fakesrc_filltype_type =
g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
}
return fakesrc_filltype_type;
}
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_fake_src_debug, "fakesrc", 0, "fakesrc element");
GST_BOILERPLATE_FULL (GstFakeSrc, gst_fake_src, GstBaseSrc, GST_TYPE_BASE_SRC,
_do_init);
static void gst_fake_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_fake_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_fake_src_start (GstBaseSrc * basesrc);
static gboolean gst_fake_src_stop (GstBaseSrc * basesrc);
static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc);
static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event);
static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset,
guint length, GstBuffer ** buf);
static guint gst_fake_src_signals[LAST_SIGNAL] = { 0 };
static void
gst_fake_src_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_set_details (gstelement_class, &gst_fake_src_details);
}
static void
gst_fake_src_class_init (GstFakeSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbase_src_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstbase_src_class = (GstBaseSrcClass *) klass;
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fake_src_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fake_src_get_property);
/*
FIXME: this is not implemented; would make sense once basesrc and fakesrc
support multiple pads
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_OUTPUT,
g_param_spec_enum ("output", "output", "Output method (currently unused)",
GST_TYPE_FAKE_SRC_OUTPUT, DEFAULT_OUTPUT, G_PARAM_READWRITE));
*/
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATA,
g_param_spec_enum ("data", "data", "Data allocation method",
GST_TYPE_FAKE_SRC_DATA, DEFAULT_DATA, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZETYPE,
g_param_spec_enum ("sizetype", "sizetype",
"How to determine buffer sizes", GST_TYPE_FAKE_SRC_SIZETYPE,
DEFAULT_SIZETYPE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZEMIN,
g_param_spec_int ("sizemin", "sizemin", "Minimum buffer size", 0,
G_MAXINT, DEFAULT_SIZEMIN, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIZEMAX,
g_param_spec_int ("sizemax", "sizemax", "Maximum buffer size", 0,
G_MAXINT, DEFAULT_SIZEMAX, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARENTSIZE,
g_param_spec_int ("parentsize", "parentsize",
"Size of parent buffer for sub-buffered allocation", 0, G_MAXINT,
DEFAULT_PARENTSIZE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILLTYPE,
g_param_spec_enum ("filltype", "filltype",
"How to fill the buffer, if at all", GST_TYPE_FAKE_SRC_FILLTYPE,
DEFAULT_FILLTYPE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATARATE,
g_param_spec_int ("datarate", "Datarate",
"Timestamps buffers with number of bytes per second (0 = none)", 0,
G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SYNC,
g_param_spec_boolean ("sync", "Sync", "Sync to the clock to the datarate",
DEFAULT_SYNC, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PATTERN,
g_param_spec_string ("pattern", "pattern", "pattern", DEFAULT_PATTERN,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last-message", "last-message",
"The last status message", NULL, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "Silent",
"Don't produce last_message events", DEFAULT_SILENT,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_HANDOFFS,
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
"Send a signal before pushing the buffer", DEFAULT_SIGNAL_HANDOFFS,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
DEFAULT_DUMP, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_CAN_ACTIVATE_PUSH,
g_param_spec_boolean ("can-activate-push", "Can activate push",
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_CAN_ACTIVATE_PULL,
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_IS_LIVE,
g_param_spec_boolean ("is-live", "Is this a live source",
"True if the element cannot produce data in PAUSED", FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
/**
* GstFakeSrc::handoff:
* @fakesrc: the fakesrc instance
* @buffer: the buffer that will be pushed
* @pad: the pad that will sent it
*
* This signal gets emitted before sending the buffer.
*/
gst_fake_src_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstFakeSrcClass, handoff), NULL, NULL,
gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
GST_TYPE_PAD);
gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
gstbase_src_class->create = GST_DEBUG_FUNCPTR (gst_fake_src_create);
}
static void
gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
{
fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
fakesrc->buffer_count = 0;
fakesrc->silent = DEFAULT_SILENT;
fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
fakesrc->dump = DEFAULT_DUMP;
fakesrc->pattern_byte = 0x00;
fakesrc->data = FAKE_SRC_DATA_ALLOCATE;
fakesrc->sizetype = FAKE_SRC_SIZETYPE_EMPTY;
fakesrc->filltype = FAKE_SRC_FILLTYPE_NOTHING;
fakesrc->sizemin = DEFAULT_SIZEMIN;
fakesrc->sizemax = DEFAULT_SIZEMAX;
fakesrc->parent = NULL;
fakesrc->parentsize = DEFAULT_PARENTSIZE;
fakesrc->last_message = NULL;
fakesrc->datarate = DEFAULT_DATARATE;
fakesrc->sync = DEFAULT_SYNC;
}
static gboolean
gst_fake_src_event_handler (GstBaseSrc * basesrc, GstEvent * event)
{
GstFakeSrc *src;
src = GST_FAKE_SRC (basesrc);
if (!src->silent) {
const GstStructure *s;
gchar *sstr;
GST_OBJECT_LOCK (src);
g_free (src->last_message);
if ((s = gst_event_get_structure (event)))
sstr = gst_structure_to_string (s);
else
sstr = g_strdup ("");
src->last_message =
g_strdup_printf ("event ******* E (type: %d, %s) %p",
GST_EVENT_TYPE (event), sstr, event);
g_free (sstr);
GST_OBJECT_UNLOCK (src);
g_object_notify (G_OBJECT (src), "last_message");
}
return TRUE;
}
static void
gst_fake_src_alloc_parent (GstFakeSrc * src)
{
GstBuffer *buf;
buf = gst_buffer_new ();
GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
GST_BUFFER_SIZE (buf) = src->parentsize;
src->parent = buf;
src->parentoffset = 0;
}
static void
gst_fake_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstFakeSrc *src;
GstBaseSrc *basesrc;
src = GST_FAKE_SRC (object);
basesrc = GST_BASE_SRC (object);
switch (prop_id) {
case PROP_OUTPUT:
g_warning ("not yet implemented");
break;
case PROP_DATA:
src->data = g_value_get_enum (value);
if (src->data == FAKE_SRC_DATA_SUBBUFFER) {
if (!src->parent)
gst_fake_src_alloc_parent (src);
} else {
if (src->parent) {
gst_buffer_unref (src->parent);
src->parent = NULL;
}
}
break;
case PROP_SIZETYPE:
src->sizetype = g_value_get_enum (value);
break;
case PROP_SIZEMIN:
src->sizemin = g_value_get_int (value);
break;
case PROP_SIZEMAX:
src->sizemax = g_value_get_int (value);
break;
case PROP_PARENTSIZE:
src->parentsize = g_value_get_int (value);
break;
case PROP_FILLTYPE:
src->filltype = g_value_get_enum (value);
break;
case PROP_DATARATE:
src->datarate = g_value_get_int (value);
break;
case PROP_SYNC:
src->sync = g_value_get_boolean (value);
break;
case PROP_PATTERN:
break;
case PROP_SILENT:
src->silent = g_value_get_boolean (value);
break;
case PROP_SIGNAL_HANDOFFS:
src->signal_handoffs = g_value_get_boolean (value);
break;
case PROP_DUMP:
src->dump = g_value_get_boolean (value);
break;
case PROP_CAN_ACTIVATE_PUSH:
g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
break;
case PROP_CAN_ACTIVATE_PULL:
g_return_if_fail (!GST_OBJECT_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
src->can_activate_pull = g_value_get_boolean (value);
break;
case PROP_IS_LIVE:
gst_base_src_set_live (basesrc, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstFakeSrc *src;
GstBaseSrc *basesrc;
g_return_if_fail (GST_IS_FAKE_SRC (object));
src = GST_FAKE_SRC (object);
basesrc = GST_BASE_SRC (object);
switch (prop_id) {
case PROP_OUTPUT:
g_value_set_enum (value, src->output);
break;
case PROP_DATA:
g_value_set_enum (value, src->data);
break;
case PROP_SIZETYPE:
g_value_set_enum (value, src->sizetype);
break;
case PROP_SIZEMIN:
g_value_set_int (value, src->sizemin);
break;
case PROP_SIZEMAX:
g_value_set_int (value, src->sizemax);
break;
case PROP_PARENTSIZE:
g_value_set_int (value, src->parentsize);
break;
case PROP_FILLTYPE:
g_value_set_enum (value, src->filltype);
break;
case PROP_DATARATE:
g_value_set_int (value, src->datarate);
break;
case PROP_SYNC:
g_value_set_boolean (value, src->sync);
break;
case PROP_PATTERN:
g_value_set_string (value, src->pattern);
break;
case PROP_SILENT:
g_value_set_boolean (value, src->silent);
break;
case PROP_SIGNAL_HANDOFFS:
g_value_set_boolean (value, src->signal_handoffs);
break;
case PROP_DUMP:
g_value_set_boolean (value, src->dump);
break;
case PROP_LAST_MESSAGE:
GST_OBJECT_LOCK (src);
g_value_set_string (value, src->last_message);
GST_OBJECT_UNLOCK (src);
break;
case PROP_CAN_ACTIVATE_PUSH:
g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
break;
case PROP_CAN_ACTIVATE_PULL:
g_value_set_boolean (value, src->can_activate_pull);
break;
case PROP_IS_LIVE:
g_value_set_boolean (value, gst_base_src_is_live (basesrc));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_fake_src_prepare_buffer (GstFakeSrc * src, GstBuffer * buf)
{
if (GST_BUFFER_SIZE (buf) == 0)
return;
switch (src->filltype) {
case FAKE_SRC_FILLTYPE_ZERO:
memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
break;
case FAKE_SRC_FILLTYPE_RANDOM:
{
gint i;
guint8 *ptr = GST_BUFFER_DATA (buf);
for (i = GST_BUFFER_SIZE (buf); i; i--) {
*ptr++ = (gint8) ((255.0) * rand () / (RAND_MAX));
}
break;
}
case FAKE_SRC_FILLTYPE_PATTERN:
src->pattern_byte = 0x00;
case FAKE_SRC_FILLTYPE_PATTERN_CONT:
{
gint i;
guint8 *ptr = GST_BUFFER_DATA (buf);
for (i = GST_BUFFER_SIZE (buf); i; i--) {
*ptr++ = src->pattern_byte++;
}
break;
}
case FAKE_SRC_FILLTYPE_NOTHING:
default:
break;
}
}
static GstBuffer *
gst_fake_src_alloc_buffer (GstFakeSrc * src, guint size)
{
GstBuffer *buf;
buf = gst_buffer_new ();
GST_BUFFER_SIZE (buf) = size;
if (size != 0) {
switch (src->filltype) {
case FAKE_SRC_FILLTYPE_NOTHING:
GST_BUFFER_DATA (buf) = g_malloc (size);
GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
break;
case FAKE_SRC_FILLTYPE_ZERO:
GST_BUFFER_DATA (buf) = g_malloc0 (size);
GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
break;
case FAKE_SRC_FILLTYPE_RANDOM:
case FAKE_SRC_FILLTYPE_PATTERN:
case FAKE_SRC_FILLTYPE_PATTERN_CONT:
default:
GST_BUFFER_DATA (buf) = g_malloc (size);
GST_BUFFER_MALLOCDATA (buf) = GST_BUFFER_DATA (buf);
gst_fake_src_prepare_buffer (src, buf);
break;
}
}
return buf;
}
static guint
gst_fake_src_get_size (GstFakeSrc * src)
{
guint size;
switch (src->sizetype) {
case FAKE_SRC_SIZETYPE_FIXED:
size = src->sizemax;
break;
case FAKE_SRC_SIZETYPE_RANDOM:
size =
src->sizemin +
(guint8) (((gfloat) src->sizemax) * rand () / (RAND_MAX +
(gfloat) src->sizemin));
break;
case FAKE_SRC_SIZETYPE_EMPTY:
default:
size = 0;
break;
}
return size;
}
static GstBuffer *
gst_fake_src_create_buffer (GstFakeSrc * src)
{
GstBuffer *buf;
guint size;
gboolean dump = src->dump;
size = gst_fake_src_get_size (src);
if (size == 0)
return gst_buffer_new ();
switch (src->data) {
case FAKE_SRC_DATA_ALLOCATE:
buf = gst_fake_src_alloc_buffer (src, size);
break;
case FAKE_SRC_DATA_SUBBUFFER:
/* see if we have a parent to subbuffer */
if (!src->parent) {
gst_fake_src_alloc_parent (src);
g_assert (src->parent);
}
/* see if it's large enough */
if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
src->parentoffset += size;
} else {
/* the parent is useless now */
gst_buffer_unref (src->parent);
src->parent = NULL;
/* try again (this will allocate a new parent) */
return gst_fake_src_create_buffer (src);
}
gst_fake_src_prepare_buffer (src, buf);
break;
default:
g_warning ("fakesrc: dunno how to allocate buffers !");
buf = gst_buffer_new ();
break;
}
if (dump) {
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
}
return buf;
}
static GstFlowReturn
gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFakeSrc *src;
GstBuffer *buf;
GstClockTime time;
src = GST_FAKE_SRC (basesrc);
buf = gst_fake_src_create_buffer (src);
GST_BUFFER_OFFSET (buf) = src->buffer_count++;
if (src->datarate > 0) {
time = (src->bytes_sent * GST_SECOND) / src->datarate;
if (src->sync) {
/* gst_element_wait (GST_ELEMENT (src), time); */
}
GST_BUFFER_DURATION (buf) =
GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate;
} else if (gst_base_src_is_live (basesrc)) {
GstClock *clock;
clock = gst_element_get_clock (GST_ELEMENT (src));
if (clock) {
time = gst_clock_get_time (clock);
time -= gst_element_get_base_time (GST_ELEMENT (src));
gst_object_unref (clock);
} else {
/* not an error not to have a clock */
time = GST_CLOCK_TIME_NONE;
}
} else {
time = GST_CLOCK_TIME_NONE;
}
GST_BUFFER_TIMESTAMP (buf) = time;
if (!src->silent) {
gchar ts_str[64], dur_str[64];
GST_OBJECT_LOCK (src);
g_free (src->last_message);
if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
g_snprintf (ts_str, sizeof (ts_str), "%" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
} else {
g_strlcpy (ts_str, "none", sizeof (ts_str));
}
if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE) {
g_snprintf (dur_str, sizeof (dur_str), "%" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
} else {
g_strlcpy (dur_str, "none", sizeof (dur_str));
}
src->last_message =
g_strdup_printf ("get ******* > (%5d bytes, timestamp: %s"
", duration: %s, offset: %" G_GINT64_FORMAT ", offset_end: %"
G_GINT64_FORMAT ", flags: %d) %p", GST_BUFFER_SIZE (buf), ts_str,
dur_str, GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
GST_MINI_OBJECT (buf)->flags, buf);
GST_OBJECT_UNLOCK (src);
g_object_notify (G_OBJECT (src), "last_message");
}
if (src->signal_handoffs) {
GST_LOG_OBJECT (src, "pre handoff emit");
g_signal_emit (G_OBJECT (src), gst_fake_src_signals[SIGNAL_HANDOFF], 0,
buf, basesrc->srcpad);
GST_LOG_OBJECT (src, "post handoff emit");
}
src->bytes_sent += GST_BUFFER_SIZE (buf);
*ret = buf;
return GST_FLOW_OK;
}
static gboolean
gst_fake_src_start (GstBaseSrc * basesrc)
{
GstFakeSrc *src;
src = GST_FAKE_SRC (basesrc);
src->buffer_count = 0;
src->pattern_byte = 0x00;
src->bytes_sent = 0;
return TRUE;
}
static gboolean
gst_fake_src_stop (GstBaseSrc * basesrc)
{
GstFakeSrc *src;
src = GST_FAKE_SRC (basesrc);
GST_OBJECT_LOCK (src);
if (src->parent) {
gst_buffer_unref (src->parent);
src->parent = NULL;
}
g_free (src->last_message);
src->last_message = NULL;
GST_OBJECT_UNLOCK (src);
return TRUE;
}
static gboolean
gst_fake_src_is_seekable (GstBaseSrc * basesrc)
{
GstFakeSrc *src = GST_FAKE_SRC (basesrc);
return src->can_activate_pull;
}

View file

@ -1,168 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfakesrc.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FAKE_SRC_H__
#define __GST_FAKE_SRC_H__
#include <gst/gst.h>
#include <gst/base/gstbasesrc.h>
G_BEGIN_DECLS
/**
* GstFakeSrcOutputType:
* @FAKE_SRC_FIRST_LAST_LOOP: first pad then last pad
* @FAKE_SRC_LAST_FIRST_LOOP: last pad then first pad
* @FAKE_SRC_PING_PONG: ping pong between pads
* @FAKE_SRC_ORDERED_RANDOM: ordered random pad
* @FAKE_SRC_RANDOM: random pad
* @FAKE_SRC_PATTERN_LOOP: loop between pads in a particular pattern
* @FAKE_SRC_PING_PONG_PATTERN: ping pong based on a pattern
* @FAKE_SRC_GET_ALWAYS_SUCEEDS: a get always succeeds on a pad
*
* The different output types. Unused currently.
*/
typedef enum {
FAKE_SRC_FIRST_LAST_LOOP = 1,
FAKE_SRC_LAST_FIRST_LOOP,
FAKE_SRC_PING_PONG,
FAKE_SRC_ORDERED_RANDOM,
FAKE_SRC_RANDOM,
FAKE_SRC_PATTERN_LOOP,
FAKE_SRC_PING_PONG_PATTERN,
FAKE_SRC_GET_ALWAYS_SUCEEDS
} GstFakeSrcOutputType;
/**
* GstFakeSrcDataType:
* @FAKE_SRC_DATA_ALLOCATE: allocate buffers
* @FAKE_SRC_DATA_SUBBUFFER: subbuffer each buffer
*
* The different ways buffers are allocated.
*/
typedef enum {
FAKE_SRC_DATA_ALLOCATE = 1,
FAKE_SRC_DATA_SUBBUFFER
} GstFakeSrcDataType;
/**
* GstFakeSrcSizeType:
* @FAKE_SRC_SIZETYPE_EMPTY: create empty buffers
* @FAKE_SRC_SIZETYPE_FIXED: fixed buffer size
* @FAKE_SRC_SIZETYPE_RANDOM: random buffer size
*
* The different size of the allocated buffers.
*/
typedef enum {
FAKE_SRC_SIZETYPE_EMPTY = 1,
FAKE_SRC_SIZETYPE_FIXED,
FAKE_SRC_SIZETYPE_RANDOM
} GstFakeSrcSizeType;
/**
* GstFakeSrcFillType:
* @FAKE_SRC_FILLTYPE_NOTHING: do not fill buffers
* @FAKE_SRC_FILLTYPE_ZERO: fill buffers with 0
* @FAKE_SRC_FILLTYPE_RANDOM: fill buffers with random bytes
* @FAKE_SRC_FILLTYPE_PATTERN: fill buffers with a pattern
* @FAKE_SRC_FILLTYPE_PATTERN_CONT: fill buffers with a continuous pattern
*
* The different ways of filling the buffers.
*/
typedef enum {
FAKE_SRC_FILLTYPE_NOTHING = 1,
FAKE_SRC_FILLTYPE_ZERO,
FAKE_SRC_FILLTYPE_RANDOM,
FAKE_SRC_FILLTYPE_PATTERN,
FAKE_SRC_FILLTYPE_PATTERN_CONT
} GstFakeSrcFillType;
#define GST_TYPE_FAKE_SRC \
(gst_fake_src_get_type())
#define GST_FAKE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FAKE_SRC,GstFakeSrc))
#define GST_FAKE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FAKE_SRC,GstFakeSrcClass))
#define GST_IS_FAKE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FAKE_SRC))
#define GST_IS_FAKE_SRC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FAKE_SRC))
typedef struct _GstFakeSrc GstFakeSrc;
typedef struct _GstFakeSrcClass GstFakeSrcClass;
/**
* GstFakeSrc:
*
* Opaque #GstFakeSrc data structure.
*/
struct _GstFakeSrc {
GstBaseSrc element;
/*< private >*/
gboolean has_loop;
gboolean has_getrange;
GstFakeSrcOutputType output;
GstFakeSrcDataType data;
GstFakeSrcSizeType sizetype;
GstFakeSrcFillType filltype;
guint sizemin;
guint sizemax;
GstBuffer *parent;
guint parentsize;
guint parentoffset;
guint8 pattern_byte;
gchar *pattern;
GList *patternlist;
gint datarate;
gboolean sync;
GstClock *clock;
gint num_buffers;
gint rt_num_buffers; /* we are going to change this at runtime */
gint64 buffer_count;
gboolean silent;
gboolean signal_handoffs;
gboolean dump;
gboolean can_activate_pull;
guint64 bytes_sent;
gchar *last_message;
};
struct _GstFakeSrcClass {
GstBaseSrcClass parent_class;
/*< public >*/
/* signals */
void (*handoff) (GstElement *element, GstBuffer *buf, GstPad *pad);
};
GType gst_fake_src_get_type (void);
G_END_DECLS
#endif /* __GST_FAKE_SRC_H__ */

View file

@ -1,170 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfdsink.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gstfdsink.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_fdsink_debug);
#define GST_CAT_DEFAULT gst_fdsink_debug
static GstElementDetails gst_fdsink_details =
GST_ELEMENT_DETAILS ("Filedescriptor Sink",
"Sink/File",
"Write data to a file descriptor",
"Erik Walthinsen <omega@cse.ogi.edu>");
/* FdSink signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0,
ARG_FD
};
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_fdsink_debug, "fdsink", 0, "fdsink element");
GST_BOILERPLATE_FULL (GstFdSink, gst_fdsink, GstElement, GST_TYPE_ELEMENT,
_do_init);
static void gst_fdsink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_fdsink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_fdsink_chain (GstPad * pad, GstData * _data);
static void
gst_fdsink_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (gstelement_class, &gst_fdsink_details);
}
static void
gst_fdsink_class_init (GstFdSinkClass * klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_fdsink_set_property;
gobject_class->get_property = gst_fdsink_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FD,
g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
0, G_MAXINT, 1, G_PARAM_READWRITE));
}
static void
gst_fdsink_init (GstFdSink * fdsink)
{
fdsink->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
"sink");
gst_element_add_pad (GST_ELEMENT (fdsink), fdsink->sinkpad);
gst_pad_set_chain_function (fdsink->sinkpad, gst_fdsink_chain);
fdsink->fd = 1;
}
static void
gst_fdsink_chain (GstPad * pad, GstData * _data)
{
GstBuffer *buf = GST_BUFFER (_data);
GstFdSink *fdsink;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
fdsink = GST_FDSINK (gst_pad_get_parent (pad));
g_return_if_fail (fdsink->fd >= 0);
if (GST_BUFFER_DATA (buf)) {
GST_DEBUG ("writing %d bytes to file descriptor %d", GST_BUFFER_SIZE (buf),
fdsink->fd);
write (fdsink->fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
}
gst_buffer_unref (buf);
}
static void
gst_fdsink_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
{
GstFdSink *fdsink;
g_return_if_fail (GST_IS_FDSINK (object));
fdsink = GST_FDSINK (object);
switch (prop_id) {
case ARG_FD:
fdsink->fd = g_value_get_int (value);
break;
default:
break;
}
}
static void
gst_fdsink_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstFdSink *fdsink;
g_return_if_fail (GST_IS_FDSINK (object));
fdsink = GST_FDSINK (object);
switch (prop_id) {
case ARG_FD:
g_value_set_int (value, fdsink->fd);
break;
default:
break;
}
}

View file

@ -1,62 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfdsink.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FDSINK_H__
#define __GST_FDSINK_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_FDSINK \
(gst_fdsink_get_type())
#define GST_FDSINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FDSINK,GstFdSink))
#define GST_FDSINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FDSINK,GstFdSinkClass))
#define GST_IS_FDSINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDSINK))
#define GST_IS_FDSINK_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSINK))
typedef struct _GstFdSink GstFdSink;
typedef struct _GstFdSinkClass GstFdSinkClass;
struct _GstFdSink {
GstElement element;
GstPad *sinkpad;
int fd;
};
struct _GstFdSinkClass {
GstElementClass parent_class;
};
GType gst_fdsink_get_type(void);
G_END_DECLS
#endif /* __GST_FDSINK_H__ */

View file

@ -1,494 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Philippe Khalaf <burger@speedy.org>
*
* gstfdsrc.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gst/gst_private.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _MSC_VER
#include <io.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include "gstfdsrc.h"
/* the select call is also performed on the control sockets, that way
* we can send special commands to unblock the select call */
#define CONTROL_STOP 'S' /* stop the select call */
#define CONTROL_SOCKETS(src) src->control_sock
#define WRITE_SOCKET(src) src->control_sock[1]
#define READ_SOCKET(src) src->control_sock[0]
#define SEND_COMMAND(src, command) \
G_STMT_START { \
unsigned char c; c = command; \
write (WRITE_SOCKET(src), &c, 1); \
} G_STMT_END
#define READ_COMMAND(src, command, res) \
G_STMT_START { \
res = read(READ_SOCKET(src), &command, 1); \
} G_STMT_END
#define DEFAULT_BLOCKSIZE 4096
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_fdsrc_debug);
#define GST_CAT_DEFAULT gst_fdsrc_debug
static GstElementDetails gst_fdsrc_details = GST_ELEMENT_DETAILS ("Disk Source",
"Source/File",
"Synchronous read from a file",
"Erik Walthinsen <omega@cse.ogi.edu>");
enum
{
PROP_0,
PROP_FD,
};
static void gst_fdsrc_uri_handler_init (gpointer g_iface, gpointer iface_data);
static void
_do_init (GType fdsrc_type)
{
static const GInterfaceInfo urihandler_info = {
gst_fdsrc_uri_handler_init,
NULL,
NULL
};
g_type_add_interface_static (fdsrc_type, GST_TYPE_URI_HANDLER,
&urihandler_info);
GST_DEBUG_CATEGORY_INIT (gst_fdsrc_debug, "fdsrc", 0, "fdsrc element");
}
GST_BOILERPLATE_FULL (GstFdSrc, gst_fdsrc, GstElement, GST_TYPE_PUSH_SRC,
_do_init);
static void gst_fdsrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_fdsrc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_fdsrc_dispose (GObject * obj);
static gboolean gst_fdsrc_start (GstBaseSrc * bsrc);
static gboolean gst_fdsrc_stop (GstBaseSrc * bsrc);
static gboolean gst_fdsrc_unlock (GstBaseSrc * bsrc);
static gboolean gst_fdsrc_is_seekable (GstBaseSrc * bsrc);
static gboolean gst_fdsrc_get_size (GstBaseSrc * src, guint64 * size);
static GstFlowReturn gst_fdsrc_create (GstPushSrc * psrc, GstBuffer ** outbuf);
static void
gst_fdsrc_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_set_details (gstelement_class, &gst_fdsrc_details);
}
static void
gst_fdsrc_class_init (GstFdSrcClass * klass)
{
GObjectClass *gobject_class;
GstBaseSrcClass *gstbasesrc_class;
GstElementClass *gstelement_class;
GstPushSrcClass *gstpush_src_class;
gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
gstbasesrc_class = (GstBaseSrcClass *) klass;
gstpush_src_class = (GstPushSrcClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_PUSH_SRC);
gobject_class->set_property = gst_fdsrc_set_property;
gobject_class->get_property = gst_fdsrc_get_property;
gobject_class->dispose = gst_fdsrc_dispose;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FD,
g_param_spec_int ("fd", "fd", "An open file descriptor to read from",
0, G_MAXINT, 0, G_PARAM_READWRITE));
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_fdsrc_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_fdsrc_stop);
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_fdsrc_unlock);
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fdsrc_is_seekable);
gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_fdsrc_get_size);
gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_fdsrc_create);
}
static void
gst_fdsrc_init (GstFdSrc * fdsrc, GstFdSrcClass * klass)
{
fdsrc->fd = 0;
fdsrc->new_fd = 0;
fdsrc->seekable_fd = FALSE;
fdsrc->uri = g_strdup_printf ("fd://%d", fdsrc->fd);
fdsrc->curoffset = 0;
}
static void
gst_fdsrc_dispose (GObject * obj)
{
GstFdSrc *src = GST_FDSRC (obj);
g_free (src->uri);
src->uri = NULL;
G_OBJECT_CLASS (parent_class)->dispose (obj);
}
static void
gst_fdsrc_update_fd (GstFdSrc * src)
{
struct stat stat_results;
src->fd = src->new_fd;
g_free (src->uri);
src->uri = g_strdup_printf ("fd://%d", src->fd);
if (fstat (src->fd, &stat_results) < 0)
goto not_seekable;
if (!S_ISREG (stat_results.st_mode))
goto not_seekable;
/* Try a seek of 0 bytes offset to check for seekability */
if (lseek (src->fd, SEEK_CUR, 0) < 0)
goto not_seekable;
src->seekable_fd = TRUE;
return;
not_seekable:
src->seekable_fd = FALSE;
}
static gboolean
gst_fdsrc_start (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FDSRC (bsrc);
gint control_sock[2];
src->curoffset = 0;
gst_fdsrc_update_fd (src);
if (socketpair (PF_UNIX, SOCK_STREAM, 0, control_sock) < 0)
goto socket_pair;
READ_SOCKET (src) = control_sock[0];
WRITE_SOCKET (src) = control_sock[1];
fcntl (READ_SOCKET (src), F_SETFL, O_NONBLOCK);
fcntl (WRITE_SOCKET (src), F_SETFL, O_NONBLOCK);
return TRUE;
/* ERRORS */
socket_pair:
{
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL),
GST_ERROR_SYSTEM);
return FALSE;
}
}
static gboolean
gst_fdsrc_stop (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FDSRC (bsrc);
close (READ_SOCKET (src));
close (WRITE_SOCKET (src));
return TRUE;
}
static gboolean
gst_fdsrc_unlock (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FDSRC (bsrc);
SEND_COMMAND (src, CONTROL_STOP);
return TRUE;
}
static void
gst_fdsrc_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
{
GstFdSrc *src = GST_FDSRC (object);
switch (prop_id) {
case PROP_FD:
src->new_fd = g_value_get_int (value);
/* If state is ready or below, update the current fd immediately
* so it is reflected in get_properties and uri */
GST_OBJECT_LOCK (object);
if (GST_STATE (GST_ELEMENT (src)) <= GST_STATE_READY) {
gst_fdsrc_update_fd (src);
}
GST_OBJECT_UNLOCK (object);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_fdsrc_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstFdSrc *src = GST_FDSRC (object);
switch (prop_id) {
case PROP_FD:
g_value_set_int (value, src->fd);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstFlowReturn
gst_fdsrc_create (GstPushSrc * psrc, GstBuffer ** outbuf)
{
GstFdSrc *src;
GstBuffer *buf;
glong readbytes;
guint blocksize;
#ifndef HAVE_WIN32
fd_set readfds;
gint retval;
#endif
src = GST_FDSRC (psrc);
#ifndef HAVE_WIN32
FD_ZERO (&readfds);
FD_SET (src->fd, &readfds);
FD_SET (READ_SOCKET (src), &readfds);
do {
retval = select (FD_SETSIZE, &readfds, NULL, NULL, NULL);
} while ((retval == -1 && errno == EINTR));
if (retval == -1)
goto select_error;
if (FD_ISSET (READ_SOCKET (src), &readfds)) {
/* read all stop commands */
while (TRUE) {
gchar command;
int res;
READ_COMMAND (src, command, res);
if (res < 0) {
GST_LOG_OBJECT (src, "no more commands");
/* no more commands */
break;
}
}
goto stopped;
}
#endif
blocksize = GST_BASE_SRC (src)->blocksize;
/* create the buffer */
buf = gst_buffer_new_and_alloc (blocksize);
do {
readbytes = read (src->fd, GST_BUFFER_DATA (buf), blocksize);
} while (readbytes == -1 && errno == EINTR); /* retry if interrupted */
if (readbytes < 0)
goto read_error;
if (readbytes == 0)
goto eos;
GST_BUFFER_OFFSET (buf) = src->curoffset;
GST_BUFFER_SIZE (buf) = readbytes;
GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
src->curoffset += readbytes;
GST_DEBUG_OBJECT (psrc, "Read buffer of size %u.", readbytes);
/* we're done, return the buffer */
*outbuf = buf;
return GST_FLOW_OK;
/* ERRORS */
#ifndef HAVE_WIN32
select_error:
{
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
("select on file descriptor: %s.", g_strerror (errno)));
GST_DEBUG_OBJECT (psrc, "Error during select");
return GST_FLOW_ERROR;
}
stopped:
{
GST_DEBUG_OBJECT (psrc, "Select stopped");
return GST_FLOW_WRONG_STATE;
}
#endif
eos:
{
GST_DEBUG_OBJECT (psrc, "Read 0 bytes. EOS.");
gst_buffer_unref (buf);
return GST_FLOW_UNEXPECTED;
}
read_error:
{
GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
("read on file descriptor: %s.", g_strerror (errno)));
GST_DEBUG_OBJECT (psrc, "Error reading from fd");
gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
}
gboolean
gst_fdsrc_is_seekable (GstBaseSrc * bsrc)
{
GstFdSrc *src = GST_FDSRC (bsrc);
return src->seekable_fd;
}
gboolean
gst_fdsrc_get_size (GstBaseSrc * bsrc, guint64 * size)
{
GstFdSrc *src = GST_FDSRC (bsrc);
struct stat stat_results;
if (!src->seekable_fd) {
/* If it isn't seekable, we won't know the length (but fstat will still
* succeed, and wrongly say our length is zero. */
return FALSE;
}
if (fstat (src->fd, &stat_results) < 0)
goto could_not_stat;
*size = stat_results.st_size;
return TRUE;
/* ERROR */
could_not_stat:
{
return FALSE;
}
}
/*** GSTURIHANDLER INTERFACE *************************************************/
static guint
gst_fdsrc_uri_get_type (void)
{
return GST_URI_SRC;
}
static gchar **
gst_fdsrc_uri_get_protocols (void)
{
static gchar *protocols[] = { "fd", NULL };
return protocols;
}
static const gchar *
gst_fdsrc_uri_get_uri (GstURIHandler * handler)
{
GstFdSrc *src = GST_FDSRC (handler);
return src->uri;
}
static gboolean
gst_fdsrc_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
gchar *protocol;
GstFdSrc *src = GST_FDSRC (handler);
gint fd;
protocol = gst_uri_get_protocol (uri);
if (strcmp (protocol, "fd") != 0) {
g_free (protocol);
return FALSE;
}
g_free (protocol);
if (sscanf (uri, "fd://%d", &fd) != 1)
return FALSE;
src->new_fd = fd;
GST_OBJECT_LOCK (src);
if (GST_STATE (GST_ELEMENT (src)) <= GST_STATE_READY) {
gst_fdsrc_update_fd (src);
}
GST_OBJECT_UNLOCK (src);
return TRUE;
}
static void
gst_fdsrc_uri_handler_init (gpointer g_iface, gpointer iface_data)
{
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
iface->get_type = gst_fdsrc_uri_get_type;
iface->get_protocols = gst_fdsrc_uri_get_protocols;
iface->get_uri = gst_fdsrc_uri_get_uri;
iface->set_uri = gst_fdsrc_uri_set_uri;
}

View file

@ -1,77 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Philippe Khalaf <burger@speedy.org>
*
* gstfdsrc.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FDSRC_H__
#define __GST_FDSRC_H__
#include <gst/gst.h>
#include <gst/base/gstpushsrc.h>
G_BEGIN_DECLS
#define GST_TYPE_FDSRC \
(gst_fdsrc_get_type())
#define GST_FDSRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FDSRC,GstFdSrc))
#define GST_FDSRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FDSRC,GstFdSrcClass))
#define GST_IS_FDSRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDSRC))
#define GST_IS_FDSRC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDSRC))
typedef struct _GstFdSrc GstFdSrc;
typedef struct _GstFdSrcClass GstFdSrcClass;
struct _GstFdSrc {
GstPushSrc element;
/* new_fd is copied to fd on READY->PAUSED */
gint new_fd;
/* fd and flag indicating whether fd is seekable */
gint fd;
gboolean seekable_fd;
gchar *uri;
gint control_sock[2];
gulong curoffset; /* current offset in file */
};
struct _GstFdSrcClass {
GstPushSrcClass parent_class;
/* signals */
void (*timeout) (GstElement *element);
};
GType gst_fdsrc_get_type(void);
G_END_DECLS
#endif /* __GST_FDSRC_H__ */

View file

@ -1,495 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfilesink.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:gstfilesink
* @short_description: write stream to a file
* @see_also: #GstFileSrc
*
* Write incoming data to a file in the local file system.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "../gst-i18n-lib.h"
#include <gst/gst.h>
#include <errno.h>
#include "gstfilesink.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_file_sink_debug);
#define GST_CAT_DEFAULT gst_file_sink_debug
static GstElementDetails gst_file_sink_details =
GST_ELEMENT_DETAILS ("File Sink",
"Sink/File",
"Write stream to a file",
"Thomas <thomas@apestaart.org>");
enum
{
ARG_0,
ARG_LOCATION
};
static void gst_file_sink_dispose (GObject * object);
static void gst_file_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_file_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_file_sink_open_file (GstFileSink * sink);
static void gst_file_sink_close_file (GstFileSink * sink);
static gboolean gst_file_sink_start (GstBaseSink * sink);
static gboolean gst_file_sink_stop (GstBaseSink * sink);
static gboolean gst_file_sink_event (GstBaseSink * sink, GstEvent * event);
static GstFlowReturn gst_file_sink_render (GstBaseSink * sink,
GstBuffer * buffer);
static gboolean gst_file_sink_query (GstPad * pad, GstQuery * query);
static void gst_file_sink_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static void
_do_init (GType filesink_type)
{
static const GInterfaceInfo urihandler_info = {
gst_file_sink_uri_handler_init,
NULL,
NULL
};
g_type_add_interface_static (filesink_type, GST_TYPE_URI_HANDLER,
&urihandler_info);
GST_DEBUG_CATEGORY_INIT (gst_file_sink_debug, "filesink", 0,
"filesink element");
}
GST_BOILERPLATE_FULL (GstFileSink, gst_file_sink, GstBaseSink,
GST_TYPE_BASE_SINK, _do_init);
static void
gst_file_sink_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (gstelement_class, &gst_file_sink_details);
}
static void
gst_file_sink_class_init (GstFileSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
gobject_class->set_property = gst_file_sink_set_property;
gobject_class->get_property = gst_file_sink_get_property;
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION,
g_param_spec_string ("location", "File Location",
"Location of the file to write", NULL, G_PARAM_READWRITE));
gobject_class->dispose = gst_file_sink_dispose;
gstbasesink_class->get_times = NULL;
gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_file_sink_start);
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_file_sink_stop);
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_file_sink_render);
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_file_sink_event);
if (sizeof (off_t) < 8) {
GST_LOG ("No large file support, sizeof (off_t) = %u", sizeof (off_t));
}
}
static void
gst_file_sink_init (GstFileSink * filesink, GstFileSinkClass * g_class)
{
GstPad *pad;
pad = GST_BASE_SINK_PAD (filesink);
gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_file_sink_query));
filesink->filename = NULL;
filesink->file = NULL;
GST_BASE_SINK (filesink)->sync = FALSE;
}
static void
gst_file_sink_dispose (GObject * object)
{
GstFileSink *sink = GST_FILE_SINK (object);
G_OBJECT_CLASS (parent_class)->dispose (object);
g_free (sink->uri);
sink->uri = NULL;
g_free (sink->filename);
sink->filename = NULL;
}
static gboolean
gst_file_sink_set_location (GstFileSink * sink, const gchar * location)
{
if (sink->file) {
g_warning ("Changing the `location' property on filesink when "
"a file is open not supported.");
return FALSE;
}
g_free (sink->filename);
g_free (sink->uri);
if (location != NULL) {
sink->filename = g_strdup (location);
sink->uri = gst_uri_construct ("file", location);
} else {
sink->filename = NULL;
sink->uri = NULL;
}
return TRUE;
}
static void
gst_file_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstFileSink *sink = GST_FILE_SINK (object);
switch (prop_id) {
case ARG_LOCATION:
gst_file_sink_set_location (sink, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_file_sink_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstFileSink *sink = GST_FILE_SINK (object);
switch (prop_id) {
case ARG_LOCATION:
g_value_set_string (value, sink->filename);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_file_sink_open_file (GstFileSink * sink)
{
/* open the file */
if (sink->filename == NULL || sink->filename[0] == '\0') {
GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
(_("No file name specified for writing.")), (NULL));
return FALSE;
}
sink->file = fopen (sink->filename, "wb");
if (sink->file == NULL) {
GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
(_("Could not open file \"%s\" for writing."), sink->filename),
GST_ERROR_SYSTEM);
return FALSE;
}
sink->data_written = 0;
return TRUE;
}
static void
gst_file_sink_close_file (GstFileSink * sink)
{
if (sink->file) {
if (fclose (sink->file) != 0) {
GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
(_("Error closing file \"%s\"."), sink->filename), GST_ERROR_SYSTEM);
}
}
}
static gboolean
gst_file_sink_query (GstPad * pad, GstQuery * query)
{
GstFileSink *self;
GstFormat format;
self = GST_FILE_SINK (GST_PAD_PARENT (pad));
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
gst_query_parse_position (query, &format, NULL);
switch (format) {
case GST_FORMAT_DEFAULT:
case GST_FORMAT_BYTES:
gst_query_set_position (query, GST_FORMAT_BYTES, self->data_written);
return TRUE;
default:
return FALSE;
}
case GST_QUERY_FORMATS:
gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
return TRUE;
default:
return gst_pad_query_default (pad, query);
}
}
#if HAVE_FSEEKO
# define __GST_STDIO_SEEK_FUNCTION "fseeko"
#elif G_OS_UNIX
# define __GST_STDIO_SEEK_FUNCTION "lseek"
#else
# define __GST_STDIO_SEEK_FUNCTION "fseek"
#endif
static void
gst_file_sink_do_seek (GstFileSink * filesink, guint64 new_offset)
{
GST_DEBUG_OBJECT (filesink, "Seeking to offset %" G_GUINT64_FORMAT
" using " __GST_STDIO_SEEK_FUNCTION, new_offset);
if (fflush (filesink->file))
goto flush_failed;
#if HAVE_FSEEKO
if (fseeko (filesink->file, (off_t) new_offset, SEEK_SET) != 0)
goto seek_failed;
#elif G_OS_UNIX
if (lseek (fileno (filesink->file), (off_t) new_offset,
SEEK_SET) == (off_t) - 1)
goto seek_failed;
#else
if (fseek (filesink->file, (long) new_offset, SEEK_SET) != 0)
goto seek_failed;
#endif
return;
/* ERRORS */
flush_failed:
{
GST_DEBUG_OBJECT (filesink, "Flush failed: %s", g_strerror (errno));
return;
}
seek_failed:
{
GST_DEBUG_OBJECT (filesink, "Seeking failed: %s", g_strerror (errno));
return;
}
}
/* handle events (search) */
static gboolean
gst_file_sink_event (GstBaseSink * sink, GstEvent * event)
{
GstEventType type;
GstFileSink *filesink;
filesink = GST_FILE_SINK (sink);
type = GST_EVENT_TYPE (event);
switch (type) {
case GST_EVENT_NEWSEGMENT:
{
gint64 soffset, eoffset;
GstFormat format;
gst_event_parse_new_segment (event, NULL, NULL, &format, &soffset,
&eoffset, NULL);
if (format == GST_FORMAT_BYTES) {
gst_file_sink_do_seek (filesink, (guint64) soffset);
} else {
GST_DEBUG ("Ignored NEWSEGMENT event of format %u", (guint) format);
}
break;
}
case GST_EVENT_EOS:
if (fflush (filesink->file)) {
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
GST_ERROR_SYSTEM);
}
break;
default:
break;
}
return TRUE;
}
static gboolean
gst_file_sink_get_current_offset (GstFileSink * filesink, guint64 * p_pos)
{
off_t ret;
#if HAVE_FTELLO
ret = ftello (filesink->file);
#elif G_OS_UNIX
if (fflush (filesink->file)) {
GST_DEBUG_OBJECT (filesink, "Flush failed: %s", g_strerror (errno));
/* ignore and continue */
}
ret = lseek (fileno (filesink->file), 0, SEEK_CUR);
#else
ret = (off_t) ftell (filesink->file);
#endif
*p_pos = (guint64) ret;
return (ret != (off_t) - 1);
}
static GstFlowReturn
gst_file_sink_render (GstBaseSink * sink, GstBuffer * buffer)
{
GstFileSink *filesink;
guint64 cur_pos;
guint size;
guint64 back_pending = 0;
size = GST_BUFFER_SIZE (buffer);
filesink = GST_FILE_SINK (sink);
if (!gst_file_sink_get_current_offset (filesink, &cur_pos))
goto handle_error;
if (cur_pos < filesink->data_written)
back_pending = filesink->data_written - cur_pos;
GST_DEBUG_OBJECT (filesink, "writing %u bytes at %" G_GUINT64_FORMAT,
size, cur_pos);
if (fwrite (GST_BUFFER_DATA (buffer), size, 1, filesink->file) != 1)
goto handle_error;
filesink->data_written += size - back_pending;
return GST_FLOW_OK;
handle_error:
GST_ELEMENT_ERROR (filesink, RESOURCE, WRITE,
(_("Error while writing to file \"%s\"."), filesink->filename),
("%s", g_strerror (errno)));
return GST_FLOW_ERROR;
}
static gboolean
gst_file_sink_start (GstBaseSink * basesink)
{
return gst_file_sink_open_file (GST_FILE_SINK (basesink));
}
static gboolean
gst_file_sink_stop (GstBaseSink * basesink)
{
gst_file_sink_close_file (GST_FILE_SINK (basesink));
return TRUE;
}
/*** GSTURIHANDLER INTERFACE *************************************************/
static guint
gst_file_sink_uri_get_type (void)
{
return GST_URI_SINK;
}
static gchar **
gst_file_sink_uri_get_protocols (void)
{
static gchar *protocols[] = { "file", NULL };
return protocols;
}
static const gchar *
gst_file_sink_uri_get_uri (GstURIHandler * handler)
{
GstFileSink *sink = GST_FILE_SINK (handler);
return sink->uri;
}
static gboolean
gst_file_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
{
gchar *protocol, *location;
gboolean ret;
GstFileSink *sink = GST_FILE_SINK (handler);
protocol = gst_uri_get_protocol (uri);
if (strcmp (protocol, "file") != 0) {
g_free (protocol);
return FALSE;
}
g_free (protocol);
location = gst_uri_get_location (uri);
ret = gst_file_sink_set_location (sink, location);
g_free (location);
return ret;
}
static void
gst_file_sink_uri_handler_init (gpointer g_iface, gpointer iface_data)
{
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
iface->get_type = gst_file_sink_uri_get_type;
iface->get_protocols = gst_file_sink_uri_get_protocols;
iface->get_uri = gst_file_sink_uri_get_uri;
iface->set_uri = gst_file_sink_uri_set_uri;
}

View file

@ -1,70 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstfilesink.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FILE_SINK_H__
#define __GST_FILE_SINK_H__
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
#define GST_TYPE_FILE_SINK \
(gst_file_sink_get_type())
#define GST_FILE_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILE_SINK,GstFileSink))
#define GST_FILE_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILE_SINK,GstFileSinkClass))
#define GST_IS_FILE_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILE_SINK))
#define GST_IS_FILE_SINK_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILE_SINK))
typedef struct _GstFileSink GstFileSink;
typedef struct _GstFileSinkClass GstFileSinkClass;
/**
* GstFileSink:
*
* Opaque #GstFileSink structure.
*/
struct _GstFileSink {
GstBaseSink parent;
/*< private >*/
gchar *filename;
gchar *uri;
FILE *file;
guint64 data_written;
};
struct _GstFileSinkClass {
GstBaseSinkClass parent_class;
};
GType gst_file_sink_get_type(void);
G_END_DECLS
#endif /* __GST_FILE_SINK_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,81 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstfilesrc.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_FILE_SRC_H__
#define __GST_FILE_SRC_H__
#include <sys/types.h>
#include <gst/gst.h>
#include <gst/base/gstbasesrc.h>
G_BEGIN_DECLS
#define GST_TYPE_FILE_SRC \
(gst_file_src_get_type())
#define GST_FILE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILE_SRC,GstFileSrc))
#define GST_FILE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILE_SRC,GstFileSrcClass))
#define GST_IS_FILE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILE_SRC))
#define GST_IS_FILE_SRC_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILE_SRC))
typedef struct _GstFileSrc GstFileSrc;
typedef struct _GstFileSrcClass GstFileSrcClass;
/**
* GstFileSrc:
*
* Opaque #GstFileSrc structure.
*/
struct _GstFileSrc {
GstBaseSrc element;
/*< private >*/
guint pagesize; /* system page size */
gchar *filename; /* filename */
gchar *uri; /* caching the URI */
gint fd; /* open file descriptor */
guint64 read_position; /* position of fd */
gboolean touch; /* whether to touch every page */
gboolean using_mmap; /* whether we opened it with mmap */
gboolean seekable; /* whether the file is seekable */
gboolean is_regular; /* whether it's a (symlink to a)
regular file */
GstBuffer *mapbuf;
size_t mapsize;
};
struct _GstFileSrcClass {
GstBaseSrcClass parent_class;
};
GType gst_file_src_get_type (void);
G_END_DECLS
#endif /* __GST_FILE_SRC_H__ */

View file

@ -1,567 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2005 Wim Taymans <wim@fluendo.com>
*
* gstidentity.c:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "../gst-i18n-lib.h"
#include "gstidentity.h"
#include <gst/gstmarshal.h>
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_identity_debug);
#define GST_CAT_DEFAULT gst_identity_debug
static GstElementDetails gst_identity_details = GST_ELEMENT_DETAILS ("Identity",
"Generic",
"Pass data without modification",
"Erik Walthinsen <omega@cse.ogi.edu>");
/* Identity signals and args */
enum
{
SIGNAL_HANDOFF,
/* FILL ME */
LAST_SIGNAL
};
#define DEFAULT_SLEEP_TIME 0
#define DEFAULT_DUPLICATE 1
#define DEFAULT_ERROR_AFTER -1
#define DEFAULT_DROP_PROBABILITY 0.0
#define DEFAULT_DATARATE 0
#define DEFAULT_SILENT FALSE
#define DEFAULT_SINGLE_SEGMENT FALSE
#define DEFAULT_DUMP FALSE
#define DEFAULT_SYNC FALSE
#define DEFAULT_CHECK_PERFECT FALSE
enum
{
PROP_0,
PROP_SLEEP_TIME,
PROP_ERROR_AFTER,
PROP_DROP_PROBABILITY,
PROP_DATARATE,
PROP_SILENT,
PROP_SINGLE_SEGMENT,
PROP_LAST_MESSAGE,
PROP_DUMP,
PROP_SYNC,
PROP_CHECK_PERFECT
};
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_identity_debug, "identity", 0, "identity element");
GST_BOILERPLATE_FULL (GstIdentity, gst_identity, GstBaseTransform,
GST_TYPE_BASE_TRANSFORM, _do_init);
static void gst_identity_finalize (GObject * object);
static void gst_identity_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_identity_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_identity_event (GstBaseTransform * trans, GstEvent * event);
static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans,
GstBuffer * buf);
static gboolean gst_identity_start (GstBaseTransform * trans);
static gboolean gst_identity_stop (GstBaseTransform * trans);
static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
static void
gst_identity_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (gstelement_class, &gst_identity_details);
}
static void
gst_identity_finalize (GObject * object)
{
GstIdentity *identity;
identity = GST_IDENTITY (object);
g_free (identity->last_message);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/* fixme: do something about this */
static void
marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value,
guint n_param_values, const GValue * param_values, gpointer invocation_hint,
gpointer marshal_data)
{
typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1,
gpointer data2);
register marshalfunc_VOID__MINIOBJECT callback;
register GCClosure *cc = (GCClosure *) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 2);
if (G_CCLOSURE_SWAP_DATA (closure)) {
data1 = closure->data;
data2 = g_value_peek_pointer (param_values + 0);
} else {
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
}
callback =
(marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : cc->
callback);
callback (data1, gst_value_get_mini_object (param_values + 1), data2);
}
static void
gst_identity_class_init (GstIdentityClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseTransformClass *gstbasetrans_class;
gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SLEEP_TIME,
g_param_spec_uint ("sleep-time", "Sleep time",
"Microseconds to sleep between processing", 0, G_MAXUINT,
DEFAULT_SLEEP_TIME, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ERROR_AFTER,
g_param_spec_int ("error_after", "Error After", "Error after N buffers",
G_MININT, G_MAXINT, DEFAULT_ERROR_AFTER, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_DROP_PROBABILITY, g_param_spec_float ("drop_probability",
"Drop Probability", "The Probability a buffer is dropped", 0.0, 1.0,
DEFAULT_DROP_PROBABILITY, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DATARATE,
g_param_spec_int ("datarate", "Datarate",
"(Re)timestamps buffers with number of bytes per second (0 = inactive)",
0, G_MAXINT, DEFAULT_DATARATE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SINGLE_SEGMENT,
g_param_spec_boolean ("single-segment", "Single Segment",
"Timestamp buffers and eat newsegments so as to appear as one segment",
DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last-message", "last-message", "last-message", NULL,
G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
g_param_spec_boolean ("dump", "Dump", "Dump buffer contents",
DEFAULT_DUMP, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SYNC,
g_param_spec_boolean ("sync", "Synchronize",
"Synchronize to pipeline clock", DEFAULT_SYNC, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CHECK_PERFECT,
g_param_spec_boolean ("check-perfect", "Check For Perfect Stream",
"Verify that the stream is time- and data-contiguous",
DEFAULT_CHECK_PERFECT, G_PARAM_READWRITE));
gst_identity_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL,
marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_BUFFER);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_identity_finalize);
gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_identity_event);
gstbasetrans_class->transform_ip =
GST_DEBUG_FUNCPTR (gst_identity_transform_ip);
gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start);
gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop);
}
static void
gst_identity_init (GstIdentity * identity, GstIdentityClass * g_class)
{
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE);
identity->sleep_time = DEFAULT_SLEEP_TIME;
identity->error_after = DEFAULT_ERROR_AFTER;
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
identity->datarate = DEFAULT_DATARATE;
identity->silent = DEFAULT_SILENT;
identity->single_segment = DEFAULT_SINGLE_SEGMENT;
identity->sync = DEFAULT_SYNC;
identity->check_perfect = DEFAULT_CHECK_PERFECT;
identity->dump = DEFAULT_DUMP;
identity->last_message = NULL;
}
static gboolean
gst_identity_event (GstBaseTransform * trans, GstEvent * event)
{
GstIdentity *identity;
gboolean ret = TRUE;
identity = GST_IDENTITY (trans);
if (!identity->silent) {
const GstStructure *s;
gchar *sstr;
GST_OBJECT_LOCK (identity);
g_free (identity->last_message);
if ((s = gst_event_get_structure (event)))
sstr = gst_structure_to_string (s);
else
sstr = g_strdup ("");
identity->last_message =
g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p",
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), sstr,
event);
g_free (sstr);
GST_OBJECT_UNLOCK (identity);
g_object_notify (G_OBJECT (identity), "last_message");
}
if (identity->single_segment
&& (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
if (trans->have_newsegment == FALSE) {
GstEvent *news;
GstFormat format;
gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
NULL);
/* This is the first newsegment, send out a (0, -1) newsegment */
news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);
if (!(gst_pad_event_default (trans->sinkpad, news)))
return FALSE;
}
}
GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event);
if (identity->single_segment
&& (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
/* eat up segments */
ret = FALSE;
}
return ret;
}
static void
gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf)
{
GstClockTime timestamp;
timestamp = GST_BUFFER_TIMESTAMP (buf);
/* see if we need to do perfect stream checking */
/* invalid timestamp drops us out of check. FIXME: maybe warn ? */
if (timestamp != GST_CLOCK_TIME_NONE) {
/* check if we had a previous buffer to compare to */
if (identity->prev_timestamp != GST_CLOCK_TIME_NONE) {
guint64 offset;
if (identity->prev_timestamp + identity->prev_duration != timestamp) {
GST_WARNING_OBJECT (identity,
"Buffer not time-contiguous with previous one: " "prev ts %"
GST_TIME_FORMAT ", prev dur %" GST_TIME_FORMAT ", new ts %"
GST_TIME_FORMAT, GST_TIME_ARGS (identity->prev_timestamp),
GST_TIME_ARGS (identity->prev_duration), GST_TIME_ARGS (timestamp));
}
offset = GST_BUFFER_OFFSET (buf);
if (identity->prev_offset_end != offset) {
GST_WARNING_OBJECT (identity,
"Buffer not data-contiguous with previous one: "
"prev offset_end %" G_GINT64_FORMAT ", new offset %"
G_GINT64_FORMAT, identity->prev_offset_end, offset);
}
}
/* update prev values */
identity->prev_timestamp = timestamp;
identity->prev_duration = GST_BUFFER_DURATION (buf);
identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf);
}
}
static GstFlowReturn
gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
{
GstFlowReturn ret = GST_FLOW_OK;
GstIdentity *identity = GST_IDENTITY (trans);
GstClockTime runtimestamp = 0LL;
if (identity->check_perfect)
gst_identity_check_perfect (identity, buf);
if (identity->error_after >= 0) {
identity->error_after--;
if (identity->error_after == 0) {
GST_ELEMENT_ERROR (identity, CORE, FAILED,
(_("Failed after iterations as requested.")), (NULL));
return GST_FLOW_ERROR;
}
}
if (identity->drop_probability > 0.0) {
if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
GST_OBJECT_LOCK (identity);
g_free (identity->last_message);
identity->last_message =
g_strdup_printf ("dropping ******* (%s:%s)i (%d bytes, timestamp: %"
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
GST_BUFFER_FLAGS (buf), buf);
GST_OBJECT_UNLOCK (identity);
g_object_notify (G_OBJECT (identity), "last-message");
return GST_FLOW_OK;
}
}
if (identity->dump) {
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
}
if (!identity->silent) {
GST_OBJECT_LOCK (identity);
g_free (identity->last_message);
identity->last_message =
g_strdup_printf ("chain ******* (%s:%s)i (%d bytes, timestamp: %"
GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
GST_BUFFER_FLAGS (buf), buf);
GST_OBJECT_UNLOCK (identity);
g_object_notify (G_OBJECT (identity), "last-message");
}
if (identity->datarate > 0) {
GstClockTime time = identity->offset * GST_SECOND / identity->datarate;
GST_BUFFER_TIMESTAMP (buf) = time;
GST_BUFFER_DURATION (buf) =
GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
}
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
buf);
if (trans->segment.format == GST_FORMAT_TIME)
runtimestamp = gst_segment_to_running_time (&trans->segment,
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
if ((identity->sync) && (trans->segment.format == GST_FORMAT_TIME)) {
GstClock *clock;
GST_OBJECT_LOCK (identity);
if ((clock = GST_ELEMENT (identity)->clock)) {
GstClockReturn cret;
GstClockTime timestamp;
timestamp = runtimestamp + GST_ELEMENT (identity)->base_time;
/* save id if we need to unlock */
/* FIXME: actually unlock this somewhere in the state changes */
identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp);
GST_OBJECT_UNLOCK (identity);
cret = gst_clock_id_wait (identity->clock_id, NULL);
GST_OBJECT_LOCK (identity);
if (identity->clock_id) {
gst_clock_id_unref (identity->clock_id);
identity->clock_id = NULL;
}
if (cret == GST_CLOCK_UNSCHEDULED)
ret = GST_FLOW_UNEXPECTED;
}
GST_OBJECT_UNLOCK (identity);
}
identity->offset += GST_BUFFER_SIZE (buf);
if (identity->sleep_time && ret == GST_FLOW_OK)
g_usleep (identity->sleep_time);
if (identity->single_segment && (trans->segment.format == GST_FORMAT_TIME)
&& (ret == GST_FLOW_OK))
GST_BUFFER_TIMESTAMP (buf) = runtimestamp;
return ret;
}
static void
gst_identity_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstIdentity *identity;
identity = GST_IDENTITY (object);
switch (prop_id) {
case PROP_SLEEP_TIME:
identity->sleep_time = g_value_get_uint (value);
break;
case PROP_SILENT:
identity->silent = g_value_get_boolean (value);
break;
case PROP_SINGLE_SEGMENT:
identity->single_segment = g_value_get_boolean (value);
break;
case PROP_DUMP:
identity->dump = g_value_get_boolean (value);
break;
case PROP_ERROR_AFTER:
identity->error_after = g_value_get_int (value);
break;
case PROP_DROP_PROBABILITY:
identity->drop_probability = g_value_get_float (value);
break;
case PROP_DATARATE:
identity->datarate = g_value_get_int (value);
break;
case PROP_SYNC:
identity->sync = g_value_get_boolean (value);
break;
case PROP_CHECK_PERFECT:
identity->check_perfect = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_identity_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstIdentity *identity;
identity = GST_IDENTITY (object);
switch (prop_id) {
case PROP_SLEEP_TIME:
g_value_set_uint (value, identity->sleep_time);
break;
case PROP_ERROR_AFTER:
g_value_set_int (value, identity->error_after);
break;
case PROP_DROP_PROBABILITY:
g_value_set_float (value, identity->drop_probability);
break;
case PROP_DATARATE:
g_value_set_int (value, identity->datarate);
break;
case PROP_SILENT:
g_value_set_boolean (value, identity->silent);
break;
case PROP_SINGLE_SEGMENT:
g_value_set_boolean (value, identity->single_segment);
break;
case PROP_DUMP:
g_value_set_boolean (value, identity->dump);
break;
case PROP_LAST_MESSAGE:
GST_OBJECT_LOCK (identity);
g_value_set_string (value, identity->last_message);
GST_OBJECT_UNLOCK (identity);
break;
case PROP_SYNC:
g_value_set_boolean (value, identity->sync);
break;
case PROP_CHECK_PERFECT:
g_value_set_boolean (value, identity->check_perfect);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_identity_start (GstBaseTransform * trans)
{
GstIdentity *identity;
identity = GST_IDENTITY (trans);
identity->offset = 0;
identity->prev_timestamp = GST_CLOCK_TIME_NONE;
identity->prev_duration = GST_CLOCK_TIME_NONE;
identity->prev_offset_end = -1;
return TRUE;
}
static gboolean
gst_identity_stop (GstBaseTransform * trans)
{
GstIdentity *identity;
identity = GST_IDENTITY (trans);
GST_OBJECT_LOCK (identity);
g_free (identity->last_message);
identity->last_message = NULL;
GST_OBJECT_UNLOCK (identity);
return TRUE;
}

View file

@ -1,79 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gstidentity.h:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_IDENTITY_H__
#define __GST_IDENTITY_H__
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
G_BEGIN_DECLS
#define GST_TYPE_IDENTITY \
(gst_identity_get_type())
#define GST_IDENTITY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IDENTITY,GstIdentity))
#define GST_IDENTITY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IDENTITY,GstIdentityClass))
#define GST_IS_IDENTITY(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IDENTITY))
#define GST_IS_IDENTITY_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY))
typedef struct _GstIdentity GstIdentity;
typedef struct _GstIdentityClass GstIdentityClass;
struct _GstIdentity {
GstBaseTransform element;
GstClockID clock_id;
gint error_after;
gfloat drop_probability;
gint datarate;
guint sleep_time;
gboolean silent;
gboolean dump;
gboolean sync;
gboolean check_perfect;
gboolean single_segment;
GstClockTime prev_timestamp;
GstClockTime prev_duration;
guint64 prev_offset_end;
gchar *last_message;
guint64 offset;
};
struct _GstIdentityClass {
GstBaseTransformClass parent_class;
/* signals */
void (*handoff) (GstElement *element, GstBuffer *buf);
};
GType gst_identity_get_type(void);
G_END_DECLS
#endif /* __GST_IDENTITY_H__ */

View file

@ -1,379 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000,2001,2002,2003,2004,2005 Wim Taymans <wim@fluendo.com>
*
*
* gsttee.c: Tee element, one in N out
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gsttee.h"
#include <string.h>
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GST_DEBUG_CATEGORY_STATIC (gst_tee_debug);
#define GST_CAT_DEFAULT gst_tee_debug
static GstElementDetails gst_tee_details =
GST_ELEMENT_DETAILS ("Tee pipe fitting",
"Generic",
"1-to-N pipe fitting",
"Erik Walthinsen <omega@cse.ogi.edu>, "
"Wim \"Tim\" Taymans <wim@fluendo.com>");
enum
{
PROP_0,
PROP_NUM_SRC_PADS,
PROP_HAS_SINK_LOOP,
PROP_HAS_CHAIN,
PROP_SILENT,
PROP_LAST_MESSAGE
/* FILL ME */
};
GstStaticPadTemplate tee_src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
GST_PAD_SRC,
GST_PAD_REQUEST,
GST_STATIC_CAPS_ANY);
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_tee_debug, "tee", 0, "tee element");
GST_BOILERPLATE_FULL (GstTee, gst_tee, GstElement, GST_TYPE_ELEMENT, _do_init);
static GstPad *gst_tee_request_new_pad (GstElement * element,
GstPadTemplate * temp, const gchar * unused);
static void gst_tee_finalize (GObject * object);
static void gst_tee_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_tee_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
static void gst_tee_loop (GstPad * pad);
static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
static gboolean gst_tee_sink_activate_pull (GstPad * pad, gboolean active);
static void
gst_tee_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sinktemplate));
gst_element_class_set_details (gstelement_class, &gst_tee_details);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&tee_src_template));
}
static void
gst_tee_finalize (GObject * object)
{
GstTee *tee;
tee = GST_TEE (object);
g_free (tee->last_message);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_tee_class_init (GstTeeClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tee_finalize);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_tee_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_tee_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_SRC_PADS,
g_param_spec_int ("num-src-pads", "num-src-pads", "num-src-pads",
0, G_MAXINT, 0, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_SINK_LOOP,
g_param_spec_boolean ("has-sink-loop", "has-sink-loop", "has-sink-loop",
FALSE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_CHAIN,
g_param_spec_boolean ("has-chain", "has-chain", "has-chain",
TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "silent", "silent",
TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last_message", "last_message", "last_message",
NULL, G_PARAM_READABLE));
gstelement_class->request_new_pad =
GST_DEBUG_FUNCPTR (gst_tee_request_new_pad);
}
static void
gst_tee_init (GstTee * tee, GstTeeClass * g_class)
{
tee->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
gst_pad_set_setcaps_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
gst_pad_set_getcaps_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
tee->last_message = NULL;
}
static void
gst_tee_update_pad_functions (GstTee * tee)
{
gst_pad_set_activatepush_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
gst_pad_set_activatepull_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_pull));
if (tee->has_chain)
gst_pad_set_chain_function (tee->sinkpad,
GST_DEBUG_FUNCPTR (gst_tee_chain));
else
gst_pad_set_chain_function (tee->sinkpad, NULL);
}
static GstPad *
gst_tee_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * unused)
{
gchar *name;
GstPad *srcpad;
GstTee *tee;
tee = GST_TEE (element);
GST_OBJECT_LOCK (tee);
name = g_strdup_printf ("src%d", tee->pad_counter++);
GST_OBJECT_UNLOCK (tee);
srcpad = gst_pad_new_from_template (templ, name);
g_free (name);
gst_pad_set_setcaps_function (srcpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
gst_pad_set_getcaps_function (srcpad,
GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
gst_element_add_pad (GST_ELEMENT (tee), srcpad);
return srcpad;
}
static void
gst_tee_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
{
GstTee *tee = GST_TEE (object);
GST_OBJECT_LOCK (tee);
switch (prop_id) {
case PROP_HAS_SINK_LOOP:
tee->has_sink_loop = g_value_get_boolean (value);
gst_tee_update_pad_functions (tee);
break;
case PROP_HAS_CHAIN:
tee->has_chain = g_value_get_boolean (value);
gst_tee_update_pad_functions (tee);
break;
case PROP_SILENT:
tee->silent = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK (tee);
}
static void
gst_tee_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstTee *tee = GST_TEE (object);
GST_OBJECT_LOCK (tee);
switch (prop_id) {
case PROP_NUM_SRC_PADS:
g_value_set_int (value, GST_ELEMENT (tee)->numsrcpads);
break;
case PROP_HAS_SINK_LOOP:
g_value_set_boolean (value, tee->has_sink_loop);
break;
case PROP_HAS_CHAIN:
g_value_set_boolean (value, tee->has_chain);
break;
case PROP_SILENT:
g_value_set_boolean (value, tee->silent);
break;
case PROP_LAST_MESSAGE:
g_value_set_string (value, tee->last_message);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK (tee);
}
typedef struct
{
GstTee *tee;
GstBuffer *buffer;
} PushData;
static gboolean
gst_tee_do_push (GstPad * pad, GValue * ret, PushData * data)
{
GstFlowReturn res;
if (G_UNLIKELY (!data->tee->silent)) {
GstTee *tee = data->tee;
GstBuffer *buf = data->buffer;
g_free (tee->last_message);
tee->last_message =
g_strdup_printf ("chain ******* (%s:%s)t (%d bytes, %"
G_GUINT64_FORMAT ") %p", GST_DEBUG_PAD_NAME (pad),
GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
g_object_notify (G_OBJECT (tee), "last_message");
}
res = gst_pad_push (pad, gst_buffer_ref (data->buffer));
g_value_set_enum (ret, res);
gst_object_unref (pad);
return (res == GST_FLOW_OK);
}
static GstFlowReturn
gst_tee_handle_buffer (GstTee * tee, GstBuffer * buffer)
{
GstIterator *iter;
PushData data;
GValue ret = { 0, };
GstIteratorResult res;
tee->offset += GST_BUFFER_SIZE (buffer);
g_value_init (&ret, GST_TYPE_FLOW_RETURN);
iter = gst_element_iterate_src_pads (GST_ELEMENT (tee));
data.tee = tee;
data.buffer = buffer;
res = gst_iterator_fold (iter, (GstIteratorFoldFunction) gst_tee_do_push,
&ret, &data);
gst_iterator_free (iter);
gst_buffer_unref (buffer);
/* no need to unset gvalue */
return g_value_get_enum (&ret);
}
static GstFlowReturn
gst_tee_chain (GstPad * pad, GstBuffer * buffer)
{
GstFlowReturn res;
GstTee *tee;
tee = GST_TEE (GST_PAD_PARENT (pad));
res = gst_tee_handle_buffer (tee, buffer);
return res;
}
#define DEFAULT_SIZE 1024
static void
gst_tee_loop (GstPad * pad)
{
GstBuffer *buffer;
GstFlowReturn res;
GstTee *tee;
tee = GST_TEE (GST_PAD_PARENT (pad));
res = gst_pad_pull_range (pad, tee->offset, DEFAULT_SIZE, &buffer);
if (res != GST_FLOW_OK)
goto pause_task;
res = gst_tee_handle_buffer (tee, buffer);
if (res != GST_FLOW_OK)
goto pause_task;
return;
pause_task:
{
gst_pad_pause_task (pad);
return;
}
}
static gboolean
gst_tee_sink_activate_push (GstPad * pad, gboolean active)
{
GstTee *tee;
tee = GST_TEE (GST_OBJECT_PARENT (pad));
tee->sink_mode = active && GST_ACTIVATE_PUSH;
if (active) {
g_return_val_if_fail (tee->has_chain, FALSE);
}
return TRUE;
}
/* won't be called until we implement an activate function */
static gboolean
gst_tee_sink_activate_pull (GstPad * pad, gboolean active)
{
GstTee *tee;
tee = GST_TEE (GST_OBJECT_PARENT (pad));
tee->sink_mode = active && GST_ACTIVATE_PULL;
if (active) {
g_return_val_if_fail (tee->has_sink_loop, FALSE);
return gst_pad_start_task (pad, (GstTaskFunction) gst_tee_loop, pad);
} else {
return gst_pad_stop_task (pad);
}
}

View file

@ -1,69 +0,0 @@
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
*
* gsttee.h: Header for GstTee element
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_TEE_H__
#define __GST_TEE_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_TEE \
(gst_tee_get_type())
#define GST_TEE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEE,GstTee))
#define GST_TEE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEE,GstTeeClass))
#define GST_IS_TEE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEE))
#define GST_IS_TEE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEE))
typedef struct _GstTee GstTee;
typedef struct _GstTeeClass GstTeeClass;
struct _GstTee {
GstElement element;
GstPad *sinkpad;
gboolean silent;
gboolean has_chain;
gboolean has_sink_loop;
gint pad_counter;
guint64 offset;
GstActivateMode sink_mode;
gchar *last_message;
};
struct _GstTeeClass {
GstElementClass parent_class;
};
GType gst_tee_get_type (void);
G_END_DECLS
#endif /* __GST_TEE_H__ */

View file

@ -1,868 +0,0 @@
/* GStreamer
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* gsttypefindelement.c: element that detects type of stream
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* FIXME: need a better solution for non-seekable streams */
/* way of operation:
* 1) get a list of all typefind functions sorted best to worst
* 2) if all elements have been called with all requested data goto 8
* 3) call all functions once with all available data
* 4) if a function returns a value >= ARG_MAXIMUM goto 8
* 5) all functions with a result > ARG_MINIMUM or functions that did not get
* all requested data (where peek returned NULL) stay in list
* 6) seek to requested offset of best function that still has open data
* requests
* 7) goto 2
* 8) take best available result and use its caps
*
* The element has two scheduling modes:
*
* 1) chain based, it will collect buffers and run the typefind function on
* the buffer until something is found.
* 2) getrange based, it will proxy the getrange function to the sinkpad. It
* is assumed that the peer element is happy with whatever format we
* eventually read.
*
* When the element has no connected srcpad, and the sinkpad can operate in
* getrange based mode, the element starts its own task to figure out the
* type of the stream.
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gsttypefindelement.h"
#include "gst/gst_private.h"
#include "gst/gst-i18n-lib.h"
#include "gst/base/gsttypefindhelper.h"
#include <gst/gsttypefind.h>
#include <gst/gstutils.h>
#include <gst/gsterror.h>
GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug);
#define GST_CAT_DEFAULT gst_type_find_element_debug
static GstElementDetails gst_type_find_element_details =
GST_ELEMENT_DETAILS ("TypeFind",
"Generic",
"Finds the media type of a stream",
"Benjamin Otte <in7y118@public.uni-hamburg.de>");
/* generic templates */
GstStaticPadTemplate type_find_element_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GstStaticPadTemplate type_find_element_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
/* TypeFind signals and args */
enum
{
HAVE_TYPE,
LAST_SIGNAL
};
enum
{
ARG_0,
ARG_CAPS,
ARG_MINIMUM,
ARG_MAXIMUM
};
enum
{
MODE_NORMAL, /* act as identity */
MODE_TYPEFIND /* do typefinding */
};
#define _do_init(bla) \
GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind", \
GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
GST_BOILERPLATE_FULL (GstTypeFindElement, gst_type_find_element, GstElement,
GST_TYPE_ELEMENT, _do_init);
static void gst_type_find_element_dispose (GObject * object);
static void gst_type_find_element_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_type_find_element_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
#if 0
static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
#endif
static gboolean gst_type_find_element_src_event (GstPad * pad,
GstEvent * event);
static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_type_find_element_handle_event (GstPad * pad,
GstEvent * event);
static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad,
GstBuffer * buffer);
static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad,
guint64 offset, guint length, GstBuffer ** buffer);
static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad);
static GstStateChangeReturn
gst_type_find_element_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_type_find_element_activate (GstPad * pad);
static gboolean
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
static void
gst_type_find_element_have_type (GstTypeFindElement * typefind,
guint probability, const GstCaps * caps)
{
g_assert (typefind->caps == NULL);
g_assert (caps != NULL);
GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT, caps);
typefind->caps = gst_caps_copy (caps);
gst_pad_set_caps (typefind->src, (GstCaps *) caps);
}
static void
gst_type_find_element_base_init (gpointer g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&type_find_element_src_template));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&type_find_element_sink_template));
gst_element_class_set_details (gstelement_class,
&gst_type_find_element_details);
}
static void
gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_type_find_element_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_type_find_element_get_property);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_type_find_element_dispose);
typefind_class->have_type = gst_type_find_element_have_type;
g_object_class_install_property (gobject_class, ARG_CAPS,
g_param_spec_boxed ("caps", _("caps"),
_("detected capabilities in stream"), gst_caps_get_type (),
G_PARAM_READABLE));
g_object_class_install_property (gobject_class, ARG_MINIMUM,
g_param_spec_uint ("minimum", _("minimum"),
"minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_MINIMUM,
g_param_spec_uint ("maximum", _("maximum"),
"probability to stop typefinding", GST_TYPE_FIND_MINIMUM,
GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM, G_PARAM_READWRITE));
gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have_type",
G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2,
G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
}
static void
gst_type_find_element_init (GstTypeFindElement * typefind,
GstTypeFindElementClass * g_class)
{
/* sinkpad */
typefind->sink =
gst_pad_new_from_static_template (&type_find_element_sink_template,
"sink");
gst_pad_set_activate_function (typefind->sink,
GST_DEBUG_FUNCPTR (gst_type_find_element_activate));
gst_pad_set_chain_function (typefind->sink,
GST_DEBUG_FUNCPTR (gst_type_find_element_chain));
gst_pad_set_event_function (typefind->sink,
GST_DEBUG_FUNCPTR (gst_type_find_element_handle_event));
gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
/* srcpad */
typefind->src =
gst_pad_new_from_static_template (&type_find_element_src_template, "src");
gst_pad_set_activatepull_function (typefind->src,
GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_pull));
gst_pad_set_checkgetrange_function (typefind->src,
GST_DEBUG_FUNCPTR (gst_type_find_element_checkgetrange));
gst_pad_set_getrange_function (typefind->src,
GST_DEBUG_FUNCPTR (gst_type_find_element_getrange));
gst_pad_set_event_function (typefind->src,
GST_DEBUG_FUNCPTR (gst_type_find_element_src_event));
gst_pad_set_query_function (typefind->src,
GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
gst_pad_use_fixed_caps (typefind->src);
gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
typefind->mode = MODE_TYPEFIND;
typefind->caps = NULL;
typefind->min_probability = 1;
typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
typefind->store = NULL;
}
static void
gst_type_find_element_dispose (GObject * object)
{
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
G_OBJECT_CLASS (parent_class)->dispose (object);
if (typefind->store) {
gst_buffer_unref (typefind->store);
typefind->store = NULL;
}
}
static void
gst_type_find_element_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstTypeFindElement *typefind;
g_return_if_fail (GST_IS_TYPE_FIND_ELEMENT (object));
typefind = GST_TYPE_FIND_ELEMENT (object);
switch (prop_id) {
case ARG_MINIMUM:
typefind->min_probability = g_value_get_uint (value);
g_object_notify (object, "minimum");
break;
case ARG_MAXIMUM:
typefind->max_probability = g_value_get_uint (value);
g_object_notify (object, "maximum");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_type_find_element_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstTypeFindElement *typefind;
g_return_if_fail (GST_IS_TYPE_FIND_ELEMENT (object));
typefind = GST_TYPE_FIND_ELEMENT (object);
switch (prop_id) {
case ARG_CAPS:
g_value_set_boxed (value, typefind->caps);
break;
case ARG_MINIMUM:
g_value_set_uint (value, typefind->min_probability);
break;
case ARG_MAXIMUM:
g_value_set_uint (value, typefind->max_probability);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
{
GstTypeFindElement *typefind;
gboolean res;
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
res = gst_pad_query (GST_PAD_PEER (typefind->sink), query);
if (!res)
return FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
{
gint64 peer_pos;
GstFormat format;
if (typefind->store == NULL)
return TRUE;
gst_query_parse_position (query, &format, &peer_pos);
/* FIXME: this code assumes that there's no discont in the queue */
switch (format) {
case GST_FORMAT_BYTES:
peer_pos -= typefind->store->size;
break;
default:
/* FIXME */
break;
}
gst_query_set_position (query, format, peer_pos);
break;
}
default:
break;
}
return TRUE;
}
#if 0
static const GstEventMask *
gst_type_find_element_src_event_mask (GstPad * pad)
{
static const GstEventMask mask[] = {
{GST_EVENT_SEEK,
GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END |
GST_SEEK_FLAG_FLUSH},
/* add more if you want, event masks suck and need to die anyway */
{0,}
};
return mask;
}
#endif
static gboolean
gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
{
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
if (typefind->mode != MODE_NORMAL) {
/* need to do more? */
gst_mini_object_unref (GST_MINI_OBJECT (event));
return FALSE;
}
return gst_pad_event_default (pad, event);
}
typedef struct
{
GstTypeFindFactory *factory;
guint probability;
GstCaps *caps;
guint requested_size;
GstTypeFindElement *self;
}
TypeFindEntry;
static inline TypeFindEntry *
new_entry (void)
{
return g_new0 (TypeFindEntry, 1);
}
static void
free_entry (TypeFindEntry * entry)
{
if (entry->caps)
gst_caps_unref (entry->caps);
g_free (entry);
}
static void
start_typefinding (GstTypeFindElement * typefind)
{
g_assert (typefind->possibilities == NULL);
GST_DEBUG_OBJECT (typefind, "starting typefinding");
gst_pad_set_caps (typefind->src, NULL);
if (typefind->caps) {
gst_caps_replace (&typefind->caps, NULL);
}
typefind->mode = MODE_TYPEFIND;
typefind->stream_length_available = TRUE;
typefind->stream_length = 0;
}
static void
stop_typefinding (GstTypeFindElement * typefind)
{
GstState state;
gboolean push_cached_buffers;
gst_element_get_state (GST_ELEMENT (typefind), &state, NULL,
GST_CLOCK_TIME_NONE);
push_cached_buffers = (state >= GST_STATE_PAUSED);
GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
push_cached_buffers ? " and pushing cached buffers" : "");
if (typefind->possibilities != NULL) {
/* this should only happen on PAUSED => READY or EOS */
GST_LOG_OBJECT (typefind, "freeing remaining %u typefind functions",
g_list_length (typefind->possibilities));
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
g_list_free (typefind->possibilities);
typefind->possibilities = NULL;
}
//typefind->mode = MODE_TRANSITION;
if (typefind->store) {
if (!push_cached_buffers) {
gst_buffer_unref (typefind->store);
} else {
typefind->mode = MODE_NORMAL;
gst_buffer_set_caps (typefind->store, typefind->caps);
gst_pad_push (typefind->src, typefind->store);
}
typefind->store = NULL;
}
}
static guint64
find_element_get_length (gpointer data)
{
TypeFindEntry *entry = (TypeFindEntry *) data;
GstTypeFindElement *typefind = entry->self;
GstFormat format = GST_FORMAT_BYTES;
if (!typefind->stream_length_available) {
GST_LOG_OBJECT (entry->self,
"'%s' called get_length () but we know it's not available",
GST_PLUGIN_FEATURE_NAME (entry->factory));
return 0;
}
if (entry->self->stream_length == 0) {
if (!gst_pad_query_duration (GST_PAD_PEER (entry->self->sink), &format,
(gint64 *) & entry->self->stream_length))
goto no_length;
if (format != GST_FORMAT_BYTES) {
typefind->stream_length_available = FALSE;
entry->self->stream_length = 0;
} else {
GST_DEBUG_OBJECT (entry->self,
"'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
}
}
return entry->self->stream_length;
no_length:
{
typefind->stream_length_available = FALSE;
GST_DEBUG_OBJECT (entry->self,
"'%s' called get_length () but it's not available",
GST_PLUGIN_FEATURE_NAME (entry->factory));
return 0;
}
}
static gboolean
gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
{
gboolean res = FALSE;
TypeFindEntry *entry;
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
GST_DEBUG_OBJECT (typefind, "got event %d in mode %d", GST_EVENT_TYPE (event),
typefind->mode);
switch (typefind->mode) {
case MODE_TYPEFIND:
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
/* this should only happen when we got all available data */
entry =
(TypeFindEntry *) typefind->possibilities ? typefind->
possibilities->data : NULL;
if (entry && entry->probability >= typefind->min_probability) {
GST_INFO_OBJECT (typefind,
"'%s' is the best typefind left after we got all data, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
0, entry->probability, entry->caps);
stop_typefinding (typefind);
gst_buffer_set_caps (typefind->store, typefind->caps);
gst_pad_push (typefind->src, typefind->store);
typefind->store = NULL;
res = gst_pad_event_default (pad, event);
} else {
res = gst_pad_event_default (pad, event);
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
(NULL));
stop_typefinding (typefind);
}
break;
default:
gst_mini_object_unref (GST_MINI_OBJECT (event));
res = TRUE;
break;
}
break;
case MODE_NORMAL:
if (FALSE) { // GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) {
start_typefinding (typefind);
gst_event_unref (event);
res = TRUE;
} else {
res = gst_pad_event_default (pad, event);
}
break;
default:
g_assert_not_reached ();
}
return res;
}
static guint8 *
find_peek (gpointer data, gint64 offset, guint size)
{
TypeFindEntry *entry = (TypeFindEntry *) data;
GST_LOG_OBJECT (entry->self, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), offset, size);
if (offset != 0)
return NULL;
if (size <= entry->self->store->size) {
return GST_BUFFER_DATA (entry->self->store);
} else {
entry->requested_size = size;
GST_LOG_OBJECT (entry->self,
"setting requested peek (%" G_GINT64_FORMAT ", %u) on '%s'", offset,
size, GST_PLUGIN_FEATURE_NAME (entry->factory));
return NULL;
}
}
static void
find_suggest (gpointer data, guint probability, const GstCaps * caps)
{
TypeFindEntry *entry = (TypeFindEntry *) data;
GST_LOG_OBJECT (entry->self, "'%s' called suggest (%u, %" GST_PTR_FORMAT ")",
GST_PLUGIN_FEATURE_NAME (entry->factory), probability, caps);
if (((gint) probability) > entry->probability) {
entry->probability = probability;
gst_caps_replace (&entry->caps, (GstCaps *) caps);
}
}
#if 0
static gint
compare_type_find_entry (gconstpointer a, gconstpointer b)
{
TypeFindEntry *one = (TypeFindEntry *) a;
TypeFindEntry *two = (TypeFindEntry *) b;
if (one->probability == two->probability) {
/* FIXME: can be improved by analyzing requests */
return 0;
} else {
return two->probability - one->probability;
}
}
#endif
static gint
compare_type_find_factory (gconstpointer fac1, gconstpointer fac2)
{
return GST_PLUGIN_FEATURE (fac1)->rank - GST_PLUGIN_FEATURE (fac2)->rank;
}
static GstFlowReturn
gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
{
GstTypeFindElement *typefind;
GList *entries;
TypeFindEntry *entry;
GList *walk;
GstFlowReturn res = GST_FLOW_OK;
GstTypeFind find = { find_peek, find_suggest, NULL, find_element_get_length };
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
switch (typefind->mode) {
case MODE_NORMAL:
gst_buffer_set_caps (buffer, typefind->caps);
return gst_pad_push (typefind->src, buffer);
case MODE_TYPEFIND:{
gboolean done = TRUE;
if (typefind->store)
typefind->store = gst_buffer_join (typefind->store, buffer);
else
typefind->store = buffer;
if (typefind->possibilities == NULL) {
/* not yet started, get all typefinding functions into our "queue" */
GList *all_factories = gst_type_find_factory_get_list ();
GST_INFO_OBJECT (typefind, "starting with %u typefinding functions",
g_list_length (all_factories));
all_factories = g_list_sort (all_factories, compare_type_find_factory);
walk = all_factories;
while (all_factories) {
entry = new_entry ();
entry->factory = GST_TYPE_FIND_FACTORY (all_factories->data);
entry->self = typefind;
entry->probability = 0;
typefind->possibilities =
g_list_prepend (typefind->possibilities, entry);
all_factories = g_list_next (all_factories);
}
gst_plugin_feature_list_free (all_factories);
}
/* call every typefind function once */
walk = entries = typefind->possibilities;
GST_INFO_OBJECT (typefind, "iterating %u typefinding functions",
g_list_length (entries));
typefind->possibilities = NULL;
while (walk) {
find.data = entry = (TypeFindEntry *) walk->data;
walk = g_list_next (walk);
if (entry->probability == 0) {
entry->requested_size = 0;
gst_type_find_factory_call_function (entry->factory, &find);
} else {
typefind->possibilities =
g_list_prepend (typefind->possibilities, entry);
continue;
}
if (entry->probability == 0 && entry->requested_size == 0) {
GST_DEBUG_OBJECT (typefind,
"'%s' was removed - no chance of being the right plugin",
GST_PLUGIN_FEATURE_NAME (entry->factory));
free_entry (entry);
} else if (entry->probability >= typefind->max_probability) {
/* wooha, got caps */
GstCaps *found_caps = entry->caps;
guint probability = entry->probability;
GST_INFO_OBJECT (typefind,
"'%s' returned %u/%u probability, using it NOW",
GST_PLUGIN_FEATURE_NAME (entry->factory), probability,
typefind->max_probability);
while (walk) {
free_entry ((TypeFindEntry *) walk->data);
walk = g_list_next (walk);
}
walk = typefind->possibilities;
while (walk) {
free_entry (walk->data);
walk = g_list_next (walk);
}
g_list_free (typefind->possibilities);
typefind->possibilities = NULL;
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
probability, found_caps);
free_entry (entry);
} else {
typefind->possibilities =
g_list_prepend (typefind->possibilities, entry);
if (entry->requested_size != 0)
done = FALSE;
}
}
g_list_free (entries);
/* we may now already have caps or we might be left without functions to try */
if (typefind->caps) {
stop_typefinding (typefind);
} else if (typefind->possibilities == NULL) {
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
stop_typefinding (typefind);
return GST_FLOW_ERROR;
} else if (done) {
TypeFindEntry *best = NULL;
walk = typefind->possibilities;
while (walk) {
entry = (TypeFindEntry *) typefind->possibilities->data;
if ((!best || entry->probability > best->probability) &&
entry->probability >= typefind->min_probability) {
best = entry;
}
walk = g_list_next (walk);
}
if (best) {
GST_INFO_OBJECT (typefind,
"'%s' is the only typefind left, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
0, entry->probability, entry->caps);
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
g_list_free (typefind->possibilities);
typefind->possibilities = NULL;
stop_typefinding (typefind);
} else {
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
stop_typefinding (typefind);
return GST_FLOW_ERROR;
}
}
break;
}
default:
g_assert_not_reached ();
return GST_FLOW_ERROR;
}
return res;
}
static gboolean
gst_type_find_element_checkgetrange (GstPad * srcpad)
{
GstTypeFindElement *typefind;
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
return gst_pad_check_pull_range (typefind->sink);
}
static GstFlowReturn
gst_type_find_element_getrange (GstPad * srcpad,
guint64 offset, guint length, GstBuffer ** buffer)
{
GstTypeFindElement *typefind;
GstFlowReturn ret;
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (srcpad));
ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
if (ret == GST_FLOW_OK && buffer && *buffer)
gst_buffer_set_caps (*buffer, typefind->caps);
return ret;
}
static gboolean
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active)
{
GstTypeFindElement *typefind;
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
return gst_pad_activate_pull (typefind->sink, active);
}
static gboolean
gst_type_find_element_activate (GstPad * pad)
{
GstCaps *found_caps = NULL;
GstTypeFindElement *typefind;
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
/* 1. try to activate in pull mode. if not, switch to push and succeed.
2. try to pull type find.
3. deactivate pull mode.
4. src pad might have been activated push by the state change. deactivate.
5. if we didn't find any caps, fail.
6. emit have-type; maybe the app connected the source pad to something.
7. if the sink pad is activated, we are in pull mode. succeed.
otherwise activate both pads in push mode and succeed.
*/
/* 1 */
if (!gst_pad_activate_pull (pad, TRUE)) {
start_typefinding (typefind);
return gst_pad_activate_push (pad, TRUE);
}
/* 2 */
{
GstPad *peer;
peer = gst_pad_get_peer (pad);
if (peer) {
gint64 size;
GstFormat format = GST_FORMAT_BYTES;
gst_pad_query_duration (peer, &format, &size);
found_caps = gst_type_find_helper (peer, (guint64) size);
gst_object_unref (peer);
}
}
/* 3 */
gst_pad_activate_pull (pad, FALSE);
/* 4 */
gst_pad_activate_push (typefind->src, FALSE);
/* 5 */
if (!found_caps)
return FALSE;
/* 6 */
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
0, 100, found_caps);
gst_caps_unref (found_caps);
typefind->mode = MODE_NORMAL;
/* 7 */
if (gst_pad_is_active (pad))
return TRUE;
else {
gboolean ret;
ret = gst_pad_activate_push (typefind->src, TRUE);
ret &= gst_pad_activate_push (pad, TRUE);
return ret;
}
}
static GstStateChangeReturn
gst_type_find_element_change_state (GstElement * element,
GstStateChange transition)
{
GstStateChangeReturn ret;
GstTypeFindElement *typefind;
typefind = GST_TYPE_FIND_ELEMENT (element);
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_caps_replace (&typefind->caps, NULL);
break;
default:
break;
}
return ret;
}

View file

@ -1,76 +0,0 @@
/* GStreamer
* Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* gsttypefindelement.h: element that detects type of stream
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_TYPE_FIND_ELEMENT_H__
#define __GST_TYPE_FIND_ELEMENT_H__
#include <gst/gstinfo.h>
#include <gst/gstelement.h>
/* #include <gst/gstbufferstore.h> */
#include "gstbufferstore.h"
G_BEGIN_DECLS
#define GST_TYPE_TYPE_FIND_ELEMENT (gst_type_find_element_get_type ())
#define GST_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElement))
#define GST_IS_TYPE_FIND_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TYPE_FIND_ELEMENT))
#define GST_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElementClass))
#define GST_IS_TYPE_FIND_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TYPE_FIND_ELEMENT))
#define GST_TYPE_FIND_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TYPE_FIND_ELEMENT, GstTypeFindElementClass))
typedef struct _GstTypeFindElement GstTypeFindElement;
typedef struct _GstTypeFindElementClass GstTypeFindElementClass;
struct _GstTypeFindElement {
GstElement element;
GstPad * sink;
GstPad * src;
guint min_probability;
guint max_probability;
GstCaps * caps;
guint mode;
GstBuffer * store;
guint64 stream_length;
gboolean stream_length_available;
GList * possibilities;
};
struct _GstTypeFindElementClass {
GstElementClass parent_class;
/* signals */
void (*have_type) (GstTypeFindElement *element,
guint probability,
const GstCaps * caps);
};
GType gst_type_find_element_get_type (void);
G_END_DECLS
#endif /* __GST_TYPE_FIND_ELEMENT_H__ */

View file

@ -1,5 +0,0 @@
*.bb
*.bbg
*.da
*.def
*.gcno

View file

@ -1,16 +0,0 @@
plugin_LTLIBRARIES = libgstindexers.la
# file index uses xml
if GST_DISABLE_LOADSAVE
GST_LOADSAVE_SRC =
else
GST_LOADSAVE_SRC = gstfileindex.c
endif
if HAVE_MMAP
else
GST_LOADSAVE_SRC =
endif
libgstindexers_la_SOURCES = gstindexers.c gstmemindex.c $(GST_LOADSAVE_SRC)
libgstindexers_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstindexers_la_LIBADD = $(GST_OBJ_LIBS)
libgstindexers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

File diff suppressed because it is too large Load diff

View file

@ -1,44 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gst/gst_private.h>
#include <gst/gstversion.h>
#include <gst/gstplugin.h>
extern gboolean gst_mem_index_plugin_init (GstPlugin * plugin);
extern gboolean gst_file_index_plugin_init (GstPlugin * plugin);
static gboolean
plugin_init (GstPlugin * plugin)
{
gboolean res = TRUE;
res &= gst_mem_index_plugin_init (plugin);
#ifdef HAVE_MMAP
res &= gst_file_index_plugin_init (plugin);
#endif
return res;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"gstindexers",
"GStreamer core indexers",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);

View file

@ -1,426 +0,0 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gst/gst.h>
#define GST_TYPE_MEM_INDEX \
(gst_index_get_type ())
#define GST_MEM_INDEX(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MEM_INDEX, GstMemIndex))
#define GST_MEM_INDEX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MEM_INDEX, GstMemIndexClass))
#define GST_IS_MEM_INDEX(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MEM_INDEX))
#define GST_IS_MEM_INDEX_CLASS(obj) \
(GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MEM_INDEX))
/*
* Object model:
*
* All entries are simply added to a GList first. Then we build
* an index to each entry for each id/format
*
*
* memindex
* -----------------------------...
* ! !
* id1 id2
* ------------
* ! !
* format1 format2
* ! !
* GTree GTree
*
*
* The memindex creates a MemIndexId object for each writer id, a
* Hashtable is kept to map the id to the MemIndexId
*
* The MemIndexId keeps a MemIndexFormatIndex for each format the
* specific writer wants indexed.
*
* The MemIndexFormatIndex keeps all the values of the particular
* format in a GTree, The values of the GTree point back to the entry.
*
* Finding a value for an id/format requires locating the correct GTree,
* then do a lookup in the Tree to get the required value.
*/
typedef struct
{
GstFormat format;
gint offset;
GTree *tree;
}
GstMemIndexFormatIndex;
typedef struct
{
gint id;
GHashTable *format_index;
}
GstMemIndexId;
typedef struct _GstMemIndex GstMemIndex;
typedef struct _GstMemIndexClass GstMemIndexClass;
struct _GstMemIndex
{
GstIndex parent;
GList *associations;
GHashTable *id_index;
};
struct _GstMemIndexClass
{
GstIndexClass parent_class;
};
/* Index signals and args */
enum
{
LAST_SIGNAL
};
enum
{
ARG_0,
/* FILL ME */
};
static void gst_mem_index_class_init (GstMemIndexClass * klass);
static void gst_mem_index_init (GstMemIndex * index);
static void gst_mem_index_dispose (GObject * object);
static void gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry);
static GstIndexEntry *gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
GstIndexLookupMethod method, GstAssocFlags flags,
GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data);
#define CLASS(mem_index) GST_MEM_INDEX_CLASS (G_OBJECT_GET_CLASS (mem_index))
static GstIndex *parent_class = NULL;
/*static guint gst_mem_index_signals[LAST_SIGNAL] = { 0 }; */
GType
gst_mem_index_get_type (void)
{
static GType mem_index_type = 0;
if (!mem_index_type) {
static const GTypeInfo mem_index_info = {
sizeof (GstMemIndexClass),
NULL,
NULL,
(GClassInitFunc) gst_mem_index_class_init,
NULL,
NULL,
sizeof (GstMemIndex),
1,
(GInstanceInitFunc) gst_mem_index_init,
NULL
};
mem_index_type =
g_type_register_static (GST_TYPE_INDEX, "GstMemIndex", &mem_index_info,
0);
}
return mem_index_type;
}
static void
gst_mem_index_class_init (GstMemIndexClass * klass)
{
GObjectClass *gobject_class;
GstIndexClass *gstindex_class;
gobject_class = (GObjectClass *) klass;
gstindex_class = (GstIndexClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_INDEX);
gobject_class->dispose = gst_mem_index_dispose;
gstindex_class->add_entry = gst_mem_index_add_entry;
gstindex_class->get_assoc_entry = gst_mem_index_get_assoc_entry;
}
static void
gst_mem_index_init (GstMemIndex * index)
{
GST_DEBUG ("created new mem index");
index->associations = NULL;
index->id_index = g_hash_table_new (g_int_hash, g_int_equal);
}
static void
gst_mem_index_dispose (GObject * object)
{
//GstMemIndex *memindex = GST_MEM_INDEX (object);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_mem_index_add_id (GstIndex * index, GstIndexEntry * entry)
{
GstMemIndex *memindex = GST_MEM_INDEX (index);
GstMemIndexId *id_index;
id_index = g_hash_table_lookup (memindex->id_index, &entry->id);
if (!id_index) {
id_index = g_new0 (GstMemIndexId, 1);
id_index->id = entry->id;
id_index->format_index = g_hash_table_new (g_int_hash, g_int_equal);
g_hash_table_insert (memindex->id_index, &id_index->id, id_index);
}
}
static gint
mem_index_compare (gconstpointer a, gconstpointer b, gpointer user_data)
{
GstMemIndexFormatIndex *index = user_data;
gint64 val1, val2;
gint64 diff;
val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset);
val2 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) b), index->offset);
diff = (val2 - val1);
return (diff == 0 ? 0 : (diff > 0 ? 1 : -1));
}
static void
gst_mem_index_index_format (GstMemIndexId * id_index, GstIndexEntry * entry,
gint assoc)
{
GstMemIndexFormatIndex *index;
GstFormat *format;
format = &GST_INDEX_ASSOC_FORMAT (entry, assoc);
index = g_hash_table_lookup (id_index->format_index, format);
if (!index) {
index = g_new0 (GstMemIndexFormatIndex, 1);
index->format = *format;
index->offset = assoc;
index->tree = g_tree_new_with_data (mem_index_compare, index);
g_hash_table_insert (id_index->format_index, &index->format, index);
}
g_tree_insert (index->tree, entry, entry);
}
static void
gst_mem_index_add_association (GstIndex * index, GstIndexEntry * entry)
{
GstMemIndex *memindex = GST_MEM_INDEX (index);
GstMemIndexId *id_index;
memindex->associations = g_list_prepend (memindex->associations, entry);
id_index = g_hash_table_lookup (memindex->id_index, &entry->id);
if (id_index) {
gint i;
for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
gst_mem_index_index_format (id_index, entry, i);
}
}
}
static void
gst_mem_index_add_object (GstIndex * index, GstIndexEntry * entry)
{
}
static void
gst_mem_index_add_format (GstIndex * index, GstIndexEntry * entry)
{
}
static void
gst_mem_index_add_entry (GstIndex * index, GstIndexEntry * entry)
{
GST_LOG_OBJECT (index, "added this entry");
switch (entry->type) {
case GST_INDEX_ENTRY_ID:
gst_mem_index_add_id (index, entry);
break;
case GST_INDEX_ENTRY_ASSOCIATION:
gst_mem_index_add_association (index, entry);
break;
case GST_INDEX_ENTRY_OBJECT:
gst_mem_index_add_object (index, entry);
break;
case GST_INDEX_ENTRY_FORMAT:
gst_mem_index_add_format (index, entry);
break;
default:
break;
}
}
typedef struct
{
gint64 value;
GstMemIndexFormatIndex *index;
gboolean exact;
GstIndexEntry *lower;
gint64 low_diff;
GstIndexEntry *higher;
gint64 high_diff;
}
GstMemIndexSearchData;
static gint
mem_index_search (gconstpointer a, gconstpointer b)
{
GstMemIndexSearchData *data = (GstMemIndexSearchData *) b;
GstMemIndexFormatIndex *index = data->index;
gint64 val1, val2;
gint64 diff;
val1 = GST_INDEX_ASSOC_VALUE (((GstIndexEntry *) a), index->offset);
val2 = data->value;
diff = (val1 - val2);
if (diff == 0)
return 0;
/* exact matching, don't update low/high */
if (data->exact)
return (diff > 0 ? 1 : -1);
if (diff < 0) {
if (diff > data->low_diff) {
data->low_diff = diff;
data->lower = (GstIndexEntry *) a;
}
diff = -1;
} else {
if (diff < data->high_diff) {
data->high_diff = diff;
data->higher = (GstIndexEntry *) a;
}
diff = 1;
}
return diff;
}
static GstIndexEntry *
gst_mem_index_get_assoc_entry (GstIndex * index, gint id,
GstIndexLookupMethod method,
GstAssocFlags flags,
GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
{
GstMemIndex *memindex = GST_MEM_INDEX (index);
GstMemIndexId *id_index;
GstMemIndexFormatIndex *format_index;
GstIndexEntry *entry;
GstMemIndexSearchData data;
id_index = g_hash_table_lookup (memindex->id_index, &id);
if (!id_index)
return NULL;
format_index = g_hash_table_lookup (id_index->format_index, &format);
if (!format_index)
return NULL;
data.value = value;
data.index = format_index;
data.exact = (method == GST_INDEX_LOOKUP_EXACT);
/* setup data for low/high checks if we are not looking
* for an exact match */
if (!data.exact) {
data.low_diff = G_MININT64;
data.lower = NULL;
data.high_diff = G_MAXINT64;
data.higher = NULL;
}
entry = g_tree_search (format_index->tree, mem_index_search, &data);
/* get the low/high values if we're not exact */
if (entry == NULL && !data.exact) {
if (method == GST_INDEX_LOOKUP_BEFORE)
entry = data.lower;
else if (method == GST_INDEX_LOOKUP_AFTER) {
entry = data.higher;
}
}
if (entry) {
if ((GST_INDEX_ASSOC_FLAGS (entry) & flags) != flags) {
GList *l_entry = g_list_find (memindex->associations, entry);
entry = NULL;
while (l_entry) {
entry = (GstIndexEntry *) l_entry->data;
if (entry->id == id && (GST_INDEX_ASSOC_FLAGS (entry) & flags) == flags)
break;
if (method == GST_INDEX_LOOKUP_BEFORE)
l_entry = g_list_next (l_entry);
else if (method == GST_INDEX_LOOKUP_AFTER) {
l_entry = g_list_previous (l_entry);
}
}
}
}
return entry;
}
gboolean
gst_mem_index_plugin_init (GstPlugin * plugin)
{
GstIndexFactory *factory;
factory = gst_index_factory_new ("memindex",
"A index that stores entries in memory", gst_mem_index_get_type ());
if (factory == NULL) {
g_warning ("failed to create memindex factory");
return FALSE;
}
GST_PLUGIN_FEATURE (factory)->plugin_name = g_strdup (plugin->desc.name);
GST_PLUGIN_FEATURE (factory)->loaded = TRUE;
gst_registry_add_feature (gst_registry_get_default (),
GST_PLUGIN_FEATURE (factory));
return TRUE;
}