mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-04 05:22:30 +00:00
gst/debug/: Port progressreport, navseek, navigationtest, testsink and breakmydata.
Original commit message from CVS: * gst/debug/Makefile.am: * gst/debug/breakmydata.c: * gst/debug/gstdebug.c: * gst/debug/gstnavigationtest.c: * gst/debug/gstnavseek.c: * gst/debug/gstnavseek.h: * gst/debug/progressreport.c: * gst/debug/testplugin.c: Port progressreport, navseek, navigationtest, testsink and breakmydata.
This commit is contained in:
parent
76620459d5
commit
2fa12d1a6d
9 changed files with 736 additions and 596 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2005-10-05 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/debug/Makefile.am:
|
||||
* gst/debug/breakmydata.c:
|
||||
* gst/debug/gstdebug.c:
|
||||
* gst/debug/gstnavigationtest.c:
|
||||
* gst/debug/gstnavseek.c:
|
||||
* gst/debug/gstnavseek.h:
|
||||
* gst/debug/progressreport.c:
|
||||
* gst/debug/testplugin.c:
|
||||
Port progressreport, navseek, navigationtest, testsink and
|
||||
breakmydata.
|
||||
|
||||
2005-10-05 Edward Hervey <edward@fluendo.com>
|
||||
|
||||
* ext/dv/gstdvdemux.c: (gst_dvdemux_src_convert),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
plugin_LTLIBRARIES = libgstefence.la # libgstnavigationtest.la libgstdebug.la
|
||||
plugin_LTLIBRARIES = libgstefence.la libgstdebug.la libgstnavigationtest.la
|
||||
|
||||
noinst_HEADERS = efence.h gstnavigationtest.h gstnavseek.h tests.h
|
||||
|
||||
|
@ -7,18 +7,20 @@ libgstefence_la_CFLAGS = $(GST_CFLAGS)
|
|||
libgstefence_la_LIBADD = $(GST_LIBS)
|
||||
libgstefence_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
# libgstnavigationtest_la_SOURCES = gstnavigationtest.c
|
||||
# libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/gst/videofilter
|
||||
# libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
#
|
||||
# libgstdebug_la_SOURCES = \
|
||||
# gstdebug.c \
|
||||
# breakmydata.c \
|
||||
# negotiation.c \
|
||||
# gstnavseek.c \
|
||||
# progressreport.c \
|
||||
# tests.c \
|
||||
# testplugin.c
|
||||
#
|
||||
# libgstdebug_la_CFLAGS = $(GST_CFLAGS)
|
||||
# libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstnavigationtest_la_SOURCES = gstnavigationtest.c
|
||||
libgstnavigationtest_la_CFLAGS = $(GST_CFLAGS) -I$(top_srcdir)/gst/videofilter
|
||||
libgstnavigationtest_la_LIBADD = $(GST_LIBS) $(top_builddir)/gst/videofilter/libgstvideofilter-@GST_MAJORMINOR@.la
|
||||
libgstnavigationtest_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
libgstdebug_la_SOURCES = \
|
||||
gstdebug.c \
|
||||
breakmydata.c \
|
||||
progressreport.c \
|
||||
gstnavseek.c \
|
||||
tests.c \
|
||||
testplugin.c
|
||||
# negotiation.c
|
||||
|
||||
libgstdebug_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
|
||||
libgstdebug_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
|
||||
libgstdebug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_break_my_data_debug);
|
||||
#define GST_CAT_DEFAULT gst_break_my_data_debug
|
||||
|
@ -56,10 +57,7 @@ typedef struct _GstBreakMyDataClass GstBreakMyDataClass;
|
|||
|
||||
struct _GstBreakMyData
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstBaseTransform basetransform;
|
||||
|
||||
GRand *rand;
|
||||
guint skipped;
|
||||
|
@ -72,113 +70,91 @@ struct _GstBreakMyData
|
|||
|
||||
struct _GstBreakMyDataClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
GstBaseTransformClass parent_class;
|
||||
};
|
||||
|
||||
GST_BOILERPLATE (GstBreakMyData, gst_break_my_data, GstElement,
|
||||
GST_TYPE_ELEMENT)
|
||||
|
||||
static void gst_break_my_data_set_property (GObject * object,
|
||||
static void gst_break_my_data_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_break_my_data_get_property (GObject * object,
|
||||
static void gst_break_my_data_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_break_my_data_chain (GstPad * pad, GstData * _data);
|
||||
static GstStateChangeReturn gst_break_my_data_change_state (GstElement *
|
||||
element);
|
||||
static GstFlowReturn gst_break_my_data_transform_ip (GstBaseTransform * trans,
|
||||
GstBuffer * buf);
|
||||
static gboolean gst_break_my_data_stop (GstBaseTransform * trans);
|
||||
static gboolean gst_break_my_data_start (GstBaseTransform * trans);
|
||||
|
||||
static GstElementDetails details = GST_ELEMENT_DETAILS ("breakmydata",
|
||||
"Testing",
|
||||
"randomly change data in the stream",
|
||||
"Benjamin Otte <otte@gnome>");
|
||||
|
||||
GstStaticPadTemplate bmd_src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GstStaticPadTemplate bmd_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GST_BOILERPLATE (GstBreakMyData, gst_break_my_data, GstBaseTransform,
|
||||
GST_TYPE_BASE_TRANSFORM)
|
||||
|
||||
static void gst_break_my_data_base_init (gpointer g_class)
|
||||
{
|
||||
static GstElementDetails details = GST_ELEMENT_DETAILS ("breakmydata",
|
||||
"Testing",
|
||||
"randomly change data in the stream",
|
||||
"Benjamin Otte <otte@gnome>");
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&bmd_sink_template));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&bmd_src_template));
|
||||
|
||||
gst_element_class_set_details (gstelement_class, &details);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_break_my_data_class_init (GstBreakMyDataClass * klass)
|
||||
{
|
||||
GObjectClass *object = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element = GST_ELEMENT_CLASS (klass);
|
||||
GstBaseTransformClass *gstbasetrans_class;
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
object->set_property = GST_DEBUG_FUNCPTR (gst_break_my_data_set_property);
|
||||
object->get_property = GST_DEBUG_FUNCPTR (gst_break_my_data_get_property);
|
||||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
|
||||
g_object_class_install_property (object, ARG_SEED,
|
||||
gobject_class->set_property =
|
||||
GST_DEBUG_FUNCPTR (gst_break_my_data_set_property);
|
||||
gobject_class->get_property =
|
||||
GST_DEBUG_FUNCPTR (gst_break_my_data_get_property);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_SEED,
|
||||
g_param_spec_uint ("seed", "seed",
|
||||
"seed for randomness (initialized when goint from READY to PAUSED)",
|
||||
"seed for randomness (initialized when going from READY to PAUSED)",
|
||||
0, 0xFFFFFFFF, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object, ARG_SET_TO,
|
||||
g_object_class_install_property (gobject_class, ARG_SET_TO,
|
||||
g_param_spec_int ("set-to", "set-to",
|
||||
"set changed bytes to this value (-1 means random value",
|
||||
-1, 255, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object, ARG_SKIP,
|
||||
g_object_class_install_property (gobject_class, ARG_SKIP,
|
||||
g_param_spec_uint ("skip", "skip",
|
||||
"amount of bytes skipped at the beginning of stream",
|
||||
0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object, ARG_PROBABILITY,
|
||||
g_object_class_install_property (gobject_class, ARG_PROBABILITY,
|
||||
g_param_spec_double ("probability", "probability",
|
||||
"probability that a buffer is changed", 0.0, 1.0, 0.0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
"probability for each byte in the buffer to be changed", 0.0, 1.0,
|
||||
0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
element->change_state = gst_break_my_data_change_state;
|
||||
gstbasetrans_class->transform_ip =
|
||||
GST_DEBUG_FUNCPTR (gst_break_my_data_transform_ip);
|
||||
gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_break_my_data_start);
|
||||
gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_break_my_data_stop);
|
||||
gstbasetrans_class->passthrough_on_same_caps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_break_my_data_init (GstBreakMyData * break_my_data)
|
||||
gst_break_my_data_init (GstBreakMyData * bmd, GstBreakMyDataClass * g_class)
|
||||
{
|
||||
break_my_data->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (break_my_data), break_my_data->sinkpad);
|
||||
gst_pad_set_chain_function (break_my_data->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_break_my_data_chain));
|
||||
gst_pad_set_link_function (break_my_data->sinkpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (break_my_data->sinkpad, gst_pad_proxy_getcaps);
|
||||
|
||||
break_my_data->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (break_my_data), break_my_data->srcpad);
|
||||
gst_pad_set_link_function (break_my_data->srcpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (break_my_data->srcpad, gst_pad_proxy_getcaps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_break_my_data_chain (GstPad * pad, GstData * data)
|
||||
{
|
||||
GstBuffer *copy = NULL, *buf = GST_BUFFER (data);
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (gst_pad_get_parent (pad));
|
||||
guint i, size;
|
||||
|
||||
if (bmd->skipped < bmd->skip) {
|
||||
i = bmd->skip - bmd->skipped;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
GST_LOG_OBJECT (bmd,
|
||||
"got buffer %p (size %u, timestamp %" G_GUINT64_FORMAT ", offset %"
|
||||
G_GUINT64_FORMAT "", buf, size, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_OFFSET (buf));
|
||||
for (; i < size; i++) {
|
||||
if (g_rand_double_range (bmd->rand, 0, 1) < bmd->probability) {
|
||||
guint8 new;
|
||||
|
||||
if (!copy)
|
||||
copy = gst_buffer_copy_on_write (buf);
|
||||
if (bmd->set < 0) {
|
||||
new = g_rand_int_range (bmd->rand, 0, 256);
|
||||
} else {
|
||||
new = bmd->set;
|
||||
}
|
||||
GST_INFO_OBJECT (bmd, "changing byte %u from 0x%2X to 0x%2X", i,
|
||||
(gint) GST_BUFFER_DATA (copy)[i], (gint) new);
|
||||
GST_BUFFER_DATA (copy)[i] = new;
|
||||
}
|
||||
}
|
||||
/* don't overflow */
|
||||
bmd->skipped += MIN (G_MAXUINT - bmd->skipped, GST_BUFFER_SIZE (buf));
|
||||
gst_pad_push (bmd->srcpad, GST_DATA (copy ? copy : buf));
|
||||
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (bmd), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -187,6 +163,8 @@ gst_break_my_data_set_property (GObject * object, guint prop_id,
|
|||
{
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (object);
|
||||
|
||||
GST_LOCK (bmd);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SEED:
|
||||
bmd->seed = g_value_get_uint (value);
|
||||
|
@ -204,6 +182,8 @@ gst_break_my_data_set_property (GObject * object, guint prop_id,
|
|||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_UNLOCK (bmd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -212,6 +192,8 @@ gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
{
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (object);
|
||||
|
||||
GST_LOCK (bmd);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SEED:
|
||||
g_value_set_uint (value, bmd->seed);
|
||||
|
@ -229,27 +211,80 @@ gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_UNLOCK (bmd);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_break_my_data_change_state (GstElement * element, GstStateChange transition)
|
||||
static GstFlowReturn
|
||||
gst_break_my_data_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
||||
{
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (element);
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
|
||||
guint i, size;
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
bmd->rand = g_rand_new_with_seed (bmd->seed);
|
||||
bmd->skipped = 0;
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
g_rand_free (bmd->rand);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
g_return_val_if_fail (gst_buffer_is_writable (buf), GST_FLOW_ERROR);
|
||||
|
||||
GST_LOCK (bmd);
|
||||
|
||||
if (bmd->skipped < bmd->skip) {
|
||||
i = bmd->skip - bmd->skipped;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
|
||||
(element), GST_STATE_CHANGE_SUCCESS);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
GST_LOG_OBJECT (bmd,
|
||||
"got buffer %p (size %u, timestamp %" G_GUINT64_FORMAT ", offset %"
|
||||
G_GUINT64_FORMAT "", buf, size, GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_OFFSET (buf));
|
||||
|
||||
for (; i < size; i++) {
|
||||
if (g_rand_double_range (bmd->rand, 0, 1.0) <= bmd->probability) {
|
||||
guint8 new;
|
||||
|
||||
if (bmd->set < 0) {
|
||||
new = g_rand_int_range (bmd->rand, 0, 256);
|
||||
} else {
|
||||
new = bmd->set;
|
||||
}
|
||||
GST_INFO_OBJECT (bmd, "changing byte %u from 0x%02X to 0x%02X", i,
|
||||
(guint) GST_READ_UINT8 (GST_BUFFER_DATA (buf) + i),
|
||||
(guint) ((guint8) new));
|
||||
GST_BUFFER_DATA (buf)[i] = new;
|
||||
}
|
||||
}
|
||||
/* don't overflow */
|
||||
bmd->skipped += MIN (G_MAXUINT - bmd->skipped, GST_BUFFER_SIZE (buf));
|
||||
|
||||
GST_UNLOCK (bmd);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_break_my_data_start (GstBaseTransform * trans)
|
||||
{
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
|
||||
|
||||
GST_LOCK (bmd);
|
||||
bmd->rand = g_rand_new_with_seed (bmd->seed);
|
||||
bmd->skipped = 0;
|
||||
GST_UNLOCK (bmd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_break_my_data_stop (GstBaseTransform * trans)
|
||||
{
|
||||
GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
|
||||
|
||||
GST_LOCK (bmd);
|
||||
g_rand_free (bmd->rand);
|
||||
bmd->rand = NULL;
|
||||
GST_UNLOCK (bmd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -23,20 +23,20 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
|
||||
gboolean gst_break_my_data_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_negotiation_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_progress_report_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_navseek_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_progressreport_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_test_plugin_init (GstPlugin * plugin);
|
||||
gboolean gst_break_my_data_plugin_init (GstPlugin * plugin);
|
||||
|
||||
/* gboolean gst_negotiation_plugin_init (GstPlugin * plugin); */
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
if (!gst_break_my_data_plugin_init (plugin) ||
|
||||
!gst_negotiation_plugin_init (plugin) ||
|
||||
!gst_navseek_plugin_init (plugin) ||
|
||||
!gst_progressreport_plugin_init (plugin) ||
|
||||
/* !gst_negotiation_plugin_init (plugin) || */
|
||||
!gst_progress_report_plugin_init (plugin) ||
|
||||
!gst_test_plugin_init (plugin))
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -27,24 +27,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/*#define DEBUG_ENABLED */
|
||||
#include <gstnavigationtest.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* GstNavigationtest signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
|
@ -61,10 +47,6 @@ static void gst_navigationtest_init (GTypeInstance * instance,
|
|||
|
||||
static gboolean gst_navigationtest_handle_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
static void gst_navigationtest_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_navigationtest_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_navigationtest_change_state (GstElement * element,
|
||||
|
@ -74,7 +56,7 @@ static void gst_navigationtest_planar411 (GstVideofilter * videofilter,
|
|||
void *dest, void *src);
|
||||
static void gst_navigationtest_setup (GstVideofilter * videofilter);
|
||||
|
||||
static GstVideofilterClass *parent_class = NULL;
|
||||
static GstVideofilterClass *parent_class; /* NULL */
|
||||
|
||||
GType
|
||||
gst_navigationtest_get_type (void)
|
||||
|
@ -130,15 +112,11 @@ gst_navigationtest_base_init (gpointer g_class)
|
|||
static void
|
||||
gst_navigationtest_class_init (gpointer g_class, gpointer class_data)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (g_class);
|
||||
|
||||
gobject_class->set_property = gst_navigationtest_set_property;
|
||||
gobject_class->get_property = gst_navigationtest_get_property;
|
||||
|
||||
element_class->change_state = gst_navigationtest_change_state;
|
||||
|
||||
videofilter_class->setup = gst_navigationtest_setup;
|
||||
|
@ -147,67 +125,58 @@ gst_navigationtest_class_init (gpointer g_class, gpointer class_data)
|
|||
static void
|
||||
gst_navigationtest_init (GTypeInstance * instance, gpointer g_class)
|
||||
{
|
||||
GstNavigationtest *navigationtest = GST_NAVIGATIONTEST (instance);
|
||||
GstVideofilter *videofilter;
|
||||
|
||||
GST_DEBUG ("gst_navigationtest_init");
|
||||
|
||||
videofilter = GST_VIDEOFILTER (navigationtest);
|
||||
GstNavigationtest *navtest = GST_NAVIGATIONTEST (instance);
|
||||
GstVideofilter *videofilter = GST_VIDEOFILTER (navtest);
|
||||
|
||||
gst_pad_set_event_function (videofilter->srcpad,
|
||||
gst_navigationtest_handle_src_event);
|
||||
GST_DEBUG_FUNCPTR (gst_navigationtest_handle_src_event));
|
||||
|
||||
navigationtest->x = -1;
|
||||
navigationtest->y = -1;
|
||||
navtest->x = -1;
|
||||
navtest->y = -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstNavigationtest *navigationtest;
|
||||
GstNavigationtest *navtest;
|
||||
const gchar *type;
|
||||
|
||||
navigationtest = GST_NAVIGATIONTEST (gst_pad_get_parent (pad));
|
||||
navtest = GST_NAVIGATIONTEST (GST_PAD_PARENT (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NAVIGATION:
|
||||
type = gst_structure_get_string (event->event_data.structure.structure,
|
||||
"event");
|
||||
{
|
||||
const GstStructure *s = gst_event_get_structure (event);
|
||||
|
||||
type = gst_structure_get_string (s, "event");
|
||||
if (g_str_equal (type, "mouse-move")) {
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_x", &navigationtest->x);
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_y", &navigationtest->y);
|
||||
gst_structure_get_double (s, "pointer_x", &navtest->x);
|
||||
gst_structure_get_double (s, "pointer_y", &navtest->y);
|
||||
} else if (g_str_equal (type, "mouse-button-press")) {
|
||||
ButtonClick *click = g_new (ButtonClick, 1);
|
||||
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_x", &click->x);
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_y", &click->y);
|
||||
click->images_left = ceil (GST_VIDEOFILTER (navigationtest)->framerate);
|
||||
gst_structure_get_double (s, "pointer_x", &click->x);
|
||||
gst_structure_get_double (s, "pointer_y", &click->y);
|
||||
click->images_left = ceil (GST_VIDEOFILTER (navtest)->framerate);
|
||||
/* green */
|
||||
click->cy = 150;
|
||||
click->cu = 46;
|
||||
click->cv = 21;
|
||||
navigationtest->clicks =
|
||||
g_slist_prepend (navigationtest->clicks, click);
|
||||
navtest->clicks = g_slist_prepend (navtest->clicks, click);
|
||||
} else if (g_str_equal (type, "mouse-button-release")) {
|
||||
ButtonClick *click = g_new (ButtonClick, 1);
|
||||
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_x", &click->x);
|
||||
gst_structure_get_double (event->event_data.structure.structure,
|
||||
"pointer_y", &click->y);
|
||||
click->images_left = ceil (GST_VIDEOFILTER (navigationtest)->framerate);
|
||||
gst_structure_get_double (s, "pointer_x", &click->x);
|
||||
gst_structure_get_double (s, "pointer_y", &click->y);
|
||||
click->images_left = ceil (GST_VIDEOFILTER (navtest)->framerate);
|
||||
/* red */
|
||||
click->cy = 76;
|
||||
click->cu = 85;
|
||||
click->cv = 255;
|
||||
navigationtest->clicks =
|
||||
g_slist_prepend (navigationtest->clicks, click);
|
||||
navtest->clicks = g_slist_prepend (navtest->clicks, click);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -215,64 +184,7 @@ gst_navigationtest_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_navigationtest_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNavigationtest *src;
|
||||
|
||||
g_return_if_fail (GST_IS_NAVIGATIONTEST (object));
|
||||
src = GST_NAVIGATIONTEST (object);
|
||||
|
||||
GST_DEBUG ("gst_navigationtest_set_property");
|
||||
switch (prop_id) {
|
||||
#if 0
|
||||
case ARG_METHOD:
|
||||
src->method = g_value_get_enum (value);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_navigationtest_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNavigationtest *src;
|
||||
|
||||
g_return_if_fail (GST_IS_NAVIGATIONTEST (object));
|
||||
src = GST_NAVIGATIONTEST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
#if 0
|
||||
case ARG_METHOD:
|
||||
g_value_set_enum (value, src->method);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
if (!gst_library_load ("gstvideofilter"))
|
||||
return FALSE;
|
||||
|
||||
return gst_element_register (plugin, "navigationtest", GST_RANK_NONE,
|
||||
GST_TYPE_NAVIGATIONTEST);
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"navigationtest",
|
||||
"Template for a video filter",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
||||
|
||||
static void gst_navigationtest_setup (GstVideofilter * videofilter)
|
||||
gst_navigationtest_setup (GstVideofilter * videofilter)
|
||||
{
|
||||
GstNavigationtest *navigationtest;
|
||||
|
||||
|
@ -328,19 +240,20 @@ static void
|
|||
gst_navigationtest_planar411 (GstVideofilter * videofilter,
|
||||
void *dest, void *src)
|
||||
{
|
||||
GstNavigationtest *navigationtest;
|
||||
int width = gst_videofilter_get_input_width (videofilter);
|
||||
int height = gst_videofilter_get_input_height (videofilter);
|
||||
GstNavigationtest *navtest = (GstNavigationtest *) videofilter;
|
||||
gint width, height;
|
||||
GSList *walk;
|
||||
|
||||
g_return_if_fail (GST_IS_NAVIGATIONTEST (videofilter));
|
||||
navigationtest = GST_NAVIGATIONTEST (videofilter);
|
||||
|
||||
width = gst_videofilter_get_input_width (videofilter);
|
||||
height = gst_videofilter_get_input_height (videofilter);
|
||||
|
||||
/* do something interesting here. This simply copies the source
|
||||
* to the destination. */
|
||||
memcpy (dest, src, width * height + (width / 2) * (height / 2) * 2);
|
||||
|
||||
walk = navigationtest->clicks;
|
||||
walk = navtest->clicks;
|
||||
while (walk) {
|
||||
ButtonClick *click = walk->data;
|
||||
|
||||
|
@ -348,32 +261,55 @@ gst_navigationtest_planar411 (GstVideofilter * videofilter,
|
|||
draw_box_planar411 (dest, width, height, rint (click->x),
|
||||
rint (click->y), click->cy, click->cu, click->cv);
|
||||
if (--click->images_left < 1) {
|
||||
navigationtest->clicks = g_slist_remove (navigationtest->clicks, click);
|
||||
navtest->clicks = g_slist_remove (navtest->clicks, click);
|
||||
g_free (click);
|
||||
}
|
||||
}
|
||||
draw_box_planar411 (dest, width, height, rint (navigationtest->x),
|
||||
rint (navigationtest->y), 0, 128, 128);
|
||||
draw_box_planar411 (dest, width, height, rint (navtest->x),
|
||||
rint (navtest->y), 0, 128, 128);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_navigationtest_change_state (GstElement * element,
|
||||
GstStateChange transition)
|
||||
{
|
||||
GstNavigationtest *navigation = GST_NAVIGATIONTEST (element);
|
||||
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
||||
GstNavigationtest *navtest = GST_NAVIGATIONTEST (element);
|
||||
|
||||
/* upwards state changes */
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
while (navigation->clicks) {
|
||||
g_free (navigation->clicks->data);
|
||||
navigation->clicks =
|
||||
g_slist_remove (navigation->clicks, navigation->clicks->data);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
return GST_STATE_CHANGE_SUCCESS;
|
||||
/* downwards state changes */
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
{
|
||||
g_slist_foreach (navtest->clicks, (GFunc) g_free, NULL);
|
||||
g_slist_free (navtest->clicks);
|
||||
navtest->clicks = NULL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
return gst_element_register (plugin, "navigationtest", GST_RANK_NONE,
|
||||
GST_TYPE_NAVIGATIONTEST);
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"navigationtest",
|
||||
"Template for a video filter",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
|
||||
|
|
|
@ -27,22 +27,14 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gstnavseek.h>
|
||||
#include "gstnavseek.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* GstNavSeek signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_SEEKOFFSET
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
GstStaticPadTemplate navseek_src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
|
@ -55,49 +47,30 @@ GstStaticPadTemplate navseek_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static void gst_navseek_base_init (gpointer g_class);
|
||||
static void gst_navseek_class_init (gpointer g_class, gpointer class_data);
|
||||
static void gst_navseek_init (GTypeInstance * instance, gpointer g_class);
|
||||
static GstElementDetails navseek_details =
|
||||
GST_ELEMENT_DETAILS ("Seek based on left-right arrows",
|
||||
"Filter/Video",
|
||||
"Seek based on navigation keys left-right",
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>");
|
||||
|
||||
static gboolean gst_navseek_event (GstBaseTransform * trans, GstEvent * event);
|
||||
static GstFlowReturn gst_navseek_transform_ip (GstBaseTransform * basetrans,
|
||||
GstBuffer * buf);
|
||||
static gboolean gst_navseek_handle_src_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_navseek_stop (GstBaseTransform * trans);
|
||||
static gboolean gst_navseek_start (GstBaseTransform * trans);
|
||||
|
||||
static void gst_navseek_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_navseek_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_navseek_chain (GstPad * pad, GstData * _data);
|
||||
|
||||
static GType
|
||||
gst_navseek_get_type (void)
|
||||
{
|
||||
static GType navseek_type = 0;
|
||||
|
||||
if (!navseek_type) {
|
||||
static const GTypeInfo navseek_info = {
|
||||
sizeof (GstNavSeekClass),
|
||||
gst_navseek_base_init,
|
||||
NULL,
|
||||
gst_navseek_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstNavSeek),
|
||||
0,
|
||||
gst_navseek_init,
|
||||
};
|
||||
|
||||
navseek_type = g_type_register_static (GST_TYPE_ELEMENT,
|
||||
"GstNavSeek", &navseek_info, 0);
|
||||
}
|
||||
return navseek_type;
|
||||
}
|
||||
GST_BOILERPLATE (GstNavSeek, gst_navseek, GstBaseTransform,
|
||||
GST_TYPE_BASE_TRANSFORM);
|
||||
|
||||
static void
|
||||
gst_navseek_base_init (gpointer g_class)
|
||||
{
|
||||
static GstElementDetails navseek_details =
|
||||
GST_ELEMENT_DETAILS ("Seek based on left-right arrows",
|
||||
"Filter/Video",
|
||||
"Seek based on navigation keys left-right",
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>");
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
|
@ -109,43 +82,36 @@ gst_navseek_base_init (gpointer g_class)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_navseek_class_init (gpointer g_class, gpointer class_data)
|
||||
gst_navseek_class_init (GstNavSeekClass * klass)
|
||||
{
|
||||
GstBaseTransformClass *gstbasetrans_class;
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (g_class);
|
||||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (g_class),
|
||||
gobject_class->set_property = gst_navseek_set_property;
|
||||
gobject_class->get_property = gst_navseek_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
ARG_SEEKOFFSET, g_param_spec_double ("seek-offset", "Seek Offset",
|
||||
"Time in seconds to seek by", 0.0, G_MAXDOUBLE, 5.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_navseek_set_property;
|
||||
gobject_class->get_property = gst_navseek_get_property;
|
||||
gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_navseek_event);
|
||||
gstbasetrans_class->transform_ip =
|
||||
GST_DEBUG_FUNCPTR (gst_navseek_transform_ip);
|
||||
gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_navseek_start);
|
||||
gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_navseek_stop);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_navseek_init (GTypeInstance * instance, gpointer g_class)
|
||||
gst_navseek_init (GstNavSeek * navseek, GstNavSeekClass * g_class)
|
||||
{
|
||||
GstNavSeek *navseek = GST_NAVSEEK (instance);
|
||||
gst_pad_set_event_function (GST_BASE_TRANSFORM (navseek)->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_navseek_handle_src_event));
|
||||
|
||||
navseek->sinkpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&navseek_sink_template), "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (navseek), navseek->sinkpad);
|
||||
gst_pad_set_chain_function (navseek->sinkpad, gst_navseek_chain);
|
||||
gst_pad_set_link_function (navseek->sinkpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (navseek->sinkpad, gst_pad_proxy_getcaps);
|
||||
|
||||
navseek->srcpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&navseek_src_template), "src");
|
||||
gst_element_add_pad (GST_ELEMENT (navseek), navseek->srcpad);
|
||||
gst_pad_set_link_function (navseek->srcpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (navseek->srcpad, gst_pad_proxy_getcaps);
|
||||
gst_pad_set_event_function (navseek->srcpad, gst_navseek_handle_src_event);
|
||||
|
||||
GST_FLAG_SET (GST_ELEMENT (navseek), GST_ELEMENT_EVENT_AWARE);
|
||||
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (navseek), TRUE);
|
||||
|
||||
navseek->seek_offset = 5.0;
|
||||
navseek->loop = FALSE;
|
||||
|
@ -158,74 +124,90 @@ gst_navseek_init (GTypeInstance * instance, gpointer g_class)
|
|||
static void
|
||||
gst_navseek_seek (GstNavSeek * navseek, gint64 offset)
|
||||
{
|
||||
/* Query for the current time then attempt to set to time + offset */
|
||||
gint64 peer_value;
|
||||
GstFormat peer_format = GST_FORMAT_TIME;
|
||||
gboolean ret;
|
||||
GstPad *peer_pad;
|
||||
gint64 peer_value;
|
||||
|
||||
if (gst_pad_query (gst_pad_get_peer (navseek->sinkpad),
|
||||
GST_QUERY_POSITION, &peer_format, &peer_value)) {
|
||||
if (peer_format != GST_FORMAT_TIME)
|
||||
return;
|
||||
|
||||
/* Query for the current time then attempt to set to time + offset */
|
||||
peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
|
||||
ret = gst_pad_query_position (peer_pad, &peer_format, &peer_value, NULL);
|
||||
|
||||
if (ret && peer_format == GST_FORMAT_TIME) {
|
||||
GstEvent *event;
|
||||
|
||||
peer_value += offset;
|
||||
if (peer_value < 0)
|
||||
peer_value = 0;
|
||||
|
||||
gst_element_seek (GST_ELEMENT (navseek),
|
||||
GST_SEEK_METHOD_SET | GST_FORMAT_TIME | GST_SEEK_FLAG_ACCURATE |
|
||||
GST_SEEK_FLAG_FLUSH, peer_value);
|
||||
event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
|
||||
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
|
||||
GST_SEEK_TYPE_SET, peer_value, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
|
||||
|
||||
gst_pad_send_event (peer_pad, event);
|
||||
}
|
||||
|
||||
gst_object_unref (peer_pad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_navseek_segseek (GstNavSeek * navseek)
|
||||
{
|
||||
GstEvent *event;
|
||||
GstPad *peer_pad;
|
||||
|
||||
if ((navseek->segment_start == GST_CLOCK_TIME_NONE) ||
|
||||
(navseek->segment_end == GST_CLOCK_TIME_NONE) ||
|
||||
(!GST_PAD_IS_LINKED (navseek->sinkpad))) {
|
||||
(!GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (navseek->loop) {
|
||||
event =
|
||||
gst_event_new_segment_seek (GST_SEEK_METHOD_SET | GST_FORMAT_TIME |
|
||||
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT_LOOP,
|
||||
navseek->segment_start, navseek->segment_end);
|
||||
gst_event_new_seek (1.0, GST_FORMAT_TIME,
|
||||
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SEGMENT,
|
||||
GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
|
||||
navseek->segment_end);
|
||||
} else {
|
||||
event =
|
||||
gst_event_new_segment_seek (GST_SEEK_METHOD_SET | GST_FORMAT_TIME |
|
||||
GST_SEEK_FLAG_ACCURATE, navseek->segment_start, navseek->segment_end);
|
||||
gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_ACCURATE,
|
||||
GST_SEEK_TYPE_SET, navseek->segment_start, GST_SEEK_TYPE_SET,
|
||||
navseek->segment_end);
|
||||
}
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
gst_pad_send_event (gst_pad_get_peer (navseek->sinkpad), event);
|
||||
peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
|
||||
gst_pad_send_event (peer_pad, event);
|
||||
gst_object_unref (peer_pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_navseek_handle_src_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstNavSeek *navseek;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
navseek = GST_NAVSEEK (gst_pad_get_parent (pad));
|
||||
navseek = GST_NAVSEEK (GST_PAD_PARENT (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NAVIGATION:
|
||||
/* Check for a keyup and convert left/right to a seek event */
|
||||
{
|
||||
GstStructure *structure;
|
||||
const GstStructure *structure;
|
||||
const gchar *event_type;
|
||||
|
||||
structure = event->event_data.structure.structure;
|
||||
event_type = gst_structure_get_string (structure, "event");
|
||||
structure = gst_event_get_structure (event);
|
||||
g_return_val_if_fail (structure != NULL, FALSE);
|
||||
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
event_type = gst_structure_get_string (structure, "event");
|
||||
g_return_val_if_fail (event_type != NULL, FALSE);
|
||||
|
||||
if (strcmp (event_type, "key-press") == 0) {
|
||||
const char *key = gst_structure_get_string (structure, "key");
|
||||
const gchar *key;
|
||||
|
||||
key = gst_structure_get_string (structure, "key");
|
||||
g_return_val_if_fail (key != NULL, FALSE);
|
||||
|
||||
g_assert (key != NULL);
|
||||
if (strcmp (key, "Left") == 0) {
|
||||
/* Seek backward by 5 secs */
|
||||
gst_navseek_seek (navseek, -1.0 * navseek->seek_offset * GST_SECOND);
|
||||
|
@ -253,42 +235,28 @@ gst_navseek_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if ((event) && GST_PAD_IS_LINKED (navseek->sinkpad)) {
|
||||
return gst_pad_send_event (gst_pad_get_peer (navseek->sinkpad), event);
|
||||
|
||||
if (event && GST_PAD_IS_LINKED (GST_BASE_TRANSFORM (navseek)->sinkpad)) {
|
||||
GstPad *peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (navseek)->sinkpad);
|
||||
|
||||
ret = gst_pad_send_event (peer_pad, event);
|
||||
gst_object_unref (peer_pad);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_navseek_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNavSeek *src;
|
||||
|
||||
g_return_if_fail (GST_IS_NAVSEEK (object));
|
||||
src = GST_NAVSEEK (object);
|
||||
GstNavSeek *navseek = GST_NAVSEEK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SEEKOFFSET:
|
||||
src->seek_offset = g_value_get_double (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_navseek_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNavSeek *src;
|
||||
|
||||
g_return_if_fail (GST_IS_NAVSEEK (object));
|
||||
src = GST_NAVSEEK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SEEKOFFSET:
|
||||
g_value_set_double (value, src->seek_offset);
|
||||
GST_LOCK (navseek);
|
||||
navseek->seek_offset = g_value_get_double (value);
|
||||
GST_UNLOCK (navseek);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -297,34 +265,79 @@ gst_navseek_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static void
|
||||
gst_navseek_chain (GstPad * pad, GstData * _data)
|
||||
gst_navseek_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstNavSeek *navseek;
|
||||
GstNavSeek *navseek = GST_NAVSEEK (object);
|
||||
|
||||
navseek = GST_NAVSEEK (gst_pad_get_parent (pad));
|
||||
switch (prop_id) {
|
||||
case ARG_SEEKOFFSET:
|
||||
GST_LOCK (navseek);
|
||||
g_value_set_double (value, navseek->seek_offset);
|
||||
GST_UNLOCK (navseek);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_IS_BUFFER (_data) &&
|
||||
GST_BUFFER_TIMESTAMP_IS_VALID (GST_BUFFER (_data))) {
|
||||
static gboolean
|
||||
gst_navseek_event (GstBaseTransform * trans, GstEvent * event)
|
||||
{
|
||||
GstNavSeek *navseek = GST_NAVSEEK (trans);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
GST_LOCK (navseek);
|
||||
if (navseek->loop)
|
||||
gst_navseek_segseek (navseek);
|
||||
GST_UNLOCK (navseek);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_navseek_transform_ip (GstBaseTransform * basetrans, GstBuffer * buf)
|
||||
{
|
||||
GstNavSeek *navseek = GST_NAVSEEK (basetrans);
|
||||
|
||||
GST_LOCK (navseek);
|
||||
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
if (navseek->grab_seg_start) {
|
||||
navseek->segment_start = GST_BUFFER_TIMESTAMP (GST_BUFFER (_data));
|
||||
navseek->segment_start = GST_BUFFER_TIMESTAMP (buf);
|
||||
navseek->segment_end = GST_CLOCK_TIME_NONE;
|
||||
navseek->grab_seg_start = FALSE;
|
||||
}
|
||||
|
||||
if (navseek->grab_seg_end) {
|
||||
navseek->segment_end = GST_BUFFER_TIMESTAMP (GST_BUFFER (_data));
|
||||
navseek->segment_end = GST_BUFFER_TIMESTAMP (buf);
|
||||
navseek->grab_seg_end = FALSE;
|
||||
gst_navseek_segseek (navseek);
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_IS_EVENT (_data) &&
|
||||
(GST_EVENT_TYPE (GST_EVENT (_data)) == GST_EVENT_SEGMENT_DONE) &&
|
||||
navseek->loop) {
|
||||
gst_navseek_segseek (navseek);
|
||||
}
|
||||
GST_UNLOCK (navseek);
|
||||
|
||||
gst_pad_push (navseek->srcpad, _data);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_navseek_start (GstBaseTransform * trans)
|
||||
{
|
||||
/* anything we should be doing here? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_navseek_stop (GstBaseTransform * trans)
|
||||
{
|
||||
/* anything we should be doing here? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -41,20 +42,18 @@ typedef struct _GstNavSeek GstNavSeek;
|
|||
typedef struct _GstNavSeekClass GstNavSeekClass;
|
||||
|
||||
struct _GstNavSeek {
|
||||
GstElement element;
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstBaseTransform basetransform;
|
||||
|
||||
gdouble seek_offset;
|
||||
gboolean loop;
|
||||
gboolean grab_seg_start;
|
||||
gboolean grab_seg_end;
|
||||
GstClockTime segment_start;
|
||||
GstClockTime segment_end;
|
||||
gdouble seek_offset;
|
||||
gboolean loop;
|
||||
gboolean grab_seg_start;
|
||||
gboolean grab_seg_end;
|
||||
GstClockTime segment_start;
|
||||
GstClockTime segment_end;
|
||||
};
|
||||
|
||||
struct _GstNavSeekClass {
|
||||
GstElementClass parent_class;
|
||||
GstBaseTransformClass parent_class;
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -24,211 +24,320 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#define GST_TYPE_PROGRESSREPORT \
|
||||
(gst_progressreport_get_type())
|
||||
#define GST_PROGRESSREPORT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROGRESSREPORT,GstProgressReport))
|
||||
#define GST_PROGRESSREPORT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROGRESSREPORT,GstProgressReportClass))
|
||||
#define GST_IS_PROGRESSREPORT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROGRESSREPORT))
|
||||
#define GST_IS_PROGRESSREPORT_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESSREPORT))
|
||||
#define GST_TYPE_PROGRESS_REPORT \
|
||||
(gst_progress_report_get_type())
|
||||
#define GST_PROGRESS_REPORT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PROGRESS_REPORT,GstProgressReport))
|
||||
#define GST_PROGRESS_REPORT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PROGRESS_REPORT,GstProgressReportClass))
|
||||
#define GST_IS_PROGRESS_REPORT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PROGRESS_REPORT))
|
||||
#define GST_IS_PROGRESS_REPORT_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PROGRESS_REPORT))
|
||||
|
||||
typedef struct _GstProgressReport GstProgressReport;
|
||||
typedef struct _GstProgressReportClass GstProgressReportClass;
|
||||
|
||||
struct _GstProgressReport
|
||||
{
|
||||
GstElement element;
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
GstBaseTransform basetransform;
|
||||
|
||||
gint update_freq;
|
||||
gboolean silent;
|
||||
GTimeVal start_time;
|
||||
GTimeVal last_report;
|
||||
};
|
||||
|
||||
struct _GstProgressReportClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
/* GstProgressReport signals and args */
|
||||
enum
|
||||
{
|
||||
/* FILL ME */
|
||||
LAST_SIGNAL
|
||||
GstBaseTransformClass parent_class;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_UPDATE_FREQ
|
||||
/* FILL ME */
|
||||
ARG_UPDATE_FREQ,
|
||||
ARG_SILENT
|
||||
};
|
||||
|
||||
GstStaticPadTemplate progressreport_src_template =
|
||||
GstStaticPadTemplate progress_report_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
GstStaticPadTemplate progressreport_sink_template =
|
||||
GstStaticPadTemplate progress_report_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static void gst_progressreport_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_progressreport_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void gst_progressreport_chain (GstPad * pad, GstData * _data);
|
||||
static GstElementDetails progress_report_details =
|
||||
GST_ELEMENT_DETAILS ("Progress Report",
|
||||
"Testing",
|
||||
"Periodically query and report on processing progress",
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>");
|
||||
|
||||
GST_BOILERPLATE (GstProgressReport, gst_progressreport, GstElement,
|
||||
GST_TYPE_ELEMENT);
|
||||
#define DEFAULT_UPDATE_FREQ 5
|
||||
#define DEFAULT_SILENT FALSE
|
||||
|
||||
static void gst_progress_report_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_progress_report_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static gboolean gst_progress_report_event (GstBaseTransform * trans,
|
||||
GstEvent * event);
|
||||
static GstFlowReturn gst_progress_report_transform_ip (GstBaseTransform * trans,
|
||||
GstBuffer * buf);
|
||||
|
||||
static gboolean gst_progress_report_start (GstBaseTransform * trans);
|
||||
static gboolean gst_progress_report_stop (GstBaseTransform * trans);
|
||||
|
||||
GST_BOILERPLATE (GstProgressReport, gst_progress_report, GstBaseTransform,
|
||||
GST_TYPE_BASE_TRANSFORM);
|
||||
|
||||
static void
|
||||
gst_progressreport_base_init (gpointer g_class)
|
||||
gst_progress_report_base_init (gpointer g_class)
|
||||
{
|
||||
static GstElementDetails progressreport_details =
|
||||
GST_ELEMENT_DETAILS ("Progress Report",
|
||||
"Testing",
|
||||
"Periodically query and report on processing progress",
|
||||
"Jan Schmidt <thaytan@mad.scientist.com>");
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&progressreport_sink_template));
|
||||
gst_static_pad_template_get (&progress_report_sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&progressreport_src_template));
|
||||
gst_static_pad_template_get (&progress_report_src_template));
|
||||
|
||||
gst_element_class_set_details (element_class, &progressreport_details);
|
||||
gst_element_class_set_details (element_class, &progress_report_details);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_class_init (GstProgressReportClass * g_class)
|
||||
gst_progress_report_class_init (GstProgressReportClass * g_class)
|
||||
{
|
||||
GstBaseTransformClass *gstbasetrans_class;
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (g_class);
|
||||
gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (g_class);
|
||||
|
||||
gobject_class->set_property = gst_progress_report_set_property;
|
||||
gobject_class->get_property = gst_progress_report_get_property;
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (g_class),
|
||||
ARG_UPDATE_FREQ, g_param_spec_int ("update-freq", "Update Frequency",
|
||||
"Number of seconds between reports when data is flowing", 1, G_MAXINT,
|
||||
5, G_PARAM_READWRITE));
|
||||
DEFAULT_UPDATE_FREQ, G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_progressreport_set_property;
|
||||
gobject_class->get_property = gst_progressreport_get_property;
|
||||
g_object_class_install_property (G_OBJECT_CLASS (g_class),
|
||||
ARG_SILENT, g_param_spec_boolean ("silent",
|
||||
"Do not print output to stdout", "Do not print output to stdout",
|
||||
DEFAULT_SILENT, G_PARAM_READWRITE));
|
||||
|
||||
gstbasetrans_class->event = GST_DEBUG_FUNCPTR (gst_progress_report_event);
|
||||
gstbasetrans_class->transform_ip =
|
||||
GST_DEBUG_FUNCPTR (gst_progress_report_transform_ip);
|
||||
gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_progress_report_start);
|
||||
gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_progress_report_stop);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_init (GstProgressReport * instance,
|
||||
gst_progress_report_init (GstProgressReport * report,
|
||||
GstProgressReportClass * g_class)
|
||||
{
|
||||
GstProgressReport *progressreport = GST_PROGRESSREPORT (instance);
|
||||
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (report), TRUE);
|
||||
|
||||
progressreport->sinkpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&progressreport_sink_template), "sink");
|
||||
gst_element_add_pad (GST_ELEMENT (progressreport), progressreport->sinkpad);
|
||||
gst_pad_set_chain_function (progressreport->sinkpad,
|
||||
gst_progressreport_chain);
|
||||
gst_pad_set_link_function (progressreport->sinkpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (progressreport->sinkpad, gst_pad_proxy_getcaps);
|
||||
|
||||
progressreport->srcpad =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&progressreport_src_template), "src");
|
||||
gst_element_add_pad (GST_ELEMENT (progressreport), progressreport->srcpad);
|
||||
gst_pad_set_link_function (progressreport->srcpad, gst_pad_proxy_pad_link);
|
||||
gst_pad_set_getcaps_function (progressreport->srcpad, gst_pad_proxy_getcaps);
|
||||
|
||||
g_get_current_time (&(progressreport->last_report));
|
||||
progressreport->start_time = progressreport->last_report;
|
||||
progressreport->update_freq = 5;
|
||||
report->update_freq = DEFAULT_UPDATE_FREQ;
|
||||
report->silent = DEFAULT_SILENT;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_report (GstProgressReport * progressreport,
|
||||
GTimeVal cur_time)
|
||||
gst_progress_report_report (GstProgressReport * filter, GTimeVal cur_time)
|
||||
{
|
||||
/* Query for the current time then attempt to set to time + offset */
|
||||
GstFormat try_formats[] = { GST_FORMAT_TIME, GST_FORMAT_BYTES,
|
||||
GST_FORMAT_PERCENT, GST_FORMAT_BUFFERS,
|
||||
GST_FORMAT_DEFAULT
|
||||
};
|
||||
GstPad *peer_pad;
|
||||
gint64 cur_progress;
|
||||
gint64 total_progress;
|
||||
GstFormat peer_format = GST_FORMAT_DEFAULT;
|
||||
gint hh, mm, ss;
|
||||
glong run_time = cur_time.tv_sec - progressreport->start_time.tv_sec;
|
||||
gint hh, mm, ss, i;
|
||||
glong run_time;
|
||||
|
||||
GST_LOCK (filter);
|
||||
run_time = cur_time.tv_sec - filter->start_time.tv_sec;
|
||||
|
||||
hh = (run_time / 3600) % 100;
|
||||
mm = (run_time / 60) % 60;
|
||||
ss = (run_time % 60);
|
||||
|
||||
if (gst_pad_query (gst_pad_get_peer (progressreport->sinkpad),
|
||||
GST_QUERY_POSITION, &peer_format, &cur_progress)) {
|
||||
GstFormat peer_format2 = peer_format;
|
||||
gchar *format_name = NULL;
|
||||
gboolean got_total = FALSE;
|
||||
peer_pad = gst_pad_get_peer (GST_BASE_TRANSFORM (filter)->sinkpad);
|
||||
/* Query for the current time then attempt to set to time + offset */
|
||||
for (i = 0; i < G_N_ELEMENTS (try_formats); ++i) {
|
||||
const gchar *format_name = NULL;
|
||||
GstFormat format;
|
||||
|
||||
if ((gst_pad_query (gst_pad_get_peer (progressreport->sinkpad),
|
||||
GST_QUERY_TOTAL, &peer_format2, &total_progress)) &&
|
||||
(peer_format == peer_format2))
|
||||
got_total = TRUE;
|
||||
format = try_formats[i];
|
||||
|
||||
switch (peer_format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
format_name = "bytes";
|
||||
break;
|
||||
case GST_FORMAT_TIME:
|
||||
format_name = "seconds";
|
||||
cur_progress /= GST_SECOND;
|
||||
total_progress /= GST_SECOND;
|
||||
break;
|
||||
case GST_FORMAT_BUFFERS:
|
||||
format_name = "buffers";
|
||||
break;
|
||||
case GST_FORMAT_PERCENT:
|
||||
format_name = "percent";
|
||||
break;
|
||||
default:
|
||||
format_name = "unknown";
|
||||
break;
|
||||
if (gst_pad_query_position (peer_pad, &format, &cur_progress,
|
||||
&total_progress)) {
|
||||
switch (format) {
|
||||
case GST_FORMAT_BYTES:
|
||||
format_name = "bytes";
|
||||
break;
|
||||
case GST_FORMAT_BUFFERS:
|
||||
format_name = "buffers";
|
||||
break;
|
||||
case GST_FORMAT_PERCENT:
|
||||
format_name = "percent";
|
||||
break;
|
||||
case GST_FORMAT_TIME:
|
||||
format_name = "seconds";
|
||||
cur_progress /= GST_SECOND;
|
||||
total_progress /= GST_SECOND;
|
||||
break;
|
||||
case GST_FORMAT_DEFAULT:
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
format_name = "bogounits";
|
||||
caps = GST_PAD_CAPS (GST_BASE_TRANSFORM (filter)->sinkpad);
|
||||
if (caps && gst_caps_is_fixed (caps) && !gst_caps_is_any (caps)) {
|
||||
GstStructure *s = gst_caps_get_structure (caps, 0);
|
||||
const gchar *mime_type = gst_structure_get_name (s);
|
||||
|
||||
if (g_str_has_prefix (mime_type, "video/")
|
||||
|| g_str_has_prefix (mime_type, "image/")) {
|
||||
format_name = "frames";
|
||||
} else if (g_str_has_prefix (mime_type, "audio/")) {
|
||||
format_name = "samples";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
const GstFormatDefinition *details;
|
||||
|
||||
details = gst_format_get_details (format);
|
||||
if (details) {
|
||||
format_name = details->nick;
|
||||
} else {
|
||||
format_name = "unknown";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter->silent) {
|
||||
if (total_progress > 0) {
|
||||
g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " / %"
|
||||
G_GINT64_FORMAT " %s (%4.1f %%)\n", GST_OBJECT_NAME (filter), hh,
|
||||
mm, ss, cur_progress, total_progress, format_name,
|
||||
(gdouble) cur_progress / total_progress * 100.0);
|
||||
} else {
|
||||
g_print ("%s (%02d:%02d:%02d): %" G_GINT64_FORMAT " %s\n",
|
||||
GST_OBJECT_NAME (filter), hh, mm, ss, cur_progress, format_name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (got_total == TRUE) {
|
||||
g_print ("%s (%2d:%2d:%2d): %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT
|
||||
" %s (%3.2g %%)\n",
|
||||
gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss,
|
||||
cur_progress, total_progress, format_name,
|
||||
((gdouble) (cur_progress)) / total_progress * 100);
|
||||
} else {
|
||||
g_print ("%s (%2d:%2d:%2d): %" G_GINT64_FORMAT " %s\n",
|
||||
gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss,
|
||||
cur_progress, format_name);
|
||||
}
|
||||
} else {
|
||||
g_print ("%s (%2d:%2d:%2d): Could not query current position.\n",
|
||||
gst_object_get_name (GST_OBJECT (progressreport)), hh, mm, ss);
|
||||
}
|
||||
|
||||
if (i == G_N_ELEMENTS (try_formats)) {
|
||||
g_print ("%s (%2d:%2d:%2d): Could not query current position.\n",
|
||||
GST_OBJECT_NAME (filter), hh, mm, ss);
|
||||
}
|
||||
|
||||
GST_UNLOCK (filter);
|
||||
|
||||
gst_object_unref (peer_pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_progress_report_event (GstBaseTransform * trans, GstEvent * event)
|
||||
{
|
||||
GstProgressReport *filter;
|
||||
|
||||
filter = GST_PROGRESS_REPORT (trans);
|
||||
|
||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
|
||||
GTimeVal cur_time;
|
||||
|
||||
g_get_current_time (&cur_time);
|
||||
gst_progress_report_report (filter, cur_time);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_progress_report_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
||||
{
|
||||
GstProgressReport *filter;
|
||||
gboolean need_update;
|
||||
GTimeVal cur_time;
|
||||
|
||||
g_get_current_time (&cur_time);
|
||||
|
||||
filter = GST_PROGRESS_REPORT (trans);
|
||||
|
||||
/* Check if update_freq seconds have passed since the last update */
|
||||
GST_LOCK (filter);
|
||||
need_update =
|
||||
((cur_time.tv_sec - filter->last_report.tv_sec) >= filter->update_freq);
|
||||
GST_UNLOCK (filter);
|
||||
|
||||
if (need_update) {
|
||||
gst_progress_report_report (filter, cur_time);
|
||||
GST_LOCK (filter);
|
||||
filter->last_report = cur_time;
|
||||
GST_UNLOCK (filter);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_progress_report_start (GstBaseTransform * trans)
|
||||
{
|
||||
GstProgressReport *filter;
|
||||
|
||||
filter = GST_PROGRESS_REPORT (trans);
|
||||
|
||||
g_get_current_time (&filter->last_report);
|
||||
filter->start_time = filter->last_report;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_progress_report_stop (GstBaseTransform * trans)
|
||||
{
|
||||
/* anything we should be doing here? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_set_property (GObject * object, guint prop_id,
|
||||
gst_progress_report_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstProgressReport *src;
|
||||
GstProgressReport *filter;
|
||||
|
||||
g_return_if_fail (GST_IS_PROGRESSREPORT (object));
|
||||
src = GST_PROGRESSREPORT (object);
|
||||
filter = GST_PROGRESS_REPORT (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_UPDATE_FREQ:
|
||||
src->update_freq = g_value_get_int (value);
|
||||
GST_LOCK (filter);
|
||||
filter->update_freq = g_value_get_int (value);
|
||||
GST_UNLOCK (filter);
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
GST_LOCK (filter);
|
||||
filter->silent = g_value_get_boolean (value);
|
||||
GST_UNLOCK (filter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -236,17 +345,23 @@ gst_progressreport_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_get_property (GObject * object, guint prop_id,
|
||||
gst_progress_report_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstProgressReport *src;
|
||||
GstProgressReport *filter;
|
||||
|
||||
g_return_if_fail (GST_IS_PROGRESSREPORT (object));
|
||||
src = GST_PROGRESSREPORT (object);
|
||||
filter = GST_PROGRESS_REPORT (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_UPDATE_FREQ:
|
||||
g_value_set_int (value, src->update_freq);
|
||||
GST_LOCK (filter);
|
||||
g_value_set_int (value, filter->update_freq);
|
||||
GST_UNLOCK (filter);
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
GST_LOCK (filter);
|
||||
g_value_set_boolean (value, filter->silent);
|
||||
GST_UNLOCK (filter);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -254,29 +369,10 @@ gst_progressreport_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_progressreport_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
GstProgressReport *progressreport;
|
||||
GTimeVal cur_time;
|
||||
|
||||
g_get_current_time (&cur_time);
|
||||
|
||||
progressreport = GST_PROGRESSREPORT (gst_pad_get_parent (pad));
|
||||
|
||||
/* Check if update_freq seconds have passed since the last update */
|
||||
if ((cur_time.tv_sec - progressreport->last_report.tv_sec) >=
|
||||
progressreport->update_freq) {
|
||||
gst_progressreport_report (progressreport, cur_time);
|
||||
progressreport->last_report = cur_time;
|
||||
}
|
||||
|
||||
gst_pad_push (progressreport->srcpad, _data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_progressreport_plugin_init (GstPlugin * plugin, GstPluginClass * g_class)
|
||||
gst_progress_report_plugin_init (GstPlugin * plugin, GstPluginClass * g_class)
|
||||
{
|
||||
return gst_element_register (plugin, "progressreport", GST_RANK_NONE,
|
||||
GST_TYPE_PROGRESSREPORT);
|
||||
GST_TYPE_PROGRESS_REPORT);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasesink.h>
|
||||
#include "tests.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_test_debug);
|
||||
|
@ -48,9 +49,7 @@ typedef struct _GstTestClass GstTestClass;
|
|||
|
||||
struct _GstTest
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstBaseSink basesink;
|
||||
|
||||
gpointer tests[TESTS_COUNT];
|
||||
GValue values[TESTS_COUNT];
|
||||
|
@ -58,50 +57,71 @@ struct _GstTest
|
|||
|
||||
struct _GstTestClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
GstBaseSinkClass parent_class;
|
||||
|
||||
gchar *param_names[2 * TESTS_COUNT];
|
||||
};
|
||||
|
||||
GST_BOILERPLATE (GstTest, gst_test, GstElement, GST_TYPE_ELEMENT)
|
||||
static gboolean gst_test_start (GstBaseSink * trans);
|
||||
static gboolean gst_test_stop (GstBaseSink * trans);
|
||||
static gboolean gst_test_sink_event (GstBaseSink * basesink, GstEvent * event);
|
||||
static GstFlowReturn gst_test_render_buffer (GstBaseSink * basesink,
|
||||
GstBuffer * buf);
|
||||
|
||||
static void gst_test_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_test_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
static void gst_test_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_test_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void gst_test_chain (GstPad * pad, GstData * _data);
|
||||
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
|
||||
static GstElementDetails details = GST_ELEMENT_DETAILS ("gsttestsink",
|
||||
"Testing",
|
||||
"perform a number of tests",
|
||||
"Benjamin Otte <otte@gnome>");
|
||||
|
||||
GST_BOILERPLATE (GstTest, gst_test, GstBaseSink, GST_TYPE_BASE_SINK)
|
||||
|
||||
static void gst_test_base_init (gpointer g_class)
|
||||
{
|
||||
static GstElementDetails details = GST_ELEMENT_DETAILS ("gsttestsink",
|
||||
"Testing",
|
||||
"perform a number of tests",
|
||||
"Benjamin Otte <otte@gnome>");
|
||||
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, &details);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_class_init (GstTestClass * klass)
|
||||
{
|
||||
GObjectClass *object = G_OBJECT_CLASS (klass);
|
||||
GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
guint i;
|
||||
|
||||
object->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property);
|
||||
object->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property);
|
||||
object_class->set_property = GST_DEBUG_FUNCPTR (gst_test_set_property);
|
||||
object_class->get_property = GST_DEBUG_FUNCPTR (gst_test_get_property);
|
||||
|
||||
for (i = 0; i < TESTS_COUNT; i++) {
|
||||
GParamSpec *spec;
|
||||
|
||||
spec = tests[i].get_spec (&tests[i], FALSE);
|
||||
klass->param_names[2 * i] = g_strdup (g_param_spec_get_name (spec));
|
||||
g_object_class_install_property (object, 2 * i + 1, spec);
|
||||
g_object_class_install_property (object_class, 2 * i + 1, spec);
|
||||
spec = tests[i].get_spec (&tests[i], TRUE);
|
||||
klass->param_names[2 * i + 1] = g_strdup (g_param_spec_get_name (spec));
|
||||
g_object_class_install_property (object, 2 * i + 2, spec);
|
||||
g_object_class_install_property (object_class, 2 * i + 2, spec);
|
||||
}
|
||||
|
||||
basesink_class->preroll = GST_DEBUG_FUNCPTR (gst_test_render_buffer);
|
||||
basesink_class->render = GST_DEBUG_FUNCPTR (gst_test_render_buffer);
|
||||
basesink_class->event = GST_DEBUG_FUNCPTR (gst_test_sink_event);
|
||||
basesink_class->start = GST_DEBUG_FUNCPTR (gst_test_start);
|
||||
basesink_class->stop = GST_DEBUG_FUNCPTR (gst_test_stop);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -110,13 +130,6 @@ gst_test_init (GstTest * test, GstTestClass * g_class)
|
|||
GstTestClass *klass;
|
||||
guint i;
|
||||
|
||||
GST_FLAG_SET (test, GST_ELEMENT_EVENT_AWARE);
|
||||
|
||||
test->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (test), test->sinkpad);
|
||||
gst_pad_set_chain_function (test->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_test_chain));
|
||||
|
||||
klass = GST_TEST_GET_CLASS (test);
|
||||
for (i = 0; i < TESTS_COUNT; i++) {
|
||||
GParamSpec *spec = g_object_class_find_property (G_OBJECT_CLASS (klass),
|
||||
|
@ -150,61 +163,88 @@ tests_set (GstTest * test)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_test_chain (GstPad * pad, GstData * data)
|
||||
static gboolean
|
||||
gst_test_sink_event (GstBaseSink * basesink, GstEvent * event)
|
||||
{
|
||||
guint i;
|
||||
GstTest *test = GST_TEST (gst_pad_get_parent (pad));
|
||||
GstTestClass *klass = GST_TEST_GET_CLASS (test);
|
||||
GstTestClass *klass = GST_TEST_GET_CLASS (basesink);
|
||||
GstTest *test = GST_TEST (basesink);
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (GST_IS_EVENT (data)) {
|
||||
GstEvent *event = GST_EVENT (data);
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
/*
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
|
||||
tests_unset (test);
|
||||
tests_set (test);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case GST_EVENT_EOS:{
|
||||
gint i;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
|
||||
tests_unset (test);
|
||||
tests_set (test);
|
||||
}
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
g_object_freeze_notify (G_OBJECT (test));
|
||||
for (i = 0; i < TESTS_COUNT; i++) {
|
||||
if (test->tests[i]) {
|
||||
if (!tests[i].finish (test->tests[i], &test->values[i])) {
|
||||
GValue v = { 0, };
|
||||
gchar *real, *expected;
|
||||
g_object_freeze_notify (G_OBJECT (test));
|
||||
for (i = 0; i < TESTS_COUNT; i++) {
|
||||
if (test->tests[i]) {
|
||||
if (!tests[i].finish (test->tests[i], &test->values[i])) {
|
||||
GValue v = { 0, };
|
||||
gchar *real, *expected;
|
||||
|
||||
expected = gst_value_serialize (&test->values[i]);
|
||||
g_value_init (&v, G_VALUE_TYPE (&test->values[i]));
|
||||
g_object_get_property (G_OBJECT (test), klass->param_names[2 * i],
|
||||
&v);
|
||||
real = gst_value_serialize (&v);
|
||||
g_value_unset (&v);
|
||||
GST_ELEMENT_ERROR (test, STREAM, FORMAT, (NULL),
|
||||
("test %s returned value \"%s\" and not expected value \"%s\"",
|
||||
klass->param_names[2 * i], real, expected));
|
||||
g_free (real);
|
||||
g_free (expected);
|
||||
}
|
||||
g_object_notify (G_OBJECT (test), klass->param_names[2 * i]);
|
||||
expected = gst_value_serialize (&test->values[i]);
|
||||
g_value_init (&v, G_VALUE_TYPE (&test->values[i]));
|
||||
g_object_get_property (G_OBJECT (test), klass->param_names[2 * i],
|
||||
&v);
|
||||
real = gst_value_serialize (&v);
|
||||
g_value_unset (&v);
|
||||
GST_ELEMENT_ERROR (test, STREAM, FORMAT, (NULL),
|
||||
("test %s returned value \"%s\" and not expected value \"%s\"",
|
||||
klass->param_names[2 * i], real, expected));
|
||||
g_free (real);
|
||||
g_free (expected);
|
||||
}
|
||||
g_object_notify (G_OBJECT (test), klass->param_names[2 * i]);
|
||||
}
|
||||
g_object_thaw_notify (G_OBJECT (test));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_object_thaw_notify (G_OBJECT (test));
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
gst_pad_event_default (pad, event);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_test_render_buffer (GstBaseSink * basesink, GstBuffer * buf)
|
||||
{
|
||||
GstTest *test = GST_TEST (basesink);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < TESTS_COUNT; i++) {
|
||||
if (test->tests[i]) {
|
||||
tests[i].add (test->tests[i], GST_BUFFER (data));
|
||||
tests[i].add (test->tests[i], buf);
|
||||
}
|
||||
}
|
||||
gst_data_unref (data);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_test_start (GstBaseSink * sink)
|
||||
{
|
||||
GstTest *test = GST_TEST (sink);
|
||||
|
||||
tests_set (test);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_test_stop (GstBaseSink * sink)
|
||||
{
|
||||
GstTest *test = GST_TEST (sink);
|
||||
|
||||
tests_unset (test);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -223,7 +263,9 @@ gst_test_set_property (GObject * object, guint prop_id,
|
|||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
} else {
|
||||
/* expected values */
|
||||
GST_LOCK (test);
|
||||
g_value_copy (value, &test->values[prop_id / 2 - 1]);
|
||||
GST_UNLOCK (test);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,6 +281,8 @@ gst_test_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
return;
|
||||
}
|
||||
|
||||
GST_LOCK (test);
|
||||
|
||||
if (prop_id % 2) {
|
||||
/* real values */
|
||||
tests[id].get_value (test->tests[id], value);
|
||||
|
@ -246,6 +290,8 @@ gst_test_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
/* expected values */
|
||||
g_value_copy (&test->values[id], value);
|
||||
}
|
||||
|
||||
GST_UNLOCK (test);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
Loading…
Reference in a new issue