www.pudn.com > gsts2ps.rar > gstts2ps.c
/////////gstts2ps.c #include "gstts2ps.h" #include#include #include #include GST_DEBUG_CATEGORY_STATIC (gstts2ps_debug); #define GST_CAT_DEFAULT (gstts2ps_debug) static GstElementDetails ts2ps_details = { "TS2PS", "Filter/TS2PS", "Mpeg Transport Stream to Program Stream Converter", "P2P-VCR, C-Lab, University of Paderborn" }; /* Object signals and args */ enum { LAST_SIGNAL }; /* Arguments */ enum { ARG_0, ARG_TS2PS_V_PID, ARG_TS2PS_A_PID, ARG_TS2PS_BUFFERSIZE }; static GstStaticPadTemplate ps_src_factory = GST_STATIC_PAD_TEMPLATE ( "src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int) 2, " "systemstream = (boolean) TRUE" ) ); static void gst_ts2ps_base_init (GstTs2PsClass *klass); static void gst_ts2ps_class_init (GstTs2PsClass *klass); static void gst_ts2ps_init (GstTs2Ps *object); static void gst_ts2ps_dispose (GObject *object); static void gst_ts2ps_finalize (GObject *object); static void gst_ts2ps_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gst_ts2ps_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static GstPadLinkReturn gst_ts2ps_srcconnect_func (GstPad *pad, GstCaps *caps, gboolean newcaps); //static GstElementStateReturn gst_ts2ps_change_state (GstElement *element); static void gst_ts2ps_loop (GstElement* element); GstBuffer * gst_ts2ps_get (GstPad * pad); static void gst_ts2ps_push (uint8_t *buf, int count, void *p); void gst_ts2ps_parse_payload (GstTsParse *ts_parse, guint8 *data, int length); static void gst_ts2ps_handle_event (GstTsParse *ts_parse, GstEvent *event); static GstTsParseClass *parent_class = NULL; /* ****************************** * * * Private-Methods * * * * * ****************************** */ /* ****************************** * * * GObject Related * * * * * ****************************** */ GType gst_ts2ps_get_type (void) { static GType gst_ts2ps_type = 0; if (!gst_ts2ps_type) { static const GTypeInfo ts2ps_info = { sizeof (GstTs2PsClass), (GBaseInitFunc) gst_ts2ps_base_init, NULL, (GClassInitFunc) gst_ts2ps_class_init, NULL, NULL, sizeof (GstTs2Ps), 0, (GInstanceInitFunc) gst_ts2ps_init, }; gst_ts2ps_type = g_type_register_static (GST_TYPE_TSPARSE, "GstTs2Ps", &ts2ps_info, 0); GST_DEBUG_CATEGORY_INIT (gstts2ps_debug, "ts2ps", 0, "Mpeg TS to PS Element"); } return gst_ts2ps_type; } /* initialize the plugin's class */ static void gst_ts2ps_base_init (GstTs2PsClass *klass) { GObjectClass *gobject_class; GstElementClass *element_class = (GstElementClass*) klass; gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&ps_src_factory)); } /* initialize the plugin's class */ static void gst_ts2ps_class_init (GstTs2PsClass *klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; GstTsParseClass *ts_parse_class; GST_INFO("gst_ts2ps_class_init"); gobject_class = (GObjectClass*) klass; gstelement_class = (GstElementClass*) klass; ts_parse_class = (GstTsParseClass*) klass; parent_class = g_type_class_ref (GST_TYPE_TSPARSE); gobject_class->set_property = gst_ts2ps_set_property; gobject_class->get_property = gst_ts2ps_get_property; gobject_class->dispose = gst_ts2ps_dispose; gobject_class->finalize = gst_ts2ps_finalize; g_object_class_install_property (gobject_class, ARG_TS2PS_V_PID, g_param_spec_int ("vpid", "vpid", "Video Program ID", 0, G_MAXINT, 0, G_PARAM_READWRITE) ); g_object_class_install_property (gobject_class, ARG_TS2PS_A_PID, g_param_spec_int ("apid", "apid", "Audio Program ID", 0, G_MAXINT, 0, G_PARAM_READWRITE) ); g_object_class_install_property (gobject_class, ARG_TS2PS_BUFFERSIZE, g_param_spec_int ("buffersize", "buffersize", "Buffersize in bytes", 2048, G_MAXINT, DEFAULT_BUFFERSIZE, G_PARAM_READWRITE) ); ts_parse_class->parse_payload = gst_ts2ps_parse_payload; ts_parse_class->handle_event = gst_ts2ps_handle_event; } /* initialize the new element * instantiate pads and add them to element * set functions * initialize structure */ static void gst_ts2ps_init (GstTs2Ps *object) { GstTsParse *ts_parse = (GstTsParse*) object; GST_INFO("gst_ts2ps_init"); object->buffersize = DEFAULT_BUFFERSIZE; /* set to something sane for testing purpose */ //* 3SAT (Germany) object->apid = 220; object->vpid = 210; //*/ object->ps_buffer = g_malloc(object->buffersize); object->ps_off = 0; init_ipack(&object->pa, 2048, gst_ts2ps_push, 1); init_ipack(&object->pv, 2048, gst_ts2ps_push, 1); /* Set private data in packet to our object */ object->pa.data = object; object->pv.data = object; gst_element_remove_pad (GST_ELEMENT (ts_parse), ts_parse->srcpad); ts_parse->srcpad = gst_pad_new_from_template( gst_static_pad_template_get (&ps_src_factory), "src"); gst_element_add_pad (GST_ELEMENT (ts_parse), ts_parse->srcpad); } static void gst_ts2ps_set_property (GObject *_object, guint prop_id, const GValue *value, GParamSpec *pspec) { GstTs2Ps *object; g_return_if_fail (GST_IS_TS2PS (_object)); object = GST_TS2PS (_object); switch (prop_id) { case ARG_TS2PS_V_PID: object->vpid = g_value_get_int(value); break; case ARG_TS2PS_A_PID: object->apid = g_value_get_int(value); break; case ARG_TS2PS_BUFFERSIZE: object->buffersize = g_value_get_int(value); g_free(object->ps_buffer); object->ps_buffer = g_malloc(object->buffersize); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gst_ts2ps_get_property (GObject *_object, guint prop_id, GValue *value, GParamSpec *pspec) { GstTs2Ps *object; g_return_if_fail (GST_IS_TS2PS (_object)); object = GST_TS2PS (_object); switch (prop_id) { case ARG_TS2PS_V_PID: g_value_set_int(value, object->vpid); break; case ARG_TS2PS_A_PID: g_value_set_int(value, object->apid); break; case ARG_TS2PS_BUFFERSIZE: g_value_set_int(value, object->buffersize); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gst_ts2ps_dispose (GObject *_object) { GstTs2Ps *object; GST_DEBUG("gst_ts2ps_dispose"); g_return_if_fail (GST_IS_TS2PS (_object)); object = GST_TS2PS (_object); G_OBJECT_CLASS (parent_class)->dispose (_object); } static void gst_ts2ps_finalize (GObject *_object) { GstTs2Ps *object; GST_DEBUG("gst_ts2ps_finalize"); g_return_if_fail (GST_IS_TS2PS (_object)); object = GST_TS2PS (_object); G_OBJECT_CLASS (parent_class)->finalize (_object); } /* ****************************** * * * Plugin Realisation * * * ****************************** */ /* entry point to initialize the plug-in * initialize the plug-in itself * register the element factories and pad templates * register the features */ gboolean gst_ts2ps_plugin_init (GstPlugin *plugin) { return gst_element_register (plugin, "ts2ps", GST_RANK_NONE, GST_TYPE_TS2PS); } static void gst_ts2ps_handle_event(GstTsParse *ts_parse, GstEvent *event) { GstTs2Ps *object = GST_TS2PS(ts_parse); gint etype; etype = event ? GST_EVENT_TYPE (event) : GST_EVENT_EOS; switch (etype) { case GST_EVENT_EOS: break; case GST_EVENT_DISCONTINUOUS: fprintf(stderr, "gst_ts2ps handling discont\n"); if (GST_EVENT_DISCONT_NEW_MEDIA(event)) { init_ipack(&object->pa, 2048, gst_ts2ps_push, 1); init_ipack(&object->pv, 2048, gst_ts2ps_push, 1); } break; case GST_EVENT_FLUSH: break; } parent_class->handle_event(object, event); } /* The output routine for sending a PS */ static void gst_ts2ps_push(uint8_t *buf, int count, void *p) { GstTs2Ps *object = GST_TS2PS(p); GstBuffer *gst_buf; GST_DEBUG("%s (..., %d, ...)", __FUNCTION__, count); /* will we fill the ps_buffer? */ if (object->ps_off+count >= object->buffersize) { int r = object->ps_off +count - object->buffersize; /* fill buffer, and make a copy */ memcpy(object->ps_buffer + object->ps_off, buf, count-r); object->out_buffer = g_memdup(object->ps_buffer, object->buffersize); /* take care about the rest */ memcpy(object->ps_buffer, buf+count-r, r); object->ps_off = r; /* one buffer finished */ object->finished = TRUE; } else { memcpy(object->ps_buffer + object->ps_off, buf, count); object->ps_off += count; } } void gst_ts2ps_parse_payload (GstTsParse *ts_parse, guint8 *data, int length) { GstTs2Ps *object = GST_TS2PS(ts_parse); GstBuffer* buf; ipack* p; GST_DEBUG("Data: 0x%x, Length: %d", data, length); if (ts_parse->transport_error) { GST_DEBUG("Transport Error"); return; } if (ts_parse->pid == object->vpid) { GST_DEBUG("Video PID"); p = &object->pv; } else if (ts_parse->pid == object->apid) { GST_DEBUG("Audio PID"); p = &object->pa; } else { GST_INFO("Additional PID in TS: %d\n", ts_parse->pid); return; } if (ts_parse->unit_start) { if (p->plength == MMAX_PLENGTH-6){ p->plength = p->found-6; p->found = 0; GST_DEBUG("Unit Start pushing???"); send_ipack(p); reset_ipack(p); } } instant_repack(data, length, p); if (object->finished) { GST_DEBUG ("pushing buffer"); buf = gst_buffer_new(); GST_BUFFER_DATA(buf) = object->out_buffer; GST_BUFFER_SIZE(buf) = object->buffersize; GST_BUFFER_TIMESTAMP(buf) = GST_CLOCK_TIME_NONE; gst_pad_push(ts_parse->srcpad, GST_DATA(buf)); object->finished = FALSE; } }