Author: dmeyer
Date: Tue Feb 6 11:15:07 2007
New Revision: 2462
Added:
trunk/WIP/record/src/gstmain.c
trunk/WIP/record/src/gsttssplitter.c
trunk/WIP/record/src/gsttssplitter.h
trunk/WIP/record/test/splitter.py
Modified:
trunk/WIP/record/setup.py
trunk/WIP/record/src/__init__.py
trunk/WIP/record/src/gstdvbtuner.c
trunk/WIP/record/src/gstdvbtuner.h
Log:
add tssplitter from soenke for testing
Modified: trunk/WIP/record/setup.py
==============================================================================
--- trunk/WIP/record/setup.py (original)
+++ trunk/WIP/record/setup.py Tue Feb 6 11:15:07 2007
@@ -12,10 +12,9 @@
# It is a gstreamer plugin not in the gstreamer plugin path.
# When kaa.record2 is init, this module will be added to
# gstreaner on runtime.
-tuner = Extension('kaa.record2._gstdvbtuner',
- [ 'src/gstdvbtuner.c' ],
+tuner = Extension('kaa.record2._gstrecord',
+ [ 'src/gstdvbtuner.c', 'src/gsttssplitter.c',
'src/gstmain.c' ],
config='src/config.h')
-
tuner.config('#define VERSION "0.1"')
tuner.config('#define PACKAGE "kaa.record"')
Modified: trunk/WIP/record/src/__init__.py
==============================================================================
--- trunk/WIP/record/src/__init__.py (original)
+++ trunk/WIP/record/src/__init__.py Tue Feb 6 11:15:07 2007
@@ -3,4 +3,4 @@
dirname = os.path.dirname(__file__)
# add our gstreamer plugins
-gst.plugin_load_file(dirname + '/_gstdvbtuner.so')
+gst.plugin_load_file(dirname + '/_gstrecord.so')
Modified: trunk/WIP/record/src/gstdvbtuner.c
==============================================================================
--- trunk/WIP/record/src/gstdvbtuner.c (original)
+++ trunk/WIP/record/src/gstdvbtuner.c Tue Feb 6 11:15:07 2007
@@ -66,17 +66,20 @@
#include <unistd.h>
#include <string.h>
-#include "dvb/dmx.h"
-#include "dvb/frontend.h"
-
#include "gstdvbtuner.h"
#include "config.h"
+static void gst_dvbtuner_set_new_adapter_fn(GstDvbTuner *filter);
+static void gst_dvbtuner_tuner_init(GstDvbTuner *filter);
+static void gst_dvbtuner_tuner_release(GstDvbTuner *filter);
+static void gst_dvbtuner_add_pid (GstDvbTuner *filter, uint pid);
+static void gst_dvbtuner_remove_pid (GstDvbTuner *filter, uint pid);
+static void gst_dvbtuner_clear_pids (GstDvbTuner *filter);
+static void gst_dvbtuner_tune (GstDvbTuner *filter);
+static gchar* gst_dvbtuner_get_status(GstDvbTuner *filter);
-/*
**********************************************************************************++
*/
-GST_DEBUG_CATEGORY_STATIC (gst_dvbtuner_debug);
-#define GST_CAT_DEFAULT gst_dvbtuner_debug
+/*
**********************************************************************************++
*/
/* Filter signals and args */
enum
@@ -267,10 +270,10 @@
if (!guard_pattern_type) {
static GEnumValue pattern_types[] = {
- { GUARD_INTERVAL_1_32, "1_32", "1_32" },
- { GUARD_INTERVAL_1_16, "1_16", "1_16" },
- { GUARD_INTERVAL_1_8, "1_8", "1_8" },
- { GUARD_INTERVAL_1_4, "1_4", "1_4" },
+ { GUARD_INTERVAL_1_32, "1/32", "1/32" },
+ { GUARD_INTERVAL_1_16, "1/16", "1/16" },
+ { GUARD_INTERVAL_1_8, "1/8", "1/8" },
+ { GUARD_INTERVAL_1_4, "1/4", "1/4" },
{ GUARD_INTERVAL_AUTO, "AUTO", "AUTO" },
{ 0, NULL, NULL },
};
@@ -295,8 +298,8 @@
if (!transmission_mode_pattern_type) {
static GEnumValue pattern_types[] = {
- { TRANSMISSION_MODE_2K, "2k", "2k" },
- { TRANSMISSION_MODE_8K, "8k", "8k" },
+ { TRANSMISSION_MODE_2K, "2K", "2K" },
+ { TRANSMISSION_MODE_8K, "8K", "8K" },
{ TRANSMISSION_MODE_AUTO, "AUTO", "AUTO" },
{ 0, NULL, NULL },
};
@@ -406,7 +409,7 @@
gobject_class->get_property = gst_dvbtuner_get_property;
g_object_class_install_property (gobject_class, PROP_DEBUG_OUTPUT,
- g_param_spec_boolean ("debug-output", "DebugOutput", "Produce verbose
debug output ?",
+ g_param_spec_boolean ("debug-output", "DebugOutput", "Produce verbose
debug output?",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_ADAPTER,
@@ -1045,71 +1048,6 @@
}
}
-/* GstElement vmethod implementations */
-
-/* this function handles the link with other elements */
-/* static gboolean */
-/* gst_dvbtuner_set_caps (GstPad * pad, GstCaps * caps) */
-/* { */
-/* GstDvbTuner *filter; */
-/* GstPad *otherpad; */
-
-/* filter = GST_DVBTUNER (gst_pad_get_parent (pad)); */
-/* otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; */
-
-/* return gst_pad_set_caps (pad, caps); */
-/* } */
-
-/* chain function
- * this function does the actual processing
- */
-
-/* static GstFlowReturn */
-/* gst_dvbtuner_chain (GstPad * pad, GstBuffer * buf) */
-/* { */
-/* GstDvbTuner *filter; */
-
-/* filter = GST_DVBTUNER (GST_OBJECT_PARENT (pad)); */
-
-/* if (filter->debug_output == FALSE) */
-/* g_print ("I'm plugged, therefore I'm in."); */
-
-/* /\* just push out the incoming buffer without touching it *\/ */
-/* return gst_pad_push (filter->srcpad, buf); */
-/* } */
-
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and pad templates
- * register the features
- *
- * exchange the string 'plugin' with your elemnt name
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- /* exchange the strings 'plugin' and 'Template plugin' with your
- * plugin name and description */
- GST_DEBUG_CATEGORY_INIT (gst_dvbtuner_debug, "dvbtuner",
- 0, "plugin for tuning dvb devices");
-
- return gst_element_register (plugin, "dvbtuner",
- GST_RANK_NONE, GST_TYPE_DVBTUNER);
-}
-
-/* this is the structure that gstreamer looks for to register plugins
- *
- * exchange the strings 'plugin' and 'Template plugin' with you plugin name and
- * description
- */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "freevo",
- "freevo specific plugins",
- plugin_init, VERSION, "GPL", "FreevoBinaryPackage",
"http://www.freevo.org/")
-
-
/******/
static void
Modified: trunk/WIP/record/src/gstdvbtuner.h
==============================================================================
--- trunk/WIP/record/src/gstdvbtuner.h (original)
+++ trunk/WIP/record/src/gstdvbtuner.h Tue Feb 6 11:15:07 2007
@@ -47,9 +47,13 @@
#include <sys/time.h>
#include <time.h>
+#include <stdint.h>
#include <gst/gst.h>
+#include "dvb/dmx.h"
+#include "dvb/frontend.h"
+
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
@@ -149,15 +153,6 @@
GType gst_dvbtuner_get_type (void);
-static void gst_dvbtuner_set_new_adapter_fn(GstDvbTuner *filter);
-static void gst_dvbtuner_tuner_init(GstDvbTuner *filter);
-static void gst_dvbtuner_tuner_release(GstDvbTuner *filter);
-static void gst_dvbtuner_add_pid (GstDvbTuner *filter, uint pid);
-static void gst_dvbtuner_remove_pid (GstDvbTuner *filter, uint pid);
-static void gst_dvbtuner_clear_pids (GstDvbTuner *filter);
-static void gst_dvbtuner_tune (GstDvbTuner *filter);
-static gchar* gst_dvbtuner_get_status(GstDvbTuner *filter);
-
G_END_DECLS
#endif /* __GST_DVBTUNER_H__ */
Added: trunk/WIP/record/src/gstmain.c
==============================================================================
--- (empty file)
+++ trunk/WIP/record/src/gstmain.c Tue Feb 6 11:15:07 2007
@@ -0,0 +1,27 @@
+#include "config.h"
+
+#include <gst/gst.h>
+
+#include "gstdvbtuner.h"
+#include "gsttssplitter.h"
+
+GST_DEBUG_CATEGORY (kaa_debug);
+#define GST_CAT_DEFAULT kaa_debug
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GST_DEBUG_CATEGORY_INIT (kaa_debug, "kaa", 0,
+ "special elements for processing dvb/video cards - used by kaa");
+
+ return gst_element_register (plugin, "tssplitter",
+ GST_RANK_NONE, GST_TYPE_TSSPLITTER) &&
+ gst_element_register (plugin, "dvbtuner",
+ GST_RANK_NONE, GST_TYPE_DVBTUNER);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "kaarecord",
+ "Plugin contains kaa specific plugins for dvb cards and video stream
processing",
+ plugin_init, VERSION, "LGPL", "KaaRecord", "http://www.freevo.org/kaa")
Added: trunk/WIP/record/src/gsttssplitter.c
==============================================================================
--- (empty file)
+++ trunk/WIP/record/src/gsttssplitter.c Tue Feb 6 11:15:07 2007
@@ -0,0 +1,636 @@
+/**
+ * SECTION:element-plugin
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * <para>
+ * <programlisting>
+ * gst-launch -v -m audiotestsrc ! plugin ! fakesink silent=TRUE
+ * </programlisting>
+ * </para>
+ * </refsect2>
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <glib-object.h>
+
+#include <gst/gst.h>
+
+#include "gsttssplitter.h"
+
+static void gst_tssplitter_set_filter(GstTSSplitter *filter, char *name, char*
pidlist);
+static void gst_tssplitter_remove_filter(GstTSSplitter *filter, char *name);
+
+/* Filter signals and args */
+enum
+{
+ SIGNAL_0,
+
+ /* methods */
+ SIGNAL_SET_FILTER,
+ SIGNAL_REMOVE_FILTER,
+
+ /* signals */
+ SIGNAL_NEW_PID_FOUND,
+
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_DEBUG_OUTPUT,
+ PROP_SIGNAL_NEW_PIDS,
+ PROP_LAST
+};
+
+static guint gst_tssplitter_signals[LAST_SIGNAL] = { 0 };
+
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+
GST_PAD_SINK,
+
GST_PAD_ALWAYS,
+
GST_STATIC_CAPS ("ANY")
+ );
+
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+
GST_PAD_REQUEST,
+
GST_STATIC_CAPS ("ANY")
+ );
+
+/*
**********************************************************************************++
*/
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#else /* !G_ENABLE_DEBUG */
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#endif
+
+void
+ marshal_VOID__STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ 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 = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data :
cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ data2);
+}
+
+/*
**********************************************************************************++
*/
+
+int getbit(char *set, int number)
+{
+ set += number / 8;
+ return (*set & (1 << (number % 8))) != 0; /* 0 or 1 */
+}
+
+void setbit(char *set, int number, int value)
+{
+ set += number / 8;
+ if (value)
+ *set |= 1 << (number % 8); /* set bit */
+ else
+ *set &= ~(1 << (number % 8)); /* clear bit */
+}
+
+/*
**********************************************************************************++
*/
+
+GST_BOILERPLATE (GstTSSplitter, gst_tssplitter, GstElement,
+ GST_TYPE_ELEMENT);
+
+static void gst_tssplitter_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_tssplitter_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static gboolean gst_tssplitter_set_caps (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_tssplitter_chain (GstPad * pad, GstBuffer * buf);
+
+static void
+gst_tssplitter_base_init (gpointer gclass)
+{
+ static GstElementDetails element_details = {
+ "Splitter for MPEG Transport Streams",
+ "Freevo/TSSplitter",
+ "split transport stream into multiple transport streams",
+ "Soenke Schwardt <[EMAIL PROTECTED]>"
+ };
+ GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+ /* FIXME obsolete */
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get
(&src_factory));
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
+ gst_element_class_set_details (element_class, &element_details);
+}
+
+/* initialize the plugin's class */
+static void
+gst_tssplitter_class_init (GstTSSplitterClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+
+ gobject_class->set_property = gst_tssplitter_set_property;
+ gobject_class->get_property = gst_tssplitter_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_DEBUG_OUTPUT,
+ g_param_spec_boolean ("debug-output", "DebugOutput", "Produce verbose
debug output?",
+ FALSE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_SIGNAL_NEW_PIDS,
+ g_param_spec_boolean ("signalnewpids", "SignalOnNewPids", "Send signal
if new pid is found?",
+ FALSE, G_PARAM_READWRITE));
+
+ gst_tssplitter_signals[SIGNAL_SET_FILTER] =
+ g_signal_new ("set-filter", /* signal
name */
+ G_TYPE_FROM_CLASS (klass), /* itype */
+ G_SIGNAL_RUN_LAST, /* signal
flags */
+ G_STRUCT_OFFSET (GstTSSplitterClass, set_filter),/* class
closure */
+ NULL, /*
accumulator */
+ NULL, /* accu_data
*/
+ marshal_VOID__STRING_STRING, /*
c_marshaller */
+ G_TYPE_NONE, /* return
type */
+ 2, /* n_params
*/
+ G_TYPE_STRING, /* param
name */
+ G_TYPE_STRING); /* param
pids */
+
+ gst_tssplitter_signals[SIGNAL_REMOVE_FILTER] =
+ g_signal_new ("remove-filter", /* signal
name */
+ G_TYPE_FROM_CLASS (klass), /* itype */
+ G_SIGNAL_RUN_LAST, /* signal
flags */
+ G_STRUCT_OFFSET (GstTSSplitterClass, remove_filter),/* class
closure */
+ NULL, /*
accumulator */
+ NULL, /* accu_data
*/
+ g_cclosure_marshal_VOID__STRING, /*
c_marshaller */
+ G_TYPE_NONE, /* return
type */
+ 1, /* n_params
*/
+ G_TYPE_STRING); /* param
name */
+
+ klass->set_filter = GST_DEBUG_FUNCPTR (gst_tssplitter_set_filter);
+ klass->remove_filter = GST_DEBUG_FUNCPTR (gst_tssplitter_remove_filter);
+}
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set functions
+ * initialize structure
+ */
+static void
+gst_tssplitter_init (GstTSSplitter * filter,
+ GstTSSplitterClass * gclass)
+{
+ int i;
+ GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
+
+ filter->sinkpad =
+ gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
"sink"), "sink");
+ gst_pad_set_setcaps_function (filter->sinkpad, gst_tssplitter_set_caps);
+ gst_pad_set_getcaps_function (filter->sinkpad, gst_pad_proxy_getcaps);
+
+/* filter->srcpad = */
+/* gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
"src"), "src"); */
+/* gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps); */
+
+ gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+/* gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); */
+ gst_pad_set_chain_function (filter->sinkpad, gst_tssplitter_chain);
+
+ /* init internal data */
+ filter->debug_output = FALSE;
+ filter->signal_new_pids = FALSE;
+
+ /* init filter list */
+ filter->filterlist_len = GST_TSSPLITTER_INIT_FILTERLIST_LEN;
+ filter->filterlist_free = GST_TSSPLITTER_INIT_FILTERLIST_LEN;
+ filter->filterlist = g_malloc( sizeof(GstTSSplitterFilter) *
GST_TSSPLITTER_INIT_FILTERLIST_LEN );
+ for(i = 0; i < GST_TSSPLITTER_INIT_FILTERLIST_LEN; ++i) {
+ filter->filterlist[i].name = NULL;
+ filter->filterlist[i].pidlist = NULL;
+ filter->filterlist[i].pad = NULL;
+ }
+ filter->inbuffer = gst_buffer_new();
+}
+
+static void
+gst_tssplitter_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstTSSplitter *filter = GST_TSSPLITTER (object);
+
+ switch (prop_id) {
+ case PROP_DEBUG_OUTPUT:
+ filter->debug_output = g_value_get_boolean (value);
+ break;
+ case PROP_SIGNAL_NEW_PIDS:
+ filter->signal_new_pids = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_tssplitter_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstTSSplitter *filter = GST_TSSPLITTER (object);
+
+ switch (prop_id) {
+ case PROP_DEBUG_OUTPUT:
+ g_value_set_boolean (value, filter->debug_output);
+ break;
+ case PROP_SIGNAL_NEW_PIDS:
+ g_value_set_boolean (value, filter->signal_new_pids);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* GstElement vmethod implementations */
+
+/* this function handles the link with other elements */
+static gboolean
+gst_tssplitter_set_caps (GstPad * pad, GstCaps * caps)
+{
+ GstTSSplitter *filter;
+ GstPad *otherpad;
+
+ filter = GST_TSSPLITTER (gst_pad_get_parent (pad));
+ DEBUGf("chain\n");
+ otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
+
+ return gst_pad_set_caps (pad, caps);
+}
+
+/* chain function
+ * this function does the actual processing
+ */
+
+#define COLOR_RED "\x1b[0;31m"
+#define COLOR_GREEN "\x1b[0;32m"
+#define COLOR_GELB "\x1b[0;33m"
+#define COLOR_BLUE "\x1b[0;34m"
+#define COLOR_PURPLE "\x1b[0;35m"
+#define COLOR_CYAN "\x1b[0;36m"
+#define COLOR_WHITE "\x1b[0;37m"
+#define COLOR_NORMAL "\x1b[0m"
+
+/*
+ * printHexDump()
+ * gibt packetlen Zeichen aus dem buffer als HexDump aus
+ */
+void printHexDump( int packetlen, unsigned char *buffer ) {
+ int pos=0;
+ // Ausgeben, solange Paketl�nge bzw. dumpLength nicht �berschritten wird
+ while (pos < packetlen) {
+ // Anfang einer Zeile? Dann den aktuellen Offset ausgeben
+ if (pos%16 == 0) {
+ printf(COLOR_RED "%06x: " COLOR_NORMAL , pos);
+ }
+ // Hexdump von einem Byte ausgeben
+ printf("%02x ", buffer[pos]);
+ // ein Zeichen im Paket weiterspringen
+ pos++;
+ // Sind wir am Ende einer Zeile? Wenn ja, dann die lesbaren Zeichen
ausgeben
+ if (pos%16 == 0) {
+ printf(" ");
+ int i;
+ for(i=16; i > 0; i--) {
+ if ((32 <= buffer[pos-i]) &&
+ (buffer[pos-i] <= 127)) {
+ printf("%c", buffer[pos-i]);
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+ }
+ // Die letzte Zeile des HexDumps ist ausgegeben worden.
+ // Waren in der letzten Zeile weniger als 16 Zeichen (==> lesbare Zeichen
wurden nicht ausgegeben)?
+ if (pos%16 != 0) {
+ // ja, entsprechend gro�en Leerraum ausgeben
+ printf(" ");
+ int i;
+ for(i=16-(pos%16); i > 0; i--) {
+ printf(" ");
+ }
+ // die verbliebenen Zeichen ausgeben
+ for(i=(pos%16); i > 0; i--) {
+ if ((32 <= buffer[pos-i]) &&
+ (buffer[pos-i] <= 127)) {
+ printf("%c", buffer[pos-i]);
+ } else {
+ printf(".");
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+
+
+static gint process_ts_frames(GstTSSplitter *filter, guint8* buffer, int
buflen)
+{
+ unsigned int i;
+
+ if (buflen < 2*188) {
+ DEBUGf("FIXME: got less than 2*188 bytes");
+ return buflen;
+ }
+
+ // check if they are really transport stream frames
+ for ( i = 0; i < 188 ; i++){
+ if (( buffer[i] == 0x47 ) &&
+ ( buffer[i+188] == 0x47 )) {
+ break;
+ }
+ }
+ if ( i == 188){
+ DEBUGf( "not a transport stream or stream broken");
+ return buflen-188;
+ } else if (i) {
+ DEBUGf( "dropping %d bytes to get TS in sync", i);
+ // if unequal 0 then cutoff bogus
+ /* buffer += i; */
+ /* buflen -= i; */
+ }
+
+/* DEBUGf("processing %d bytes", buflen); */
+
+ // iterate through all complete frames
+ while( buflen - i >= 188 ) {
+
+ // check frame
+ if (buffer[i] != 0x47) {
+
+ // frame invalid
+ DEBUGf( "invalid ts frame (i=%d - val=0x%02x)", i, buffer[i] );
+
+ // check if they are really transport stream frames
+ while( ((buflen - i) >= 188) && (buffer[i] != 0x47) ) {
+ ++i;
+ }
+ DEBUGf( "trying new position (i=%d - val=0x%02x)", i, buffer[i] );
+ if ( buffer[i] != 0x47) {
+ DEBUGf( "not a transport stream or stream broken (after seek)");
+ return 188;
+ }
+
+ } else {
+
+ // frame ok
+ int ts_error = ((int)(buffer[i+1] & 0x80) >> 7);
+ int pid = ((((int)buffer[i+1] & 0x1F) << 8) | ((int)buffer[i+2] &
0xFF));
+ int ts_sc = ((int)(buffer[i+3] & 0xC0) >> 6);
+
+ // FIXME TODO implement counter to reduce output
+ if (ts_error) {
+ DEBUGf( "ts frame is damaged i=%d!",i);
+ }
+ if (ts_sc) {
+ DEBUGf( "ts frame is scrambled!");
+ }
+
+ GstTSSplitterFilter *filterlist = filter->filterlist;
+ int cnt = filter->filterlist_len;
+ // iterate over all registered filters
+ while (filterlist->name && (cnt > 0)) {
+
+ if (getbit(filterlist->pidlist, pid)) {
+ assert(filterlist->name);
+ assert(filterlist->pad);
+
+ // fill gst buffer
+ GstBuffer *gstbuf = gst_buffer_new_and_alloc(188);
+ gst_buffer_set_data(gstbuf, &buffer[i], 188);
+
+ // add ts frame to pad
+ gst_pad_push (filterlist->pad, gstbuf);
+
+ DEBUGf("Adding ts frame to pad '%s'\n", filterlist->name);
+ }
+ filterlist++;
+ }
+ }
+ // jump to next ts frame
+ i += 188;
+ }
+
+ // return remaining bytes
+ return (buflen - i);
+}
+
+
+static GstFlowReturn
+gst_tssplitter_chain (GstPad * pad, GstBuffer * buf)
+{
+ GstTSSplitter *filter;
+ static int i = 0;
+
+ filter = GST_TSSPLITTER (GST_OBJECT_PARENT (pad));
+ // DEBUGf("chain\n");
+
+/* DEBUGf("bytes from last iteration=%d\n",
GST_BUFFER_SIZE(filter->inbuffer)); */
+/* printHexDump( GST_BUFFER_SIZE(filter->inbuffer), filter->inbuffer->data
); */
+
+ GstBuffer *gstbuf = gst_buffer_merge( filter->inbuffer, buf );
+/* DEBUGf("bytes in new buffer=%d\n", GST_BUFFER_SIZE(gstbuf)); */
+/* printHexDump( GST_BUFFER_SIZE(filter->inbuffer) + 64, gstbuf->data ); */
+
+ int remaining = process_ts_frames(filter, gstbuf->data, gstbuf->size);
+/* DEBUGf("remaining bytes = %d", remaining); */
+/* printf("\nREMAINING BYTES2:\n"); */
+/* printHexDump( (remaining), &gstbuf->data[ GST_BUFFER_SIZE(gstbuf) -
remaining ] ); */
+
+/* DEBUGf("remaining=%d > buffer=%d", remaining,
GST_BUFFER_SIZE(filter->inbuffer)); */
+ if (remaining > GST_BUFFER_SIZE(filter->inbuffer)) {
+ gst_buffer_unref(filter->inbuffer);
+ filter->inbuffer = gst_buffer_new_and_alloc(remaining+20*188);
+ }
+
+ GstBuffer *tmpbuf = gst_buffer_create_sub(gstbuf, GST_BUFFER_SIZE(gstbuf) -
remaining, remaining);
+ gst_buffer_unref(filter->inbuffer);
+ filter->inbuffer = gst_buffer_copy(tmpbuf);
+ gst_buffer_unref(tmpbuf);
+
+ gst_buffer_unref(gstbuf);
+
+/* - EIGENEN EINGANGS-BUFFER F�R M�GLICHE RESTE ANLEGEN UND DIESE BEIM
N�CHSTEN AUFRUF BEACHTEN */
+/* - Pointer auf Restebuffer an TSFrameSuchFunktion �bergeben */
+/* - Pointer auf IncomingBuffer an TSFrameSuchFunktion �bergeben */
+
+ /*
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-libs/html/GstAdapter.html
*/
+
+ i += buf->size;
+/* DEBUGf("processing data: bufsize=%d len=%d", buf->size, i); */
+
+ return GST_FLOW_OK;
+ /* just push out the incoming buffer without touching it */
+ /* return gst_pad_push (filter->srcpad, buf); */
+}
+
+
+/* TSFrameSuchFunktion: */
+/* - suchen nach TS Frame Preambel */
+/* - PID raussuchen */
+/* - gesamte Filterlist durchsuchen */
+/* - wenn PID matcht, dann TSFrame an das Pad anh�ngen */
+
+
+static GstTSSplitterFilter *gst_tssplitter_find_filter(GstTSSplitter *filter,
char *name)
+{
+ DEBUGf("find filter(%s)", name);
+ int i;
+ for(i = 0; i < filter->filterlist_len; ++i) {
+ if (filter->filterlist[i].name && (!strcasecmp(filter->filterlist[i].name,
name))) {
+ return &filter->filterlist[i];
+ }
+ }
+ return NULL;
+}
+
+static GstTSSplitterFilter *gst_tssplitter_add_new_filter(GstTSSplitter
*filter, char *name)
+{
+ int i = -1;
+ /* request more mempry if needed */
+ if (filter->filterlist_free == 0) {
+ DEBUGf("no free space (cnt=%d/free=%d) - requesting more memory",
+ filter->filterlist_len, filter->filterlist_free);
+
+ gint oldsize = filter->filterlist_len;
+ filter->filterlist_len += 5;
+ filter->filterlist = g_realloc( filter->filterlist,
sizeof(GstTSSplitterFilter) * filter->filterlist_len );
+ assert(filter->filterlist);
+ filter->filterlist_free += 5;
+ for(i=oldsize; i<filter->filterlist_len; ++i) {
+ filter->filterlist[i].name = NULL;
+ filter->filterlist[i].pidlist = NULL;
+ filter->filterlist[i].pad = NULL;
+ }
+ }
+
+ i = filter->filterlist_len - filter->filterlist_free;
+ // fill new pidfilter
+ DEBUGf("adding new filter %s", name);
+ filter->filterlist[i].name = strdup(name);
+ filter->filterlist[i].pad =
+ gst_pad_new_from_template (gst_element_class_get_pad_template
(GST_ELEMENT_GET_CLASS (filter), "src"), name);
+ filter->filterlist[i].pidlist = malloc( sizeof(char) * (1 << 13) + 5 );
+ memset( filter->filterlist[i].pidlist, 0, (sizeof(char) * (1 << 13) + 5) );
+
+ // add new pad
+ gst_element_add_pad (GST_ELEMENT (filter), filter->filterlist[i].pad);
+
+ filter->filterlist_free--;
+
+ return &(filter->filterlist[i]);
+}
+
+
+static void
+gst_tssplitter_set_filter(GstTSSplitter *filter, char *name, char* pidlist)
+{
+ GstTSSplitterFilter *pidfilter = NULL;
+ int len=strlen(pidlist);
+ int i = 0;
+ int pid = 0;
+
+ DEBUGf("set_filter(%s)=%s", name, pidlist);
+
+ pidfilter = gst_tssplitter_find_filter(filter, name);
+ DEBUGf("find_filter(%s)=%p", name, pidfilter);
+
+ if (!pidfilter) {
+ // pidfilter not found ==> add a new one
+ pidfilter = gst_tssplitter_add_new_filter(filter, name);
+ }
+ assert(pidfilter);
+
+ // parse pid list
+ while (len > 0) {
+ for(i=0; i<len; ++i) {
+ if (pidlist[i] == ',') {
+ pidlist[i] = '\0';
+ pid = atoi(pidlist);
+
+ // DEBUGf("setfilter: pid=%d", pid);
+ setbit(pidfilter->pidlist, pid, 1);
+
+ pidlist += (i+1);
+ len -= (i+1);
+ break;
+ }
+ }
+ if (i == len) {
+ pid = atoi(pidlist);
+ // DEBUGf("setfilter: pid=%d", pid);
+ setbit(pidfilter->pidlist, pid, 1);
+ break;
+ }
+ }
+
+ return;
+}
+
+
+static void
+gst_tssplitter_remove_filter(GstTSSplitter *filter, char *name)
+{
+ DEBUGf("remove_filter(%s)", name);
+
+ GstTSSplitterFilter *pidfilter = NULL;
+
+ pidfilter = gst_tssplitter_find_filter(filter, name);
+ DEBUGf("remove_filter(%s)=%p", name, pidfilter);
+ if (!pidfilter)
+ return;
+
+ // TODO/FIXME
+ // PAD ENTFERNEN
+ // PIDLIST FREIGEBEN
+ // FILTER FREIGEBEN
+ // FILTER GGF. UMSORTIEREN
+
+ return;
+}
Added: trunk/WIP/record/src/gsttssplitter.h
==============================================================================
--- (empty file)
+++ trunk/WIP/record/src/gsttssplitter.h Tue Feb 6 11:15:07 2007
@@ -0,0 +1,123 @@
+/*
+ * GStreamer
+ * Copyright 2005 Thomas Vander Stichele <[EMAIL PROTECTED]>
+ * Copyright 2005 Ronald S. Bultje <[EMAIL PROTECTED]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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_TSSPLITTER_H__
+#define __GST_TSSPLITTER_H__
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_TSSPLITTER \
+ (gst_tssplitter_get_type())
+#define GST_TSSPLITTER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TSSPLITTER,GstTSSplitter))
+#define GST_TSSPLITTER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TSSPLITTER,GstTSSplitterClass))
+/* #define GST_IS_PLUGIN_TEMPLATE(obj) \ */
+/* (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TSSPLITTER)) */
+/* #define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \ */
+/* (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TSSPLITTER)) */
+
+#define DEBUGf( fmt, args... ) \
+ do { \
+ if (filter->debug_output) { \
+ struct timeval tv; \
+ gettimeofday( &tv, NULL ); \
+ struct tm *curtime; \
+ time_t now = time(NULL); \
+ curtime = localtime( &now ); \
+ g_print( "\n%02d:%02d:%02d.%03d %10s:%04d (%s): " fmt, \
+ curtime->tm_hour, curtime->tm_min, curtime->tm_sec,
((int)tv.tv_usec / 1000), \
+ __FILE__, __LINE__, __FUNCTION__, ##args);
\
+ } \
+ } while(0);
+
+
+#define GST_TSSPLITTER_INIT_FILTERLIST_LEN 5
+
+typedef struct _GstTSSplitter GstTSSplitter;
+typedef struct _GstTSSplitterClass GstTSSplitterClass;
+typedef struct _GstTSSplitterFilter GstTSSplitterFilter;
+
+
+struct _GstTSSplitterFilter
+{
+ char *name;
+ char *pidlist;
+ GstPad *pad;
+};
+
+struct _GstTSSplitter
+{
+ GstElement element;
+
+ GstPad *sinkpad, *srcpad;
+
+ GstBuffer *inbuffer;
+
+ gboolean debug_output;
+ gboolean signal_new_pids;
+ gint filterlist_len;
+ gint filterlist_free;
+ GstTSSplitterFilter *filterlist;
+};
+
+struct _GstTSSplitterClass
+{
+ GstElementClass parent_class;
+
+ void (*set_filter) (GstTSSplitter *filter, char *name,
char* pidlist);
+ void (*remove_filter) (GstTSSplitter *filter, char *name);
+};
+
+GType gst_tssplitter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_TSSPLITTER_H__ */
Added: trunk/WIP/record/test/splitter.py
==============================================================================
--- (empty file)
+++ trunk/WIP/record/test/splitter.py Tue Feb 6 11:15:07 2007
@@ -0,0 +1,92 @@
+#!/usr/bin/python
+import pygst
+pygst.require('0.10')
+import gst
+import gobject
+import sys
+import time
+import os
+
+import kaa.record2
+
+filtername2obj = {}
+
+def onNewPad(splitter, pad):
+ global filtername2obj
+ print "\n---"
+ print "pad added!"
+ print 'PAD:',pad
+ print 'PADNAME:',pad.get_name()
+ print 'PADCAPS:',pad.get_caps()
+ if not filtername2obj.has_key(pad.get_name()):
+ print "NOT FOUND"
+ return
+# print pad.get_caps()[0]
+# print pad.get_caps()[0].get_name()
+# format = pad.get_caps()[0].get_name()
+ print "OBJNAME:", filtername2obj[pad.get_name()].get_name()
+ pad.link(filtername2obj[pad.get_name()].get_compatible_pad(pad))
+
+ print "---"
+
+
+def main():
+ global foo
+
+ fdsrc = gst.element_factory_make("filesrc", "quelle")
+ fdsrc.set_property('location', '/home/dmeyer/stream.dump')
+
+ tssplitter = gst.element_factory_make("tssplitter", "mysplitter")
+ tssplitter.set_property('debug-output', True)
+ tssplitter.connect("pad-added", onNewPad)
+
+ pipeline = gst.Pipeline("splitterchain")
+ pipeline.add(fdsrc, tssplitter)
+
+ fdsrc.link(tssplitter)
+
+ pipeline.set_state(gst.STATE_PLAYING);
+
+ filesinkA = gst.element_factory_make('filesink', 'sinkA')
+ filesinkA.set_property('location', '/tmp/filesinkA.ts')
+ filesinkA.set_property('sync', '1')
+ pipeline.add(filesinkA)
+ filtername2obj["myfilter1"] = filesinkA
+
+ filesinkB = gst.element_factory_make('filesink', 'sinkB')
+ filesinkB.set_property('location', '/tmp/filesinkB.ts')
+ filesinkB.set_property('sync', '1')
+ pipeline.add(filesinkB)
+ filtername2obj["myfilter2"] = filesinkB
+
+
+ tssplitter.emit("set-filter", "myfilter2", "386")
+ tssplitter.emit("set-filter", "myfilter1", "110,120")
+
+ print "SLEEPING"
+ time.sleep(1)
+ print "DONE"
+
+# fdsrc.set_state(gst.STATE_PLAYING);
+# tssplitter.set_state(gst.STATE_PLAYING);
+# filesinkA.set_state(gst.STATE_PLAYING);
+# filesinkB.set_state(gst.STATE_PLAYING);
+ mainloop = gobject.MainLoop()
+
+ def bus_event(bus, message):
+ t = message.type
+ if t == gst.MESSAGE_EOS:
+ mainloop.quit()
+ elif t == gst.MESSAGE_ERROR:
+ err, debug = message.parse_error()
+ print "Error: %s" % err, debug
+ mainloop.quit()
+ return True
+ pipeline.get_bus().add_watch(bus_event)
+
+ mainloop.run()
+ pipeline.set_state(gst.STATE_NULL)
+
+
+if __name__ == "__main__":
+ main()
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog